github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/dbs_api.go (about)

     1  // Copyright 2020 The ql Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSES/QL-LICENSE file.
     4  
     5  // Copyright 2020 WHTCORPS INC, Inc.
     6  //
     7  // Licensed under the Apache License, Version 2.0 (the "License");
     8  // you may not use this file except in compliance with the License.
     9  // You may obtain a copy of the License at
    10  //
    11  //     http://www.apache.org/licenses/LICENSE-2.0
    12  //
    13  // Unless required by applicable law or agreed to in writing, software
    14  // distributed under the License is distributed on an "AS IS" BASIS,
    15  // See the License for the specific language governing permissions and
    16  // limitations under the License.
    17  
    18  package dbs
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/hex"
    23  	"encoding/json"
    24  	"fmt"
    25  	"math"
    26  	"strconv"
    27  	"strings"
    28  	"sync/atomic"
    29  	"time"
    30  
    31  	"github.com/cznic/mathutil"
    32  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    33  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    34  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    35  	"github.com/whtcorpsinc/BerolinaSQL/format"
    36  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    37  	field_types "github.com/whtcorpsinc/BerolinaSQL/types"
    38  	"github.com/whtcorpsinc/errors"
    39  	"github.com/whtcorpsinc/milevadb/blockcodec"
    40  	"github.com/whtcorpsinc/milevadb/causet"
    41  	"github.com/whtcorpsinc/milevadb/causet/blocks"
    42  	"github.com/whtcorpsinc/milevadb/config"
    43  	"github.com/whtcorpsinc/milevadb/dbs/memristed"
    44  	"github.com/whtcorpsinc/milevadb/ekv"
    45  	"github.com/whtcorpsinc/milevadb/memex"
    46  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    47  	"github.com/whtcorpsinc/milevadb/soliton"
    48  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    49  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    50  	"github.com/whtcorpsinc/milevadb/soliton/defCauslate"
    51  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    52  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    53  	"github.com/whtcorpsinc/milevadb/soliton/petriutil"
    54  	"github.com/whtcorpsinc/milevadb/soliton/set"
    55  	"github.com/whtcorpsinc/milevadb/spacetime/autoid"
    56  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    57  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    58  	"github.com/whtcorpsinc/milevadb/types"
    59  	driver "github.com/whtcorpsinc/milevadb/types/BerolinaSQL_driver"
    60  	"go.uber.org/zap"
    61  )
    62  
    63  const (
    64  	memexIndexPrefix             = "_V$"
    65  	changingDeferredCausetPrefix = "_DefCaus$_"
    66  	changingIndexPrefix          = "_Idx$_"
    67  )
    68  
    69  func (d *dbs) CreateSchema(ctx stochastikctx.Context, schemaReplicant perceptron.CIStr, charsetInfo *ast.CharsetOpt) error {
    70  	dbInfo := &perceptron.DBInfo{Name: schemaReplicant}
    71  	if charsetInfo != nil {
    72  		chs, defCausl, err := ResolveCharsetDefCauslation(ast.CharsetOpt{Chs: charsetInfo.Chs, DefCaus: charsetInfo.DefCaus})
    73  		if err != nil {
    74  			return errors.Trace(err)
    75  		}
    76  		dbInfo.Charset = chs
    77  		dbInfo.DefCauslate = defCausl
    78  	} else {
    79  		dbInfo.Charset, dbInfo.DefCauslate = charset.GetDefaultCharsetAndDefCauslate()
    80  	}
    81  	return d.CreateSchemaWithInfo(ctx, dbInfo, OnExistError, false /*tryRetainID*/)
    82  }
    83  
    84  func (d *dbs) CreateSchemaWithInfo(
    85  	ctx stochastikctx.Context,
    86  	dbInfo *perceptron.DBInfo,
    87  	onExist OnExist,
    88  	tryRetainID bool,
    89  ) error {
    90  	is := d.GetSchemaReplicantWithInterceptor(ctx)
    91  	_, ok := is.SchemaByName(dbInfo.Name)
    92  	if ok {
    93  		err := schemareplicant.ErrDatabaseExists.GenWithStackByArgs(dbInfo.Name)
    94  		switch onExist {
    95  		case OnExistIgnore:
    96  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
    97  			return nil
    98  		case OnExistError, OnExistReplace:
    99  			// FIXME: can we implement MariaDB's CREATE OR REPLACE SCHEMA?
   100  			return err
   101  		}
   102  	}
   103  
   104  	if err := checkTooLongSchema(dbInfo.Name); err != nil {
   105  		return errors.Trace(err)
   106  	}
   107  
   108  	if err := checkCharsetAndDefCauslation(dbInfo.Charset, dbInfo.DefCauslate); err != nil {
   109  		return errors.Trace(err)
   110  	}
   111  
   112  	// FIXME: support `tryRetainID`.
   113  	genIDs, err := d.genGlobalIDs(1)
   114  	if err != nil {
   115  		return errors.Trace(err)
   116  	}
   117  	dbInfo.ID = genIDs[0]
   118  
   119  	job := &perceptron.Job{
   120  		SchemaID:   dbInfo.ID,
   121  		SchemaName: dbInfo.Name.L,
   122  		Type:       perceptron.CausetActionCreateSchema,
   123  		BinlogInfo: &perceptron.HistoryInfo{},
   124  		Args:       []interface{}{dbInfo},
   125  	}
   126  
   127  	err = d.doDBSJob(ctx, job)
   128  	err = d.callHookOnChanged(err)
   129  	return errors.Trace(err)
   130  }
   131  
   132  func (d *dbs) AlterSchema(ctx stochastikctx.Context, stmt *ast.AlterDatabaseStmt) (err error) {
   133  	// Resolve target charset and defCauslation from options.
   134  	var toCharset, toDefCauslate string
   135  	for _, val := range stmt.Options {
   136  		switch val.Tp {
   137  		case ast.DatabaseOptionCharset:
   138  			if toCharset == "" {
   139  				toCharset = val.Value
   140  			} else if toCharset != val.Value {
   141  				return ErrConflictingDeclarations.GenWithStackByArgs(toCharset, val.Value)
   142  			}
   143  		case ast.DatabaseOptionDefCauslate:
   144  			info, err := defCauslate.GetDefCauslationByName(val.Value)
   145  			if err != nil {
   146  				return errors.Trace(err)
   147  			}
   148  			if toCharset == "" {
   149  				toCharset = info.CharsetName
   150  			} else if toCharset != info.CharsetName {
   151  				return ErrConflictingDeclarations.GenWithStackByArgs(toCharset, info.CharsetName)
   152  			}
   153  			toDefCauslate = info.Name
   154  		}
   155  	}
   156  	if toDefCauslate == "" {
   157  		if toDefCauslate, err = charset.GetDefaultDefCauslation(toCharset); err != nil {
   158  			return errors.Trace(err)
   159  		}
   160  	}
   161  
   162  	// Check if need to change charset/defCauslation.
   163  	dbName := perceptron.NewCIStr(stmt.Name)
   164  	is := d.GetSchemaReplicantWithInterceptor(ctx)
   165  	dbInfo, ok := is.SchemaByName(dbName)
   166  	if !ok {
   167  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(dbName.O)
   168  	}
   169  	if dbInfo.Charset == toCharset && dbInfo.DefCauslate == toDefCauslate {
   170  		return nil
   171  	}
   172  
   173  	// Do the DBS job.
   174  	job := &perceptron.Job{
   175  		SchemaID:   dbInfo.ID,
   176  		SchemaName: dbInfo.Name.L,
   177  		Type:       perceptron.CausetActionModifySchemaCharsetAndDefCauslate,
   178  		BinlogInfo: &perceptron.HistoryInfo{},
   179  		Args:       []interface{}{toCharset, toDefCauslate},
   180  	}
   181  	err = d.doDBSJob(ctx, job)
   182  	err = d.callHookOnChanged(err)
   183  	return errors.Trace(err)
   184  }
   185  
   186  func (d *dbs) DropSchema(ctx stochastikctx.Context, schemaReplicant perceptron.CIStr) (err error) {
   187  	is := d.GetSchemaReplicantWithInterceptor(ctx)
   188  	old, ok := is.SchemaByName(schemaReplicant)
   189  	if !ok {
   190  		return errors.Trace(schemareplicant.ErrDatabaseNotExists)
   191  	}
   192  	job := &perceptron.Job{
   193  		SchemaID:   old.ID,
   194  		SchemaName: old.Name.L,
   195  		Type:       perceptron.CausetActionDropSchema,
   196  		BinlogInfo: &perceptron.HistoryInfo{},
   197  	}
   198  
   199  	err = d.doDBSJob(ctx, job)
   200  	err = d.callHookOnChanged(err)
   201  	if err != nil {
   202  		return errors.Trace(err)
   203  	}
   204  	if !config.TableLockEnabled() {
   205  		return nil
   206  	}
   207  	// Clear causet locks hold by the stochastik.
   208  	tbs := is.SchemaTables(schemaReplicant)
   209  	lockTableIDs := make([]int64, 0)
   210  	for _, tb := range tbs {
   211  		if ok, _ := ctx.CheckTableLocked(tb.Meta().ID); ok {
   212  			lockTableIDs = append(lockTableIDs, tb.Meta().ID)
   213  		}
   214  	}
   215  	ctx.ReleaseTableLockByTableIDs(lockTableIDs)
   216  	return nil
   217  }
   218  
   219  func checkTooLongSchema(schemaReplicant perceptron.CIStr) error {
   220  	if len(schemaReplicant.L) > allegrosql.MaxDatabaseNameLength {
   221  		return ErrTooLongIdent.GenWithStackByArgs(schemaReplicant)
   222  	}
   223  	return nil
   224  }
   225  
   226  func checkTooLongTable(causet perceptron.CIStr) error {
   227  	if len(causet.L) > allegrosql.MaxTableNameLength {
   228  		return ErrTooLongIdent.GenWithStackByArgs(causet)
   229  	}
   230  	return nil
   231  }
   232  
   233  func checkTooLongIndex(index perceptron.CIStr) error {
   234  	if len(index.L) > allegrosql.MaxIndexIdentifierLen {
   235  		return ErrTooLongIdent.GenWithStackByArgs(index)
   236  	}
   237  	return nil
   238  }
   239  
   240  func setDeferredCausetFlagWithConstraint(defCausMap map[string]*causet.DeferredCauset, v *ast.Constraint) {
   241  	switch v.Tp {
   242  	case ast.ConstraintPrimaryKey:
   243  		for _, key := range v.Keys {
   244  			if key.Expr != nil {
   245  				continue
   246  			}
   247  			c, ok := defCausMap[key.DeferredCauset.Name.L]
   248  			if !ok {
   249  				continue
   250  			}
   251  			c.Flag |= allegrosql.PriKeyFlag
   252  			// Primary key can not be NULL.
   253  			c.Flag |= allegrosql.NotNullFlag
   254  		}
   255  	case ast.ConstraintUniq, ast.ConstraintUniqIndex, ast.ConstraintUniqKey:
   256  		for i, key := range v.Keys {
   257  			if key.Expr != nil {
   258  				continue
   259  			}
   260  			c, ok := defCausMap[key.DeferredCauset.Name.L]
   261  			if !ok {
   262  				continue
   263  			}
   264  			if i == 0 {
   265  				// Only the first defCausumn can be set
   266  				// if unique index has multi defCausumns,
   267  				// the flag should be MultipleKeyFlag.
   268  				// See https://dev.allegrosql.com/doc/refman/5.7/en/show-defCausumns.html
   269  				if len(v.Keys) > 1 {
   270  					c.Flag |= allegrosql.MultipleKeyFlag
   271  				} else {
   272  					c.Flag |= allegrosql.UniqueKeyFlag
   273  				}
   274  			}
   275  		}
   276  	case ast.ConstraintKey, ast.ConstraintIndex:
   277  		for i, key := range v.Keys {
   278  			if key.Expr != nil {
   279  				continue
   280  			}
   281  			c, ok := defCausMap[key.DeferredCauset.Name.L]
   282  			if !ok {
   283  				continue
   284  			}
   285  			if i == 0 {
   286  				// Only the first defCausumn can be set.
   287  				c.Flag |= allegrosql.MultipleKeyFlag
   288  			}
   289  		}
   290  	}
   291  }
   292  
   293  func buildDeferredCausetsAndConstraints(
   294  	ctx stochastikctx.Context,
   295  	defCausDefs []*ast.DeferredCausetDef,
   296  	constraints []*ast.Constraint,
   297  	tblCharset string,
   298  	tblDefCauslate string,
   299  ) ([]*causet.DeferredCauset, []*ast.Constraint, error) {
   300  	defCausMap := map[string]*causet.DeferredCauset{}
   301  	// outPriKeyConstraint is the primary key constraint out of defCausumn definition. such as: create causet t1 (id int , age int, primary key(id));
   302  	var outPriKeyConstraint *ast.Constraint
   303  	for _, v := range constraints {
   304  		if v.Tp == ast.ConstraintPrimaryKey {
   305  			outPriKeyConstraint = v
   306  			break
   307  		}
   308  	}
   309  	defcaus := make([]*causet.DeferredCauset, 0, len(defCausDefs))
   310  	for i, defCausDef := range defCausDefs {
   311  		defCaus, cts, err := buildDeferredCausetAndConstraint(ctx, i, defCausDef, outPriKeyConstraint, tblCharset, tblDefCauslate)
   312  		if err != nil {
   313  			return nil, nil, errors.Trace(err)
   314  		}
   315  		defCaus.State = perceptron.StatePublic
   316  		constraints = append(constraints, cts...)
   317  		defcaus = append(defcaus, defCaus)
   318  		defCausMap[defCausDef.Name.Name.L] = defCaus
   319  	}
   320  	// Traverse causet Constraints and set defCaus.flag.
   321  	for _, v := range constraints {
   322  		setDeferredCausetFlagWithConstraint(defCausMap, v)
   323  	}
   324  	return defcaus, constraints, nil
   325  }
   326  
   327  // ResolveCharsetDefCauslation will resolve the charset and defCauslate by the order of parameters:
   328  // * If any given ast.CharsetOpt is not empty, the resolved charset and defCauslate will be returned.
   329  // * If all ast.CharsetOpts are empty, the default charset and defCauslate will be returned.
   330  func ResolveCharsetDefCauslation(charsetOpts ...ast.CharsetOpt) (string, string, error) {
   331  	for _, v := range charsetOpts {
   332  		if v.DefCaus != "" {
   333  			defCauslation, err := defCauslate.GetDefCauslationByName(v.DefCaus)
   334  			if err != nil {
   335  				return "", "", errors.Trace(err)
   336  			}
   337  			if v.Chs != "" && defCauslation.CharsetName != v.Chs {
   338  				return "", "", charset.ErrDefCauslationCharsetMismatch.GenWithStackByArgs(v.DefCaus, v.Chs)
   339  			}
   340  			return defCauslation.CharsetName, v.DefCaus, nil
   341  		}
   342  		if v.Chs != "" {
   343  			defCausl, err := charset.GetDefaultDefCauslation(v.Chs)
   344  			if err != nil {
   345  				return "", "", errors.Trace(err)
   346  			}
   347  			return v.Chs, defCausl, err
   348  		}
   349  	}
   350  	chs, defCausl := charset.GetDefaultCharsetAndDefCauslate()
   351  	return chs, defCausl, nil
   352  }
   353  
   354  func typesNeedCharset(tp byte) bool {
   355  	switch tp {
   356  	case allegrosql.TypeString, allegrosql.TypeVarchar, allegrosql.TypeVarString,
   357  		allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob,
   358  		allegrosql.TypeEnum, allegrosql.TypeSet:
   359  		return true
   360  	}
   361  	return false
   362  }
   363  
   364  func setCharsetDefCauslationFlenDecimal(tp *types.FieldType, defCausCharset, defCausDefCauslate string) error {
   365  	if typesNeedCharset(tp.Tp) {
   366  		tp.Charset = defCausCharset
   367  		tp.DefCauslate = defCausDefCauslate
   368  	} else {
   369  		tp.Charset = charset.CharsetBin
   370  		tp.DefCauslate = charset.CharsetBin
   371  	}
   372  
   373  	// Use default value for flen or decimal when they are unspecified.
   374  	defaultFlen, defaultDecimal := allegrosql.GetDefaultFieldLengthAndDecimal(tp.Tp)
   375  	if tp.Flen == types.UnspecifiedLength {
   376  		tp.Flen = defaultFlen
   377  		if allegrosql.HasUnsignedFlag(tp.Flag) && tp.Tp != allegrosql.TypeLonglong && allegrosql.IsIntegerType(tp.Tp) {
   378  			// Issue #4684: the flen of unsigned integer(except bigint) is 1 digit shorter than signed integer
   379  			// because it has no prefix "+" or "-" character.
   380  			tp.Flen--
   381  		}
   382  	}
   383  	if tp.Decimal == types.UnspecifiedLength {
   384  		tp.Decimal = defaultDecimal
   385  	}
   386  	return nil
   387  }
   388  
   389  // buildDeferredCausetAndConstraint builds causet.DeferredCauset and ast.Constraint from the parameters.
   390  // outPriKeyConstraint is the primary key constraint out of defCausumn definition. For example:
   391  // `create causet t1 (id int , age int, primary key(id));`
   392  func buildDeferredCausetAndConstraint(
   393  	ctx stochastikctx.Context,
   394  	offset int,
   395  	defCausDef *ast.DeferredCausetDef,
   396  	outPriKeyConstraint *ast.Constraint,
   397  	tblCharset string,
   398  	tblDefCauslate string,
   399  ) (*causet.DeferredCauset, []*ast.Constraint, error) {
   400  	if defCausName := defCausDef.Name.Name.L; defCausName == perceptron.ExtraHandleName.L {
   401  		return nil, nil, ErrWrongDeferredCausetName.GenWithStackByArgs(defCausName)
   402  	}
   403  
   404  	// specifiedDefCauslate refers to the last defCauslate specified in defCausDef.Options.
   405  	chs, defCausl, err := getCharsetAndDefCauslateInDeferredCausetDef(defCausDef)
   406  	if err != nil {
   407  		return nil, nil, errors.Trace(err)
   408  	}
   409  	chs, defCausl, err = ResolveCharsetDefCauslation(
   410  		ast.CharsetOpt{Chs: chs, DefCaus: defCausl},
   411  		ast.CharsetOpt{Chs: tblCharset, DefCaus: tblDefCauslate},
   412  	)
   413  	if err != nil {
   414  		return nil, nil, errors.Trace(err)
   415  	}
   416  
   417  	if err := setCharsetDefCauslationFlenDecimal(defCausDef.Tp, chs, defCausl); err != nil {
   418  		return nil, nil, errors.Trace(err)
   419  	}
   420  	defCaus, cts, err := defCausumnDefToDefCaus(ctx, offset, defCausDef, outPriKeyConstraint)
   421  	if err != nil {
   422  		return nil, nil, errors.Trace(err)
   423  	}
   424  	return defCaus, cts, nil
   425  }
   426  
   427  // checkDeferredCausetDefaultValue checks the default value of the defCausumn.
   428  // In non-strict ALLEGROALLEGROSQL mode, if the default value of the defCausumn is an empty string, the default value can be ignored.
   429  // In strict ALLEGROALLEGROSQL mode, TEXT/BLOB/JSON can't have not null default values.
   430  // In NO_ZERO_DATE ALLEGROALLEGROSQL mode, TIMESTAMP/DATE/DATETIME type can't have zero date like '0000-00-00' or '0000-00-00 00:00:00'.
   431  func checkDeferredCausetDefaultValue(ctx stochastikctx.Context, defCaus *causet.DeferredCauset, value interface{}) (bool, interface{}, error) {
   432  	hasDefaultValue := true
   433  	if value != nil && (defCaus.Tp == allegrosql.TypeJSON ||
   434  		defCaus.Tp == allegrosql.TypeTinyBlob || defCaus.Tp == allegrosql.TypeMediumBlob ||
   435  		defCaus.Tp == allegrosql.TypeLongBlob || defCaus.Tp == allegrosql.TypeBlob) {
   436  		// In non-strict ALLEGROALLEGROSQL mode.
   437  		if !ctx.GetStochastikVars().ALLEGROSQLMode.HasStrictMode() && value == "" {
   438  			if defCaus.Tp == allegrosql.TypeBlob || defCaus.Tp == allegrosql.TypeLongBlob {
   439  				// The TEXT/BLOB default value can be ignored.
   440  				hasDefaultValue = false
   441  			}
   442  			// In non-strict ALLEGROALLEGROSQL mode, if the defCausumn type is json and the default value is null, it is initialized to an empty array.
   443  			if defCaus.Tp == allegrosql.TypeJSON {
   444  				value = `null`
   445  			}
   446  			sc := ctx.GetStochastikVars().StmtCtx
   447  			sc.AppendWarning(errBlobCantHaveDefault.GenWithStackByArgs(defCaus.Name.O))
   448  			return hasDefaultValue, value, nil
   449  		}
   450  		// In strict ALLEGROALLEGROSQL mode or default value is not an empty string.
   451  		return hasDefaultValue, value, errBlobCantHaveDefault.GenWithStackByArgs(defCaus.Name.O)
   452  	}
   453  	if value != nil && ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() &&
   454  		ctx.GetStochastikVars().ALLEGROSQLMode.HasStrictMode() && types.IsTypeTime(defCaus.Tp) {
   455  		if vv, ok := value.(string); ok {
   456  			timeValue, err := memex.GetTimeValue(ctx, vv, defCaus.Tp, int8(defCaus.Decimal))
   457  			if err != nil {
   458  				return hasDefaultValue, value, errors.Trace(err)
   459  			}
   460  			if timeValue.GetMysqlTime().CoreTime() == types.ZeroCoreTime {
   461  				return hasDefaultValue, value, types.ErrInvalidDefault.GenWithStackByArgs(defCaus.Name.O)
   462  			}
   463  		}
   464  	}
   465  	return hasDefaultValue, value, nil
   466  }
   467  
   468  func checkSequenceDefaultValue(defCaus *causet.DeferredCauset) error {
   469  	if allegrosql.IsIntegerType(defCaus.Tp) {
   470  		return nil
   471  	}
   472  	return ErrDeferredCausetTypeUnsupportedNextValue.GenWithStackByArgs(defCaus.DeferredCausetInfo.Name.O)
   473  }
   474  
   475  func convertTimestamFIDelefaultValToUTC(ctx stochastikctx.Context, defaultVal interface{}, defCaus *causet.DeferredCauset) (interface{}, error) {
   476  	if defaultVal == nil || defCaus.Tp != allegrosql.TypeTimestamp {
   477  		return defaultVal, nil
   478  	}
   479  	if vv, ok := defaultVal.(string); ok {
   480  		if vv != types.ZeroDatetimeStr && !strings.EqualFold(vv, ast.CurrentTimestamp) {
   481  			t, err := types.ParseTime(ctx.GetStochastikVars().StmtCtx, vv, defCaus.Tp, int8(defCaus.Decimal))
   482  			if err != nil {
   483  				return defaultVal, errors.Trace(err)
   484  			}
   485  			err = t.ConvertTimeZone(ctx.GetStochastikVars().Location(), time.UTC)
   486  			if err != nil {
   487  				return defaultVal, errors.Trace(err)
   488  			}
   489  			defaultVal = t.String()
   490  		}
   491  	}
   492  	return defaultVal, nil
   493  }
   494  
   495  // isExplicitTimeStamp is used to check if explicit_defaults_for_timestamp is on or off.
   496  // Check out this link for more details.
   497  // https://dev.allegrosql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp
   498  func isExplicitTimeStamp() bool {
   499  	// TODO: implement the behavior as MyALLEGROSQL when explicit_defaults_for_timestamp = off, then this function could return false.
   500  	return true
   501  }
   502  
   503  // processDeferredCausetFlags is used by defCausumnDefToDefCaus and processDeferredCausetOptions. It is intended to unify behaviors on `create/add` and `modify/change` memexs. Check milevadb#issue#19342.
   504  func processDeferredCausetFlags(defCaus *causet.DeferredCauset) {
   505  	if defCaus.FieldType.EvalType().IsStringHoTT() && defCaus.Charset == charset.CharsetBin {
   506  		defCaus.Flag |= allegrosql.BinaryFlag
   507  	}
   508  	if defCaus.Tp == allegrosql.TypeBit {
   509  		// For BIT field, it's charset is binary but does not have binary flag.
   510  		defCaus.Flag &= ^allegrosql.BinaryFlag
   511  		defCaus.Flag |= allegrosql.UnsignedFlag
   512  	}
   513  	if defCaus.Tp == allegrosql.TypeYear {
   514  		// For Year field, it's charset is binary but does not have binary flag.
   515  		defCaus.Flag &= ^allegrosql.BinaryFlag
   516  		defCaus.Flag |= allegrosql.ZerofillFlag
   517  	}
   518  
   519  	// If you specify ZEROFILL for a numeric defCausumn, MyALLEGROSQL automatically adds the UNSIGNED attribute to the defCausumn.
   520  	// See https://dev.allegrosql.com/doc/refman/5.7/en/numeric-type-overview.html for more details.
   521  	// But some types like bit and year, won't show its unsigned flag in `show create causet`.
   522  	if allegrosql.HasZerofillFlag(defCaus.Flag) {
   523  		defCaus.Flag |= allegrosql.UnsignedFlag
   524  	}
   525  }
   526  
   527  // defCausumnDefToDefCaus converts DeferredCausetDef to DefCaus and TableConstraints.
   528  // outPriKeyConstraint is the primary key constraint out of defCausumn definition. such as: create causet t1 (id int , age int, primary key(id));
   529  func defCausumnDefToDefCaus(ctx stochastikctx.Context, offset int, defCausDef *ast.DeferredCausetDef, outPriKeyConstraint *ast.Constraint) (*causet.DeferredCauset, []*ast.Constraint, error) {
   530  	var constraints = make([]*ast.Constraint, 0)
   531  	defCaus := causet.ToDeferredCauset(&perceptron.DeferredCausetInfo{
   532  		Offset:    offset,
   533  		Name:      defCausDef.Name.Name,
   534  		FieldType: *defCausDef.Tp,
   535  		// TODO: remove this version field after there is no old version.
   536  		Version: perceptron.CurrLatestDeferredCausetInfoVersion,
   537  	})
   538  
   539  	if !isExplicitTimeStamp() {
   540  		// Check and set TimestampFlag, OnUFIDelateNowFlag and NotNullFlag.
   541  		if defCaus.Tp == allegrosql.TypeTimestamp {
   542  			defCaus.Flag |= allegrosql.TimestampFlag
   543  			defCaus.Flag |= allegrosql.OnUFIDelateNowFlag
   544  			defCaus.Flag |= allegrosql.NotNullFlag
   545  		}
   546  	}
   547  	var err error
   548  	setOnUFIDelateNow := false
   549  	hasDefaultValue := false
   550  	hasNullFlag := false
   551  	if defCausDef.Options != nil {
   552  		length := types.UnspecifiedLength
   553  
   554  		keys := []*ast.IndexPartSpecification{
   555  			{
   556  				DeferredCauset: defCausDef.Name,
   557  				Length:         length,
   558  			},
   559  		}
   560  
   561  		var sb strings.Builder
   562  		restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes |
   563  			format.RestoreSpacesAroundBinaryOperation
   564  		restoreCtx := format.NewRestoreCtx(restoreFlags, &sb)
   565  
   566  		for _, v := range defCausDef.Options {
   567  			switch v.Tp {
   568  			case ast.DeferredCausetOptionNotNull:
   569  				defCaus.Flag |= allegrosql.NotNullFlag
   570  			case ast.DeferredCausetOptionNull:
   571  				defCaus.Flag &= ^allegrosql.NotNullFlag
   572  				removeOnUFIDelateNowFlag(defCaus)
   573  				hasNullFlag = true
   574  			case ast.DeferredCausetOptionAutoIncrement:
   575  				defCaus.Flag |= allegrosql.AutoIncrementFlag
   576  			case ast.DeferredCausetOptionPrimaryKey:
   577  				// Check PriKeyFlag first to avoid extra duplicate constraints.
   578  				if defCaus.Flag&allegrosql.PriKeyFlag == 0 {
   579  					constraint := &ast.Constraint{Tp: ast.ConstraintPrimaryKey, Keys: keys}
   580  					constraints = append(constraints, constraint)
   581  					defCaus.Flag |= allegrosql.PriKeyFlag
   582  				}
   583  			case ast.DeferredCausetOptionUniqKey:
   584  				// Check UniqueFlag first to avoid extra duplicate constraints.
   585  				if defCaus.Flag&allegrosql.UniqueFlag == 0 {
   586  					constraint := &ast.Constraint{Tp: ast.ConstraintUniqKey, Keys: keys}
   587  					constraints = append(constraints, constraint)
   588  					defCaus.Flag |= allegrosql.UniqueKeyFlag
   589  				}
   590  			case ast.DeferredCausetOptionDefaultValue:
   591  				hasDefaultValue, err = setDefaultValue(ctx, defCaus, v)
   592  				if err != nil {
   593  					return nil, nil, errors.Trace(err)
   594  				}
   595  				removeOnUFIDelateNowFlag(defCaus)
   596  			case ast.DeferredCausetOptionOnUFIDelate:
   597  				// TODO: Support other time functions.
   598  				if defCaus.Tp == allegrosql.TypeTimestamp || defCaus.Tp == allegrosql.TypeDatetime {
   599  					if !memex.IsValidCurrentTimestampExpr(v.Expr, defCausDef.Tp) {
   600  						return nil, nil, ErrInvalidOnUFIDelate.GenWithStackByArgs(defCaus.Name)
   601  					}
   602  				} else {
   603  					return nil, nil, ErrInvalidOnUFIDelate.GenWithStackByArgs(defCaus.Name)
   604  				}
   605  				defCaus.Flag |= allegrosql.OnUFIDelateNowFlag
   606  				setOnUFIDelateNow = true
   607  			case ast.DeferredCausetOptionComment:
   608  				err := setDeferredCausetComment(ctx, defCaus, v)
   609  				if err != nil {
   610  					return nil, nil, errors.Trace(err)
   611  				}
   612  			case ast.DeferredCausetOptionGenerated:
   613  				sb.Reset()
   614  				err = v.Expr.Restore(restoreCtx)
   615  				if err != nil {
   616  					return nil, nil, errors.Trace(err)
   617  				}
   618  				defCaus.GeneratedExprString = sb.String()
   619  				defCaus.GeneratedStored = v.Stored
   620  				_, dependDefCausNames := findDependedDeferredCausetNames(defCausDef)
   621  				defCaus.Dependences = dependDefCausNames
   622  			case ast.DeferredCausetOptionDefCauslate:
   623  				if field_types.HasCharset(defCausDef.Tp) {
   624  					defCaus.FieldType.DefCauslate = v.StrValue
   625  				}
   626  			case ast.DeferredCausetOptionFulltext:
   627  				ctx.GetStochastikVars().StmtCtx.AppendWarning(ErrTableCantHandleFt)
   628  			case ast.DeferredCausetOptionCheck:
   629  				ctx.GetStochastikVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("DeferredCauset check"))
   630  			}
   631  		}
   632  	}
   633  
   634  	processDefaultValue(defCaus, hasDefaultValue, setOnUFIDelateNow)
   635  
   636  	processDeferredCausetFlags(defCaus)
   637  
   638  	err = checkPriKeyConstraint(defCaus, hasDefaultValue, hasNullFlag, outPriKeyConstraint)
   639  	if err != nil {
   640  		return nil, nil, errors.Trace(err)
   641  	}
   642  	err = checkDeferredCausetValueConstraint(defCaus, defCaus.DefCauslate)
   643  	if err != nil {
   644  		return nil, nil, errors.Trace(err)
   645  	}
   646  	err = checkDefaultValue(ctx, defCaus, hasDefaultValue)
   647  	if err != nil {
   648  		return nil, nil, errors.Trace(err)
   649  	}
   650  	err = checkDeferredCausetFieldLength(defCaus)
   651  	if err != nil {
   652  		return nil, nil, errors.Trace(err)
   653  	}
   654  	return defCaus, constraints, nil
   655  }
   656  
   657  // getDefaultValue will get the default value for defCausumn.
   658  // 1: get the expr restored string for the defCausumn which uses sequence next value as default value.
   659  // 2: get specific default value for the other defCausumn.
   660  func getDefaultValue(ctx stochastikctx.Context, defCaus *causet.DeferredCauset, c *ast.DeferredCausetOption) (interface{}, bool, error) {
   661  	tp, fsp := defCaus.FieldType.Tp, defCaus.FieldType.Decimal
   662  	if tp == allegrosql.TypeTimestamp || tp == allegrosql.TypeDatetime {
   663  		switch x := c.Expr.(type) {
   664  		case *ast.FuncCallExpr:
   665  			if x.FnName.L == ast.CurrentTimestamp {
   666  				defaultFsp := 0
   667  				if len(x.Args) == 1 {
   668  					if val := x.Args[0].(*driver.ValueExpr); val != nil {
   669  						defaultFsp = int(val.GetInt64())
   670  					}
   671  				}
   672  				if defaultFsp != fsp {
   673  					return nil, false, ErrInvalidDefaultValue.GenWithStackByArgs(defCaus.Name.O)
   674  				}
   675  			}
   676  		}
   677  		vd, err := memex.GetTimeValue(ctx, c.Expr, tp, int8(fsp))
   678  		value := vd.GetValue()
   679  		if err != nil {
   680  			return nil, false, ErrInvalidDefaultValue.GenWithStackByArgs(defCaus.Name.O)
   681  		}
   682  
   683  		// Value is nil means `default null`.
   684  		if value == nil {
   685  			return nil, false, nil
   686  		}
   687  
   688  		// If value is types.Time, convert it to string.
   689  		if vv, ok := value.(types.Time); ok {
   690  			return vv.String(), false, nil
   691  		}
   692  
   693  		return value, false, nil
   694  	}
   695  	// handle default next value of sequence. (keep the expr string)
   696  	str, isSeqExpr, err := tryToGetSequenceDefaultValue(c)
   697  	if err != nil {
   698  		return nil, false, errors.Trace(err)
   699  	}
   700  	if isSeqExpr {
   701  		return str, true, nil
   702  	}
   703  
   704  	// evaluate the non-sequence expr to a certain value.
   705  	v, err := memex.EvalAstExpr(ctx, c.Expr)
   706  	if err != nil {
   707  		return nil, false, errors.Trace(err)
   708  	}
   709  
   710  	if v.IsNull() {
   711  		return nil, false, nil
   712  	}
   713  
   714  	if v.HoTT() == types.HoTTBinaryLiteral || v.HoTT() == types.HoTTMysqlBit {
   715  		if tp == allegrosql.TypeBit ||
   716  			tp == allegrosql.TypeString || tp == allegrosql.TypeVarchar || tp == allegrosql.TypeVarString ||
   717  			tp == allegrosql.TypeBlob || tp == allegrosql.TypeLongBlob || tp == allegrosql.TypeMediumBlob || tp == allegrosql.TypeTinyBlob ||
   718  			tp == allegrosql.TypeJSON {
   719  			// For BinaryLiteral / string fields, when getting default value we cast the value into BinaryLiteral{}, thus we return
   720  			// its raw string content here.
   721  			return v.GetBinaryLiteral().ToString(), false, nil
   722  		}
   723  		// For other HoTT of fields (e.g. INT), we supply its integer as string value.
   724  		value, err := v.GetBinaryLiteral().ToInt(ctx.GetStochastikVars().StmtCtx)
   725  		if err != nil {
   726  			return nil, false, err
   727  		}
   728  		return strconv.FormatUint(value, 10), false, nil
   729  	}
   730  
   731  	switch tp {
   732  	case allegrosql.TypeSet:
   733  		val, err := setSetDefaultValue(v, defCaus)
   734  		return val, false, err
   735  	case allegrosql.TypeDuration:
   736  		if v, err = v.ConvertTo(ctx.GetStochastikVars().StmtCtx, &defCaus.FieldType); err != nil {
   737  			return "", false, errors.Trace(err)
   738  		}
   739  	case allegrosql.TypeBit:
   740  		if v.HoTT() == types.HoTTInt64 || v.HoTT() == types.HoTTUint64 {
   741  			// For BIT fields, convert int into BinaryLiteral.
   742  			return types.NewBinaryLiteralFromUint(v.GetUint64(), -1).ToString(), false, nil
   743  		}
   744  	}
   745  
   746  	val, err := v.ToString()
   747  	return val, false, err
   748  }
   749  
   750  func tryToGetSequenceDefaultValue(c *ast.DeferredCausetOption) (expr string, isExpr bool, err error) {
   751  	if f, ok := c.Expr.(*ast.FuncCallExpr); ok && f.FnName.L == ast.NextVal {
   752  		var sb strings.Builder
   753  		restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes |
   754  			format.RestoreSpacesAroundBinaryOperation
   755  		restoreCtx := format.NewRestoreCtx(restoreFlags, &sb)
   756  		if err := c.Expr.Restore(restoreCtx); err != nil {
   757  			return "", true, err
   758  		}
   759  		return sb.String(), true, nil
   760  	}
   761  	return "", false, nil
   762  }
   763  
   764  // setSetDefaultValue sets the default value for the set type. See https://dev.allegrosql.com/doc/refman/5.7/en/set.html.
   765  func setSetDefaultValue(v types.Causet, defCaus *causet.DeferredCauset) (string, error) {
   766  	if v.HoTT() == types.HoTTInt64 {
   767  		setCnt := len(defCaus.Elems)
   768  		maxLimit := int64(1<<uint(setCnt) - 1)
   769  		val := v.GetInt64()
   770  		if val < 1 || val > maxLimit {
   771  			return "", ErrInvalidDefaultValue.GenWithStackByArgs(defCaus.Name.O)
   772  		}
   773  		setVal, err := types.ParseSetValue(defCaus.Elems, uint64(val))
   774  		if err != nil {
   775  			return "", errors.Trace(err)
   776  		}
   777  		v.SetMysqlSet(setVal, defCaus.DefCauslate)
   778  		return v.ToString()
   779  	}
   780  
   781  	str, err := v.ToString()
   782  	if err != nil {
   783  		return "", errors.Trace(err)
   784  	}
   785  	if str == "" {
   786  		return str, nil
   787  	}
   788  
   789  	ctor := defCauslate.GetDefCauslator(defCaus.DefCauslate)
   790  	valMap := make(map[string]struct{}, len(defCaus.Elems))
   791  	dVals := strings.Split(str, ",")
   792  	for _, dv := range dVals {
   793  		valMap[string(ctor.Key(dv))] = struct{}{}
   794  	}
   795  	var existCnt int
   796  	for dv := range valMap {
   797  		for i := range defCaus.Elems {
   798  			e := string(ctor.Key(defCaus.Elems[i]))
   799  			if e == dv {
   800  				existCnt++
   801  				break
   802  			}
   803  		}
   804  	}
   805  	if existCnt != len(valMap) {
   806  		return "", ErrInvalidDefaultValue.GenWithStackByArgs(defCaus.Name.O)
   807  	}
   808  	setVal, err := types.ParseSetName(defCaus.Elems, str, defCaus.DefCauslate)
   809  	if err != nil {
   810  		return "", ErrInvalidDefaultValue.GenWithStackByArgs(defCaus.Name.O)
   811  	}
   812  	v.SetMysqlSet(setVal, defCaus.DefCauslate)
   813  
   814  	return v.ToString()
   815  }
   816  
   817  func removeOnUFIDelateNowFlag(c *causet.DeferredCauset) {
   818  	// For timestamp DefCaus, if it is set null or default value,
   819  	// OnUFIDelateNowFlag should be removed.
   820  	if allegrosql.HasTimestampFlag(c.Flag) {
   821  		c.Flag &= ^allegrosql.OnUFIDelateNowFlag
   822  	}
   823  }
   824  
   825  func processDefaultValue(c *causet.DeferredCauset, hasDefaultValue bool, setOnUFIDelateNow bool) {
   826  	setTimestamFIDelefaultValue(c, hasDefaultValue, setOnUFIDelateNow)
   827  
   828  	setYearDefaultValue(c, hasDefaultValue)
   829  
   830  	// Set `NoDefaultValueFlag` if this field doesn't have a default value and
   831  	// it is `not null` and not an `AUTO_INCREMENT` field or `TIMESTAMP` field.
   832  	setNoDefaultValueFlag(c, hasDefaultValue)
   833  }
   834  
   835  func setYearDefaultValue(c *causet.DeferredCauset, hasDefaultValue bool) {
   836  	if hasDefaultValue {
   837  		return
   838  	}
   839  
   840  	if c.Tp == allegrosql.TypeYear && allegrosql.HasNotNullFlag(c.Flag) {
   841  		if err := c.SetDefaultValue("0000"); err != nil {
   842  			logutil.BgLogger().Error("set default value failed", zap.Error(err))
   843  		}
   844  	}
   845  }
   846  
   847  func setTimestamFIDelefaultValue(c *causet.DeferredCauset, hasDefaultValue bool, setOnUFIDelateNow bool) {
   848  	if hasDefaultValue {
   849  		return
   850  	}
   851  
   852  	// For timestamp DefCaus, if is not set default value or not set null, use current timestamp.
   853  	if allegrosql.HasTimestampFlag(c.Flag) && allegrosql.HasNotNullFlag(c.Flag) {
   854  		if setOnUFIDelateNow {
   855  			if err := c.SetDefaultValue(types.ZeroDatetimeStr); err != nil {
   856  				logutil.BgLogger().Error("set default value failed", zap.Error(err))
   857  			}
   858  		} else {
   859  			if err := c.SetDefaultValue(strings.ToUpper(ast.CurrentTimestamp)); err != nil {
   860  				logutil.BgLogger().Error("set default value failed", zap.Error(err))
   861  			}
   862  		}
   863  	}
   864  }
   865  
   866  func setNoDefaultValueFlag(c *causet.DeferredCauset, hasDefaultValue bool) {
   867  	if hasDefaultValue {
   868  		return
   869  	}
   870  
   871  	if !allegrosql.HasNotNullFlag(c.Flag) {
   872  		return
   873  	}
   874  
   875  	// Check if it is an `AUTO_INCREMENT` field or `TIMESTAMP` field.
   876  	if !allegrosql.HasAutoIncrementFlag(c.Flag) && !allegrosql.HasTimestampFlag(c.Flag) {
   877  		c.Flag |= allegrosql.NoDefaultValueFlag
   878  	}
   879  }
   880  
   881  func checkDefaultValue(ctx stochastikctx.Context, c *causet.DeferredCauset, hasDefaultValue bool) error {
   882  	if !hasDefaultValue {
   883  		return nil
   884  	}
   885  
   886  	if c.GetDefaultValue() != nil {
   887  		if c.DefaultIsExpr {
   888  			return nil
   889  		}
   890  		if _, err := causet.GetDefCausDefaultValue(ctx, c.ToInfo()); err != nil {
   891  			return types.ErrInvalidDefault.GenWithStackByArgs(c.Name)
   892  		}
   893  		return nil
   894  	}
   895  	// Primary key default null is invalid.
   896  	if allegrosql.HasPriKeyFlag(c.Flag) {
   897  		return ErrPrimaryCantHaveNull
   898  	}
   899  
   900  	// Set not null but default null is invalid.
   901  	if allegrosql.HasNotNullFlag(c.Flag) {
   902  		return types.ErrInvalidDefault.GenWithStackByArgs(c.Name)
   903  	}
   904  
   905  	return nil
   906  }
   907  
   908  // checkPriKeyConstraint check all parts of a PRIMARY KEY must be NOT NULL
   909  func checkPriKeyConstraint(defCaus *causet.DeferredCauset, hasDefaultValue, hasNullFlag bool, outPriKeyConstraint *ast.Constraint) error {
   910  	// Primary key should not be null.
   911  	if allegrosql.HasPriKeyFlag(defCaus.Flag) && hasDefaultValue && defCaus.GetDefaultValue() == nil {
   912  		return types.ErrInvalidDefault.GenWithStackByArgs(defCaus.Name)
   913  	}
   914  	// Set primary key flag for outer primary key constraint.
   915  	// Such as: create causet t1 (id int , age int, primary key(id))
   916  	if !allegrosql.HasPriKeyFlag(defCaus.Flag) && outPriKeyConstraint != nil {
   917  		for _, key := range outPriKeyConstraint.Keys {
   918  			if key.Expr == nil && key.DeferredCauset.Name.L != defCaus.Name.L {
   919  				continue
   920  			}
   921  			defCaus.Flag |= allegrosql.PriKeyFlag
   922  			break
   923  		}
   924  	}
   925  	// Primary key should not be null.
   926  	if allegrosql.HasPriKeyFlag(defCaus.Flag) && hasNullFlag {
   927  		return ErrPrimaryCantHaveNull
   928  	}
   929  	return nil
   930  }
   931  
   932  func checkDeferredCausetValueConstraint(defCaus *causet.DeferredCauset, defCauslation string) error {
   933  	if defCaus.Tp != allegrosql.TypeEnum && defCaus.Tp != allegrosql.TypeSet {
   934  		return nil
   935  	}
   936  	valueMap := make(map[string]bool, len(defCaus.Elems))
   937  	ctor := defCauslate.GetDefCauslator(defCauslation)
   938  	for i := range defCaus.Elems {
   939  		val := string(ctor.Key(defCaus.Elems[i]))
   940  		if _, ok := valueMap[val]; ok {
   941  			tpStr := "ENUM"
   942  			if defCaus.Tp == allegrosql.TypeSet {
   943  				tpStr = "SET"
   944  			}
   945  			return types.ErrDuplicatedValueInType.GenWithStackByArgs(defCaus.Name, defCaus.Elems[i], tpStr)
   946  		}
   947  		valueMap[val] = true
   948  	}
   949  	return nil
   950  }
   951  
   952  func checkDuplicateDeferredCauset(defcaus []*perceptron.DeferredCausetInfo) error {
   953  	defCausNames := set.StringSet{}
   954  	for _, defCaus := range defcaus {
   955  		defCausName := defCaus.Name
   956  		if defCausNames.Exist(defCausName.L) {
   957  			return schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(defCausName.O)
   958  		}
   959  		defCausNames.Insert(defCausName.L)
   960  	}
   961  	return nil
   962  }
   963  
   964  func containsDeferredCausetOption(defCausDef *ast.DeferredCausetDef, opTp ast.DeferredCausetOptionType) bool {
   965  	for _, option := range defCausDef.Options {
   966  		if option.Tp == opTp {
   967  			return true
   968  		}
   969  	}
   970  	return false
   971  }
   972  
   973  // IsAutoRandomDeferredCausetID returns true if the given defCausumn ID belongs to an auto_random defCausumn.
   974  func IsAutoRandomDeferredCausetID(tblInfo *perceptron.TableInfo, defCausID int64) bool {
   975  	return tblInfo.PKIsHandle && tblInfo.ContainsAutoRandomBits() && tblInfo.GetPkDefCausInfo().ID == defCausID
   976  }
   977  
   978  func checkGeneratedDeferredCauset(defCausDefs []*ast.DeferredCausetDef) error {
   979  	var defCausName2Generation = make(map[string]defCausumnGenerationInDBS, len(defCausDefs))
   980  	var exists bool
   981  	var autoIncrementDeferredCauset string
   982  	for i, defCausDef := range defCausDefs {
   983  		for _, option := range defCausDef.Options {
   984  			if option.Tp == ast.DeferredCausetOptionGenerated {
   985  				if err := checkIllegalFn4GeneratedDeferredCauset(defCausDef.Name.Name.L, option.Expr); err != nil {
   986  					return errors.Trace(err)
   987  				}
   988  			}
   989  		}
   990  		if containsDeferredCausetOption(defCausDef, ast.DeferredCausetOptionAutoIncrement) {
   991  			exists, autoIncrementDeferredCauset = true, defCausDef.Name.Name.L
   992  		}
   993  		generated, depDefCauss := findDependedDeferredCausetNames(defCausDef)
   994  		if !generated {
   995  			defCausName2Generation[defCausDef.Name.Name.L] = defCausumnGenerationInDBS{
   996  				position:  i,
   997  				generated: false,
   998  			}
   999  		} else {
  1000  			defCausName2Generation[defCausDef.Name.Name.L] = defCausumnGenerationInDBS{
  1001  				position:    i,
  1002  				generated:   true,
  1003  				dependences: depDefCauss,
  1004  			}
  1005  		}
  1006  	}
  1007  
  1008  	// Check whether the generated defCausumn refers to any auto-increment defCausumns
  1009  	if exists {
  1010  		for defCausName, generated := range defCausName2Generation {
  1011  			if _, found := generated.dependences[autoIncrementDeferredCauset]; found {
  1012  				return ErrGeneratedDeferredCausetRefAutoInc.GenWithStackByArgs(defCausName)
  1013  			}
  1014  		}
  1015  	}
  1016  
  1017  	for _, defCausDef := range defCausDefs {
  1018  		defCausName := defCausDef.Name.Name.L
  1019  		if err := verifyDeferredCausetGeneration(defCausName2Generation, defCausName); err != nil {
  1020  			return errors.Trace(err)
  1021  		}
  1022  	}
  1023  	return nil
  1024  }
  1025  
  1026  func checkTooLongDeferredCauset(defcaus []*perceptron.DeferredCausetInfo) error {
  1027  	for _, defCaus := range defcaus {
  1028  		defCausName := defCaus.Name.O
  1029  		if len(defCausName) > allegrosql.MaxDeferredCausetNameLength {
  1030  			return ErrTooLongIdent.GenWithStackByArgs(defCausName)
  1031  		}
  1032  	}
  1033  	return nil
  1034  }
  1035  
  1036  func checkTooManyDeferredCausets(defCausDefs []*perceptron.DeferredCausetInfo) error {
  1037  	if uint32(len(defCausDefs)) > atomic.LoadUint32(&TableDeferredCausetCountLimit) {
  1038  		return errTooManyFields
  1039  	}
  1040  	return nil
  1041  }
  1042  
  1043  // checkDeferredCausetsAttributes checks attributes for multiple defCausumns.
  1044  func checkDeferredCausetsAttributes(defCausDefs []*perceptron.DeferredCausetInfo) error {
  1045  	for _, defCausDef := range defCausDefs {
  1046  		if err := checkDeferredCausetAttributes(defCausDef.Name.O, &defCausDef.FieldType); err != nil {
  1047  			return errors.Trace(err)
  1048  		}
  1049  	}
  1050  	return nil
  1051  }
  1052  
  1053  func checkDeferredCausetFieldLength(defCaus *causet.DeferredCauset) error {
  1054  	if defCaus.Tp == allegrosql.TypeVarchar {
  1055  		if err := IsTooBigFieldLength(defCaus.Flen, defCaus.Name.O, defCaus.Charset); err != nil {
  1056  			return errors.Trace(err)
  1057  		}
  1058  	}
  1059  
  1060  	return nil
  1061  }
  1062  
  1063  // IsTooBigFieldLength check if the varchar type defCausumn exceeds the maximum length limit.
  1064  func IsTooBigFieldLength(defCausDefTpFlen int, defCausDefName, setCharset string) error {
  1065  	desc, err := charset.GetCharsetDesc(setCharset)
  1066  	if err != nil {
  1067  		return errors.Trace(err)
  1068  	}
  1069  	maxFlen := allegrosql.MaxFieldVarCharLength
  1070  	maxFlen /= desc.Maxlen
  1071  	if defCausDefTpFlen != types.UnspecifiedLength && defCausDefTpFlen > maxFlen {
  1072  		return types.ErrTooBigFieldLength.GenWithStack("DeferredCauset length too big for defCausumn '%s' (max = %d); use BLOB or TEXT instead", defCausDefName, maxFlen)
  1073  	}
  1074  	return nil
  1075  }
  1076  
  1077  // checkDeferredCausetAttributes check attributes for single defCausumn.
  1078  func checkDeferredCausetAttributes(defCausName string, tp *types.FieldType) error {
  1079  	switch tp.Tp {
  1080  	case allegrosql.TypeNewDecimal, allegrosql.TypeDouble, allegrosql.TypeFloat:
  1081  		if tp.Flen < tp.Decimal {
  1082  			return types.ErrMBiggerThanD.GenWithStackByArgs(defCausName)
  1083  		}
  1084  	case allegrosql.TypeDatetime, allegrosql.TypeDuration, allegrosql.TypeTimestamp:
  1085  		if tp.Decimal != int(types.UnspecifiedFsp) && (tp.Decimal < int(types.MinFsp) || tp.Decimal > int(types.MaxFsp)) {
  1086  			return types.ErrTooBigPrecision.GenWithStackByArgs(tp.Decimal, defCausName, types.MaxFsp)
  1087  		}
  1088  	}
  1089  	return nil
  1090  }
  1091  
  1092  func checkDuplicateConstraint(namesMap map[string]bool, name string, foreign bool) error {
  1093  	if name == "" {
  1094  		return nil
  1095  	}
  1096  	nameLower := strings.ToLower(name)
  1097  	if namesMap[nameLower] {
  1098  		if foreign {
  1099  			return schemareplicant.ErrCannotAddForeign
  1100  		}
  1101  		return ErrDupKeyName.GenWithStack("duplicate key name %s", name)
  1102  	}
  1103  	namesMap[nameLower] = true
  1104  	return nil
  1105  }
  1106  
  1107  func setEmptyConstraintName(namesMap map[string]bool, constr *ast.Constraint, foreign bool) {
  1108  	if constr.Name == "" && len(constr.Keys) > 0 {
  1109  		var defCausName string
  1110  		for _, keyPart := range constr.Keys {
  1111  			if keyPart.Expr != nil {
  1112  				defCausName = "memex_index"
  1113  			}
  1114  		}
  1115  		if defCausName == "" {
  1116  			defCausName = constr.Keys[0].DeferredCauset.Name.L
  1117  		}
  1118  		constrName := defCausName
  1119  		i := 2
  1120  		if strings.EqualFold(constrName, allegrosql.PrimaryKeyName) {
  1121  			constrName = fmt.Sprintf("%s_%d", constrName, 2)
  1122  			i = 3
  1123  		}
  1124  		for namesMap[constrName] {
  1125  			// We loop forever until we find constrName that haven't been used.
  1126  			if foreign {
  1127  				constrName = fmt.Sprintf("fk_%s_%d", defCausName, i)
  1128  			} else {
  1129  				constrName = fmt.Sprintf("%s_%d", defCausName, i)
  1130  			}
  1131  			i++
  1132  		}
  1133  		constr.Name = constrName
  1134  		namesMap[constrName] = true
  1135  	}
  1136  }
  1137  
  1138  func checkConstraintNames(constraints []*ast.Constraint) error {
  1139  	constrNames := map[string]bool{}
  1140  	fkNames := map[string]bool{}
  1141  
  1142  	// Check not empty constraint name whether is duplicated.
  1143  	for _, constr := range constraints {
  1144  		if constr.Tp == ast.ConstraintForeignKey {
  1145  			err := checkDuplicateConstraint(fkNames, constr.Name, true)
  1146  			if err != nil {
  1147  				return errors.Trace(err)
  1148  			}
  1149  		} else {
  1150  			err := checkDuplicateConstraint(constrNames, constr.Name, false)
  1151  			if err != nil {
  1152  				return errors.Trace(err)
  1153  			}
  1154  		}
  1155  	}
  1156  
  1157  	// Set empty constraint names.
  1158  	for _, constr := range constraints {
  1159  		if constr.Tp == ast.ConstraintForeignKey {
  1160  			setEmptyConstraintName(fkNames, constr, true)
  1161  		} else {
  1162  			setEmptyConstraintName(constrNames, constr, false)
  1163  		}
  1164  	}
  1165  
  1166  	return nil
  1167  }
  1168  
  1169  // checkInvisibleIndexOnPK check if primary key is invisible index.
  1170  // Note: PKIsHandle == true means the causet already has a visible primary key,
  1171  // we do not need do a check for this case and return directly,
  1172  // because whether primary key is invisible has been check when creating causet.
  1173  func checkInvisibleIndexOnPK(tblInfo *perceptron.TableInfo) error {
  1174  	if tblInfo.PKIsHandle {
  1175  		return nil
  1176  	}
  1177  	pk := getPrimaryKey(tblInfo)
  1178  	if pk != nil && pk.Invisible {
  1179  		return ErrPHoTTexCantBeInvisible
  1180  	}
  1181  	return nil
  1182  }
  1183  
  1184  // getPrimaryKey extract the primary key in a causet and return `IndexInfo`
  1185  // The returned primary key could be explicit or implicit.
  1186  // If there is no explicit primary key in causet,
  1187  // the first UNIQUE INDEX on NOT NULL defCausumns will be the implicit primary key.
  1188  // For more information about implicit primary key, see
  1189  // https://dev.allegrosql.com/doc/refman/8.0/en/invisible-indexes.html
  1190  func getPrimaryKey(tblInfo *perceptron.TableInfo) *perceptron.IndexInfo {
  1191  	var implicitPK *perceptron.IndexInfo
  1192  
  1193  	for _, key := range tblInfo.Indices {
  1194  		if key.Primary {
  1195  			// causet has explicit primary key
  1196  			return key
  1197  		}
  1198  		// The case index without any defCausumns should never happen, but still do a check here
  1199  		if len(key.DeferredCausets) == 0 {
  1200  			continue
  1201  		}
  1202  		// find the first unique key with NOT NULL defCausumns
  1203  		if implicitPK == nil && key.Unique {
  1204  			// ensure all defCausumns in unique key have NOT NULL flag
  1205  			allDefCausNotNull := true
  1206  			skip := false
  1207  			for _, idxDefCaus := range key.DeferredCausets {
  1208  				defCaus := perceptron.FindDeferredCausetInfo(tblInfo.DefCauss(), idxDefCaus.Name.L)
  1209  				// This index has a defCausumn in DeleteOnly state,
  1210  				// or it is memex index (it defined on a hidden defCausumn),
  1211  				// it can not be implicit PK, go to next index iterator
  1212  				if defCaus == nil || defCaus.Hidden {
  1213  					skip = true
  1214  					break
  1215  				}
  1216  				if !allegrosql.HasNotNullFlag(defCaus.Flag) {
  1217  					allDefCausNotNull = false
  1218  					break
  1219  				}
  1220  			}
  1221  			if skip {
  1222  				continue
  1223  			}
  1224  			if allDefCausNotNull {
  1225  				implicitPK = key
  1226  			}
  1227  		}
  1228  	}
  1229  	return implicitPK
  1230  }
  1231  
  1232  func setTableAutoRandomBits(ctx stochastikctx.Context, tbInfo *perceptron.TableInfo, defCausDefs []*ast.DeferredCausetDef) error {
  1233  	pkDefCausName := tbInfo.GetPkName()
  1234  	for _, defCaus := range defCausDefs {
  1235  		if containsDeferredCausetOption(defCaus, ast.DeferredCausetOptionAutoRandom) {
  1236  			if defCaus.Tp.Tp != allegrosql.TypeLonglong {
  1237  				return ErrInvalidAutoRandom.GenWithStackByArgs(
  1238  					fmt.Sprintf(autoid.AutoRandomOnNonBigIntDeferredCauset, types.TypeStr(defCaus.Tp.Tp)))
  1239  			}
  1240  			if !tbInfo.PKIsHandle || defCaus.Name.Name.L != pkDefCausName.L {
  1241  				errMsg := fmt.Sprintf(autoid.AutoRandomPKisNotHandleErrMsg, defCaus.Name.Name.O)
  1242  				return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)
  1243  			}
  1244  			if containsDeferredCausetOption(defCaus, ast.DeferredCausetOptionAutoIncrement) {
  1245  				return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithAutoIncErrMsg)
  1246  			}
  1247  			if containsDeferredCausetOption(defCaus, ast.DeferredCausetOptionDefaultValue) {
  1248  				return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg)
  1249  			}
  1250  
  1251  			autoRandBits, err := extractAutoRandomBitsFromDefCausDef(defCaus)
  1252  			if err != nil {
  1253  				return errors.Trace(err)
  1254  			}
  1255  
  1256  			layout := autoid.NewAutoRandomIDLayout(defCaus.Tp, autoRandBits)
  1257  			if autoRandBits == 0 {
  1258  				return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomNonPositive)
  1259  			} else if autoRandBits > autoid.MaxAutoRandomBits {
  1260  				errMsg := fmt.Sprintf(autoid.AutoRandomOverflowErrMsg,
  1261  					autoid.MaxAutoRandomBits, autoRandBits, defCaus.Name.Name.O)
  1262  				return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)
  1263  			}
  1264  			tbInfo.AutoRandomBits = autoRandBits
  1265  
  1266  			msg := fmt.Sprintf(autoid.AutoRandomAvailableAllocTimesNote, layout.IncrementalBitsCapacity())
  1267  			ctx.GetStochastikVars().StmtCtx.AppendNote(errors.Errorf(msg))
  1268  		}
  1269  	}
  1270  	return nil
  1271  }
  1272  
  1273  func extractAutoRandomBitsFromDefCausDef(defCausDef *ast.DeferredCausetDef) (uint64, error) {
  1274  	for _, op := range defCausDef.Options {
  1275  		if op.Tp == ast.DeferredCausetOptionAutoRandom {
  1276  			return convertAutoRandomBitsToUnsigned(op.AutoRandomBitLength)
  1277  		}
  1278  	}
  1279  	return 0, nil
  1280  }
  1281  
  1282  func convertAutoRandomBitsToUnsigned(autoRandomBits int) (uint64, error) {
  1283  	if autoRandomBits == types.UnspecifiedLength {
  1284  		return autoid.DefaultAutoRandomBits, nil
  1285  	} else if autoRandomBits < 0 {
  1286  		return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomNonPositive)
  1287  	}
  1288  	return uint64(autoRandomBits), nil
  1289  }
  1290  
  1291  func buildTableInfo(
  1292  	ctx stochastikctx.Context,
  1293  	blockName perceptron.CIStr,
  1294  	defcaus []*causet.DeferredCauset,
  1295  	constraints []*ast.Constraint,
  1296  	charset string,
  1297  	defCauslate string) (tbInfo *perceptron.TableInfo, err error) {
  1298  	tbInfo = &perceptron.TableInfo{
  1299  		Name:        blockName,
  1300  		Version:     perceptron.CurrLatestTableInfoVersion,
  1301  		Charset:     charset,
  1302  		DefCauslate: defCauslate,
  1303  	}
  1304  	tblDeferredCausets := make([]*causet.DeferredCauset, 0, len(defcaus))
  1305  	for _, v := range defcaus {
  1306  		v.ID = allocateDeferredCausetID(tbInfo)
  1307  		tbInfo.DeferredCausets = append(tbInfo.DeferredCausets, v.ToInfo())
  1308  		tblDeferredCausets = append(tblDeferredCausets, causet.ToDeferredCauset(v.ToInfo()))
  1309  	}
  1310  	for _, constr := range constraints {
  1311  		// Build hidden defCausumns if necessary.
  1312  		hiddenDefCauss, err := buildHiddenDeferredCausetInfo(ctx, constr.Keys, perceptron.NewCIStr(constr.Name), tbInfo, tblDeferredCausets)
  1313  		if err != nil {
  1314  			return nil, err
  1315  		}
  1316  		for _, hiddenDefCaus := range hiddenDefCauss {
  1317  			hiddenDefCaus.State = perceptron.StatePublic
  1318  			hiddenDefCaus.ID = allocateDeferredCausetID(tbInfo)
  1319  			hiddenDefCaus.Offset = len(tbInfo.DeferredCausets)
  1320  			tbInfo.DeferredCausets = append(tbInfo.DeferredCausets, hiddenDefCaus)
  1321  			tblDeferredCausets = append(tblDeferredCausets, causet.ToDeferredCauset(hiddenDefCaus))
  1322  		}
  1323  		if constr.Tp == ast.ConstraintForeignKey {
  1324  			for _, fk := range tbInfo.ForeignKeys {
  1325  				if fk.Name.L == strings.ToLower(constr.Name) {
  1326  					return nil, schemareplicant.ErrCannotAddForeign
  1327  				}
  1328  			}
  1329  			fk, err := buildFKInfo(perceptron.NewCIStr(constr.Name), constr.Keys, constr.Refer, defcaus, tbInfo)
  1330  			if err != nil {
  1331  				return nil, err
  1332  			}
  1333  			fk.State = perceptron.StatePublic
  1334  
  1335  			tbInfo.ForeignKeys = append(tbInfo.ForeignKeys, fk)
  1336  			continue
  1337  		}
  1338  		if constr.Tp == ast.ConstraintPrimaryKey {
  1339  			lastDefCaus, err := checkPKOnGeneratedDeferredCauset(tbInfo, constr.Keys)
  1340  			if err != nil {
  1341  				return nil, err
  1342  			}
  1343  			if !config.GetGlobalConfig().AlterPrimaryKey {
  1344  				singleIntPK := isSingleIntPK(constr, lastDefCaus)
  1345  				clusteredIdx := ctx.GetStochastikVars().EnableClusteredIndex
  1346  				if singleIntPK || clusteredIdx {
  1347  					// Primary key cannot be invisible.
  1348  					if constr.Option != nil && constr.Option.Visibility == ast.IndexVisibilityInvisible {
  1349  						return nil, ErrPHoTTexCantBeInvisible
  1350  					}
  1351  				}
  1352  				if singleIntPK {
  1353  					tbInfo.PKIsHandle = true
  1354  					// Avoid creating index for PK handle defCausumn.
  1355  					continue
  1356  				}
  1357  				if clusteredIdx {
  1358  					tbInfo.IsCommonHandle = true
  1359  				}
  1360  			}
  1361  		}
  1362  
  1363  		if constr.Tp == ast.ConstraintFulltext {
  1364  			sc := ctx.GetStochastikVars().StmtCtx
  1365  			sc.AppendWarning(ErrTableCantHandleFt)
  1366  			continue
  1367  		}
  1368  		// build index info.
  1369  		idxInfo, err := buildIndexInfo(tbInfo, perceptron.NewCIStr(constr.Name), constr.Keys, perceptron.StatePublic)
  1370  		if err != nil {
  1371  			return nil, errors.Trace(err)
  1372  		}
  1373  		if len(hiddenDefCauss) > 0 {
  1374  			addIndexDeferredCausetFlag(tbInfo, idxInfo)
  1375  		}
  1376  		// check if the index is primary or unique.
  1377  		switch constr.Tp {
  1378  		case ast.ConstraintPrimaryKey:
  1379  			idxInfo.Primary = true
  1380  			idxInfo.Unique = true
  1381  			idxInfo.Name = perceptron.NewCIStr(allegrosql.PrimaryKeyName)
  1382  		case ast.ConstraintUniq, ast.ConstraintUniqKey, ast.ConstraintUniqIndex:
  1383  			idxInfo.Unique = true
  1384  		}
  1385  		// set index type.
  1386  		if constr.Option != nil {
  1387  			idxInfo.Comment, err = validateCommentLength(ctx.GetStochastikVars(), idxInfo.Name.String(), constr.Option)
  1388  			if err != nil {
  1389  				return nil, errors.Trace(err)
  1390  			}
  1391  			if constr.Option.Visibility == ast.IndexVisibilityInvisible {
  1392  				idxInfo.Invisible = true
  1393  			}
  1394  			if constr.Option.Tp == perceptron.IndexTypeInvalid {
  1395  				// Use btree as default index type.
  1396  				idxInfo.Tp = perceptron.IndexTypeBtree
  1397  			} else {
  1398  				idxInfo.Tp = constr.Option.Tp
  1399  			}
  1400  		} else {
  1401  			// Use btree as default index type.
  1402  			idxInfo.Tp = perceptron.IndexTypeBtree
  1403  		}
  1404  		idxInfo.ID = allocateIndexID(tbInfo)
  1405  		tbInfo.Indices = append(tbInfo.Indices, idxInfo)
  1406  	}
  1407  	return
  1408  }
  1409  
  1410  func isSingleIntPK(constr *ast.Constraint, lastDefCaus *perceptron.DeferredCausetInfo) bool {
  1411  	if len(constr.Keys) != 1 {
  1412  		return false
  1413  	}
  1414  	switch lastDefCaus.Tp {
  1415  	case allegrosql.TypeLong, allegrosql.TypeLonglong,
  1416  		allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24:
  1417  		return true
  1418  	}
  1419  	return false
  1420  }
  1421  
  1422  // checkTableInfoValidExtra is like checkTableInfoValid, but also assumes the
  1423  // causet info comes from untrusted source and performs further checks such as
  1424  // name length and defCausumn count.
  1425  // (checkTableInfoValid is also used in repairing objects which don't perform
  1426  // these checks. Perhaps the two functions should be merged together regardless?)
  1427  func checkTableInfoValidExtra(tbInfo *perceptron.TableInfo) error {
  1428  	if err := checkTooLongTable(tbInfo.Name); err != nil {
  1429  		return err
  1430  	}
  1431  
  1432  	if err := checkDuplicateDeferredCauset(tbInfo.DeferredCausets); err != nil {
  1433  		return err
  1434  	}
  1435  	if err := checkTooLongDeferredCauset(tbInfo.DeferredCausets); err != nil {
  1436  		return err
  1437  	}
  1438  	if err := checkTooManyDeferredCausets(tbInfo.DeferredCausets); err != nil {
  1439  		return errors.Trace(err)
  1440  	}
  1441  	if err := checkDeferredCausetsAttributes(tbInfo.DeferredCausets); err != nil {
  1442  		return errors.Trace(err)
  1443  	}
  1444  
  1445  	// FIXME: perform checkConstraintNames
  1446  	if err := checkCharsetAndDefCauslation(tbInfo.Charset, tbInfo.DefCauslate); err != nil {
  1447  		return errors.Trace(err)
  1448  	}
  1449  
  1450  	oldState := tbInfo.State
  1451  	tbInfo.State = perceptron.StatePublic
  1452  	err := checkTableInfoValid(tbInfo)
  1453  	tbInfo.State = oldState
  1454  	return err
  1455  }
  1456  
  1457  func checkTableInfoValidWithStmt(ctx stochastikctx.Context, tbInfo *perceptron.TableInfo, s *ast.CreateTableStmt) error {
  1458  	// All of these rely on the AST structure of memexs, which were
  1459  	// lost in the perceptron (got serialized into strings).
  1460  	if err := checkGeneratedDeferredCauset(s.DefCauss); err != nil {
  1461  		return errors.Trace(err)
  1462  	}
  1463  	if s.Partition != nil {
  1464  		err := checkPartitionExprValid(ctx, tbInfo, s.Partition.Expr)
  1465  		if err != nil {
  1466  			return errors.Trace(err)
  1467  		}
  1468  
  1469  		pi := tbInfo.Partition
  1470  		if pi != nil {
  1471  			switch pi.Type {
  1472  			case perceptron.PartitionTypeRange:
  1473  				err = checkPartitionByRange(ctx, tbInfo, s)
  1474  			case perceptron.PartitionTypeHash:
  1475  				err = checkPartitionByHash(ctx, tbInfo, s)
  1476  			}
  1477  			if err != nil {
  1478  				return errors.Trace(err)
  1479  			}
  1480  		}
  1481  
  1482  		if err = checkPartitioningKeysConstraints(ctx, s, tbInfo); err != nil {
  1483  			return errors.Trace(err)
  1484  		}
  1485  	}
  1486  	return nil
  1487  }
  1488  
  1489  // checkTableInfoValid uses to check causet info valid. This is used to validate causet info.
  1490  func checkTableInfoValid(tblInfo *perceptron.TableInfo) error {
  1491  	_, err := blocks.TableFromMeta(nil, tblInfo)
  1492  	if err != nil {
  1493  		return err
  1494  	}
  1495  	return checkInvisibleIndexOnPK(tblInfo)
  1496  }
  1497  
  1498  func buildTableInfoWithLike(ident ast.Ident, referTblInfo *perceptron.TableInfo) (*perceptron.TableInfo, error) {
  1499  	// Check the referred causet is a real causet object.
  1500  	if referTblInfo.IsSequence() || referTblInfo.IsView() {
  1501  		return nil, ErrWrongObject.GenWithStackByArgs(ident.Schema, referTblInfo.Name, "BASE TABLE")
  1502  	}
  1503  	tblInfo := *referTblInfo
  1504  	// Check non-public defCausumn and adjust defCausumn offset.
  1505  	newDeferredCausets := referTblInfo.DefCauss()
  1506  	newIndices := make([]*perceptron.IndexInfo, 0, len(tblInfo.Indices))
  1507  	for _, idx := range tblInfo.Indices {
  1508  		if idx.State == perceptron.StatePublic {
  1509  			newIndices = append(newIndices, idx)
  1510  		}
  1511  	}
  1512  	tblInfo.DeferredCausets = newDeferredCausets
  1513  	tblInfo.Indices = newIndices
  1514  	tblInfo.Name = ident.Name
  1515  	tblInfo.AutoIncID = 0
  1516  	tblInfo.ForeignKeys = nil
  1517  	if tblInfo.TiFlashReplica != nil {
  1518  		replica := *tblInfo.TiFlashReplica
  1519  		// Keep the tiflash replica setting, remove the replica available status.
  1520  		replica.AvailablePartitionIDs = nil
  1521  		replica.Available = false
  1522  		tblInfo.TiFlashReplica = &replica
  1523  	}
  1524  	if referTblInfo.Partition != nil {
  1525  		pi := *referTblInfo.Partition
  1526  		pi.Definitions = make([]perceptron.PartitionDefinition, len(referTblInfo.Partition.Definitions))
  1527  		copy(pi.Definitions, referTblInfo.Partition.Definitions)
  1528  		tblInfo.Partition = &pi
  1529  	}
  1530  	return &tblInfo, nil
  1531  }
  1532  
  1533  // BuildTableInfoFromAST builds perceptron.TableInfo from a ALLEGROALLEGROSQL memex.
  1534  // Note: TableID and PartitionID are left as uninitialized value.
  1535  func BuildTableInfoFromAST(s *ast.CreateTableStmt) (*perceptron.TableInfo, error) {
  1536  	return buildTableInfoWithCheck(mock.NewContext(), s, allegrosql.DefaultCharset, "")
  1537  }
  1538  
  1539  // buildTableInfoWithCheck builds perceptron.TableInfo from a ALLEGROALLEGROSQL memex.
  1540  // Note: TableID and PartitionIDs are left as uninitialized value.
  1541  func buildTableInfoWithCheck(ctx stochastikctx.Context, s *ast.CreateTableStmt, dbCharset, dbDefCauslate string) (*perceptron.TableInfo, error) {
  1542  	tbInfo, err := buildTableInfoWithStmt(ctx, s, dbCharset, dbDefCauslate)
  1543  	if err != nil {
  1544  		return nil, err
  1545  	}
  1546  	// Fix issue 17952 which will cause partition range expr can't be parsed as Int.
  1547  	// checkTableInfoValidWithStmt will do the constant fold the partition memex first,
  1548  	// then checkTableInfoValidExtra will pass the blockInfo check successfully.
  1549  	if err = checkTableInfoValidWithStmt(ctx, tbInfo, s); err != nil {
  1550  		return nil, err
  1551  	}
  1552  	if err = checkTableInfoValidExtra(tbInfo); err != nil {
  1553  		return nil, err
  1554  	}
  1555  	return tbInfo, nil
  1556  }
  1557  
  1558  // buildTableInfoWithStmt builds perceptron.TableInfo from a ALLEGROALLEGROSQL memex without validity check
  1559  func buildTableInfoWithStmt(ctx stochastikctx.Context, s *ast.CreateTableStmt, dbCharset, dbDefCauslate string) (*perceptron.TableInfo, error) {
  1560  	defCausDefs := s.DefCauss
  1561  	blockCharset, blockDefCauslate, err := getCharsetAndDefCauslateInTableOption(0, s.Options)
  1562  	if err != nil {
  1563  		return nil, errors.Trace(err)
  1564  	}
  1565  	blockCharset, blockDefCauslate, err = ResolveCharsetDefCauslation(
  1566  		ast.CharsetOpt{Chs: blockCharset, DefCaus: blockDefCauslate},
  1567  		ast.CharsetOpt{Chs: dbCharset, DefCaus: dbDefCauslate},
  1568  	)
  1569  	if err != nil {
  1570  		return nil, errors.Trace(err)
  1571  	}
  1572  
  1573  	// The defCausumn charset haven't been resolved here.
  1574  	defcaus, newConstraints, err := buildDeferredCausetsAndConstraints(ctx, defCausDefs, s.Constraints, blockCharset, blockDefCauslate)
  1575  	if err != nil {
  1576  		return nil, errors.Trace(err)
  1577  	}
  1578  	err = checkConstraintNames(newConstraints)
  1579  	if err != nil {
  1580  		return nil, errors.Trace(err)
  1581  	}
  1582  
  1583  	var tbInfo *perceptron.TableInfo
  1584  	tbInfo, err = buildTableInfo(ctx, s.Block.Name, defcaus, newConstraints, blockCharset, blockDefCauslate)
  1585  	if err != nil {
  1586  		return nil, errors.Trace(err)
  1587  	}
  1588  
  1589  	if err = setTableAutoRandomBits(ctx, tbInfo, defCausDefs); err != nil {
  1590  		return nil, errors.Trace(err)
  1591  	}
  1592  
  1593  	tbInfo.Partition, err = buildTablePartitionInfo(ctx, s)
  1594  	if err != nil {
  1595  		return nil, errors.Trace(err)
  1596  	}
  1597  
  1598  	if err = handleTableOptions(s.Options, tbInfo); err != nil {
  1599  		return nil, errors.Trace(err)
  1600  	}
  1601  	return tbInfo, nil
  1602  }
  1603  
  1604  func (d *dbs) assignTableID(tbInfo *perceptron.TableInfo) error {
  1605  	genIDs, err := d.genGlobalIDs(1)
  1606  	if err != nil {
  1607  		return errors.Trace(err)
  1608  	}
  1609  	tbInfo.ID = genIDs[0]
  1610  	return nil
  1611  }
  1612  
  1613  func (d *dbs) assignPartitionIDs(tbInfo *perceptron.TableInfo) error {
  1614  	if tbInfo.Partition == nil {
  1615  		return nil
  1616  	}
  1617  	partitionDefs := tbInfo.Partition.Definitions
  1618  	genIDs, err := d.genGlobalIDs(len(partitionDefs))
  1619  	if err != nil {
  1620  		return errors.Trace(err)
  1621  	}
  1622  	for i := range partitionDefs {
  1623  		partitionDefs[i].ID = genIDs[i]
  1624  	}
  1625  	return nil
  1626  }
  1627  
  1628  func (d *dbs) CreateTable(ctx stochastikctx.Context, s *ast.CreateTableStmt) (err error) {
  1629  	ident := ast.Ident{Schema: s.Block.Schema, Name: s.Block.Name}
  1630  	is := d.GetSchemaReplicantWithInterceptor(ctx)
  1631  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  1632  	if !ok {
  1633  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(ident.Schema)
  1634  	}
  1635  
  1636  	var referTbl causet.Block
  1637  	if s.ReferTable != nil {
  1638  		referIdent := ast.Ident{Schema: s.ReferTable.Schema, Name: s.ReferTable.Name}
  1639  		_, ok := is.SchemaByName(referIdent.Schema)
  1640  		if !ok {
  1641  			return schemareplicant.ErrTableNotExists.GenWithStackByArgs(referIdent.Schema, referIdent.Name)
  1642  		}
  1643  		referTbl, err = is.TableByName(referIdent.Schema, referIdent.Name)
  1644  		if err != nil {
  1645  			return schemareplicant.ErrTableNotExists.GenWithStackByArgs(referIdent.Schema, referIdent.Name)
  1646  		}
  1647  	}
  1648  
  1649  	// build blockInfo
  1650  	var tbInfo *perceptron.TableInfo
  1651  	if s.ReferTable != nil {
  1652  		tbInfo, err = buildTableInfoWithLike(ident, referTbl.Meta())
  1653  	} else {
  1654  		tbInfo, err = buildTableInfoWithStmt(ctx, s, schemaReplicant.Charset, schemaReplicant.DefCauslate)
  1655  	}
  1656  	if err != nil {
  1657  		return errors.Trace(err)
  1658  	}
  1659  
  1660  	if err = checkTableInfoValidWithStmt(ctx, tbInfo, s); err != nil {
  1661  		return err
  1662  	}
  1663  
  1664  	onExist := OnExistError
  1665  	if s.IfNotExists {
  1666  		onExist = OnExistIgnore
  1667  	}
  1668  
  1669  	return d.CreateTableWithInfo(ctx, schemaReplicant.Name, tbInfo, onExist, false /*tryRetainID*/)
  1670  }
  1671  
  1672  func (d *dbs) CreateTableWithInfo(
  1673  	ctx stochastikctx.Context,
  1674  	dbName perceptron.CIStr,
  1675  	tbInfo *perceptron.TableInfo,
  1676  	onExist OnExist,
  1677  	tryRetainID bool,
  1678  ) (err error) {
  1679  	is := d.GetSchemaReplicantWithInterceptor(ctx)
  1680  	schemaReplicant, ok := is.SchemaByName(dbName)
  1681  	if !ok {
  1682  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(dbName)
  1683  	}
  1684  
  1685  	var oldViewTblID int64
  1686  	if oldTable, err := is.TableByName(schemaReplicant.Name, tbInfo.Name); err == nil {
  1687  		err = schemareplicant.ErrTableExists.GenWithStackByArgs(ast.Ident{Schema: schemaReplicant.Name, Name: tbInfo.Name})
  1688  		switch onExist {
  1689  		case OnExistIgnore:
  1690  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  1691  			return nil
  1692  		case OnExistReplace:
  1693  			// only CREATE OR REPLACE VIEW is supported at the moment.
  1694  			if tbInfo.View != nil {
  1695  				if oldTable.Meta().IsView() {
  1696  					oldViewTblID = oldTable.Meta().ID
  1697  					break
  1698  				}
  1699  				// The object to replace isn't a view.
  1700  				return ErrWrongObject.GenWithStackByArgs(dbName, tbInfo.Name, "VIEW")
  1701  			}
  1702  			return err
  1703  		default:
  1704  			return err
  1705  		}
  1706  	}
  1707  
  1708  	// FIXME: Implement `tryRetainID`
  1709  	if err := d.assignTableID(tbInfo); err != nil {
  1710  		return errors.Trace(err)
  1711  	}
  1712  	if err := d.assignPartitionIDs(tbInfo); err != nil {
  1713  		return errors.Trace(err)
  1714  	}
  1715  
  1716  	if err := checkTableInfoValidExtra(tbInfo); err != nil {
  1717  		return err
  1718  	}
  1719  
  1720  	var actionType perceptron.CausetActionType
  1721  	args := []interface{}{tbInfo}
  1722  	switch {
  1723  	case tbInfo.View != nil:
  1724  		actionType = perceptron.CausetActionCreateView
  1725  		args = append(args, onExist == OnExistReplace, oldViewTblID)
  1726  	case tbInfo.Sequence != nil:
  1727  		actionType = perceptron.CausetActionCreateSequence
  1728  	default:
  1729  		actionType = perceptron.CausetActionCreateTable
  1730  	}
  1731  
  1732  	job := &perceptron.Job{
  1733  		SchemaID:   schemaReplicant.ID,
  1734  		TableID:    tbInfo.ID,
  1735  		SchemaName: schemaReplicant.Name.L,
  1736  		Type:       actionType,
  1737  		BinlogInfo: &perceptron.HistoryInfo{},
  1738  		Args:       args,
  1739  	}
  1740  
  1741  	err = d.doDBSJob(ctx, job)
  1742  	if err != nil {
  1743  		// causet exists, but if_not_exists flags is true, so we ignore this error.
  1744  		if onExist == OnExistIgnore && schemareplicant.ErrTableExists.Equal(err) {
  1745  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  1746  			err = nil
  1747  		}
  1748  	} else if actionType == perceptron.CausetActionCreateTable {
  1749  		d.preSplitAndScatter(ctx, tbInfo, tbInfo.GetPartitionInfo())
  1750  		if tbInfo.AutoIncID > 1 {
  1751  			// Default blockAutoIncID base is 0.
  1752  			// If the first ID is expected to greater than 1, we need to do rebase.
  1753  			newEnd := tbInfo.AutoIncID - 1
  1754  			if err = d.handleAutoIncID(tbInfo, schemaReplicant.ID, newEnd, autoid.RowIDAllocType); err != nil {
  1755  				return errors.Trace(err)
  1756  			}
  1757  		}
  1758  		if tbInfo.AutoRandID > 1 {
  1759  			// Default blockAutoRandID base is 0.
  1760  			// If the first ID is expected to greater than 1, we need to do rebase.
  1761  			newEnd := tbInfo.AutoRandID - 1
  1762  			err = d.handleAutoIncID(tbInfo, schemaReplicant.ID, newEnd, autoid.AutoRandomType)
  1763  		}
  1764  	}
  1765  
  1766  	err = d.callHookOnChanged(err)
  1767  	return errors.Trace(err)
  1768  }
  1769  
  1770  // preSplitAndScatter performs pre-split and scatter of the causet's regions.
  1771  // If `pi` is not nil, will only split region for `pi`, this is used when add partition.
  1772  func (d *dbs) preSplitAndScatter(ctx stochastikctx.Context, tbInfo *perceptron.TableInfo, pi *perceptron.PartitionInfo) {
  1773  	sp, ok := d.causetstore.(ekv.SplitblockStore)
  1774  	if !ok || atomic.LoadUint32(&EnableSplitTableRegion) == 0 {
  1775  		return
  1776  	}
  1777  	var (
  1778  		preSplit      func()
  1779  		scatterRegion bool
  1780  	)
  1781  	val, err := variable.GetGlobalSystemVar(ctx.GetStochastikVars(), variable.MilevaDBScatterRegion)
  1782  	if err != nil {
  1783  		logutil.BgLogger().Warn("[dbs] won't scatter region", zap.Error(err))
  1784  	} else {
  1785  		scatterRegion = variable.MilevaDBOptOn(val)
  1786  	}
  1787  	if pi != nil {
  1788  		preSplit = func() { splitPartitionTableRegion(ctx, sp, tbInfo, pi, scatterRegion) }
  1789  	} else {
  1790  		preSplit = func() { splitTableRegion(ctx, sp, tbInfo, scatterRegion) }
  1791  	}
  1792  	if scatterRegion {
  1793  		preSplit()
  1794  	} else {
  1795  		go preSplit()
  1796  	}
  1797  }
  1798  
  1799  func (d *dbs) RecoverTable(ctx stochastikctx.Context, recoverInfo *RecoverInfo) (err error) {
  1800  	is := d.GetSchemaReplicantWithInterceptor(ctx)
  1801  	schemaID, tbInfo := recoverInfo.SchemaID, recoverInfo.TableInfo
  1802  	// Check schemaReplicant exist.
  1803  	schemaReplicant, ok := is.SchemaByID(schemaID)
  1804  	if !ok {
  1805  		return errors.Trace(schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(
  1806  			fmt.Sprintf("(Schema ID %d)", schemaID),
  1807  		))
  1808  	}
  1809  	// Check not exist causet with same name.
  1810  	if ok := is.TableExists(schemaReplicant.Name, tbInfo.Name); ok {
  1811  		return schemareplicant.ErrTableExists.GenWithStackByArgs(tbInfo.Name)
  1812  	}
  1813  
  1814  	tbInfo.State = perceptron.StateNone
  1815  	job := &perceptron.Job{
  1816  		SchemaID:   schemaID,
  1817  		TableID:    tbInfo.ID,
  1818  		SchemaName: schemaReplicant.Name.L,
  1819  		Type:       perceptron.CausetActionRecoverTable,
  1820  		BinlogInfo: &perceptron.HistoryInfo{},
  1821  		Args: []interface{}{tbInfo, recoverInfo.CurAutoIncID, recoverInfo.DropJobID,
  1822  			recoverInfo.SnapshotTS, recoverTableCheckFlagNone, recoverInfo.CurAutoRandID},
  1823  	}
  1824  	err = d.doDBSJob(ctx, job)
  1825  	err = d.callHookOnChanged(err)
  1826  	return errors.Trace(err)
  1827  }
  1828  
  1829  func (d *dbs) CreateView(ctx stochastikctx.Context, s *ast.CreateViewStmt) (err error) {
  1830  	viewInfo, err := buildViewInfo(ctx, s)
  1831  	if err != nil {
  1832  		return err
  1833  	}
  1834  
  1835  	defcaus := make([]*causet.DeferredCauset, len(s.DefCauss))
  1836  	for i, v := range s.DefCauss {
  1837  		defcaus[i] = causet.ToDeferredCauset(&perceptron.DeferredCausetInfo{
  1838  			Name:   v,
  1839  			ID:     int64(i),
  1840  			Offset: i,
  1841  			State:  perceptron.StatePublic,
  1842  		})
  1843  	}
  1844  
  1845  	tblCharset := ""
  1846  	tblDefCauslate := ""
  1847  	if v, ok := ctx.GetStochastikVars().GetSystemVar("character_set_client"); ok {
  1848  		tblCharset = v
  1849  	}
  1850  	if v, ok := ctx.GetStochastikVars().GetSystemVar("defCauslation_connection"); ok {
  1851  		tblDefCauslate = v
  1852  	}
  1853  
  1854  	tbInfo, err := buildTableInfo(ctx, s.ViewName.Name, defcaus, nil, tblCharset, tblDefCauslate)
  1855  	if err != nil {
  1856  		return err
  1857  	}
  1858  	tbInfo.View = viewInfo
  1859  
  1860  	onExist := OnExistError
  1861  	if s.OrReplace {
  1862  		onExist = OnExistReplace
  1863  	}
  1864  
  1865  	return d.CreateTableWithInfo(ctx, s.ViewName.Schema, tbInfo, onExist, false /*tryRetainID*/)
  1866  }
  1867  
  1868  func buildViewInfo(ctx stochastikctx.Context, s *ast.CreateViewStmt) (*perceptron.ViewInfo, error) {
  1869  	// Always Use `format.RestoreNameBackQuotes` to restore `SELECT` memex despite the `ANSI_QUOTES` ALLEGROALLEGROSQL Mode is enabled or not.
  1870  	restoreFlag := format.RestoreStringSingleQuotes | format.RestoreKeyWordUppercase | format.RestoreNameBackQuotes
  1871  	var sb strings.Builder
  1872  	if err := s.Select.Restore(format.NewRestoreCtx(restoreFlag, &sb)); err != nil {
  1873  		return nil, err
  1874  	}
  1875  
  1876  	return &perceptron.ViewInfo{Definer: s.Definer, Algorithm: s.Algorithm,
  1877  		Security: s.Security, SelectStmt: sb.String(), CheckOption: s.CheckOption, DefCauss: nil}, nil
  1878  }
  1879  
  1880  func checkPartitionByHash(ctx stochastikctx.Context, tbInfo *perceptron.TableInfo, s *ast.CreateTableStmt) error {
  1881  	pi := tbInfo.Partition
  1882  	if err := checkAddPartitionTooManyPartitions(pi.Num); err != nil {
  1883  		return err
  1884  	}
  1885  	if err := checkNoHashPartitions(ctx, pi.Num); err != nil {
  1886  		return err
  1887  	}
  1888  	if err := checkPartitionFuncValid(ctx, tbInfo, s.Partition.Expr); err != nil {
  1889  		return err
  1890  	}
  1891  	return checkPartitionFuncType(ctx, s, tbInfo)
  1892  }
  1893  
  1894  // checkPartitionByRange checks validity of a "BY RANGE" partition.
  1895  func checkPartitionByRange(ctx stochastikctx.Context, tbInfo *perceptron.TableInfo, s *ast.CreateTableStmt) error {
  1896  	pi := tbInfo.Partition
  1897  	if err := checkPartitionNameUnique(pi); err != nil {
  1898  		return err
  1899  	}
  1900  
  1901  	if err := checkAddPartitionTooManyPartitions(uint64(len(pi.Definitions))); err != nil {
  1902  		return err
  1903  	}
  1904  
  1905  	if err := checkNoRangePartitions(len(pi.Definitions)); err != nil {
  1906  		return err
  1907  	}
  1908  
  1909  	if len(pi.DeferredCausets) == 0 {
  1910  		if err := checkCreatePartitionValue(ctx, tbInfo); err != nil {
  1911  			return err
  1912  		}
  1913  
  1914  		// s maybe nil when add partition.
  1915  		if s == nil {
  1916  			return nil
  1917  		}
  1918  
  1919  		if err := checkPartitionFuncValid(ctx, tbInfo, s.Partition.Expr); err != nil {
  1920  			return err
  1921  		}
  1922  		return checkPartitionFuncType(ctx, s, tbInfo)
  1923  	}
  1924  
  1925  	// Check for range defCausumns partition.
  1926  	if err := checkRangeDeferredCausetsPartitionType(tbInfo); err != nil {
  1927  		return err
  1928  	}
  1929  
  1930  	if s != nil {
  1931  		for _, def := range s.Partition.Definitions {
  1932  			exprs := def.Clause.(*ast.PartitionDefinitionClauseLessThan).Exprs
  1933  			if err := checkRangeDeferredCausetsTypeAndValuesMatch(ctx, tbInfo, exprs); err != nil {
  1934  				return err
  1935  			}
  1936  		}
  1937  	}
  1938  
  1939  	return checkRangeDeferredCausetsPartitionValue(ctx, tbInfo)
  1940  }
  1941  
  1942  func checkRangeDeferredCausetsPartitionType(tbInfo *perceptron.TableInfo) error {
  1943  	for _, defCaus := range tbInfo.Partition.DeferredCausets {
  1944  		defCausInfo := getDeferredCausetInfoByName(tbInfo, defCaus.L)
  1945  		if defCausInfo == nil {
  1946  			return errors.Trace(ErrFieldNotFoundPart)
  1947  		}
  1948  		// The permitted data types are shown in the following list:
  1949  		// All integer types
  1950  		// DATE and DATETIME
  1951  		// CHAR, VARCHAR, BINARY, and VARBINARY
  1952  		// See https://dev.allegrosql.com/doc/allegrosql-partitioning-excerpt/5.7/en/partitioning-defCausumns.html
  1953  		switch defCausInfo.FieldType.Tp {
  1954  		case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong:
  1955  		case allegrosql.TypeDate, allegrosql.TypeDatetime:
  1956  		case allegrosql.TypeVarchar, allegrosql.TypeString:
  1957  		default:
  1958  			return ErrNotAllowedTypeInPartition.GenWithStackByArgs(defCaus.O)
  1959  		}
  1960  	}
  1961  	return nil
  1962  }
  1963  
  1964  func checkRangeDeferredCausetsPartitionValue(ctx stochastikctx.Context, tbInfo *perceptron.TableInfo) error {
  1965  	// Range defCausumns partition key supports multiple data types with integer、datetime、string.
  1966  	pi := tbInfo.Partition
  1967  	defs := pi.Definitions
  1968  	if len(defs) < 1 {
  1969  		return ast.ErrPartitionsMustBeDefined.GenWithStackByArgs("RANGE")
  1970  	}
  1971  
  1972  	curr := &defs[0]
  1973  	if len(curr.LessThan) != len(pi.DeferredCausets) {
  1974  		return errors.Trace(ast.ErrPartitionDeferredCausetList)
  1975  	}
  1976  	var prev *perceptron.PartitionDefinition
  1977  	for i := 1; i < len(defs); i++ {
  1978  		prev, curr = curr, &defs[i]
  1979  		succ, err := checkTwoRangeDeferredCausets(ctx, curr, prev, pi, tbInfo)
  1980  		if err != nil {
  1981  			return err
  1982  		}
  1983  		if !succ {
  1984  			return errors.Trace(ErrRangeNotIncreasing)
  1985  		}
  1986  	}
  1987  	return nil
  1988  }
  1989  
  1990  func checkTwoRangeDeferredCausets(ctx stochastikctx.Context, curr, prev *perceptron.PartitionDefinition, pi *perceptron.PartitionInfo, tbInfo *perceptron.TableInfo) (bool, error) {
  1991  	if len(curr.LessThan) != len(pi.DeferredCausets) {
  1992  		return false, errors.Trace(ast.ErrPartitionDeferredCausetList)
  1993  	}
  1994  	for i := 0; i < len(pi.DeferredCausets); i++ {
  1995  		// Special handling for MAXVALUE.
  1996  		if strings.EqualFold(curr.LessThan[i], partitionMaxValue) {
  1997  			// If current is maxvalue, it certainly >= previous.
  1998  			return true, nil
  1999  		}
  2000  		if strings.EqualFold(prev.LessThan[i], partitionMaxValue) {
  2001  			// Current is not maxvalue, and previous is maxvalue.
  2002  			return false, nil
  2003  		}
  2004  
  2005  		// Current and previous is the same.
  2006  		if strings.EqualFold(curr.LessThan[i], prev.LessThan[i]) {
  2007  			continue
  2008  		}
  2009  
  2010  		// The tuples of defCausumn values used to define the partitions are strictly increasing:
  2011  		// PARTITION p0 VALUES LESS THAN (5,10,'ggg')
  2012  		// PARTITION p1 VALUES LESS THAN (10,20,'mmm')
  2013  		// PARTITION p2 VALUES LESS THAN (15,30,'sss')
  2014  		succ, err := parseAndEvalBoolExpr(ctx, fmt.Sprintf("(%s) > (%s)", curr.LessThan[i], prev.LessThan[i]), tbInfo)
  2015  		if err != nil {
  2016  			return false, err
  2017  		}
  2018  
  2019  		if succ {
  2020  			return true, nil
  2021  		}
  2022  	}
  2023  	return false, nil
  2024  }
  2025  
  2026  func parseAndEvalBoolExpr(ctx stochastikctx.Context, expr string, tbInfo *perceptron.TableInfo) (bool, error) {
  2027  	e, err := memex.ParseSimpleExprWithTableInfo(ctx, expr, tbInfo)
  2028  	if err != nil {
  2029  		return false, err
  2030  	}
  2031  	res, _, err1 := e.EvalInt(ctx, chunk.Row{})
  2032  	if err1 != nil {
  2033  		return false, err1
  2034  	}
  2035  	return res > 0, nil
  2036  }
  2037  
  2038  func checkCharsetAndDefCauslation(cs string, co string) error {
  2039  	if !charset.ValidCharsetAndDefCauslation(cs, co) {
  2040  		return ErrUnknownCharacterSet.GenWithStackByArgs(cs)
  2041  	}
  2042  	if co != "" {
  2043  		if _, err := defCauslate.GetDefCauslationByName(co); err != nil {
  2044  			return errors.Trace(err)
  2045  		}
  2046  	}
  2047  	return nil
  2048  }
  2049  
  2050  // handleAutoIncID handles auto_increment option in DBS. It creates a ID counter for the causet and initiates the counter to a proper value.
  2051  // For example if the option sets auto_increment to 10. The counter will be set to 9. So the next allocated ID will be 10.
  2052  func (d *dbs) handleAutoIncID(tbInfo *perceptron.TableInfo, schemaID int64, newEnd int64, tp autoid.SlabPredictorType) error {
  2053  	allocs := autoid.NewSlabPredictorsFromTblInfo(d.causetstore, schemaID, tbInfo)
  2054  	if alloc := allocs.Get(tp); alloc != nil {
  2055  		err := alloc.Rebase(tbInfo.ID, newEnd, false)
  2056  		if err != nil {
  2057  			return errors.Trace(err)
  2058  		}
  2059  	}
  2060  	return nil
  2061  }
  2062  
  2063  // handleTableOptions uFIDelates blockInfo according to causet options.
  2064  func handleTableOptions(options []*ast.TableOption, tbInfo *perceptron.TableInfo) error {
  2065  	for _, op := range options {
  2066  		switch op.Tp {
  2067  		case ast.TableOptionAutoIncrement:
  2068  			tbInfo.AutoIncID = int64(op.UintValue)
  2069  		case ast.TableOptionAutoIdCache:
  2070  			if op.UintValue > uint64(math.MaxInt64) {
  2071  				// TODO: Refine this error.
  2072  				return errors.New("causet option auto_id_cache overflows int64")
  2073  			}
  2074  			tbInfo.AutoIdCache = int64(op.UintValue)
  2075  		case ast.TableOptionAutoRandomBase:
  2076  			tbInfo.AutoRandID = int64(op.UintValue)
  2077  		case ast.TableOptionComment:
  2078  			tbInfo.Comment = op.StrValue
  2079  		case ast.TableOptionCompression:
  2080  			tbInfo.Compression = op.StrValue
  2081  		case ast.TableOptionShardRowID:
  2082  			if op.UintValue > 0 && tbInfo.PKIsHandle {
  2083  				return errUnsupportedShardRowIDBits
  2084  			}
  2085  			tbInfo.ShardRowIDBits = op.UintValue
  2086  			if tbInfo.ShardRowIDBits > shardRowIDBitsMax {
  2087  				tbInfo.ShardRowIDBits = shardRowIDBitsMax
  2088  			}
  2089  			tbInfo.MaxShardRowIDBits = tbInfo.ShardRowIDBits
  2090  		case ast.TableOptionPreSplitRegion:
  2091  			tbInfo.PreSplitRegions = op.UintValue
  2092  		case ast.TableOptionCharset, ast.TableOptionDefCauslate:
  2093  			// We don't handle charset and defCauslate here since they're handled in `getCharsetAndDefCauslateInTableOption`.
  2094  		}
  2095  	}
  2096  	if tbInfo.PreSplitRegions > tbInfo.ShardRowIDBits {
  2097  		tbInfo.PreSplitRegions = tbInfo.ShardRowIDBits
  2098  	}
  2099  	return nil
  2100  }
  2101  
  2102  // isIgnorableSpec checks if the spec type is ignorable.
  2103  // Some specs are parsed by ignored. This is for compatibility.
  2104  func isIgnorableSpec(tp ast.AlterTableType) bool {
  2105  	// AlterTableLock/AlterTableAlgorithm are ignored.
  2106  	return tp == ast.AlterTableLock || tp == ast.AlterTableAlgorithm
  2107  }
  2108  
  2109  // getCharsetAndDefCauslateInDeferredCausetDef will iterate defCauslate in the options, validate it by checking the charset
  2110  // of defCausumn definition. If there's no defCauslate in the option, the default defCauslate of defCausumn's charset will be used.
  2111  func getCharsetAndDefCauslateInDeferredCausetDef(def *ast.DeferredCausetDef) (chs, defCausl string, err error) {
  2112  	chs = def.Tp.Charset
  2113  	defCausl = def.Tp.DefCauslate
  2114  	if chs != "" && defCausl == "" {
  2115  		if defCausl, err = charset.GetDefaultDefCauslation(chs); err != nil {
  2116  			return "", "", errors.Trace(err)
  2117  		}
  2118  	}
  2119  	for _, opt := range def.Options {
  2120  		if opt.Tp == ast.DeferredCausetOptionDefCauslate {
  2121  			info, err := defCauslate.GetDefCauslationByName(opt.StrValue)
  2122  			if err != nil {
  2123  				return "", "", errors.Trace(err)
  2124  			}
  2125  			if chs == "" {
  2126  				chs = info.CharsetName
  2127  			} else if chs != info.CharsetName {
  2128  				return "", "", ErrDefCauslationCharsetMismatch.GenWithStackByArgs(info.Name, chs)
  2129  			}
  2130  			defCausl = info.Name
  2131  		}
  2132  	}
  2133  	return
  2134  }
  2135  
  2136  // getCharsetAndDefCauslateInTableOption will iterate the charset and defCauslate in the options,
  2137  // and returns the last charset and defCauslate in options. If there is no charset in the options,
  2138  // the returns charset will be "", the same as defCauslate.
  2139  func getCharsetAndDefCauslateInTableOption(startIdx int, options []*ast.TableOption) (chs, defCausl string, err error) {
  2140  	for i := startIdx; i < len(options); i++ {
  2141  		opt := options[i]
  2142  		// we set the charset to the last option. example: alter causet t charset latin1 charset utf8 defCauslate utf8_bin;
  2143  		// the charset will be utf8, defCauslate will be utf8_bin
  2144  		switch opt.Tp {
  2145  		case ast.TableOptionCharset:
  2146  			info, err := charset.GetCharsetDesc(opt.StrValue)
  2147  			if err != nil {
  2148  				return "", "", err
  2149  			}
  2150  			if len(chs) == 0 {
  2151  				chs = info.Name
  2152  			} else if chs != info.Name {
  2153  				return "", "", ErrConflictingDeclarations.GenWithStackByArgs(chs, info.Name)
  2154  			}
  2155  			if len(defCausl) == 0 {
  2156  				defCausl = info.DefaultDefCauslation
  2157  			}
  2158  		case ast.TableOptionDefCauslate:
  2159  			info, err := defCauslate.GetDefCauslationByName(opt.StrValue)
  2160  			if err != nil {
  2161  				return "", "", err
  2162  			}
  2163  			if len(chs) == 0 {
  2164  				chs = info.CharsetName
  2165  			} else if chs != info.CharsetName {
  2166  				return "", "", ErrDefCauslationCharsetMismatch.GenWithStackByArgs(info.Name, chs)
  2167  			}
  2168  			defCausl = info.Name
  2169  		}
  2170  	}
  2171  	return
  2172  }
  2173  
  2174  func needToOverwriteDefCausCharset(options []*ast.TableOption) bool {
  2175  	for i := len(options) - 1; i >= 0; i-- {
  2176  		opt := options[i]
  2177  		switch opt.Tp {
  2178  		case ast.TableOptionCharset:
  2179  			// Only overwrite defCausumns charset if the option contains `CONVERT TO`.
  2180  			return opt.UintValue == ast.TableOptionCharsetWithConvertTo
  2181  		}
  2182  	}
  2183  	return false
  2184  }
  2185  
  2186  // resolveAlterTableSpec resolves alter causet algorithm and removes ignore causet spec in specs.
  2187  // returns valied specs, and the occurred error.
  2188  func resolveAlterTableSpec(ctx stochastikctx.Context, specs []*ast.AlterTableSpec) ([]*ast.AlterTableSpec, error) {
  2189  	validSpecs := make([]*ast.AlterTableSpec, 0, len(specs))
  2190  	algorithm := ast.AlgorithmTypeDefault
  2191  	for _, spec := range specs {
  2192  		if spec.Tp == ast.AlterTableAlgorithm {
  2193  			// Find the last AlterTableAlgorithm.
  2194  			algorithm = spec.Algorithm
  2195  		}
  2196  		if isIgnorableSpec(spec.Tp) {
  2197  			continue
  2198  		}
  2199  		validSpecs = append(validSpecs, spec)
  2200  	}
  2201  
  2202  	// Verify whether the algorithm is supported.
  2203  	for _, spec := range validSpecs {
  2204  		resolvedAlgorithm, err := ResolveAlterAlgorithm(spec, algorithm)
  2205  		if err != nil {
  2206  			// If MilevaDB failed to choose a better algorithm, report the error
  2207  			if resolvedAlgorithm == ast.AlgorithmTypeDefault {
  2208  				return nil, errors.Trace(err)
  2209  			}
  2210  			// For the compatibility, we return warning instead of error when a better algorithm is chosed by MilevaDB
  2211  			ctx.GetStochastikVars().StmtCtx.AppendError(err)
  2212  		}
  2213  
  2214  		spec.Algorithm = resolvedAlgorithm
  2215  	}
  2216  
  2217  	// Only handle valid specs.
  2218  	return validSpecs, nil
  2219  }
  2220  
  2221  func isSameTypeMultiSpecs(specs []*ast.AlterTableSpec) bool {
  2222  	specType := specs[0].Tp
  2223  	for _, spec := range specs {
  2224  		if spec.Tp != specType {
  2225  			return false
  2226  		}
  2227  	}
  2228  	return true
  2229  }
  2230  
  2231  func (d *dbs) AlterTable(ctx stochastikctx.Context, ident ast.Ident, specs []*ast.AlterTableSpec) (err error) {
  2232  	validSpecs, err := resolveAlterTableSpec(ctx, specs)
  2233  	if err != nil {
  2234  		return errors.Trace(err)
  2235  	}
  2236  
  2237  	is := d.infoHandle.Get()
  2238  	if is.TableIsView(ident.Schema, ident.Name) || is.TableIsSequence(ident.Schema, ident.Name) {
  2239  		return ErrWrongObject.GenWithStackByArgs(ident.Schema, ident.Name, "BASE TABLE")
  2240  	}
  2241  
  2242  	if len(validSpecs) > 1 {
  2243  		if isSameTypeMultiSpecs(validSpecs) {
  2244  			switch validSpecs[0].Tp {
  2245  			case ast.AlterTableAddDeferredCausets:
  2246  				err = d.AddDeferredCausets(ctx, ident, validSpecs)
  2247  			case ast.AlterTableDropDeferredCauset:
  2248  				err = d.DropDeferredCausets(ctx, ident, validSpecs)
  2249  			default:
  2250  				return errRunMultiSchemaChanges
  2251  			}
  2252  			if err != nil {
  2253  				return errors.Trace(err)
  2254  			}
  2255  			return nil
  2256  		}
  2257  		return errRunMultiSchemaChanges
  2258  	}
  2259  
  2260  	for _, spec := range validSpecs {
  2261  		var handledCharsetOrDefCauslate bool
  2262  		switch spec.Tp {
  2263  		case ast.AlterTableAddDeferredCausets:
  2264  			if len(spec.NewDeferredCausets) != 1 {
  2265  				err = d.AddDeferredCausets(ctx, ident, []*ast.AlterTableSpec{spec})
  2266  			} else {
  2267  				err = d.AddDeferredCauset(ctx, ident, spec)
  2268  			}
  2269  		case ast.AlterTableAddPartitions:
  2270  			err = d.AddTablePartitions(ctx, ident, spec)
  2271  		case ast.AlterTableCoalescePartitions:
  2272  			err = d.CoalescePartitions(ctx, ident, spec)
  2273  		case ast.AlterTableReorganizePartition:
  2274  			err = errors.Trace(errUnsupportedReorganizePartition)
  2275  		case ast.AlterTableCheckPartitions:
  2276  			err = errors.Trace(errUnsupportedCheckPartition)
  2277  		case ast.AlterTableRebuildPartition:
  2278  			err = errors.Trace(errUnsupportedRebuildPartition)
  2279  		case ast.AlterTableOptimizePartition:
  2280  			err = errors.Trace(errUnsupportedOptimizePartition)
  2281  		case ast.AlterTableRemovePartitioning:
  2282  			err = errors.Trace(errUnsupportedRemovePartition)
  2283  		case ast.AlterTableRepairPartition:
  2284  			err = errors.Trace(errUnsupportedRepairPartition)
  2285  		case ast.AlterTableDropDeferredCauset:
  2286  			err = d.DropDeferredCauset(ctx, ident, spec)
  2287  		case ast.AlterTableDropIndex:
  2288  			err = d.DropIndex(ctx, ident, perceptron.NewCIStr(spec.Name), spec.IfExists)
  2289  		case ast.AlterTableDropPrimaryKey:
  2290  			err = d.DropIndex(ctx, ident, perceptron.NewCIStr(allegrosql.PrimaryKeyName), spec.IfExists)
  2291  		case ast.AlterTableRenameIndex:
  2292  			err = d.RenameIndex(ctx, ident, spec)
  2293  		case ast.AlterTableDropPartition:
  2294  			err = d.DropTablePartition(ctx, ident, spec)
  2295  		case ast.AlterTableTruncatePartition:
  2296  			err = d.TruncateTablePartition(ctx, ident, spec)
  2297  		case ast.AlterTableExchangePartition:
  2298  			err = d.ExchangeTablePartition(ctx, ident, spec)
  2299  		case ast.AlterTableAddConstraint:
  2300  			constr := spec.Constraint
  2301  			switch spec.Constraint.Tp {
  2302  			case ast.ConstraintKey, ast.ConstraintIndex:
  2303  				err = d.CreateIndex(ctx, ident, ast.IndexKeyTypeNone, perceptron.NewCIStr(constr.Name),
  2304  					spec.Constraint.Keys, constr.Option, constr.IfNotExists)
  2305  			case ast.ConstraintUniq, ast.ConstraintUniqIndex, ast.ConstraintUniqKey:
  2306  				err = d.CreateIndex(ctx, ident, ast.IndexKeyTypeUnique, perceptron.NewCIStr(constr.Name),
  2307  					spec.Constraint.Keys, constr.Option, false) // IfNotExists should be not applied
  2308  			case ast.ConstraintForeignKey:
  2309  				// NOTE: we do not handle `symbol` and `index_name` well in the BerolinaSQL and we do not check ForeignKey already exists,
  2310  				// so we just also ignore the `if not exists` check.
  2311  				err = d.CreateForeignKey(ctx, ident, perceptron.NewCIStr(constr.Name), spec.Constraint.Keys, spec.Constraint.Refer)
  2312  			case ast.ConstraintPrimaryKey:
  2313  				err = d.CreatePrimaryKey(ctx, ident, perceptron.NewCIStr(constr.Name), spec.Constraint.Keys, constr.Option)
  2314  			case ast.ConstraintFulltext:
  2315  				ctx.GetStochastikVars().StmtCtx.AppendWarning(ErrTableCantHandleFt)
  2316  			case ast.ConstraintCheck:
  2317  				ctx.GetStochastikVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("ADD CONSTRAINT CHECK"))
  2318  			default:
  2319  				// Nothing to do now.
  2320  			}
  2321  		case ast.AlterTableDropForeignKey:
  2322  			// NOTE: we do not check `if not exists` and `if exists` for ForeignKey now.
  2323  			err = d.DropForeignKey(ctx, ident, perceptron.NewCIStr(spec.Name))
  2324  		case ast.AlterTableModifyDeferredCauset:
  2325  			err = d.ModifyDeferredCauset(ctx, ident, spec)
  2326  		case ast.AlterTableChangeDeferredCauset:
  2327  			err = d.ChangeDeferredCauset(ctx, ident, spec)
  2328  		case ast.AlterTableRenameDeferredCauset:
  2329  			err = d.RenameDeferredCauset(ctx, ident, spec)
  2330  		case ast.AlterTableAlterDeferredCauset:
  2331  			err = d.AlterDeferredCauset(ctx, ident, spec)
  2332  		case ast.AlterTableRenameTable:
  2333  			newIdent := ast.Ident{Schema: spec.NewTable.Schema, Name: spec.NewTable.Name}
  2334  			isAlterTable := true
  2335  			err = d.RenameTable(ctx, ident, newIdent, isAlterTable)
  2336  		case ast.AlterTableAlterPartition:
  2337  			err = d.AlterTablePartition(ctx, ident, spec)
  2338  		case ast.AlterTablePartition:
  2339  			// Prevent silent succeed if user executes ALTER TABLE x PARTITION BY ...
  2340  			err = errors.New("alter causet partition is unsupported")
  2341  		case ast.AlterTableOption:
  2342  			for i, opt := range spec.Options {
  2343  				switch opt.Tp {
  2344  				case ast.TableOptionShardRowID:
  2345  					if opt.UintValue > shardRowIDBitsMax {
  2346  						opt.UintValue = shardRowIDBitsMax
  2347  					}
  2348  					err = d.ShardRowID(ctx, ident, opt.UintValue)
  2349  				case ast.TableOptionAutoIncrement:
  2350  					err = d.RebaseAutoID(ctx, ident, int64(opt.UintValue), autoid.RowIDAllocType)
  2351  				case ast.TableOptionAutoIdCache:
  2352  					if opt.UintValue > uint64(math.MaxInt64) {
  2353  						// TODO: Refine this error.
  2354  						return errors.New("causet option auto_id_cache overflows int64")
  2355  					}
  2356  					err = d.AlterTableAutoIDCache(ctx, ident, int64(opt.UintValue))
  2357  				case ast.TableOptionAutoRandomBase:
  2358  					err = d.RebaseAutoID(ctx, ident, int64(opt.UintValue), autoid.AutoRandomType)
  2359  				case ast.TableOptionComment:
  2360  					spec.Comment = opt.StrValue
  2361  					err = d.AlterTableComment(ctx, ident, spec)
  2362  				case ast.TableOptionCharset, ast.TableOptionDefCauslate:
  2363  					// getCharsetAndDefCauslateInTableOption will get the last charset and defCauslate in the options,
  2364  					// so it should be handled only once.
  2365  					if handledCharsetOrDefCauslate {
  2366  						continue
  2367  					}
  2368  					var toCharset, toDefCauslate string
  2369  					toCharset, toDefCauslate, err = getCharsetAndDefCauslateInTableOption(i, spec.Options)
  2370  					if err != nil {
  2371  						return err
  2372  					}
  2373  					needsOverwriteDefCauss := needToOverwriteDefCausCharset(spec.Options)
  2374  					err = d.AlterTableCharsetAndDefCauslate(ctx, ident, toCharset, toDefCauslate, needsOverwriteDefCauss)
  2375  					handledCharsetOrDefCauslate = true
  2376  				}
  2377  
  2378  				if err != nil {
  2379  					return errors.Trace(err)
  2380  				}
  2381  			}
  2382  		case ast.AlterTableSetTiFlashReplica:
  2383  			err = d.AlterTableSetTiFlashReplica(ctx, ident, spec.TiFlashReplica)
  2384  		case ast.AlterTableOrderByDeferredCausets:
  2385  			err = d.OrderByDeferredCausets(ctx, ident)
  2386  		case ast.AlterTableIndexInvisible:
  2387  			err = d.AlterIndexVisibility(ctx, ident, spec.IndexName, spec.Visibility)
  2388  		case ast.AlterTableAlterCheck:
  2389  			ctx.GetStochastikVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("ALTER CHECK"))
  2390  		case ast.AlterTableDropCheck:
  2391  			ctx.GetStochastikVars().StmtCtx.AppendWarning(ErrUnsupportedConstraintCheck.GenWithStackByArgs("DROP CHECK"))
  2392  		case ast.AlterTableWithValidation:
  2393  			ctx.GetStochastikVars().StmtCtx.AppendWarning(errUnsupportedAlterTableWithValidation)
  2394  		case ast.AlterTableWithoutValidation:
  2395  			ctx.GetStochastikVars().StmtCtx.AppendWarning(errUnsupportedAlterTableWithoutValidation)
  2396  		default:
  2397  			// Nothing to do now.
  2398  		}
  2399  
  2400  		if err != nil {
  2401  			return errors.Trace(err)
  2402  		}
  2403  	}
  2404  
  2405  	return nil
  2406  }
  2407  
  2408  func (d *dbs) RebaseAutoID(ctx stochastikctx.Context, ident ast.Ident, newBase int64, tp autoid.SlabPredictorType) error {
  2409  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ident)
  2410  	if err != nil {
  2411  		return errors.Trace(err)
  2412  	}
  2413  	var actionType perceptron.CausetActionType
  2414  	switch tp {
  2415  	case autoid.AutoRandomType:
  2416  		tbInfo := t.Meta()
  2417  		if tbInfo.AutoRandomBits == 0 {
  2418  			return errors.Trace(ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomRebaseNotApplicable))
  2419  		}
  2420  		var autoRandDefCausTp types.FieldType
  2421  		for _, c := range tbInfo.DeferredCausets {
  2422  			if allegrosql.HasPriKeyFlag(c.Flag) {
  2423  				autoRandDefCausTp = c.FieldType
  2424  				break
  2425  			}
  2426  		}
  2427  		layout := autoid.NewAutoRandomIDLayout(&autoRandDefCausTp, tbInfo.AutoRandomBits)
  2428  		if layout.IncrementalMask()&newBase != newBase {
  2429  			errMsg := fmt.Sprintf(autoid.AutoRandomRebaseOverflow, newBase, layout.IncrementalBitsCapacity())
  2430  			return errors.Trace(ErrInvalidAutoRandom.GenWithStackByArgs(errMsg))
  2431  		}
  2432  		actionType = perceptron.CausetActionRebaseAutoRandomBase
  2433  	case autoid.RowIDAllocType:
  2434  		actionType = perceptron.CausetActionRebaseAutoID
  2435  	}
  2436  
  2437  	if alloc := t.SlabPredictors(ctx).Get(tp); alloc != nil {
  2438  		autoID, err := alloc.NextGlobalAutoID(t.Meta().ID)
  2439  		if err != nil {
  2440  			return errors.Trace(err)
  2441  		}
  2442  		// If newBase < autoID, we need to do a rebase before returning.
  2443  		// Assume there are 2 MilevaDB servers: MilevaDB-A with allocator range of 0 ~ 30000; MilevaDB-B with allocator range of 30001 ~ 60000.
  2444  		// If the user sends ALLEGROALLEGROSQL `alter causet t1 auto_increment = 100` to MilevaDB-B,
  2445  		// and MilevaDB-B finds 100 < 30001 but returns without any handling,
  2446  		// then MilevaDB-A may still allocate 99 for auto_increment defCausumn. This doesn't make sense for the user.
  2447  		newBase = int64(mathutil.MaxUint64(uint64(newBase), uint64(autoID)))
  2448  	}
  2449  	job := &perceptron.Job{
  2450  		SchemaID:   schemaReplicant.ID,
  2451  		TableID:    t.Meta().ID,
  2452  		SchemaName: schemaReplicant.Name.L,
  2453  		Type:       actionType,
  2454  		BinlogInfo: &perceptron.HistoryInfo{},
  2455  		Args:       []interface{}{newBase},
  2456  	}
  2457  	err = d.doDBSJob(ctx, job)
  2458  	err = d.callHookOnChanged(err)
  2459  	return errors.Trace(err)
  2460  }
  2461  
  2462  // ShardRowID shards the implicit event ID by adding shard value to the event ID's first few bits.
  2463  func (d *dbs) ShardRowID(ctx stochastikctx.Context, blockIdent ast.Ident, uVal uint64) error {
  2464  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, blockIdent)
  2465  	if err != nil {
  2466  		return errors.Trace(err)
  2467  	}
  2468  	if uVal == t.Meta().ShardRowIDBits {
  2469  		// Nothing need to do.
  2470  		return nil
  2471  	}
  2472  	if uVal > 0 && t.Meta().PKIsHandle {
  2473  		return errUnsupportedShardRowIDBits
  2474  	}
  2475  	err = verifyNoOverflowShardBits(d.sessPool, t, uVal)
  2476  	if err != nil {
  2477  		return err
  2478  	}
  2479  	job := &perceptron.Job{
  2480  		Type:       perceptron.CausetActionShardRowID,
  2481  		SchemaID:   schemaReplicant.ID,
  2482  		TableID:    t.Meta().ID,
  2483  		SchemaName: schemaReplicant.Name.L,
  2484  		BinlogInfo: &perceptron.HistoryInfo{},
  2485  		Args:       []interface{}{uVal},
  2486  	}
  2487  	err = d.doDBSJob(ctx, job)
  2488  	err = d.callHookOnChanged(err)
  2489  	return errors.Trace(err)
  2490  }
  2491  
  2492  func (d *dbs) getSchemaAndTableByIdent(ctx stochastikctx.Context, blockIdent ast.Ident) (dbInfo *perceptron.DBInfo, t causet.Block, err error) {
  2493  	is := d.GetSchemaReplicantWithInterceptor(ctx)
  2494  	schemaReplicant, ok := is.SchemaByName(blockIdent.Schema)
  2495  	if !ok {
  2496  		return nil, nil, schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(blockIdent.Schema)
  2497  	}
  2498  	t, err = is.TableByName(blockIdent.Schema, blockIdent.Name)
  2499  	if err != nil {
  2500  		return nil, nil, schemareplicant.ErrTableNotExists.GenWithStackByArgs(blockIdent.Schema, blockIdent.Name)
  2501  	}
  2502  	return schemaReplicant, t, nil
  2503  }
  2504  
  2505  func checkUnsupportedDeferredCausetConstraint(defCaus *ast.DeferredCausetDef, ti ast.Ident) error {
  2506  	for _, constraint := range defCaus.Options {
  2507  		switch constraint.Tp {
  2508  		case ast.DeferredCausetOptionAutoIncrement:
  2509  			return errUnsupportedAddDeferredCauset.GenWithStack("unsupported add defCausumn '%s' constraint AUTO_INCREMENT when altering '%s.%s'", defCaus.Name, ti.Schema, ti.Name)
  2510  		case ast.DeferredCausetOptionPrimaryKey:
  2511  			return errUnsupportedAddDeferredCauset.GenWithStack("unsupported add defCausumn '%s' constraint PRIMARY KEY when altering '%s.%s'", defCaus.Name, ti.Schema, ti.Name)
  2512  		case ast.DeferredCausetOptionUniqKey:
  2513  			return errUnsupportedAddDeferredCauset.GenWithStack("unsupported add defCausumn '%s' constraint UNIQUE KEY when altering '%s.%s'", defCaus.Name, ti.Schema, ti.Name)
  2514  		case ast.DeferredCausetOptionAutoRandom:
  2515  			errMsg := fmt.Sprintf(autoid.AutoRandomAlterAddDeferredCauset, defCaus.Name, ti.Schema, ti.Name)
  2516  			return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)
  2517  		}
  2518  	}
  2519  
  2520  	return nil
  2521  }
  2522  
  2523  func checkAndCreateNewDeferredCauset(ctx stochastikctx.Context, ti ast.Ident, schemaReplicant *perceptron.DBInfo, spec *ast.AlterTableSpec, t causet.Block, specNewDeferredCauset *ast.DeferredCausetDef) (*causet.DeferredCauset, error) {
  2524  	err := checkUnsupportedDeferredCausetConstraint(specNewDeferredCauset, ti)
  2525  	if err != nil {
  2526  		return nil, errors.Trace(err)
  2527  	}
  2528  
  2529  	defCausName := specNewDeferredCauset.Name.Name.O
  2530  	// Check whether added defCausumn has existed.
  2531  	defCaus := causet.FindDefCaus(t.DefCauss(), defCausName)
  2532  	if defCaus != nil {
  2533  		err = schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(defCausName)
  2534  		if spec.IfNotExists {
  2535  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2536  			return nil, nil
  2537  		}
  2538  		return nil, err
  2539  	}
  2540  	if err = checkDeferredCausetAttributes(defCausName, specNewDeferredCauset.Tp); err != nil {
  2541  		return nil, errors.Trace(err)
  2542  	}
  2543  	if len(defCausName) > allegrosql.MaxDeferredCausetNameLength {
  2544  		return nil, ErrTooLongIdent.GenWithStackByArgs(defCausName)
  2545  	}
  2546  
  2547  	// If new defCausumn is a generated defCausumn, do validation.
  2548  	// NOTE: we do check whether the defCausumn refers other generated
  2549  	// defCausumns occurring later in a causet, but we don't handle the defCaus offset.
  2550  	for _, option := range specNewDeferredCauset.Options {
  2551  		if option.Tp == ast.DeferredCausetOptionGenerated {
  2552  			if err := checkIllegalFn4GeneratedDeferredCauset(specNewDeferredCauset.Name.Name.L, option.Expr); err != nil {
  2553  				return nil, errors.Trace(err)
  2554  			}
  2555  
  2556  			if option.Stored {
  2557  				return nil, ErrUnsupportedOnGeneratedDeferredCauset.GenWithStackByArgs("Adding generated stored defCausumn through ALTER TABLE")
  2558  			}
  2559  
  2560  			_, dependDefCausNames := findDependedDeferredCausetNames(specNewDeferredCauset)
  2561  			if err = checkAutoIncrementRef(specNewDeferredCauset.Name.Name.L, dependDefCausNames, t.Meta()); err != nil {
  2562  				return nil, errors.Trace(err)
  2563  			}
  2564  			duplicateDefCausNames := make(map[string]struct{}, len(dependDefCausNames))
  2565  			for k := range dependDefCausNames {
  2566  				duplicateDefCausNames[k] = struct{}{}
  2567  			}
  2568  			defcaus := t.DefCauss()
  2569  
  2570  			if err = checkDependedDefCausExist(dependDefCausNames, defcaus); err != nil {
  2571  				return nil, errors.Trace(err)
  2572  			}
  2573  
  2574  			if err = verifyDeferredCausetGenerationSingle(duplicateDefCausNames, defcaus, spec.Position); err != nil {
  2575  				return nil, errors.Trace(err)
  2576  			}
  2577  		}
  2578  		// Specially, since sequence has been supported, if a newly added defCausumn has a
  2579  		// sequence nextval function as it's default value option, it won't fill the
  2580  		// known rows with specific sequence next value under current add defCausumn logic.
  2581  		// More explanation can refer: TestSequenceDefaultLogic's comment in sequence_test.go
  2582  		if option.Tp == ast.DeferredCausetOptionDefaultValue {
  2583  			_, isSeqExpr, err := tryToGetSequenceDefaultValue(option)
  2584  			if err != nil {
  2585  				return nil, errors.Trace(err)
  2586  			}
  2587  			if isSeqExpr {
  2588  				return nil, errors.Trace(ErrAddDeferredCausetWithSequenceAsDefault.GenWithStackByArgs(specNewDeferredCauset.Name.Name.O))
  2589  			}
  2590  		}
  2591  	}
  2592  
  2593  	blockCharset, blockDefCauslate, err := ResolveCharsetDefCauslation(
  2594  		ast.CharsetOpt{Chs: t.Meta().Charset, DefCaus: t.Meta().DefCauslate},
  2595  		ast.CharsetOpt{Chs: schemaReplicant.Charset, DefCaus: schemaReplicant.DefCauslate},
  2596  	)
  2597  	if err != nil {
  2598  		return nil, errors.Trace(err)
  2599  	}
  2600  	// Ignore causet constraints now, they will be checked later.
  2601  	// We use length(t.DefCauss()) as the default offset firstly, we will change the defCausumn's offset later.
  2602  	defCaus, _, err = buildDeferredCausetAndConstraint(
  2603  		ctx,
  2604  		len(t.DefCauss()),
  2605  		specNewDeferredCauset,
  2606  		nil,
  2607  		blockCharset,
  2608  		blockDefCauslate,
  2609  	)
  2610  	if err != nil {
  2611  		return nil, errors.Trace(err)
  2612  	}
  2613  
  2614  	defCaus.OriginDefaultValue, err = generateOriginDefaultValue(defCaus.ToInfo())
  2615  	if err != nil {
  2616  		return nil, errors.Trace(err)
  2617  	}
  2618  	return defCaus, nil
  2619  }
  2620  
  2621  // AddDeferredCauset will add a new defCausumn to the causet.
  2622  func (d *dbs) AddDeferredCauset(ctx stochastikctx.Context, ti ast.Ident, spec *ast.AlterTableSpec) error {
  2623  	specNewDeferredCauset := spec.NewDeferredCausets[0]
  2624  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ti)
  2625  	if err != nil {
  2626  		return errors.Trace(err)
  2627  	}
  2628  	if err = checkAddDeferredCausetTooManyDeferredCausets(len(t.DefCauss()) + 1); err != nil {
  2629  		return errors.Trace(err)
  2630  	}
  2631  	defCaus, err := checkAndCreateNewDeferredCauset(ctx, ti, schemaReplicant, spec, t, specNewDeferredCauset)
  2632  	if err != nil {
  2633  		return errors.Trace(err)
  2634  	}
  2635  	// Added defCausumn has existed and if_not_exists flag is true.
  2636  	if defCaus == nil {
  2637  		return nil
  2638  	}
  2639  
  2640  	job := &perceptron.Job{
  2641  		SchemaID:   schemaReplicant.ID,
  2642  		TableID:    t.Meta().ID,
  2643  		SchemaName: schemaReplicant.Name.L,
  2644  		Type:       perceptron.CausetActionAddDeferredCauset,
  2645  		BinlogInfo: &perceptron.HistoryInfo{},
  2646  		Args:       []interface{}{defCaus, spec.Position, 0},
  2647  	}
  2648  
  2649  	err = d.doDBSJob(ctx, job)
  2650  	// defCausumn exists, but if_not_exists flags is true, so we ignore this error.
  2651  	if schemareplicant.ErrDeferredCausetExists.Equal(err) && spec.IfNotExists {
  2652  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2653  		return nil
  2654  	}
  2655  	err = d.callHookOnChanged(err)
  2656  	return errors.Trace(err)
  2657  }
  2658  
  2659  // AddDeferredCausets will add multi new defCausumns to the causet.
  2660  func (d *dbs) AddDeferredCausets(ctx stochastikctx.Context, ti ast.Ident, specs []*ast.AlterTableSpec) error {
  2661  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ti)
  2662  	if err != nil {
  2663  		return errors.Trace(err)
  2664  	}
  2665  
  2666  	// Check all the defCausumns at once.
  2667  	addingDeferredCausetNames := make(map[string]bool)
  2668  	dupDeferredCausetNames := make(map[string]bool)
  2669  	for _, spec := range specs {
  2670  		for _, specNewDeferredCauset := range spec.NewDeferredCausets {
  2671  			if !addingDeferredCausetNames[specNewDeferredCauset.Name.Name.L] {
  2672  				addingDeferredCausetNames[specNewDeferredCauset.Name.Name.L] = true
  2673  				continue
  2674  			}
  2675  			if !spec.IfNotExists {
  2676  				return errors.Trace(schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(specNewDeferredCauset.Name.Name.O))
  2677  			}
  2678  			dupDeferredCausetNames[specNewDeferredCauset.Name.Name.L] = true
  2679  		}
  2680  	}
  2681  	defCausumns := make([]*causet.DeferredCauset, 0, len(addingDeferredCausetNames))
  2682  	positions := make([]*ast.DeferredCausetPosition, 0, len(addingDeferredCausetNames))
  2683  	offsets := make([]int, 0, len(addingDeferredCausetNames))
  2684  	ifNotExists := make([]bool, 0, len(addingDeferredCausetNames))
  2685  	newDeferredCausetsCount := 0
  2686  	// Check the defCausumns one by one.
  2687  	for _, spec := range specs {
  2688  		for _, specNewDeferredCauset := range spec.NewDeferredCausets {
  2689  			if spec.IfNotExists && dupDeferredCausetNames[specNewDeferredCauset.Name.Name.L] {
  2690  				err = schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(specNewDeferredCauset.Name.Name.O)
  2691  				ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2692  				continue
  2693  			}
  2694  			defCaus, err := checkAndCreateNewDeferredCauset(ctx, ti, schemaReplicant, spec, t, specNewDeferredCauset)
  2695  			if err != nil {
  2696  				return errors.Trace(err)
  2697  			}
  2698  			// Added defCausumn has existed and if_not_exists flag is true.
  2699  			if defCaus == nil && spec.IfNotExists {
  2700  				continue
  2701  			}
  2702  			defCausumns = append(defCausumns, defCaus)
  2703  			positions = append(positions, spec.Position)
  2704  			offsets = append(offsets, 0)
  2705  			ifNotExists = append(ifNotExists, spec.IfNotExists)
  2706  			newDeferredCausetsCount++
  2707  		}
  2708  	}
  2709  	if newDeferredCausetsCount == 0 {
  2710  		return nil
  2711  	}
  2712  	if err = checkAddDeferredCausetTooManyDeferredCausets(len(t.DefCauss()) + newDeferredCausetsCount); err != nil {
  2713  		return errors.Trace(err)
  2714  	}
  2715  
  2716  	job := &perceptron.Job{
  2717  		SchemaID:   schemaReplicant.ID,
  2718  		TableID:    t.Meta().ID,
  2719  		SchemaName: schemaReplicant.Name.L,
  2720  		Type:       perceptron.CausetActionAddDeferredCausets,
  2721  		BinlogInfo: &perceptron.HistoryInfo{},
  2722  		Args:       []interface{}{defCausumns, positions, offsets, ifNotExists},
  2723  	}
  2724  
  2725  	err = d.doDBSJob(ctx, job)
  2726  	if err != nil {
  2727  		return errors.Trace(err)
  2728  	}
  2729  	err = d.callHookOnChanged(err)
  2730  	return errors.Trace(err)
  2731  }
  2732  
  2733  // AddTablePartitions will add a new partition to the causet.
  2734  func (d *dbs) AddTablePartitions(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  2735  	is := d.infoHandle.Get()
  2736  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  2737  	if !ok {
  2738  		return errors.Trace(schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(schemaReplicant))
  2739  	}
  2740  	t, err := is.TableByName(ident.Schema, ident.Name)
  2741  	if err != nil {
  2742  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  2743  	}
  2744  
  2745  	spacetime := t.Meta()
  2746  	pi := spacetime.GetPartitionInfo()
  2747  	if pi == nil {
  2748  		return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
  2749  	}
  2750  
  2751  	partInfo, err := buildPartitionInfo(ctx, spacetime, d, spec)
  2752  	if err != nil {
  2753  		return errors.Trace(err)
  2754  	}
  2755  
  2756  	// partInfo contains only the new added partition, we have to combine it with the
  2757  	// old partitions to check all partitions is strictly increasing.
  2758  	tmp := *partInfo
  2759  	tmp.Definitions = append(pi.Definitions, tmp.Definitions...)
  2760  	spacetime.Partition = &tmp
  2761  	err = checkPartitionByRange(ctx, spacetime, nil)
  2762  	spacetime.Partition = pi
  2763  	if err != nil {
  2764  		if ErrSameNamePartition.Equal(err) && spec.IfNotExists {
  2765  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2766  			return nil
  2767  		}
  2768  		return errors.Trace(err)
  2769  	}
  2770  
  2771  	job := &perceptron.Job{
  2772  		SchemaID:   schemaReplicant.ID,
  2773  		TableID:    spacetime.ID,
  2774  		SchemaName: schemaReplicant.Name.L,
  2775  		Type:       perceptron.CausetActionAddTablePartition,
  2776  		BinlogInfo: &perceptron.HistoryInfo{},
  2777  		Args:       []interface{}{partInfo},
  2778  	}
  2779  
  2780  	err = d.doDBSJob(ctx, job)
  2781  	if ErrSameNamePartition.Equal(err) && spec.IfNotExists {
  2782  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2783  		return nil
  2784  	}
  2785  	if err == nil {
  2786  		d.preSplitAndScatter(ctx, spacetime, partInfo)
  2787  	}
  2788  	err = d.callHookOnChanged(err)
  2789  	return errors.Trace(err)
  2790  }
  2791  
  2792  // CoalescePartitions coalesce partitions can be used with a causet that is partitioned by hash or key to reduce the number of partitions by number.
  2793  func (d *dbs) CoalescePartitions(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  2794  	is := d.infoHandle.Get()
  2795  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  2796  	if !ok {
  2797  		return errors.Trace(schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(schemaReplicant))
  2798  	}
  2799  	t, err := is.TableByName(ident.Schema, ident.Name)
  2800  	if err != nil {
  2801  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  2802  	}
  2803  
  2804  	spacetime := t.Meta()
  2805  	if spacetime.GetPartitionInfo() == nil {
  2806  		return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
  2807  	}
  2808  
  2809  	switch spacetime.Partition.Type {
  2810  	// We don't support coalesce partitions hash type partition now.
  2811  	case perceptron.PartitionTypeHash:
  2812  		return errors.Trace(ErrUnsupportedCoalescePartition)
  2813  
  2814  	// Key type partition cannot be constructed currently, ignoring it for now.
  2815  	case perceptron.PartitionTypeKey:
  2816  
  2817  	// Coalesce partition can only be used on hash/key partitions.
  2818  	default:
  2819  		return errors.Trace(ErrCoalesceOnlyOnHashPartition)
  2820  	}
  2821  
  2822  	return errors.Trace(err)
  2823  }
  2824  
  2825  func (d *dbs) TruncateTablePartition(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  2826  	is := d.infoHandle.Get()
  2827  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  2828  	if !ok {
  2829  		return errors.Trace(schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(schemaReplicant))
  2830  	}
  2831  	t, err := is.TableByName(ident.Schema, ident.Name)
  2832  	if err != nil {
  2833  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  2834  	}
  2835  	spacetime := t.Meta()
  2836  	if spacetime.GetPartitionInfo() == nil {
  2837  		return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
  2838  	}
  2839  
  2840  	pids := make([]int64, len(spec.PartitionNames))
  2841  	for i, name := range spec.PartitionNames {
  2842  		pid, err := blocks.FindPartitionByName(spacetime, name.L)
  2843  		if err != nil {
  2844  			return errors.Trace(err)
  2845  		}
  2846  		pids[i] = pid
  2847  	}
  2848  
  2849  	job := &perceptron.Job{
  2850  		SchemaID:   schemaReplicant.ID,
  2851  		TableID:    spacetime.ID,
  2852  		SchemaName: schemaReplicant.Name.L,
  2853  		Type:       perceptron.CausetActionTruncateTablePartition,
  2854  		BinlogInfo: &perceptron.HistoryInfo{},
  2855  		Args:       []interface{}{pids},
  2856  	}
  2857  
  2858  	err = d.doDBSJob(ctx, job)
  2859  	if err != nil {
  2860  		return errors.Trace(err)
  2861  	}
  2862  	err = d.callHookOnChanged(err)
  2863  	return errors.Trace(err)
  2864  }
  2865  
  2866  func (d *dbs) DropTablePartition(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  2867  	is := d.infoHandle.Get()
  2868  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  2869  	if !ok {
  2870  		return errors.Trace(schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(schemaReplicant))
  2871  	}
  2872  	t, err := is.TableByName(ident.Schema, ident.Name)
  2873  	if err != nil {
  2874  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  2875  	}
  2876  	spacetime := t.Meta()
  2877  	if spacetime.GetPartitionInfo() == nil {
  2878  		return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
  2879  	}
  2880  
  2881  	partNames := make([]string, len(spec.PartitionNames))
  2882  	for i, partCIName := range spec.PartitionNames {
  2883  		partNames[i] = partCIName.L
  2884  	}
  2885  	err = checkDropTablePartition(spacetime, partNames)
  2886  	if err != nil {
  2887  		if ErrDropPartitionNonExistent.Equal(err) && spec.IfExists {
  2888  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2889  			return nil
  2890  		}
  2891  		return errors.Trace(err)
  2892  	}
  2893  
  2894  	job := &perceptron.Job{
  2895  		SchemaID:   schemaReplicant.ID,
  2896  		TableID:    spacetime.ID,
  2897  		SchemaName: schemaReplicant.Name.L,
  2898  		Type:       perceptron.CausetActionDropTablePartition,
  2899  		BinlogInfo: &perceptron.HistoryInfo{},
  2900  		Args:       []interface{}{partNames},
  2901  	}
  2902  
  2903  	err = d.doDBSJob(ctx, job)
  2904  	if err != nil {
  2905  		if ErrDropPartitionNonExistent.Equal(err) && spec.IfExists {
  2906  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  2907  			return nil
  2908  		}
  2909  		return errors.Trace(err)
  2910  	}
  2911  	err = d.callHookOnChanged(err)
  2912  	return errors.Trace(err)
  2913  }
  2914  
  2915  func checkFieldTypeCompatible(ft *types.FieldType, other *types.FieldType) bool {
  2916  	// int(1) could match the type with int(8)
  2917  	partialEqual := ft.Tp == other.Tp &&
  2918  		ft.Decimal == other.Decimal &&
  2919  		ft.Charset == other.Charset &&
  2920  		ft.DefCauslate == other.DefCauslate &&
  2921  		(ft.Flen == other.Flen || ft.StorageLength() != types.VarStorageLen) &&
  2922  		allegrosql.HasUnsignedFlag(ft.Flag) == allegrosql.HasUnsignedFlag(other.Flag) &&
  2923  		allegrosql.HasAutoIncrementFlag(ft.Flag) == allegrosql.HasAutoIncrementFlag(other.Flag) &&
  2924  		allegrosql.HasNotNullFlag(ft.Flag) == allegrosql.HasNotNullFlag(other.Flag) &&
  2925  		allegrosql.HasZerofillFlag(ft.Flag) == allegrosql.HasZerofillFlag(other.Flag) &&
  2926  		allegrosql.HasBinaryFlag(ft.Flag) == allegrosql.HasBinaryFlag(other.Flag) &&
  2927  		allegrosql.HasPriKeyFlag(ft.Flag) == allegrosql.HasPriKeyFlag(other.Flag)
  2928  	if !partialEqual || len(ft.Elems) != len(other.Elems) {
  2929  		return false
  2930  	}
  2931  	for i := range ft.Elems {
  2932  		if ft.Elems[i] != other.Elems[i] {
  2933  			return false
  2934  		}
  2935  	}
  2936  	return true
  2937  }
  2938  
  2939  func checkTiFlashReplicaCompatible(source *perceptron.TiFlashReplicaInfo, target *perceptron.TiFlashReplicaInfo) bool {
  2940  	if source == target {
  2941  		return true
  2942  	}
  2943  	if source == nil || target == nil {
  2944  		return false
  2945  	}
  2946  	if source.Count != target.Count ||
  2947  		source.Available != target.Available || len(source.LocationLabels) != len(target.LocationLabels) {
  2948  		return false
  2949  	}
  2950  	for i, lable := range source.LocationLabels {
  2951  		if target.LocationLabels[i] != lable {
  2952  			return false
  2953  		}
  2954  	}
  2955  	return true
  2956  }
  2957  
  2958  func checkTableDefCompatible(source *perceptron.TableInfo, target *perceptron.TableInfo) error {
  2959  	// check auto_random
  2960  	if source.AutoRandomBits != target.AutoRandomBits ||
  2961  		source.Charset != target.Charset ||
  2962  		source.DefCauslate != target.DefCauslate ||
  2963  		source.ShardRowIDBits != target.ShardRowIDBits ||
  2964  		source.MaxShardRowIDBits != target.MaxShardRowIDBits ||
  2965  		!checkTiFlashReplicaCompatible(source.TiFlashReplica, target.TiFlashReplica) {
  2966  		return errors.Trace(ErrTablesDifferentMetadata)
  2967  	}
  2968  	if len(source.DefCauss()) != len(target.DefCauss()) {
  2969  		return errors.Trace(ErrTablesDifferentMetadata)
  2970  	}
  2971  	// DefCaus compatible check
  2972  	for i, sourceDefCaus := range source.DefCauss() {
  2973  		targetDefCaus := target.DefCauss()[i]
  2974  		if isVirtualGeneratedDeferredCauset(sourceDefCaus) != isVirtualGeneratedDeferredCauset(targetDefCaus) {
  2975  			return ErrUnsupportedOnGeneratedDeferredCauset.GenWithStackByArgs("Exchanging partitions for non-generated defCausumns")
  2976  		}
  2977  		// It should strictyle compare memexs for generated defCausumns
  2978  		if sourceDefCaus.Name.L != targetDefCaus.Name.L ||
  2979  			sourceDefCaus.Hidden != targetDefCaus.Hidden ||
  2980  			!checkFieldTypeCompatible(&sourceDefCaus.FieldType, &targetDefCaus.FieldType) ||
  2981  			sourceDefCaus.GeneratedExprString != targetDefCaus.GeneratedExprString {
  2982  			return errors.Trace(ErrTablesDifferentMetadata)
  2983  		}
  2984  		if sourceDefCaus.State != perceptron.StatePublic ||
  2985  			targetDefCaus.State != perceptron.StatePublic {
  2986  			return errors.Trace(ErrTablesDifferentMetadata)
  2987  		}
  2988  		if sourceDefCaus.ID != targetDefCaus.ID {
  2989  			return ErrPartitionExchangeDifferentOption.GenWithStackByArgs(fmt.Sprintf("defCausumn: %s", sourceDefCaus.Name))
  2990  		}
  2991  	}
  2992  	if len(source.Indices) != len(target.Indices) {
  2993  		return errors.Trace(ErrTablesDifferentMetadata)
  2994  	}
  2995  	for _, sourceIdx := range source.Indices {
  2996  		var compatIdx *perceptron.IndexInfo
  2997  		for _, targetIdx := range target.Indices {
  2998  			if strings.EqualFold(sourceIdx.Name.L, targetIdx.Name.L) {
  2999  				compatIdx = targetIdx
  3000  			}
  3001  		}
  3002  		// No match index
  3003  		if compatIdx == nil {
  3004  			return errors.Trace(ErrTablesDifferentMetadata)
  3005  		}
  3006  		// Index type is not compatible
  3007  		if sourceIdx.Tp != compatIdx.Tp ||
  3008  			sourceIdx.Unique != compatIdx.Unique ||
  3009  			sourceIdx.Primary != compatIdx.Primary {
  3010  			return errors.Trace(ErrTablesDifferentMetadata)
  3011  		}
  3012  		// The index defCausumn
  3013  		if len(sourceIdx.DeferredCausets) != len(compatIdx.DeferredCausets) {
  3014  			return errors.Trace(ErrTablesDifferentMetadata)
  3015  		}
  3016  		for i, sourceIdxDefCaus := range sourceIdx.DeferredCausets {
  3017  			compatIdxDefCaus := compatIdx.DeferredCausets[i]
  3018  			if sourceIdxDefCaus.Length != compatIdxDefCaus.Length ||
  3019  				sourceIdxDefCaus.Name.L != compatIdxDefCaus.Name.L {
  3020  				return errors.Trace(ErrTablesDifferentMetadata)
  3021  			}
  3022  		}
  3023  		if sourceIdx.ID != compatIdx.ID {
  3024  			return ErrPartitionExchangeDifferentOption.GenWithStackByArgs(fmt.Sprintf("index: %s", sourceIdx.Name))
  3025  		}
  3026  	}
  3027  
  3028  	return nil
  3029  }
  3030  
  3031  func checkExchangePartition(pt *perceptron.TableInfo, nt *perceptron.TableInfo) error {
  3032  	if nt.IsView() || nt.IsSequence() {
  3033  		return errors.Trace(ErrCheckNoSuchTable)
  3034  	}
  3035  	if pt.GetPartitionInfo() == nil {
  3036  		return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
  3037  	}
  3038  	if nt.GetPartitionInfo() != nil {
  3039  		return errors.Trace(ErrPartitionExchangePartTable.GenWithStackByArgs(nt.Name))
  3040  	}
  3041  
  3042  	if nt.ForeignKeys != nil {
  3043  		return errors.Trace(ErrPartitionExchangeForeignKey.GenWithStackByArgs(nt.Name))
  3044  	}
  3045  
  3046  	// NOTE: if nt is temporary causet, it should be checked
  3047  	return nil
  3048  }
  3049  
  3050  func (d *dbs) ExchangeTablePartition(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  3051  	ptSchema, pt, err := d.getSchemaAndTableByIdent(ctx, ident)
  3052  	if err != nil {
  3053  		return errors.Trace(err)
  3054  	}
  3055  
  3056  	ptMeta := pt.Meta()
  3057  
  3058  	ntIdent := ast.Ident{Schema: spec.NewTable.Schema, Name: spec.NewTable.Name}
  3059  	ntSchema, nt, err := d.getSchemaAndTableByIdent(ctx, ntIdent)
  3060  	if err != nil {
  3061  		return errors.Trace(err)
  3062  	}
  3063  
  3064  	ntMeta := nt.Meta()
  3065  
  3066  	err = checkExchangePartition(ptMeta, ntMeta)
  3067  	if err != nil {
  3068  		return errors.Trace(err)
  3069  	}
  3070  
  3071  	partName := spec.PartitionNames[0].L
  3072  
  3073  	// NOTE: if pt is subPartitioned, it should be checked
  3074  
  3075  	defID, err := blocks.FindPartitionByName(ptMeta, partName)
  3076  	if err != nil {
  3077  		return errors.Trace(err)
  3078  	}
  3079  
  3080  	err = checkTableDefCompatible(ptMeta, ntMeta)
  3081  	if err != nil {
  3082  		return errors.Trace(err)
  3083  	}
  3084  
  3085  	job := &perceptron.Job{
  3086  		SchemaID:   ntSchema.ID,
  3087  		TableID:    ntMeta.ID,
  3088  		SchemaName: ntSchema.Name.L,
  3089  		Type:       perceptron.CausetActionExchangeTablePartition,
  3090  		BinlogInfo: &perceptron.HistoryInfo{},
  3091  		Args:       []interface{}{defID, ptSchema.ID, ptMeta.ID, partName, spec.WithValidation},
  3092  	}
  3093  
  3094  	err = d.doDBSJob(ctx, job)
  3095  	if err != nil {
  3096  		return errors.Trace(err)
  3097  	}
  3098  	err = d.callHookOnChanged(err)
  3099  	return errors.Trace(err)
  3100  }
  3101  
  3102  // DropDeferredCauset will drop a defCausumn from the causet, now we don't support drop the defCausumn with index covered.
  3103  func (d *dbs) DropDeferredCauset(ctx stochastikctx.Context, ti ast.Ident, spec *ast.AlterTableSpec) error {
  3104  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ti)
  3105  	if err != nil {
  3106  		return errors.Trace(err)
  3107  	}
  3108  
  3109  	isDropable, err := checkIsDroppableDeferredCauset(ctx, t, spec)
  3110  	if err != nil {
  3111  		return err
  3112  	}
  3113  	if !isDropable {
  3114  		return nil
  3115  	}
  3116  	defCausName := spec.OldDeferredCausetName.Name
  3117  
  3118  	job := &perceptron.Job{
  3119  		SchemaID:   schemaReplicant.ID,
  3120  		TableID:    t.Meta().ID,
  3121  		SchemaName: schemaReplicant.Name.L,
  3122  		Type:       perceptron.CausetActionDropDeferredCauset,
  3123  		BinlogInfo: &perceptron.HistoryInfo{},
  3124  		Args:       []interface{}{defCausName},
  3125  	}
  3126  
  3127  	err = d.doDBSJob(ctx, job)
  3128  	// defCausumn not exists, but if_exists flags is true, so we ignore this error.
  3129  	if ErrCantDropFieldOrKey.Equal(err) && spec.IfExists {
  3130  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  3131  		return nil
  3132  	}
  3133  	err = d.callHookOnChanged(err)
  3134  	return errors.Trace(err)
  3135  }
  3136  
  3137  // DropDeferredCausets will drop multi-defCausumns from the causet, now we don't support drop the defCausumn with index covered.
  3138  func (d *dbs) DropDeferredCausets(ctx stochastikctx.Context, ti ast.Ident, specs []*ast.AlterTableSpec) error {
  3139  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ti)
  3140  	if err != nil {
  3141  		return errors.Trace(err)
  3142  	}
  3143  	tblInfo := t.Meta()
  3144  
  3145  	dropingDeferredCausetNames := make(map[string]bool)
  3146  	dupDeferredCausetNames := make(map[string]bool)
  3147  	for _, spec := range specs {
  3148  		if !dropingDeferredCausetNames[spec.OldDeferredCausetName.Name.L] {
  3149  			dropingDeferredCausetNames[spec.OldDeferredCausetName.Name.L] = true
  3150  		} else {
  3151  			if spec.IfExists {
  3152  				dupDeferredCausetNames[spec.OldDeferredCausetName.Name.L] = true
  3153  				continue
  3154  			}
  3155  			return errors.Trace(ErrCantDropFieldOrKey.GenWithStack("defCausumn %s doesn't exist", spec.OldDeferredCausetName.Name.O))
  3156  		}
  3157  	}
  3158  
  3159  	ifExists := make([]bool, 0, len(specs))
  3160  	defCausNames := make([]perceptron.CIStr, 0, len(specs))
  3161  	for _, spec := range specs {
  3162  		if spec.IfExists && dupDeferredCausetNames[spec.OldDeferredCausetName.Name.L] {
  3163  			err = ErrCantDropFieldOrKey.GenWithStack("defCausumn %s doesn't exist", spec.OldDeferredCausetName.Name.L)
  3164  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  3165  			continue
  3166  		}
  3167  		isDropable, err := checkIsDroppableDeferredCauset(ctx, t, spec)
  3168  		if err != nil {
  3169  			return err
  3170  		}
  3171  		// DeferredCauset can't drop and if_exists flag is true.
  3172  		if !isDropable && spec.IfExists {
  3173  			continue
  3174  		}
  3175  		defCausNames = append(defCausNames, spec.OldDeferredCausetName.Name)
  3176  		ifExists = append(ifExists, spec.IfExists)
  3177  	}
  3178  	if len(defCausNames) == 0 {
  3179  		return nil
  3180  	}
  3181  	if len(tblInfo.DeferredCausets) == len(defCausNames) {
  3182  		return ErrCantRemoveAllFields.GenWithStack("can't drop all defCausumns in causet %s",
  3183  			tblInfo.Name)
  3184  	}
  3185  
  3186  	job := &perceptron.Job{
  3187  		SchemaID:   schemaReplicant.ID,
  3188  		TableID:    t.Meta().ID,
  3189  		SchemaName: schemaReplicant.Name.L,
  3190  		Type:       perceptron.CausetActionDropDeferredCausets,
  3191  		BinlogInfo: &perceptron.HistoryInfo{},
  3192  		Args:       []interface{}{defCausNames, ifExists},
  3193  	}
  3194  
  3195  	err = d.doDBSJob(ctx, job)
  3196  	if err != nil {
  3197  		return errors.Trace(err)
  3198  	}
  3199  	err = d.callHookOnChanged(err)
  3200  	return errors.Trace(err)
  3201  }
  3202  
  3203  func checkIsDroppableDeferredCauset(ctx stochastikctx.Context, t causet.Block, spec *ast.AlterTableSpec) (isDrapable bool, err error) {
  3204  	tblInfo := t.Meta()
  3205  	// Check whether dropped defCausumn has existed.
  3206  	defCausName := spec.OldDeferredCausetName.Name
  3207  	defCaus := causet.FindDefCaus(t.VisibleDefCauss(), defCausName.L)
  3208  	if defCaus == nil {
  3209  		err = ErrCantDropFieldOrKey.GenWithStack("defCausumn %s doesn't exist", defCausName)
  3210  		if spec.IfExists {
  3211  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  3212  			return false, nil
  3213  		}
  3214  		return false, err
  3215  	}
  3216  
  3217  	if err = isDroppableDeferredCauset(tblInfo, defCausName); err != nil {
  3218  		return false, errors.Trace(err)
  3219  	}
  3220  	// We don't support dropping defCausumn with PK handle covered now.
  3221  	if defCaus.IsPKHandleDeferredCauset(tblInfo) {
  3222  		return false, errUnsupportedPKHandle
  3223  	}
  3224  	return true, nil
  3225  }
  3226  
  3227  // checkModifyCharsetAndDefCauslation returns error when the charset or defCauslation is not modifiable.
  3228  // needRewriteDefCauslationData is used when trying to modify the defCauslation of a defCausumn, it is true when the defCausumn is with
  3229  // index because index of a string defCausumn is defCauslation-aware.
  3230  func checkModifyCharsetAndDefCauslation(toCharset, toDefCauslate, origCharset, origDefCauslate string, needRewriteDefCauslationData bool) error {
  3231  	if !charset.ValidCharsetAndDefCauslation(toCharset, toDefCauslate) {
  3232  		return ErrUnknownCharacterSet.GenWithStack("Unknown character set: '%s', defCauslation: '%s'", toCharset, toDefCauslate)
  3233  	}
  3234  
  3235  	if needRewriteDefCauslationData && defCauslate.NewDefCauslationEnabled() && !defCauslate.CompatibleDefCauslate(origDefCauslate, toDefCauslate) {
  3236  		return errUnsupportedModifyDefCauslation.GenWithStackByArgs(origDefCauslate, toDefCauslate)
  3237  	}
  3238  
  3239  	if (origCharset == charset.CharsetUTF8 && toCharset == charset.CharsetUTF8MB4) ||
  3240  		(origCharset == charset.CharsetUTF8 && toCharset == charset.CharsetUTF8) ||
  3241  		(origCharset == charset.CharsetUTF8MB4 && toCharset == charset.CharsetUTF8MB4) {
  3242  		// MilevaDB only allow utf8 to be changed to utf8mb4, or changing the defCauslation when the charset is utf8/utf8mb4.
  3243  		return nil
  3244  	}
  3245  
  3246  	if toCharset != origCharset {
  3247  		msg := fmt.Sprintf("charset from %s to %s", origCharset, toCharset)
  3248  		return errUnsupportedModifyCharset.GenWithStackByArgs(msg)
  3249  	}
  3250  	if toDefCauslate != origDefCauslate {
  3251  		msg := fmt.Sprintf("change defCauslate from %s to %s", origDefCauslate, toDefCauslate)
  3252  		return errUnsupportedModifyCharset.GenWithStackByArgs(msg)
  3253  	}
  3254  	return nil
  3255  }
  3256  
  3257  // CheckModifyTypeCompatible checks whether changes defCausumn type to another is compatible considering
  3258  // field length and precision.
  3259  func CheckModifyTypeCompatible(origin *types.FieldType, to *types.FieldType) (allowedChangeDeferredCausetValueMsg string, err error) {
  3260  	unsupportedMsg := fmt.Sprintf("type %v not match origin %v", to.CompactStr(), origin.CompactStr())
  3261  	var isIntType bool
  3262  	switch origin.Tp {
  3263  	case allegrosql.TypeVarchar, allegrosql.TypeString, allegrosql.TypeVarString,
  3264  		allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
  3265  		switch to.Tp {
  3266  		case allegrosql.TypeVarchar, allegrosql.TypeString, allegrosql.TypeVarString,
  3267  			allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
  3268  		default:
  3269  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(unsupportedMsg)
  3270  		}
  3271  	case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong:
  3272  		switch to.Tp {
  3273  		case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong:
  3274  			isIntType = true
  3275  		default:
  3276  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(unsupportedMsg)
  3277  		}
  3278  	case allegrosql.TypeEnum, allegrosql.TypeSet:
  3279  		var typeVar string
  3280  		if origin.Tp == allegrosql.TypeEnum {
  3281  			typeVar = "enum"
  3282  		} else {
  3283  			typeVar = "set"
  3284  		}
  3285  		if origin.Tp != to.Tp {
  3286  			msg := fmt.Sprintf("cannot modify %s type defCausumn's to type %s", typeVar, to.String())
  3287  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3288  		}
  3289  		if len(to.Elems) < len(origin.Elems) {
  3290  			msg := fmt.Sprintf("the number of %s defCausumn's elements is less than the original: %d", typeVar, len(origin.Elems))
  3291  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3292  		}
  3293  		for index, originElem := range origin.Elems {
  3294  			toElem := to.Elems[index]
  3295  			if originElem != toElem {
  3296  				msg := fmt.Sprintf("cannot modify %s defCausumn value %s to %s", typeVar, originElem, toElem)
  3297  				return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3298  			}
  3299  		}
  3300  	case allegrosql.TypeNewDecimal:
  3301  		if origin.Tp != to.Tp {
  3302  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(unsupportedMsg)
  3303  		}
  3304  		// The root cause is modifying decimal precision needs to rewrite binary representation of that decimal.
  3305  		if to.Flen != origin.Flen || to.Decimal != origin.Decimal {
  3306  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't change decimal defCausumn precision")
  3307  		}
  3308  	default:
  3309  		if origin.Tp != to.Tp {
  3310  			return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(unsupportedMsg)
  3311  		}
  3312  	}
  3313  
  3314  	if to.Flen > 0 && to.Flen < origin.Flen {
  3315  		msg := fmt.Sprintf("length %d is less than origin %d", to.Flen, origin.Flen)
  3316  		if isIntType {
  3317  			return msg, errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3318  		}
  3319  		return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3320  	}
  3321  	if to.Decimal > 0 && to.Decimal < origin.Decimal {
  3322  		msg := fmt.Sprintf("decimal %d is less than origin %d", to.Decimal, origin.Decimal)
  3323  		return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3324  	}
  3325  
  3326  	toUnsigned := allegrosql.HasUnsignedFlag(to.Flag)
  3327  	originUnsigned := allegrosql.HasUnsignedFlag(origin.Flag)
  3328  	if originUnsigned != toUnsigned {
  3329  		msg := fmt.Sprintf("can't change unsigned integer to signed or vice versa")
  3330  		if isIntType {
  3331  			return msg, errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3332  		}
  3333  		return "", errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3334  	}
  3335  	return "", nil
  3336  }
  3337  
  3338  // checkModifyTypes checks if the 'origin' type can be modified to 'to' type with out the need to
  3339  // change or check existing data in the causet.
  3340  // It returns error if the two types has incompatible Charset and DefCauslation, different sign, different
  3341  // digital/string types, or length of new Flen and Decimal is less than origin.
  3342  func checkModifyTypes(ctx stochastikctx.Context, origin *types.FieldType, to *types.FieldType, needRewriteDefCauslationData bool) error {
  3343  	changeDeferredCausetValueMsg, err := CheckModifyTypeCompatible(origin, to)
  3344  	if err != nil {
  3345  		enableChangeDeferredCausetType := ctx.GetStochastikVars().EnableChangeDeferredCausetType
  3346  		if len(changeDeferredCausetValueMsg) == 0 {
  3347  			return errors.Trace(err)
  3348  		}
  3349  
  3350  		if !enableChangeDeferredCausetType {
  3351  			msg := fmt.Sprintf("%s, and milevadb_enable_change_defCausumn_type is false", changeDeferredCausetValueMsg)
  3352  			return errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3353  		} else if allegrosql.HasPriKeyFlag(origin.Flag) {
  3354  			msg := "milevadb_enable_change_defCausumn_type is true and this defCausumn has primary key flag"
  3355  			return errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3356  		}
  3357  	}
  3358  
  3359  	err = checkModifyCharsetAndDefCauslation(to.Charset, to.DefCauslate, origin.Charset, origin.DefCauslate, needRewriteDefCauslationData)
  3360  	return errors.Trace(err)
  3361  }
  3362  
  3363  func setDefaultValue(ctx stochastikctx.Context, defCaus *causet.DeferredCauset, option *ast.DeferredCausetOption) (bool, error) {
  3364  	hasDefaultValue := false
  3365  	value, isSeqExpr, err := getDefaultValue(ctx, defCaus, option)
  3366  	if err != nil {
  3367  		return hasDefaultValue, errors.Trace(err)
  3368  	}
  3369  	if isSeqExpr {
  3370  		if err := checkSequenceDefaultValue(defCaus); err != nil {
  3371  			return false, errors.Trace(err)
  3372  		}
  3373  		defCaus.DefaultIsExpr = isSeqExpr
  3374  	}
  3375  
  3376  	if hasDefaultValue, value, err = checkDeferredCausetDefaultValue(ctx, defCaus, value); err != nil {
  3377  		return hasDefaultValue, errors.Trace(err)
  3378  	}
  3379  	value, err = convertTimestamFIDelefaultValToUTC(ctx, value, defCaus)
  3380  	if err != nil {
  3381  		return hasDefaultValue, errors.Trace(err)
  3382  	}
  3383  	err = defCaus.SetDefaultValue(value)
  3384  	if err != nil {
  3385  		return hasDefaultValue, errors.Trace(err)
  3386  	}
  3387  	return hasDefaultValue, nil
  3388  }
  3389  
  3390  func setDeferredCausetComment(ctx stochastikctx.Context, defCaus *causet.DeferredCauset, option *ast.DeferredCausetOption) error {
  3391  	value, err := memex.EvalAstExpr(ctx, option.Expr)
  3392  	if err != nil {
  3393  		return errors.Trace(err)
  3394  	}
  3395  	defCaus.Comment, err = value.ToString()
  3396  	return errors.Trace(err)
  3397  }
  3398  
  3399  // processDeferredCausetOptions is only used in getModifiableDeferredCausetJob.
  3400  func processDeferredCausetOptions(ctx stochastikctx.Context, defCaus *causet.DeferredCauset, options []*ast.DeferredCausetOption) error {
  3401  	var sb strings.Builder
  3402  	restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes |
  3403  		format.RestoreSpacesAroundBinaryOperation
  3404  	restoreCtx := format.NewRestoreCtx(restoreFlags, &sb)
  3405  
  3406  	var hasDefaultValue, setOnUFIDelateNow bool
  3407  	var err error
  3408  	for _, opt := range options {
  3409  		switch opt.Tp {
  3410  		case ast.DeferredCausetOptionDefaultValue:
  3411  			hasDefaultValue, err = setDefaultValue(ctx, defCaus, opt)
  3412  			if err != nil {
  3413  				return errors.Trace(err)
  3414  			}
  3415  		case ast.DeferredCausetOptionComment:
  3416  			err := setDeferredCausetComment(ctx, defCaus, opt)
  3417  			if err != nil {
  3418  				return errors.Trace(err)
  3419  			}
  3420  		case ast.DeferredCausetOptionNotNull:
  3421  			defCaus.Flag |= allegrosql.NotNullFlag
  3422  		case ast.DeferredCausetOptionNull:
  3423  			defCaus.Flag &= ^allegrosql.NotNullFlag
  3424  		case ast.DeferredCausetOptionAutoIncrement:
  3425  			defCaus.Flag |= allegrosql.AutoIncrementFlag
  3426  		case ast.DeferredCausetOptionPrimaryKey, ast.DeferredCausetOptionUniqKey:
  3427  			return errUnsupportedModifyDeferredCauset.GenWithStack("can't change defCausumn constraint - %v", opt.Tp)
  3428  		case ast.DeferredCausetOptionOnUFIDelate:
  3429  			// TODO: Support other time functions.
  3430  			if defCaus.Tp == allegrosql.TypeTimestamp || defCaus.Tp == allegrosql.TypeDatetime {
  3431  				if !memex.IsValidCurrentTimestampExpr(opt.Expr, &defCaus.FieldType) {
  3432  					return ErrInvalidOnUFIDelate.GenWithStackByArgs(defCaus.Name)
  3433  				}
  3434  			} else {
  3435  				return ErrInvalidOnUFIDelate.GenWithStackByArgs(defCaus.Name)
  3436  			}
  3437  			defCaus.Flag |= allegrosql.OnUFIDelateNowFlag
  3438  			setOnUFIDelateNow = true
  3439  		case ast.DeferredCausetOptionGenerated:
  3440  			sb.Reset()
  3441  			err = opt.Expr.Restore(restoreCtx)
  3442  			if err != nil {
  3443  				return errors.Trace(err)
  3444  			}
  3445  			defCaus.GeneratedExprString = sb.String()
  3446  			defCaus.GeneratedStored = opt.Stored
  3447  			defCaus.Dependences = make(map[string]struct{})
  3448  			defCaus.GeneratedExpr = opt.Expr
  3449  			for _, defCausName := range findDeferredCausetNamesInExpr(opt.Expr) {
  3450  				defCaus.Dependences[defCausName.Name.L] = struct{}{}
  3451  			}
  3452  		case ast.DeferredCausetOptionDefCauslate:
  3453  			defCaus.DefCauslate = opt.StrValue
  3454  		case ast.DeferredCausetOptionReference:
  3455  			return errors.Trace(errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't modify with references"))
  3456  		case ast.DeferredCausetOptionFulltext:
  3457  			return errors.Trace(errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't modify with full text"))
  3458  		case ast.DeferredCausetOptionCheck:
  3459  			return errors.Trace(errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't modify with check"))
  3460  		// Ignore DeferredCausetOptionAutoRandom. It will be handled later.
  3461  		case ast.DeferredCausetOptionAutoRandom:
  3462  		default:
  3463  			return errors.Trace(errUnsupportedModifyDeferredCauset.GenWithStackByArgs(fmt.Sprintf("unknown defCausumn option type: %d", opt.Tp)))
  3464  		}
  3465  	}
  3466  
  3467  	processDefaultValue(defCaus, hasDefaultValue, setOnUFIDelateNow)
  3468  
  3469  	processDeferredCausetFlags(defCaus)
  3470  
  3471  	if hasDefaultValue {
  3472  		return errors.Trace(checkDefaultValue(ctx, defCaus, true))
  3473  	}
  3474  
  3475  	return nil
  3476  }
  3477  
  3478  func (d *dbs) getModifiableDeferredCausetJob(ctx stochastikctx.Context, ident ast.Ident, originalDefCausName perceptron.CIStr,
  3479  	spec *ast.AlterTableSpec) (*perceptron.Job, error) {
  3480  	specNewDeferredCauset := spec.NewDeferredCausets[0]
  3481  	is := d.infoHandle.Get()
  3482  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  3483  	if !ok {
  3484  		return nil, errors.Trace(schemareplicant.ErrDatabaseNotExists)
  3485  	}
  3486  	t, err := is.TableByName(ident.Schema, ident.Name)
  3487  	if err != nil {
  3488  		return nil, errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  3489  	}
  3490  
  3491  	defCaus := causet.FindDefCaus(t.DefCauss(), originalDefCausName.L)
  3492  	if defCaus == nil {
  3493  		return nil, schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(originalDefCausName, ident.Name)
  3494  	}
  3495  	newDefCausName := specNewDeferredCauset.Name.Name
  3496  	if newDefCausName.L == perceptron.ExtraHandleName.L {
  3497  		return nil, ErrWrongDeferredCausetName.GenWithStackByArgs(newDefCausName.L)
  3498  	}
  3499  	// If we want to rename the defCausumn name, we need to check whether it already exists.
  3500  	if newDefCausName.L != originalDefCausName.L {
  3501  		c := causet.FindDefCaus(t.DefCauss(), newDefCausName.L)
  3502  		if c != nil {
  3503  			return nil, schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(newDefCausName)
  3504  		}
  3505  	}
  3506  	// Check the defCausumn with foreign key.
  3507  	if fkInfo := getDeferredCausetForeignKeyInfo(originalDefCausName.L, t.Meta().ForeignKeys); fkInfo != nil {
  3508  		return nil, errFKIncompatibleDeferredCausets.GenWithStackByArgs(originalDefCausName, fkInfo.Name)
  3509  	}
  3510  
  3511  	// Constraints in the new defCausumn means adding new constraints. Errors should thrown,
  3512  	// which will be done by `processDeferredCausetOptions` later.
  3513  	if specNewDeferredCauset.Tp == nil {
  3514  		// Make sure the defCausumn definition is simple field type.
  3515  		return nil, errors.Trace(errUnsupportedModifyDeferredCauset)
  3516  	}
  3517  
  3518  	if err = checkDeferredCausetAttributes(specNewDeferredCauset.Name.OrigDefCausName(), specNewDeferredCauset.Tp); err != nil {
  3519  		return nil, errors.Trace(err)
  3520  	}
  3521  
  3522  	newDefCaus := causet.ToDeferredCauset(&perceptron.DeferredCausetInfo{
  3523  		ID: defCaus.ID,
  3524  		// We use this PR(https://github.com/whtcorpsinc/milevadb/pull/6274) as the dividing line to define whether it is a new version or an old version MilevaDB.
  3525  		// The old version MilevaDB initializes the defCausumn's offset and state here.
  3526  		// The new version MilevaDB doesn't initialize the defCausumn's offset and state, and it will do the initialization in run DBS function.
  3527  		// When we do the rolling upgrade the following may happen:
  3528  		// a new version MilevaDB builds the DBS job that doesn't be set the defCausumn's offset and state,
  3529  		// and the old version MilevaDB is the DBS tenant, it doesn't get offset and state from the causetstore. Then it will encounter errors.
  3530  		// So here we set offset and state to support the rolling upgrade.
  3531  		Offset:             defCaus.Offset,
  3532  		State:              defCaus.State,
  3533  		OriginDefaultValue: defCaus.OriginDefaultValue,
  3534  		FieldType:          *specNewDeferredCauset.Tp,
  3535  		Name:               newDefCausName,
  3536  		Version:            defCaus.Version,
  3537  	})
  3538  
  3539  	var chs, defCausl string
  3540  	// TODO: Remove it when all causet versions are greater than or equal to TableInfoVersion1.
  3541  	// If newDefCaus's charset is empty and the causet's version less than TableInfoVersion1,
  3542  	// we will not modify the charset of the defCausumn. This behavior is not compatible with MyALLEGROSQL.
  3543  	if len(newDefCaus.FieldType.Charset) == 0 && t.Meta().Version < perceptron.TableInfoVersion1 {
  3544  		chs = defCaus.FieldType.Charset
  3545  		defCausl = defCaus.FieldType.DefCauslate
  3546  	} else {
  3547  		chs, defCausl, err = getCharsetAndDefCauslateInDeferredCausetDef(specNewDeferredCauset)
  3548  		if err != nil {
  3549  			return nil, errors.Trace(err)
  3550  		}
  3551  		chs, defCausl, err = ResolveCharsetDefCauslation(
  3552  			ast.CharsetOpt{Chs: chs, DefCaus: defCausl},
  3553  			ast.CharsetOpt{Chs: t.Meta().Charset, DefCaus: t.Meta().DefCauslate},
  3554  			ast.CharsetOpt{Chs: schemaReplicant.Charset, DefCaus: schemaReplicant.DefCauslate},
  3555  		)
  3556  		if err != nil {
  3557  			return nil, errors.Trace(err)
  3558  		}
  3559  	}
  3560  
  3561  	if err = setCharsetDefCauslationFlenDecimal(&newDefCaus.FieldType, chs, defCausl); err != nil {
  3562  		return nil, errors.Trace(err)
  3563  	}
  3564  
  3565  	if err = processDeferredCausetOptions(ctx, newDefCaus, specNewDeferredCauset.Options); err != nil {
  3566  		return nil, errors.Trace(err)
  3567  	}
  3568  
  3569  	if err = checkDeferredCausetValueConstraint(newDefCaus, newDefCaus.DefCauslate); err != nil {
  3570  		return nil, errors.Trace(err)
  3571  	}
  3572  
  3573  	if err = checkModifyTypes(ctx, &defCaus.FieldType, &newDefCaus.FieldType, isDeferredCausetWithIndex(defCaus.Name.L, t.Meta().Indices)); err != nil {
  3574  		if strings.Contains(err.Error(), "Unsupported modifying defCauslation") {
  3575  			defCausErrMsg := "Unsupported modifying defCauslation of defCausumn '%s' from '%s' to '%s' when index is defined on it."
  3576  			err = errUnsupportedModifyDefCauslation.GenWithStack(defCausErrMsg, defCaus.Name.L, defCaus.DefCauslate, newDefCaus.DefCauslate)
  3577  		}
  3578  		return nil, errors.Trace(err)
  3579  	}
  3580  	if ctx.GetStochastikVars().EnableChangeDeferredCausetType && needChangeDeferredCausetData(defCaus.DeferredCausetInfo, newDefCaus.DeferredCausetInfo) {
  3581  		if newDefCaus.IsGenerated() || defCaus.IsGenerated() {
  3582  			// TODO: Make it compatible with MyALLEGROSQL error.
  3583  			msg := fmt.Sprintf("milevadb_enable_change_defCausumn_type is true, newDefCaus IsGenerated %v, oldDefCaus IsGenerated %v", newDefCaus.IsGenerated(), defCaus.IsGenerated())
  3584  			return nil, errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
  3585  		} else if t.Meta().Partition != nil {
  3586  			return nil, errUnsupportedModifyDeferredCauset.GenWithStackByArgs("milevadb_enable_change_defCausumn_type is true, causet is partition causet")
  3587  		}
  3588  	}
  3589  
  3590  	// Copy index related options to the new spec.
  3591  	indexFlags := defCaus.FieldType.Flag & (allegrosql.PriKeyFlag | allegrosql.UniqueKeyFlag | allegrosql.MultipleKeyFlag)
  3592  	newDefCaus.FieldType.Flag |= indexFlags
  3593  	if allegrosql.HasPriKeyFlag(defCaus.FieldType.Flag) {
  3594  		newDefCaus.FieldType.Flag |= allegrosql.NotNullFlag
  3595  		// TODO: If user explicitly set NULL, we should throw error ErrPrimaryCantHaveNull.
  3596  	}
  3597  
  3598  	// We don't support modifying defCausumn from not_auto_increment to auto_increment.
  3599  	if !allegrosql.HasAutoIncrementFlag(defCaus.Flag) && allegrosql.HasAutoIncrementFlag(newDefCaus.Flag) {
  3600  		return nil, errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't set auto_increment")
  3601  	}
  3602  	// Disallow modifying defCausumn from auto_increment to not auto_increment if the stochastik variable `AllowRemoveAutoInc` is false.
  3603  	if !ctx.GetStochastikVars().AllowRemoveAutoInc && allegrosql.HasAutoIncrementFlag(defCaus.Flag) && !allegrosql.HasAutoIncrementFlag(newDefCaus.Flag) {
  3604  		return nil, errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't remove auto_increment without @@milevadb_allow_remove_auto_inc enabled")
  3605  	}
  3606  
  3607  	// We support modifying the type definitions of 'null' to 'not null' now.
  3608  	var modifyDeferredCausetTp byte
  3609  	if !allegrosql.HasNotNullFlag(defCaus.Flag) && allegrosql.HasNotNullFlag(newDefCaus.Flag) {
  3610  		if err = checkForNullValue(ctx, defCaus.Tp != newDefCaus.Tp, ident.Schema, ident.Name, newDefCaus.Name, defCaus.DeferredCausetInfo); err != nil {
  3611  			return nil, errors.Trace(err)
  3612  		}
  3613  		// `modifyDeferredCausetTp` indicates that there is a type modification.
  3614  		modifyDeferredCausetTp = allegrosql.TypeNull
  3615  	}
  3616  
  3617  	if err = checkDeferredCausetFieldLength(newDefCaus); err != nil {
  3618  		return nil, err
  3619  	}
  3620  
  3621  	if err = checkDeferredCausetWithIndexConstraint(t.Meta(), defCaus.DeferredCausetInfo, newDefCaus.DeferredCausetInfo); err != nil {
  3622  		return nil, err
  3623  	}
  3624  
  3625  	// As same with MyALLEGROSQL, we don't support modifying the stored status for generated defCausumns.
  3626  	if err = checkModifyGeneratedDeferredCauset(t, defCaus, newDefCaus, specNewDeferredCauset); err != nil {
  3627  		return nil, errors.Trace(err)
  3628  	}
  3629  
  3630  	var newAutoRandBits uint64
  3631  	if newAutoRandBits, err = checkAutoRandom(t.Meta(), defCaus, specNewDeferredCauset); err != nil {
  3632  		return nil, errors.Trace(err)
  3633  	}
  3634  
  3635  	job := &perceptron.Job{
  3636  		SchemaID:   schemaReplicant.ID,
  3637  		TableID:    t.Meta().ID,
  3638  		SchemaName: schemaReplicant.Name.L,
  3639  		Type:       perceptron.CausetActionModifyDeferredCauset,
  3640  		BinlogInfo: &perceptron.HistoryInfo{},
  3641  		Args:       []interface{}{&newDefCaus, originalDefCausName, spec.Position, modifyDeferredCausetTp, newAutoRandBits},
  3642  	}
  3643  	return job, nil
  3644  }
  3645  
  3646  // checkDeferredCausetWithIndexConstraint is used to check the related index constraint of the modified defCausumn.
  3647  // Index has a max-prefix-length constraint. eg: a varchar(100), index idx(a), modifying defCausumn a to a varchar(4000)
  3648  // will cause index idx to break the max-prefix-length constraint.
  3649  func checkDeferredCausetWithIndexConstraint(tbInfo *perceptron.TableInfo, originalDefCaus, newDefCaus *perceptron.DeferredCausetInfo) error {
  3650  	var defCausumns []*perceptron.DeferredCausetInfo
  3651  	for _, indexInfo := range tbInfo.Indices {
  3652  		containDeferredCauset := false
  3653  		for _, defCaus := range indexInfo.DeferredCausets {
  3654  			if defCaus.Name.L == originalDefCaus.Name.L {
  3655  				containDeferredCauset = true
  3656  				break
  3657  			}
  3658  		}
  3659  		if !containDeferredCauset {
  3660  			continue
  3661  		}
  3662  		if defCausumns == nil {
  3663  			defCausumns = make([]*perceptron.DeferredCausetInfo, 0, len(tbInfo.DeferredCausets))
  3664  			defCausumns = append(defCausumns, tbInfo.DeferredCausets...)
  3665  			// replace old defCausumn with new defCausumn.
  3666  			for i, defCaus := range defCausumns {
  3667  				if defCaus.Name.L != originalDefCaus.Name.L {
  3668  					continue
  3669  				}
  3670  				defCausumns[i] = newDefCaus.Clone()
  3671  				defCausumns[i].Name = originalDefCaus.Name
  3672  				break
  3673  			}
  3674  		}
  3675  		err := checHoTTexPrefixLength(defCausumns, indexInfo.DeferredCausets)
  3676  		if err != nil {
  3677  			return err
  3678  		}
  3679  	}
  3680  	return nil
  3681  }
  3682  
  3683  func checkAutoRandom(blockInfo *perceptron.TableInfo, originDefCaus *causet.DeferredCauset, specNewDeferredCauset *ast.DeferredCausetDef) (uint64, error) {
  3684  	// Disallow add/drop actions on auto_random.
  3685  	var oldRandBits uint64
  3686  	if blockInfo.PKIsHandle && (blockInfo.GetPkName().L == originDefCaus.Name.L) {
  3687  		oldRandBits = blockInfo.AutoRandomBits
  3688  	}
  3689  	newRandBits, err := extractAutoRandomBitsFromDefCausDef(specNewDeferredCauset)
  3690  	if err != nil {
  3691  		return 0, errors.Trace(err)
  3692  	}
  3693  	switch {
  3694  	case oldRandBits == newRandBits:
  3695  		break
  3696  	case oldRandBits == 0 || newRandBits == 0:
  3697  		return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomAlterErrMsg)
  3698  	case autoid.MaxAutoRandomBits < newRandBits:
  3699  		errMsg := fmt.Sprintf(autoid.AutoRandomOverflowErrMsg,
  3700  			autoid.MaxAutoRandomBits, newRandBits, specNewDeferredCauset.Name.Name.O)
  3701  		return 0, ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)
  3702  	case oldRandBits < newRandBits:
  3703  		break // Increasing auto_random shard bits is allowed.
  3704  	case oldRandBits > newRandBits:
  3705  		return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomDecreaseBitErrMsg)
  3706  	}
  3707  
  3708  	if oldRandBits != 0 {
  3709  		// Disallow changing the defCausumn field type.
  3710  		if originDefCaus.Tp != specNewDeferredCauset.Tp.Tp {
  3711  			return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomModifyDefCausTypeErrMsg)
  3712  		}
  3713  		// Disallow changing auto_increment on auto_random defCausumn.
  3714  		if containsDeferredCausetOption(specNewDeferredCauset, ast.DeferredCausetOptionAutoIncrement) != allegrosql.HasAutoIncrementFlag(originDefCaus.Flag) {
  3715  			return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithAutoIncErrMsg)
  3716  		}
  3717  		// Disallow specifying a default value on auto_random defCausumn.
  3718  		if containsDeferredCausetOption(specNewDeferredCauset, ast.DeferredCausetOptionDefaultValue) {
  3719  			return 0, ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg)
  3720  		}
  3721  	}
  3722  	return newRandBits, nil
  3723  }
  3724  
  3725  // ChangeDeferredCauset renames an existing defCausumn and modifies the defCausumn's definition,
  3726  // currently we only support limited HoTT of changes
  3727  // that do not need to change or check data on the causet.
  3728  func (d *dbs) ChangeDeferredCauset(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  3729  	specNewDeferredCauset := spec.NewDeferredCausets[0]
  3730  	if len(specNewDeferredCauset.Name.Schema.O) != 0 && ident.Schema.L != specNewDeferredCauset.Name.Schema.L {
  3731  		return ErrWrongDBName.GenWithStackByArgs(specNewDeferredCauset.Name.Schema.O)
  3732  	}
  3733  	if len(spec.OldDeferredCausetName.Schema.O) != 0 && ident.Schema.L != spec.OldDeferredCausetName.Schema.L {
  3734  		return ErrWrongDBName.GenWithStackByArgs(spec.OldDeferredCausetName.Schema.O)
  3735  	}
  3736  	if len(specNewDeferredCauset.Name.Block.O) != 0 && ident.Name.L != specNewDeferredCauset.Name.Block.L {
  3737  		return ErrWrongTableName.GenWithStackByArgs(specNewDeferredCauset.Name.Block.O)
  3738  	}
  3739  	if len(spec.OldDeferredCausetName.Block.O) != 0 && ident.Name.L != spec.OldDeferredCausetName.Block.L {
  3740  		return ErrWrongTableName.GenWithStackByArgs(spec.OldDeferredCausetName.Block.O)
  3741  	}
  3742  
  3743  	job, err := d.getModifiableDeferredCausetJob(ctx, ident, spec.OldDeferredCausetName.Name, spec)
  3744  	if err != nil {
  3745  		if schemareplicant.ErrDeferredCausetNotExists.Equal(err) && spec.IfExists {
  3746  			ctx.GetStochastikVars().StmtCtx.AppendNote(schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(spec.OldDeferredCausetName.Name, ident.Name))
  3747  			return nil
  3748  		}
  3749  		return errors.Trace(err)
  3750  	}
  3751  
  3752  	err = d.doDBSJob(ctx, job)
  3753  	// defCausumn not exists, but if_exists flags is true, so we ignore this error.
  3754  	if schemareplicant.ErrDeferredCausetNotExists.Equal(err) && spec.IfExists {
  3755  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  3756  		return nil
  3757  	}
  3758  	err = d.callHookOnChanged(err)
  3759  	return errors.Trace(err)
  3760  }
  3761  
  3762  // RenameDeferredCauset renames an existing defCausumn.
  3763  func (d *dbs) RenameDeferredCauset(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  3764  	oldDefCausName := spec.OldDeferredCausetName.Name
  3765  	newDefCausName := spec.NewDeferredCausetName.Name
  3766  	if oldDefCausName.L == newDefCausName.L {
  3767  		return nil
  3768  	}
  3769  	if newDefCausName.L == perceptron.ExtraHandleName.L {
  3770  		return ErrWrongDeferredCausetName.GenWithStackByArgs(newDefCausName.L)
  3771  	}
  3772  
  3773  	schemaReplicant, tbl, err := d.getSchemaAndTableByIdent(ctx, ident)
  3774  	if err != nil {
  3775  		return errors.Trace(err)
  3776  	}
  3777  
  3778  	oldDefCaus := causet.FindDefCaus(tbl.VisibleDefCauss(), oldDefCausName.L)
  3779  	if oldDefCaus == nil {
  3780  		return schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(oldDefCausName, ident.Name)
  3781  	}
  3782  
  3783  	allDefCauss := tbl.DefCauss()
  3784  	defCausWithNewNameAlreadyExist := causet.FindDefCaus(allDefCauss, newDefCausName.L) != nil
  3785  	if defCausWithNewNameAlreadyExist {
  3786  		return schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(newDefCausName)
  3787  	}
  3788  
  3789  	if fkInfo := getDeferredCausetForeignKeyInfo(oldDefCausName.L, tbl.Meta().ForeignKeys); fkInfo != nil {
  3790  		return errFKIncompatibleDeferredCausets.GenWithStackByArgs(oldDefCausName, fkInfo.Name)
  3791  	}
  3792  
  3793  	// Check generated memex.
  3794  	for _, defCaus := range allDefCauss {
  3795  		if defCaus.GeneratedExpr == nil {
  3796  			continue
  3797  		}
  3798  		dependedDefCausNames := findDeferredCausetNamesInExpr(defCaus.GeneratedExpr)
  3799  		for _, name := range dependedDefCausNames {
  3800  			if name.Name.L == oldDefCausName.L {
  3801  				return ErrBadField.GenWithStackByArgs(oldDefCausName.O, "generated defCausumn function")
  3802  			}
  3803  		}
  3804  	}
  3805  
  3806  	newDefCaus := oldDefCaus.Clone()
  3807  	newDefCaus.Name = newDefCausName
  3808  	job := &perceptron.Job{
  3809  		SchemaID:   schemaReplicant.ID,
  3810  		TableID:    tbl.Meta().ID,
  3811  		SchemaName: schemaReplicant.Name.L,
  3812  		Type:       perceptron.CausetActionModifyDeferredCauset,
  3813  		BinlogInfo: &perceptron.HistoryInfo{},
  3814  		Args:       []interface{}{&newDefCaus, oldDefCausName, spec.Position, 0},
  3815  	}
  3816  	err = d.doDBSJob(ctx, job)
  3817  	err = d.callHookOnChanged(err)
  3818  	return errors.Trace(err)
  3819  }
  3820  
  3821  // ModifyDeferredCauset does modification on an existing defCausumn, currently we only support limited HoTT of changes
  3822  // that do not need to change or check data on the causet.
  3823  func (d *dbs) ModifyDeferredCauset(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  3824  	specNewDeferredCauset := spec.NewDeferredCausets[0]
  3825  	if len(specNewDeferredCauset.Name.Schema.O) != 0 && ident.Schema.L != specNewDeferredCauset.Name.Schema.L {
  3826  		return ErrWrongDBName.GenWithStackByArgs(specNewDeferredCauset.Name.Schema.O)
  3827  	}
  3828  	if len(specNewDeferredCauset.Name.Block.O) != 0 && ident.Name.L != specNewDeferredCauset.Name.Block.L {
  3829  		return ErrWrongTableName.GenWithStackByArgs(specNewDeferredCauset.Name.Block.O)
  3830  	}
  3831  
  3832  	originalDefCausName := specNewDeferredCauset.Name.Name
  3833  	job, err := d.getModifiableDeferredCausetJob(ctx, ident, originalDefCausName, spec)
  3834  	if err != nil {
  3835  		if schemareplicant.ErrDeferredCausetNotExists.Equal(err) && spec.IfExists {
  3836  			ctx.GetStochastikVars().StmtCtx.AppendNote(schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(originalDefCausName, ident.Name))
  3837  			return nil
  3838  		}
  3839  		return errors.Trace(err)
  3840  	}
  3841  
  3842  	err = d.doDBSJob(ctx, job)
  3843  	// defCausumn not exists, but if_exists flags is true, so we ignore this error.
  3844  	if schemareplicant.ErrDeferredCausetNotExists.Equal(err) && spec.IfExists {
  3845  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  3846  		return nil
  3847  	}
  3848  	err = d.callHookOnChanged(err)
  3849  	return errors.Trace(err)
  3850  }
  3851  
  3852  func (d *dbs) AlterDeferredCauset(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  3853  	specNewDeferredCauset := spec.NewDeferredCausets[0]
  3854  	is := d.infoHandle.Get()
  3855  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  3856  	if !ok {
  3857  		return schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name)
  3858  	}
  3859  	t, err := is.TableByName(ident.Schema, ident.Name)
  3860  	if err != nil {
  3861  		return schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name)
  3862  	}
  3863  
  3864  	defCausName := specNewDeferredCauset.Name.Name
  3865  	// Check whether alter defCausumn has existed.
  3866  	defCaus := causet.FindDefCaus(t.DefCauss(), defCausName.L)
  3867  	if defCaus == nil {
  3868  		return ErrBadField.GenWithStackByArgs(defCausName, ident.Name)
  3869  	}
  3870  
  3871  	// Clean the NoDefaultValueFlag value.
  3872  	defCaus.Flag &= ^allegrosql.NoDefaultValueFlag
  3873  	if len(specNewDeferredCauset.Options) == 0 {
  3874  		err = defCaus.SetDefaultValue(nil)
  3875  		if err != nil {
  3876  			return errors.Trace(err)
  3877  		}
  3878  		setNoDefaultValueFlag(defCaus, false)
  3879  	} else {
  3880  		if IsAutoRandomDeferredCausetID(t.Meta(), defCaus.ID) {
  3881  			return ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomIncompatibleWithDefaultValueErrMsg)
  3882  		}
  3883  		hasDefaultValue, err := setDefaultValue(ctx, defCaus, specNewDeferredCauset.Options[0])
  3884  		if err != nil {
  3885  			return errors.Trace(err)
  3886  		}
  3887  		if err = checkDefaultValue(ctx, defCaus, hasDefaultValue); err != nil {
  3888  			return errors.Trace(err)
  3889  		}
  3890  	}
  3891  
  3892  	job := &perceptron.Job{
  3893  		SchemaID:   schemaReplicant.ID,
  3894  		TableID:    t.Meta().ID,
  3895  		SchemaName: schemaReplicant.Name.L,
  3896  		Type:       perceptron.CausetActionSetDefaultValue,
  3897  		BinlogInfo: &perceptron.HistoryInfo{},
  3898  		Args:       []interface{}{defCaus},
  3899  	}
  3900  
  3901  	err = d.doDBSJob(ctx, job)
  3902  	err = d.callHookOnChanged(err)
  3903  	return errors.Trace(err)
  3904  }
  3905  
  3906  // AlterTableComment uFIDelates the causet comment information.
  3907  func (d *dbs) AlterTableComment(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  3908  	is := d.infoHandle.Get()
  3909  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  3910  	if !ok {
  3911  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(ident.Schema)
  3912  	}
  3913  
  3914  	tb, err := is.TableByName(ident.Schema, ident.Name)
  3915  	if err != nil {
  3916  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  3917  	}
  3918  
  3919  	job := &perceptron.Job{
  3920  		SchemaID:   schemaReplicant.ID,
  3921  		TableID:    tb.Meta().ID,
  3922  		SchemaName: schemaReplicant.Name.L,
  3923  		Type:       perceptron.CausetActionModifyTableComment,
  3924  		BinlogInfo: &perceptron.HistoryInfo{},
  3925  		Args:       []interface{}{spec.Comment},
  3926  	}
  3927  
  3928  	err = d.doDBSJob(ctx, job)
  3929  	err = d.callHookOnChanged(err)
  3930  	return errors.Trace(err)
  3931  }
  3932  
  3933  // AlterTableAutoIDCache uFIDelates the causet comment information.
  3934  func (d *dbs) AlterTableAutoIDCache(ctx stochastikctx.Context, ident ast.Ident, newCache int64) error {
  3935  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ident)
  3936  	if err != nil {
  3937  		return errors.Trace(err)
  3938  	}
  3939  
  3940  	job := &perceptron.Job{
  3941  		SchemaID:   schemaReplicant.ID,
  3942  		TableID:    tb.Meta().ID,
  3943  		SchemaName: schemaReplicant.Name.L,
  3944  		Type:       perceptron.CausetActionModifyTableAutoIdCache,
  3945  		BinlogInfo: &perceptron.HistoryInfo{},
  3946  		Args:       []interface{}{newCache},
  3947  	}
  3948  
  3949  	err = d.doDBSJob(ctx, job)
  3950  	err = d.callHookOnChanged(err)
  3951  	return errors.Trace(err)
  3952  }
  3953  
  3954  // AlterTableCharsetAndDefCauslate changes the causet charset and defCauslate.
  3955  func (d *dbs) AlterTableCharsetAndDefCauslate(ctx stochastikctx.Context, ident ast.Ident, toCharset, toDefCauslate string, needsOverwriteDefCauss bool) error {
  3956  	// use the last one.
  3957  	if toCharset == "" && toDefCauslate == "" {
  3958  		return ErrUnknownCharacterSet.GenWithStackByArgs(toCharset)
  3959  	}
  3960  
  3961  	is := d.infoHandle.Get()
  3962  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  3963  	if !ok {
  3964  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(ident.Schema)
  3965  	}
  3966  
  3967  	tb, err := is.TableByName(ident.Schema, ident.Name)
  3968  	if err != nil {
  3969  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  3970  	}
  3971  
  3972  	if toCharset == "" {
  3973  		// charset does not change.
  3974  		toCharset = tb.Meta().Charset
  3975  	}
  3976  
  3977  	if toDefCauslate == "" {
  3978  		// get the default defCauslation of the charset.
  3979  		toDefCauslate, err = charset.GetDefaultDefCauslation(toCharset)
  3980  		if err != nil {
  3981  			return errors.Trace(err)
  3982  		}
  3983  	}
  3984  	doNothing, err := checkAlterTableCharset(tb.Meta(), schemaReplicant, toCharset, toDefCauslate, needsOverwriteDefCauss)
  3985  	if err != nil {
  3986  		return err
  3987  	}
  3988  	if doNothing {
  3989  		return nil
  3990  	}
  3991  
  3992  	job := &perceptron.Job{
  3993  		SchemaID:   schemaReplicant.ID,
  3994  		TableID:    tb.Meta().ID,
  3995  		SchemaName: schemaReplicant.Name.L,
  3996  		Type:       perceptron.CausetActionModifyTableCharsetAndDefCauslate,
  3997  		BinlogInfo: &perceptron.HistoryInfo{},
  3998  		Args:       []interface{}{toCharset, toDefCauslate, needsOverwriteDefCauss},
  3999  	}
  4000  	err = d.doDBSJob(ctx, job)
  4001  	err = d.callHookOnChanged(err)
  4002  	return errors.Trace(err)
  4003  }
  4004  
  4005  // AlterTableSetTiFlashReplica sets the TiFlash replicas info.
  4006  func (d *dbs) AlterTableSetTiFlashReplica(ctx stochastikctx.Context, ident ast.Ident, replicaInfo *ast.TiFlashReplicaSpec) error {
  4007  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ident)
  4008  	if err != nil {
  4009  		return errors.Trace(err)
  4010  	}
  4011  
  4012  	tbReplicaInfo := tb.Meta().TiFlashReplica
  4013  	if tbReplicaInfo != nil && tbReplicaInfo.Count == replicaInfo.Count &&
  4014  		len(tbReplicaInfo.LocationLabels) == len(replicaInfo.Labels) {
  4015  		changed := false
  4016  		for i, lable := range tbReplicaInfo.LocationLabels {
  4017  			if replicaInfo.Labels[i] != lable {
  4018  				changed = true
  4019  				break
  4020  			}
  4021  		}
  4022  		if !changed {
  4023  			return nil
  4024  		}
  4025  	}
  4026  
  4027  	err = checkTiFlashReplicaCount(ctx, replicaInfo.Count)
  4028  	if err != nil {
  4029  		return errors.Trace(err)
  4030  	}
  4031  
  4032  	job := &perceptron.Job{
  4033  		SchemaID:   schemaReplicant.ID,
  4034  		TableID:    tb.Meta().ID,
  4035  		SchemaName: schemaReplicant.Name.L,
  4036  		Type:       perceptron.CausetActionSetTiFlashReplica,
  4037  		BinlogInfo: &perceptron.HistoryInfo{},
  4038  		Args:       []interface{}{*replicaInfo},
  4039  	}
  4040  	err = d.doDBSJob(ctx, job)
  4041  	err = d.callHookOnChanged(err)
  4042  	return errors.Trace(err)
  4043  }
  4044  
  4045  func checkTiFlashReplicaCount(ctx stochastikctx.Context, replicaCount uint64) error {
  4046  	// Check the tiflash replica count should be less than the total tiflash stores.
  4047  	tiflashStoreCnt, err := schemareplicant.GetTiFlashStoreCount(ctx)
  4048  	if err != nil {
  4049  		return errors.Trace(err)
  4050  	}
  4051  	if replicaCount > tiflashStoreCnt {
  4052  		return errors.Errorf("the tiflash replica count: %d should be less than the total tiflash server count: %d", replicaCount, tiflashStoreCnt)
  4053  	}
  4054  	return nil
  4055  }
  4056  
  4057  // UFIDelateTableReplicaInfo uFIDelates the causet flash replica infos.
  4058  func (d *dbs) UFIDelateTableReplicaInfo(ctx stochastikctx.Context, physicalID int64, available bool) error {
  4059  	is := d.infoHandle.Get()
  4060  	tb, ok := is.TableByID(physicalID)
  4061  	if !ok {
  4062  		tb, _ = is.FindTableByPartitionID(physicalID)
  4063  		if tb == nil {
  4064  			return schemareplicant.ErrTableNotExists.GenWithStack("Block which ID = %d does not exist.", physicalID)
  4065  		}
  4066  	}
  4067  	tbInfo := tb.Meta()
  4068  	if tbInfo.TiFlashReplica == nil || (tbInfo.ID == physicalID && tbInfo.TiFlashReplica.Available == available) ||
  4069  		(tbInfo.ID != physicalID && available == tbInfo.TiFlashReplica.IsPartitionAvailable(physicalID)) {
  4070  		return nil
  4071  	}
  4072  
  4073  	EDB, ok := is.SchemaByTable(tbInfo)
  4074  	if !ok {
  4075  		return schemareplicant.ErrDatabaseNotExists.GenWithStack("Database of causet `%s` does not exist.", tb.Meta().Name)
  4076  	}
  4077  
  4078  	job := &perceptron.Job{
  4079  		SchemaID:   EDB.ID,
  4080  		TableID:    tb.Meta().ID,
  4081  		SchemaName: EDB.Name.L,
  4082  		Type:       perceptron.CausetActionUFIDelateTiFlashReplicaStatus,
  4083  		BinlogInfo: &perceptron.HistoryInfo{},
  4084  		Args:       []interface{}{available, physicalID},
  4085  	}
  4086  	err := d.doDBSJob(ctx, job)
  4087  	err = d.callHookOnChanged(err)
  4088  	return errors.Trace(err)
  4089  }
  4090  
  4091  // checkAlterTableCharset uses to check is it possible to change the charset of causet.
  4092  // This function returns 2 variable:
  4093  // doNothing: if doNothing is true, means no need to change any more, because the target charset is same with the charset of causet.
  4094  // err: if err is not nil, means it is not possible to change causet charset to target charset.
  4095  func checkAlterTableCharset(tblInfo *perceptron.TableInfo, dbInfo *perceptron.DBInfo, toCharset, toDefCauslate string, needsOverwriteDefCauss bool) (doNothing bool, err error) {
  4096  	origCharset := tblInfo.Charset
  4097  	origDefCauslate := tblInfo.DefCauslate
  4098  	// Old version schemaReplicant charset maybe modified when load schemaReplicant if TreatOldVersionUTF8AsUTF8MB4 was enable.
  4099  	// So even if the origCharset equal toCharset, we still need to do the dbs for old version schemaReplicant.
  4100  	if origCharset == toCharset && origDefCauslate == toDefCauslate && tblInfo.Version >= perceptron.TableInfoVersion2 {
  4101  		// nothing to do.
  4102  		doNothing = true
  4103  		for _, defCaus := range tblInfo.DeferredCausets {
  4104  			if defCaus.Charset == charset.CharsetBin {
  4105  				continue
  4106  			}
  4107  			if defCaus.Charset == toCharset && defCaus.DefCauslate == toDefCauslate {
  4108  				continue
  4109  			}
  4110  			doNothing = false
  4111  		}
  4112  		if doNothing {
  4113  			return doNothing, nil
  4114  		}
  4115  	}
  4116  
  4117  	// The causet charset may be "", if the causet is create in old MilevaDB version, such as v2.0.8.
  4118  	// This DBS will uFIDelate the causet charset to default charset.
  4119  	origCharset, origDefCauslate, err = ResolveCharsetDefCauslation(
  4120  		ast.CharsetOpt{Chs: origCharset, DefCaus: origDefCauslate},
  4121  		ast.CharsetOpt{Chs: dbInfo.Charset, DefCaus: dbInfo.DefCauslate},
  4122  	)
  4123  	if err != nil {
  4124  		return doNothing, err
  4125  	}
  4126  
  4127  	if err = checkModifyCharsetAndDefCauslation(toCharset, toDefCauslate, origCharset, origDefCauslate, false); err != nil {
  4128  		return doNothing, err
  4129  	}
  4130  	if !needsOverwriteDefCauss {
  4131  		// If we don't change the charset and defCauslation of defCausumns, skip the next checks.
  4132  		return doNothing, nil
  4133  	}
  4134  
  4135  	for _, defCaus := range tblInfo.DeferredCausets {
  4136  		if defCaus.Tp == allegrosql.TypeVarchar {
  4137  			if err = IsTooBigFieldLength(defCaus.Flen, defCaus.Name.O, toCharset); err != nil {
  4138  				return doNothing, err
  4139  			}
  4140  		}
  4141  		if defCaus.Charset == charset.CharsetBin {
  4142  			continue
  4143  		}
  4144  		if len(defCaus.Charset) == 0 {
  4145  			continue
  4146  		}
  4147  		if err = checkModifyCharsetAndDefCauslation(toCharset, toDefCauslate, defCaus.Charset, defCaus.DefCauslate, isDeferredCausetWithIndex(defCaus.Name.L, tblInfo.Indices)); err != nil {
  4148  			if strings.Contains(err.Error(), "Unsupported modifying defCauslation") {
  4149  				defCausErrMsg := "Unsupported converting defCauslation of defCausumn '%s' from '%s' to '%s' when index is defined on it."
  4150  				err = errUnsupportedModifyDefCauslation.GenWithStack(defCausErrMsg, defCaus.Name.L, defCaus.DefCauslate, toDefCauslate)
  4151  			}
  4152  			return doNothing, err
  4153  		}
  4154  	}
  4155  	return doNothing, nil
  4156  }
  4157  
  4158  // RenameIndex renames an index.
  4159  // In MilevaDB, indexes are case-insensitive (so index 'a' and 'A" are considered the same index),
  4160  // but index names are case-sensitive (we can rename index 'a' to 'A')
  4161  func (d *dbs) RenameIndex(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) error {
  4162  	is := d.infoHandle.Get()
  4163  	schemaReplicant, ok := is.SchemaByName(ident.Schema)
  4164  	if !ok {
  4165  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(ident.Schema)
  4166  	}
  4167  
  4168  	tb, err := is.TableByName(ident.Schema, ident.Name)
  4169  	if err != nil {
  4170  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ident.Schema, ident.Name))
  4171  	}
  4172  	duplicate, err := validateRenameIndex(spec.FromKey, spec.ToKey, tb.Meta())
  4173  	if duplicate {
  4174  		return nil
  4175  	}
  4176  	if err != nil {
  4177  		return errors.Trace(err)
  4178  	}
  4179  
  4180  	job := &perceptron.Job{
  4181  		SchemaID:   schemaReplicant.ID,
  4182  		TableID:    tb.Meta().ID,
  4183  		SchemaName: schemaReplicant.Name.L,
  4184  		Type:       perceptron.CausetActionRenameIndex,
  4185  		BinlogInfo: &perceptron.HistoryInfo{},
  4186  		Args:       []interface{}{spec.FromKey, spec.ToKey},
  4187  	}
  4188  
  4189  	err = d.doDBSJob(ctx, job)
  4190  	err = d.callHookOnChanged(err)
  4191  	return errors.Trace(err)
  4192  }
  4193  
  4194  // DropTable will proceed even if some causet in the list does not exists.
  4195  func (d *dbs) DropTable(ctx stochastikctx.Context, ti ast.Ident) (err error) {
  4196  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ti)
  4197  	if err != nil {
  4198  		return errors.Trace(err)
  4199  	}
  4200  
  4201  	if tb.Meta().IsView() {
  4202  		return schemareplicant.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name)
  4203  	}
  4204  	if tb.Meta().IsSequence() {
  4205  		return schemareplicant.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name)
  4206  	}
  4207  
  4208  	job := &perceptron.Job{
  4209  		SchemaID:   schemaReplicant.ID,
  4210  		TableID:    tb.Meta().ID,
  4211  		SchemaName: schemaReplicant.Name.L,
  4212  		Type:       perceptron.CausetActionDropTable,
  4213  		BinlogInfo: &perceptron.HistoryInfo{},
  4214  	}
  4215  
  4216  	err = d.doDBSJob(ctx, job)
  4217  	err = d.callHookOnChanged(err)
  4218  	if err != nil {
  4219  		return errors.Trace(err)
  4220  	}
  4221  	if !config.TableLockEnabled() {
  4222  		return nil
  4223  	}
  4224  	if ok, _ := ctx.CheckTableLocked(tb.Meta().ID); ok {
  4225  		ctx.ReleaseTableLockByTableIDs([]int64{tb.Meta().ID})
  4226  	}
  4227  	return nil
  4228  }
  4229  
  4230  // DropView will proceed even if some view in the list does not exists.
  4231  func (d *dbs) DropView(ctx stochastikctx.Context, ti ast.Ident) (err error) {
  4232  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ti)
  4233  	if err != nil {
  4234  		return errors.Trace(err)
  4235  	}
  4236  
  4237  	if !tb.Meta().IsView() {
  4238  		return ErrWrongObject.GenWithStackByArgs(ti.Schema, ti.Name, "VIEW")
  4239  	}
  4240  
  4241  	job := &perceptron.Job{
  4242  		SchemaID:   schemaReplicant.ID,
  4243  		TableID:    tb.Meta().ID,
  4244  		SchemaName: schemaReplicant.Name.L,
  4245  		Type:       perceptron.CausetActionDropView,
  4246  		BinlogInfo: &perceptron.HistoryInfo{},
  4247  	}
  4248  
  4249  	err = d.doDBSJob(ctx, job)
  4250  	err = d.callHookOnChanged(err)
  4251  	return errors.Trace(err)
  4252  }
  4253  
  4254  func (d *dbs) TruncateTable(ctx stochastikctx.Context, ti ast.Ident) error {
  4255  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ti)
  4256  	if err != nil {
  4257  		return errors.Trace(err)
  4258  	}
  4259  	if tb.Meta().IsView() || tb.Meta().IsSequence() {
  4260  		return schemareplicant.ErrTableNotExists.GenWithStackByArgs(schemaReplicant.Name.O, tb.Meta().Name.O)
  4261  	}
  4262  	genIDs, err := d.genGlobalIDs(1)
  4263  	if err != nil {
  4264  		return errors.Trace(err)
  4265  	}
  4266  	newTableID := genIDs[0]
  4267  	job := &perceptron.Job{
  4268  		SchemaID:   schemaReplicant.ID,
  4269  		TableID:    tb.Meta().ID,
  4270  		SchemaName: schemaReplicant.Name.L,
  4271  		Type:       perceptron.CausetActionTruncateTable,
  4272  		BinlogInfo: &perceptron.HistoryInfo{},
  4273  		Args:       []interface{}{newTableID},
  4274  	}
  4275  	if ok, _ := ctx.CheckTableLocked(tb.Meta().ID); ok && config.TableLockEnabled() {
  4276  		// AddTableLock here to avoid this dbs job was executed successfully but the stochastik was been kill before return.
  4277  		// The stochastik will release all causet locks it holds, if we don't add the new locking causet id here,
  4278  		// the stochastik may forget to release the new locked causet id when this dbs job was executed successfully
  4279  		// but the stochastik was killed before return.
  4280  		ctx.AddTableLock([]perceptron.TableLockTpInfo{{SchemaID: schemaReplicant.ID, TableID: newTableID, Tp: tb.Meta().Lock.Tp}})
  4281  	}
  4282  	err = d.doDBSJob(ctx, job)
  4283  	err = d.callHookOnChanged(err)
  4284  	if err != nil {
  4285  		if config.TableLockEnabled() {
  4286  			ctx.ReleaseTableLockByTableIDs([]int64{newTableID})
  4287  		}
  4288  		return errors.Trace(err)
  4289  	}
  4290  	oldTblInfo := tb.Meta()
  4291  	if oldTblInfo.PreSplitRegions > 0 {
  4292  		if _, tb, err := d.getSchemaAndTableByIdent(ctx, ti); err == nil {
  4293  			d.preSplitAndScatter(ctx, tb.Meta(), tb.Meta().GetPartitionInfo())
  4294  		}
  4295  	}
  4296  
  4297  	if !config.TableLockEnabled() {
  4298  		return nil
  4299  	}
  4300  	if ok, _ := ctx.CheckTableLocked(tb.Meta().ID); ok {
  4301  		ctx.ReleaseTableLockByTableIDs([]int64{tb.Meta().ID})
  4302  	}
  4303  	return nil
  4304  }
  4305  
  4306  func (d *dbs) RenameTable(ctx stochastikctx.Context, oldIdent, newIdent ast.Ident, isAlterTable bool) error {
  4307  	is := d.GetSchemaReplicantWithInterceptor(ctx)
  4308  	oldSchema, ok := is.SchemaByName(oldIdent.Schema)
  4309  	if !ok {
  4310  		if isAlterTable {
  4311  			return schemareplicant.ErrTableNotExists.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name)
  4312  		}
  4313  		if is.TableExists(newIdent.Schema, newIdent.Name) {
  4314  			return schemareplicant.ErrTableExists.GenWithStackByArgs(newIdent)
  4315  		}
  4316  		return errFileNotFound.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name)
  4317  	}
  4318  	oldTbl, err := is.TableByName(oldIdent.Schema, oldIdent.Name)
  4319  	if err != nil {
  4320  		if isAlterTable {
  4321  			return schemareplicant.ErrTableNotExists.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name)
  4322  		}
  4323  		if is.TableExists(newIdent.Schema, newIdent.Name) {
  4324  			return schemareplicant.ErrTableExists.GenWithStackByArgs(newIdent)
  4325  		}
  4326  		return errFileNotFound.GenWithStackByArgs(oldIdent.Schema, oldIdent.Name)
  4327  	}
  4328  	if isAlterTable && newIdent.Schema.L == oldIdent.Schema.L && newIdent.Name.L == oldIdent.Name.L {
  4329  		// oldIdent is equal to newIdent, do nothing
  4330  		return nil
  4331  	}
  4332  	newSchema, ok := is.SchemaByName(newIdent.Schema)
  4333  	if !ok {
  4334  		return ErrErrorOnRename.GenWithStackByArgs(
  4335  			fmt.Sprintf("%s.%s", oldIdent.Schema, oldIdent.Name),
  4336  			fmt.Sprintf("%s.%s", newIdent.Schema, newIdent.Name),
  4337  			168,
  4338  			fmt.Sprintf("Database `%s` doesn't exist", newIdent.Schema))
  4339  	}
  4340  	if is.TableExists(newIdent.Schema, newIdent.Name) {
  4341  		return schemareplicant.ErrTableExists.GenWithStackByArgs(newIdent)
  4342  	}
  4343  	if err := checkTooLongTable(newIdent.Name); err != nil {
  4344  		return errors.Trace(err)
  4345  	}
  4346  
  4347  	job := &perceptron.Job{
  4348  		SchemaID:   newSchema.ID,
  4349  		TableID:    oldTbl.Meta().ID,
  4350  		SchemaName: newSchema.Name.L,
  4351  		Type:       perceptron.CausetActionRenameTable,
  4352  		BinlogInfo: &perceptron.HistoryInfo{},
  4353  		Args:       []interface{}{oldSchema.ID, newIdent.Name},
  4354  	}
  4355  
  4356  	err = d.doDBSJob(ctx, job)
  4357  	err = d.callHookOnChanged(err)
  4358  	return errors.Trace(err)
  4359  }
  4360  
  4361  func getAnonymousIndex(t causet.Block, defCausName perceptron.CIStr) perceptron.CIStr {
  4362  	id := 2
  4363  	l := len(t.Indices())
  4364  	indexName := defCausName
  4365  	if strings.EqualFold(indexName.L, allegrosql.PrimaryKeyName) {
  4366  		indexName = perceptron.NewCIStr(fmt.Sprintf("%s_%d", defCausName.O, id))
  4367  		id = 3
  4368  	}
  4369  	for i := 0; i < l; i++ {
  4370  		if t.Indices()[i].Meta().Name.L == indexName.L {
  4371  			indexName = perceptron.NewCIStr(fmt.Sprintf("%s_%d", defCausName.O, id))
  4372  			i = -1
  4373  			id++
  4374  		}
  4375  	}
  4376  	return indexName
  4377  }
  4378  
  4379  func (d *dbs) CreatePrimaryKey(ctx stochastikctx.Context, ti ast.Ident, indexName perceptron.CIStr,
  4380  	indexPartSpecifications []*ast.IndexPartSpecification, indexOption *ast.IndexOption) error {
  4381  	if !config.GetGlobalConfig().AlterPrimaryKey {
  4382  		return ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported add primary key, alter-primary-key is false")
  4383  	}
  4384  
  4385  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ti)
  4386  	if err != nil {
  4387  		return errors.Trace(err)
  4388  	}
  4389  
  4390  	if err = checkTooLongIndex(indexName); err != nil {
  4391  		return ErrTooLongIdent.GenWithStackByArgs(allegrosql.PrimaryKeyName)
  4392  	}
  4393  
  4394  	indexName = perceptron.NewCIStr(allegrosql.PrimaryKeyName)
  4395  	if indexInfo := t.Meta().FindIndexByName(indexName.L); indexInfo != nil ||
  4396  		// If the causet's PKIsHandle is true, it also means that this causet has a primary key.
  4397  		t.Meta().PKIsHandle {
  4398  		return schemareplicant.ErrMultiplePriKey
  4399  	}
  4400  
  4401  	// Primary keys cannot include memex index parts. A primary key requires the generated defCausumn to be stored,
  4402  	// but memex index parts are implemented as virtual generated defCausumns, not stored generated defCausumns.
  4403  	for _, idxPart := range indexPartSpecifications {
  4404  		if idxPart.Expr != nil {
  4405  			return ErrFunctionalIndexPrimaryKey
  4406  		}
  4407  	}
  4408  
  4409  	tblInfo := t.Meta()
  4410  	// Check before the job is put to the queue.
  4411  	// This check is redundant, but useful. If DBS check fail before the job is put
  4412  	// to job queue, the fail path logic is super fast.
  4413  	// After DBS job is put to the queue, and if the check fail, MilevaDB will run the DBS cancel logic.
  4414  	// The recover step causes DBS wait a few seconds, makes the unit test painfully slow.
  4415  	// For same reason, decide whether index is global here.
  4416  	indexDeferredCausets, err := buildIndexDeferredCausets(tblInfo.DeferredCausets, indexPartSpecifications)
  4417  	if err != nil {
  4418  		return errors.Trace(err)
  4419  	}
  4420  	if _, err = checkPKOnGeneratedDeferredCauset(tblInfo, indexPartSpecifications); err != nil {
  4421  		return err
  4422  	}
  4423  
  4424  	global := false
  4425  	if tblInfo.GetPartitionInfo() != nil {
  4426  		ck, err := checkPartitionKeysConstraint(tblInfo.GetPartitionInfo(), indexDeferredCausets, tblInfo)
  4427  		if err != nil {
  4428  			return err
  4429  		}
  4430  		if !ck {
  4431  			if !config.GetGlobalConfig().EnableGlobalIndex {
  4432  				return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY")
  4433  			}
  4434  			//index defCausumns does not contain all partition defCausumns, must set global
  4435  			global = true
  4436  		}
  4437  	}
  4438  
  4439  	// May be truncate comment here, when index comment too long and sql_mode is't strict.
  4440  	if _, err = validateCommentLength(ctx.GetStochastikVars(), indexName.String(), indexOption); err != nil {
  4441  		return errors.Trace(err)
  4442  	}
  4443  
  4444  	unique := true
  4445  	sqlMode := ctx.GetStochastikVars().ALLEGROSQLMode
  4446  	job := &perceptron.Job{
  4447  		SchemaID:   schemaReplicant.ID,
  4448  		TableID:    t.Meta().ID,
  4449  		SchemaName: schemaReplicant.Name.L,
  4450  		Type:       perceptron.CausetActionAddPrimaryKey,
  4451  		BinlogInfo: &perceptron.HistoryInfo{},
  4452  		Args:       []interface{}{unique, indexName, indexPartSpecifications, indexOption, sqlMode, nil, global},
  4453  		Priority:   ctx.GetStochastikVars().DBSReorgPriority,
  4454  	}
  4455  
  4456  	err = d.doDBSJob(ctx, job)
  4457  	err = d.callHookOnChanged(err)
  4458  	return errors.Trace(err)
  4459  }
  4460  
  4461  func buildHiddenDeferredCausetInfo(ctx stochastikctx.Context, indexPartSpecifications []*ast.IndexPartSpecification, indexName perceptron.CIStr, tblInfo *perceptron.TableInfo, existDefCauss []*causet.DeferredCauset) ([]*perceptron.DeferredCausetInfo, error) {
  4462  	hiddenDefCauss := make([]*perceptron.DeferredCausetInfo, 0, len(indexPartSpecifications))
  4463  	for i, idxPart := range indexPartSpecifications {
  4464  		if idxPart.Expr == nil {
  4465  			continue
  4466  		}
  4467  		idxPart.DeferredCauset = &ast.DeferredCausetName{Name: perceptron.NewCIStr(fmt.Sprintf("%s_%s_%d", memexIndexPrefix, indexName, i))}
  4468  		// Check whether the hidden defCausumns have existed.
  4469  		defCaus := causet.FindDefCaus(existDefCauss, idxPart.DeferredCauset.Name.L)
  4470  		if defCaus != nil {
  4471  			// TODO: Use memex index related error.
  4472  			return nil, schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(defCaus.Name.String())
  4473  		}
  4474  		idxPart.Length = types.UnspecifiedLength
  4475  		// The index part is an memex, prepare a hidden defCausumn for it.
  4476  		if len(idxPart.DeferredCauset.Name.L) > allegrosql.MaxDeferredCausetNameLength {
  4477  			// TODO: Refine the error message.
  4478  			return nil, ErrTooLongIdent.GenWithStackByArgs("hidden defCausumn")
  4479  		}
  4480  		// TODO: refine the error message.
  4481  		if err := checkIllegalFn4GeneratedDeferredCauset("memex index", idxPart.Expr); err != nil {
  4482  			return nil, errors.Trace(err)
  4483  		}
  4484  
  4485  		var sb strings.Builder
  4486  		restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes |
  4487  			format.RestoreSpacesAroundBinaryOperation
  4488  		restoreCtx := format.NewRestoreCtx(restoreFlags, &sb)
  4489  		sb.Reset()
  4490  		err := idxPart.Expr.Restore(restoreCtx)
  4491  		if err != nil {
  4492  			return nil, errors.Trace(err)
  4493  		}
  4494  		expr, err := memex.RewriteSimpleExprWithTableInfo(ctx, tblInfo, idxPart.Expr)
  4495  		if err != nil {
  4496  			// TODO: refine the error message.
  4497  			return nil, err
  4498  		}
  4499  		if _, ok := expr.(*memex.DeferredCauset); ok {
  4500  			return nil, ErrFunctionalIndexOnField
  4501  		}
  4502  
  4503  		defCausInfo := &perceptron.DeferredCausetInfo{
  4504  			Name:                idxPart.DeferredCauset.Name,
  4505  			GeneratedExprString: sb.String(),
  4506  			GeneratedStored:     false,
  4507  			Version:             perceptron.CurrLatestDeferredCausetInfoVersion,
  4508  			Dependences:         make(map[string]struct{}),
  4509  			Hidden:              true,
  4510  			FieldType:           *expr.GetType(),
  4511  		}
  4512  		checkDependencies := make(map[string]struct{})
  4513  		for _, defCausName := range findDeferredCausetNamesInExpr(idxPart.Expr) {
  4514  			defCausInfo.Dependences[defCausName.Name.O] = struct{}{}
  4515  			checkDependencies[defCausName.Name.O] = struct{}{}
  4516  		}
  4517  		if err = checkDependedDefCausExist(checkDependencies, existDefCauss); err != nil {
  4518  			return nil, errors.Trace(err)
  4519  		}
  4520  		if err = checkAutoIncrementRef("", defCausInfo.Dependences, tblInfo); err != nil {
  4521  			return nil, errors.Trace(err)
  4522  		}
  4523  		idxPart.Expr = nil
  4524  		hiddenDefCauss = append(hiddenDefCauss, defCausInfo)
  4525  	}
  4526  	return hiddenDefCauss, nil
  4527  }
  4528  
  4529  func (d *dbs) CreateIndex(ctx stochastikctx.Context, ti ast.Ident, keyType ast.IndexKeyType, indexName perceptron.CIStr,
  4530  	indexPartSpecifications []*ast.IndexPartSpecification, indexOption *ast.IndexOption, ifNotExists bool) error {
  4531  	// not support Spatial and FullText index
  4532  	if keyType == ast.IndexKeyTypeFullText || keyType == ast.IndexKeyTypeSpatial {
  4533  		return errUnsupportedIndexType.GenWithStack("FULLTEXT and SPATIAL index is not supported")
  4534  	}
  4535  	unique := keyType == ast.IndexKeyTypeUnique
  4536  	schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ti)
  4537  	if err != nil {
  4538  		return errors.Trace(err)
  4539  	}
  4540  
  4541  	// Deal with anonymous index.
  4542  	if len(indexName.L) == 0 {
  4543  		defCausName := perceptron.NewCIStr("memex_index")
  4544  		if indexPartSpecifications[0].DeferredCauset != nil {
  4545  			defCausName = indexPartSpecifications[0].DeferredCauset.Name
  4546  		}
  4547  		indexName = getAnonymousIndex(t, defCausName)
  4548  	}
  4549  
  4550  	if indexInfo := t.Meta().FindIndexByName(indexName.L); indexInfo != nil {
  4551  		if indexInfo.State != perceptron.StatePublic {
  4552  			// NOTE: explicit error message. See issue #18363.
  4553  			err = ErrDupKeyName.GenWithStack("index already exist %s; "+
  4554  				"a background job is trying to add the same index, "+
  4555  				"please check by `ADMIN SHOW DBS JOBS`", indexName)
  4556  		} else {
  4557  			err = ErrDupKeyName.GenWithStack("index already exist %s", indexName)
  4558  		}
  4559  		if ifNotExists {
  4560  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  4561  			return nil
  4562  		}
  4563  		return err
  4564  	}
  4565  
  4566  	if err = checkTooLongIndex(indexName); err != nil {
  4567  		return errors.Trace(err)
  4568  	}
  4569  
  4570  	tblInfo := t.Meta()
  4571  
  4572  	// Build hidden defCausumns if necessary.
  4573  	hiddenDefCauss, err := buildHiddenDeferredCausetInfo(ctx, indexPartSpecifications, indexName, t.Meta(), t.DefCauss())
  4574  	if err != nil {
  4575  		return err
  4576  	}
  4577  	if err = checkAddDeferredCausetTooManyDeferredCausets(len(t.DefCauss()) + len(hiddenDefCauss)); err != nil {
  4578  		return errors.Trace(err)
  4579  	}
  4580  
  4581  	// Check before the job is put to the queue.
  4582  	// This check is redundant, but useful. If DBS check fail before the job is put
  4583  	// to job queue, the fail path logic is super fast.
  4584  	// After DBS job is put to the queue, and if the check fail, MilevaDB will run the DBS cancel logic.
  4585  	// The recover step causes DBS wait a few seconds, makes the unit test painfully slow.
  4586  	// For same reason, decide whether index is global here.
  4587  	indexDeferredCausets, err := buildIndexDeferredCausets(append(tblInfo.DeferredCausets, hiddenDefCauss...), indexPartSpecifications)
  4588  	if err != nil {
  4589  		return errors.Trace(err)
  4590  	}
  4591  
  4592  	global := false
  4593  	if unique && tblInfo.GetPartitionInfo() != nil {
  4594  		ck, err := checkPartitionKeysConstraint(tblInfo.GetPartitionInfo(), indexDeferredCausets, tblInfo)
  4595  		if err != nil {
  4596  			return err
  4597  		}
  4598  		if !ck {
  4599  			if !config.GetGlobalConfig().EnableGlobalIndex {
  4600  				return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX")
  4601  			}
  4602  			//index defCausumns does not contain all partition defCausumns, must set global
  4603  			global = true
  4604  		}
  4605  	}
  4606  	// May be truncate comment here, when index comment too long and sql_mode is't strict.
  4607  	if _, err = validateCommentLength(ctx.GetStochastikVars(), indexName.String(), indexOption); err != nil {
  4608  		return errors.Trace(err)
  4609  	}
  4610  	job := &perceptron.Job{
  4611  		SchemaID:   schemaReplicant.ID,
  4612  		TableID:    t.Meta().ID,
  4613  		SchemaName: schemaReplicant.Name.L,
  4614  		Type:       perceptron.CausetActionAddIndex,
  4615  		BinlogInfo: &perceptron.HistoryInfo{},
  4616  		Args:       []interface{}{unique, indexName, indexPartSpecifications, indexOption, hiddenDefCauss, global},
  4617  		Priority:   ctx.GetStochastikVars().DBSReorgPriority,
  4618  	}
  4619  
  4620  	err = d.doDBSJob(ctx, job)
  4621  	// key exists, but if_not_exists flags is true, so we ignore this error.
  4622  	if ErrDupKeyName.Equal(err) && ifNotExists {
  4623  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  4624  		return nil
  4625  	}
  4626  	err = d.callHookOnChanged(err)
  4627  	return errors.Trace(err)
  4628  }
  4629  
  4630  func buildFKInfo(fkName perceptron.CIStr, keys []*ast.IndexPartSpecification, refer *ast.ReferenceDef, defcaus []*causet.DeferredCauset, tbInfo *perceptron.TableInfo) (*perceptron.FKInfo, error) {
  4631  	if len(keys) != len(refer.IndexPartSpecifications) {
  4632  		return nil, schemareplicant.ErrForeignKeyNotMatch.GenWithStackByArgs("foreign key without name")
  4633  	}
  4634  
  4635  	// all base defCausumns of stored generated defCausumns
  4636  	baseDefCauss := make(map[string]struct{})
  4637  	for _, defCaus := range defcaus {
  4638  		if defCaus.IsGenerated() && defCaus.GeneratedStored {
  4639  			for name := range defCaus.Dependences {
  4640  				baseDefCauss[name] = struct{}{}
  4641  			}
  4642  		}
  4643  	}
  4644  
  4645  	fkInfo := &perceptron.FKInfo{
  4646  		Name:     fkName,
  4647  		RefTable: refer.Block.Name,
  4648  		DefCauss: make([]perceptron.CIStr, len(keys)),
  4649  	}
  4650  
  4651  	for i, key := range keys {
  4652  		// Check add foreign key to generated defCausumns
  4653  		// For more detail, see https://dev.allegrosql.com/doc/refman/8.0/en/innodb-foreign-key-constraints.html#innodb-foreign-key-generated-defCausumns
  4654  		for _, defCaus := range defcaus {
  4655  			if defCaus.Name.L != key.DeferredCauset.Name.L {
  4656  				continue
  4657  			}
  4658  			if defCaus.IsGenerated() {
  4659  				// Check foreign key on virtual generated defCausumns
  4660  				if !defCaus.GeneratedStored {
  4661  					return nil, schemareplicant.ErrCannotAddForeign
  4662  				}
  4663  
  4664  				// Check wrong reference options of foreign key on stored generated defCausumns
  4665  				switch refer.OnUFIDelate.ReferOpt {
  4666  				case ast.ReferOptionCascade, ast.ReferOptionSetNull, ast.ReferOptionSetDefault:
  4667  					return nil, errWrongFKOptionForGeneratedDeferredCauset.GenWithStackByArgs("ON UFIDelATE " + refer.OnUFIDelate.ReferOpt.String())
  4668  				}
  4669  				switch refer.OnDelete.ReferOpt {
  4670  				case ast.ReferOptionSetNull, ast.ReferOptionSetDefault:
  4671  					return nil, errWrongFKOptionForGeneratedDeferredCauset.GenWithStackByArgs("ON DELETE " + refer.OnDelete.ReferOpt.String())
  4672  				}
  4673  				continue
  4674  			}
  4675  			// Check wrong reference options of foreign key on base defCausumns of stored generated defCausumns
  4676  			if _, ok := baseDefCauss[defCaus.Name.L]; ok {
  4677  				switch refer.OnUFIDelate.ReferOpt {
  4678  				case ast.ReferOptionCascade, ast.ReferOptionSetNull, ast.ReferOptionSetDefault:
  4679  					return nil, schemareplicant.ErrCannotAddForeign
  4680  				}
  4681  				switch refer.OnDelete.ReferOpt {
  4682  				case ast.ReferOptionCascade, ast.ReferOptionSetNull, ast.ReferOptionSetDefault:
  4683  					return nil, schemareplicant.ErrCannotAddForeign
  4684  				}
  4685  			}
  4686  		}
  4687  		if causet.FindDefCaus(defcaus, key.DeferredCauset.Name.O) == nil {
  4688  			return nil, errKeyDeferredCausetDoesNotExits.GenWithStackByArgs(key.DeferredCauset.Name)
  4689  		}
  4690  		fkInfo.DefCauss[i] = key.DeferredCauset.Name
  4691  	}
  4692  
  4693  	fkInfo.RefDefCauss = make([]perceptron.CIStr, len(refer.IndexPartSpecifications))
  4694  	for i, key := range refer.IndexPartSpecifications {
  4695  		fkInfo.RefDefCauss[i] = key.DeferredCauset.Name
  4696  	}
  4697  
  4698  	fkInfo.OnDelete = int(refer.OnDelete.ReferOpt)
  4699  	fkInfo.OnUFIDelate = int(refer.OnUFIDelate.ReferOpt)
  4700  
  4701  	return fkInfo, nil
  4702  }
  4703  
  4704  func (d *dbs) CreateForeignKey(ctx stochastikctx.Context, ti ast.Ident, fkName perceptron.CIStr, keys []*ast.IndexPartSpecification, refer *ast.ReferenceDef) error {
  4705  	is := d.infoHandle.Get()
  4706  	schemaReplicant, ok := is.SchemaByName(ti.Schema)
  4707  	if !ok {
  4708  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(ti.Schema)
  4709  	}
  4710  
  4711  	t, err := is.TableByName(ti.Schema, ti.Name)
  4712  	if err != nil {
  4713  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name))
  4714  	}
  4715  
  4716  	fkInfo, err := buildFKInfo(fkName, keys, refer, t.DefCauss(), t.Meta())
  4717  	if err != nil {
  4718  		return errors.Trace(err)
  4719  	}
  4720  
  4721  	job := &perceptron.Job{
  4722  		SchemaID:   schemaReplicant.ID,
  4723  		TableID:    t.Meta().ID,
  4724  		SchemaName: schemaReplicant.Name.L,
  4725  		Type:       perceptron.CausetActionAddForeignKey,
  4726  		BinlogInfo: &perceptron.HistoryInfo{},
  4727  		Args:       []interface{}{fkInfo},
  4728  	}
  4729  
  4730  	err = d.doDBSJob(ctx, job)
  4731  	err = d.callHookOnChanged(err)
  4732  	return errors.Trace(err)
  4733  
  4734  }
  4735  
  4736  func (d *dbs) DropForeignKey(ctx stochastikctx.Context, ti ast.Ident, fkName perceptron.CIStr) error {
  4737  	is := d.infoHandle.Get()
  4738  	schemaReplicant, ok := is.SchemaByName(ti.Schema)
  4739  	if !ok {
  4740  		return schemareplicant.ErrDatabaseNotExists.GenWithStackByArgs(ti.Schema)
  4741  	}
  4742  
  4743  	t, err := is.TableByName(ti.Schema, ti.Name)
  4744  	if err != nil {
  4745  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name))
  4746  	}
  4747  
  4748  	job := &perceptron.Job{
  4749  		SchemaID:   schemaReplicant.ID,
  4750  		TableID:    t.Meta().ID,
  4751  		SchemaName: schemaReplicant.Name.L,
  4752  		Type:       perceptron.CausetActionDropForeignKey,
  4753  		BinlogInfo: &perceptron.HistoryInfo{},
  4754  		Args:       []interface{}{fkName},
  4755  	}
  4756  
  4757  	err = d.doDBSJob(ctx, job)
  4758  	err = d.callHookOnChanged(err)
  4759  	return errors.Trace(err)
  4760  }
  4761  
  4762  func (d *dbs) DropIndex(ctx stochastikctx.Context, ti ast.Ident, indexName perceptron.CIStr, ifExists bool) error {
  4763  	is := d.infoHandle.Get()
  4764  	schemaReplicant, ok := is.SchemaByName(ti.Schema)
  4765  	if !ok {
  4766  		return errors.Trace(schemareplicant.ErrDatabaseNotExists)
  4767  	}
  4768  	t, err := is.TableByName(ti.Schema, ti.Name)
  4769  	if err != nil {
  4770  		return errors.Trace(schemareplicant.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name))
  4771  	}
  4772  
  4773  	indexInfo := t.Meta().FindIndexByName(indexName.L)
  4774  	var isPK bool
  4775  	if indexName.L == strings.ToLower(allegrosql.PrimaryKeyName) &&
  4776  		// Before we fixed #14243, there might be a general index named `primary` but not a primary key.
  4777  		(indexInfo == nil || indexInfo.Primary) {
  4778  		isPK = true
  4779  	}
  4780  	if isPK {
  4781  		if !config.GetGlobalConfig().AlterPrimaryKey {
  4782  			return ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when alter-primary-key is false")
  4783  
  4784  		}
  4785  		// If the causet's PKIsHandle is true, we can't find the index from the causet. So we check the value of PKIsHandle.
  4786  		if indexInfo == nil && !t.Meta().PKIsHandle {
  4787  			return ErrCantDropFieldOrKey.GenWithStack("Can't DROP 'PRIMARY'; check that defCausumn/key exists")
  4788  		}
  4789  		if t.Meta().PKIsHandle {
  4790  			return ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when the causet's pkIsHandle is true")
  4791  		}
  4792  		if t.Meta().IsCommonHandle {
  4793  			return ErrUnsupportedModifyPrimaryKey.GenWithStack("Unsupported drop primary key when the causet is using clustered index")
  4794  		}
  4795  	}
  4796  	if indexInfo == nil {
  4797  		err = ErrCantDropFieldOrKey.GenWithStack("index %s doesn't exist", indexName)
  4798  		if ifExists {
  4799  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  4800  			return nil
  4801  		}
  4802  		return err
  4803  	}
  4804  
  4805  	// Check for drop index on auto_increment defCausumn.
  4806  	err = checkDropIndexOnAutoIncrementDeferredCauset(t.Meta(), indexInfo)
  4807  	if err != nil {
  4808  		return errors.Trace(err)
  4809  	}
  4810  
  4811  	jobTp := perceptron.CausetActionDropIndex
  4812  	if isPK {
  4813  		jobTp = perceptron.CausetActionDropPrimaryKey
  4814  	}
  4815  
  4816  	job := &perceptron.Job{
  4817  		SchemaID:   schemaReplicant.ID,
  4818  		TableID:    t.Meta().ID,
  4819  		SchemaName: schemaReplicant.Name.L,
  4820  		Type:       jobTp,
  4821  		BinlogInfo: &perceptron.HistoryInfo{},
  4822  		Args:       []interface{}{indexName},
  4823  	}
  4824  
  4825  	err = d.doDBSJob(ctx, job)
  4826  	// index not exists, but if_exists flags is true, so we ignore this error.
  4827  	if ErrCantDropFieldOrKey.Equal(err) && ifExists {
  4828  		ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  4829  		return nil
  4830  	}
  4831  	err = d.callHookOnChanged(err)
  4832  	return errors.Trace(err)
  4833  }
  4834  
  4835  func isDroppableDeferredCauset(tblInfo *perceptron.TableInfo, defCausName perceptron.CIStr) error {
  4836  	// Check whether there are other defCausumns depend on this defCausumn or not.
  4837  	for _, defCaus := range tblInfo.DeferredCausets {
  4838  		for dep := range defCaus.Dependences {
  4839  			if dep == defCausName.L {
  4840  				return errDependentByGeneratedDeferredCauset.GenWithStackByArgs(dep)
  4841  			}
  4842  		}
  4843  	}
  4844  	if len(tblInfo.DeferredCausets) == 1 {
  4845  		return ErrCantRemoveAllFields.GenWithStack("can't drop only defCausumn %s in causet %s",
  4846  			defCausName, tblInfo.Name)
  4847  	}
  4848  	// We only support dropping defCausumn with single-value none Primary Key index covered now.
  4849  	if !isDeferredCausetCanDropWithIndex(defCausName.L, tblInfo.Indices) {
  4850  		return errCantDropDefCausWithIndex.GenWithStack("can't drop defCausumn %s with composite index covered or Primary Key covered now", defCausName)
  4851  	}
  4852  	// Check the defCausumn with foreign key.
  4853  	if fkInfo := getDeferredCausetForeignKeyInfo(defCausName.L, tblInfo.ForeignKeys); fkInfo != nil {
  4854  		return errFkDeferredCausetCannotDrop.GenWithStackByArgs(defCausName, fkInfo.Name)
  4855  	}
  4856  	return nil
  4857  }
  4858  
  4859  // validateCommentLength checks comment length of causet, defCausumn, index and partition.
  4860  // If comment length is more than the standard length truncate it
  4861  // and causetstore the comment length upto the standard comment length size.
  4862  func validateCommentLength(vars *variable.StochastikVars, indexName string, indexOption *ast.IndexOption) (string, error) {
  4863  	if indexOption == nil {
  4864  		return "", nil
  4865  	}
  4866  
  4867  	maxLen := MaxCommentLength
  4868  	if len(indexOption.Comment) > maxLen {
  4869  		err := errTooLongIndexComment.GenWithStackByArgs(indexName, maxLen)
  4870  		if vars.StrictALLEGROSQLMode {
  4871  			return "", err
  4872  		}
  4873  		vars.StmtCtx.AppendWarning(err)
  4874  		indexOption.Comment = indexOption.Comment[:maxLen]
  4875  	}
  4876  	return indexOption.Comment, nil
  4877  }
  4878  
  4879  func buildPartitionInfo(ctx stochastikctx.Context, spacetime *perceptron.TableInfo, d *dbs, spec *ast.AlterTableSpec) (*perceptron.PartitionInfo, error) {
  4880  	if spacetime.Partition.Type == perceptron.PartitionTypeRange {
  4881  		if len(spec.PartDefinitions) == 0 {
  4882  			return nil, ast.ErrPartitionsMustBeDefined.GenWithStackByArgs(spacetime.Partition.Type)
  4883  		}
  4884  	} else {
  4885  		// we don't support ADD PARTITION for all other partition types yet.
  4886  		return nil, errors.Trace(ErrUnsupportedAddPartition)
  4887  	}
  4888  
  4889  	part := &perceptron.PartitionInfo{
  4890  		Type:            spacetime.Partition.Type,
  4891  		Expr:            spacetime.Partition.Expr,
  4892  		DeferredCausets: spacetime.Partition.DeferredCausets,
  4893  		Enable:          spacetime.Partition.Enable,
  4894  	}
  4895  
  4896  	genIDs, err := d.genGlobalIDs(len(spec.PartDefinitions))
  4897  	if err != nil {
  4898  		return nil, err
  4899  	}
  4900  	for ith, def := range spec.PartDefinitions {
  4901  		if err := def.Clause.Validate(part.Type, len(part.DeferredCausets)); err != nil {
  4902  			return nil, errors.Trace(err)
  4903  		}
  4904  		if err := checkTooLongTable(def.Name); err != nil {
  4905  			return nil, err
  4906  		}
  4907  		// For RANGE partition only VALUES LESS THAN should be possible.
  4908  		clause := def.Clause.(*ast.PartitionDefinitionClauseLessThan)
  4909  		if len(part.DeferredCausets) > 0 {
  4910  			if err := checkRangeDeferredCausetsTypeAndValuesMatch(ctx, spacetime, clause.Exprs); err != nil {
  4911  				return nil, err
  4912  			}
  4913  		}
  4914  
  4915  		comment, _ := def.Comment()
  4916  		piDef := perceptron.PartitionDefinition{
  4917  			Name:    def.Name,
  4918  			ID:      genIDs[ith],
  4919  			Comment: comment,
  4920  		}
  4921  
  4922  		buf := new(bytes.Buffer)
  4923  		for _, expr := range clause.Exprs {
  4924  			expr.Format(buf)
  4925  			piDef.LessThan = append(piDef.LessThan, buf.String())
  4926  			buf.Reset()
  4927  		}
  4928  		part.Definitions = append(part.Definitions, piDef)
  4929  	}
  4930  	return part, nil
  4931  }
  4932  
  4933  func checkRangeDeferredCausetsTypeAndValuesMatch(ctx stochastikctx.Context, spacetime *perceptron.TableInfo, exprs []ast.ExprNode) error {
  4934  	// Validate() has already checked len(defCausNames) = len(exprs)
  4935  	// create causet ... partition by range defCausumns (defcaus)
  4936  	// partition p0 values less than (expr)
  4937  	// check the type of defcaus[i] and expr is consistent.
  4938  	defCausNames := spacetime.Partition.DeferredCausets
  4939  	for i, defCausExpr := range exprs {
  4940  		if _, ok := defCausExpr.(*ast.MaxValueExpr); ok {
  4941  			continue
  4942  		}
  4943  
  4944  		defCausName := defCausNames[i]
  4945  		defCausInfo := getDeferredCausetInfoByName(spacetime, defCausName.L)
  4946  		if defCausInfo == nil {
  4947  			return errors.Trace(ErrFieldNotFoundPart)
  4948  		}
  4949  		defCausType := &defCausInfo.FieldType
  4950  
  4951  		val, err := memex.EvalAstExpr(ctx, defCausExpr)
  4952  		if err != nil {
  4953  			return err
  4954  		}
  4955  
  4956  		// Check val.ConvertTo(defCausType) doesn't work, so we need this case by case check.
  4957  		switch defCausType.Tp {
  4958  		case allegrosql.TypeDate, allegrosql.TypeDatetime:
  4959  			switch val.HoTT() {
  4960  			case types.HoTTString, types.HoTTBytes:
  4961  			default:
  4962  				return ErrWrongTypeDeferredCausetValue.GenWithStackByArgs()
  4963  			}
  4964  		}
  4965  	}
  4966  	return nil
  4967  }
  4968  
  4969  // LockTables uses to execute dagger blocks memex.
  4970  func (d *dbs) LockTables(ctx stochastikctx.Context, stmt *ast.LockTablesStmt) error {
  4971  	lockTables := make([]perceptron.TableLockTpInfo, 0, len(stmt.TableLocks))
  4972  	stochastikInfo := perceptron.StochastikInfo{
  4973  		ServerID:     d.GetID(),
  4974  		StochastikID: ctx.GetStochastikVars().ConnectionID,
  4975  	}
  4976  	uniqueTableID := make(map[int64]struct{})
  4977  	// Check whether the causet was already locked by another.
  4978  	for _, tl := range stmt.TableLocks {
  4979  		tb := tl.Block
  4980  		err := throwErrIfInMemOrSysDB(ctx, tb.Schema.L)
  4981  		if err != nil {
  4982  			return err
  4983  		}
  4984  		schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ast.Ident{Schema: tb.Schema, Name: tb.Name})
  4985  		if err != nil {
  4986  			return errors.Trace(err)
  4987  		}
  4988  		if t.Meta().IsView() || t.Meta().IsSequence() {
  4989  			return causet.ErrUnsupportedOp.GenWithStackByArgs()
  4990  		}
  4991  		err = checkTableLocked(t.Meta(), tl.Type, stochastikInfo)
  4992  		if err != nil {
  4993  			return err
  4994  		}
  4995  		if _, ok := uniqueTableID[t.Meta().ID]; ok {
  4996  			return schemareplicant.ErrNonuniqTable.GenWithStackByArgs(t.Meta().Name)
  4997  		}
  4998  		uniqueTableID[t.Meta().ID] = struct{}{}
  4999  		lockTables = append(lockTables, perceptron.TableLockTpInfo{SchemaID: schemaReplicant.ID, TableID: t.Meta().ID, Tp: tl.Type})
  5000  	}
  5001  
  5002  	unlockTables := ctx.GetAllTableLocks()
  5003  	arg := &lockTablesArg{
  5004  		LockTables:     lockTables,
  5005  		UnlockTables:   unlockTables,
  5006  		StochastikInfo: stochastikInfo,
  5007  	}
  5008  	job := &perceptron.Job{
  5009  		SchemaID:   lockTables[0].SchemaID,
  5010  		TableID:    lockTables[0].TableID,
  5011  		Type:       perceptron.CausetActionLockTable,
  5012  		BinlogInfo: &perceptron.HistoryInfo{},
  5013  		Args:       []interface{}{arg},
  5014  	}
  5015  	// AddTableLock here is avoiding this job was executed successfully but the stochastik was killed before return.
  5016  	ctx.AddTableLock(lockTables)
  5017  	err := d.doDBSJob(ctx, job)
  5018  	if err == nil {
  5019  		ctx.ReleaseTableLocks(unlockTables)
  5020  		ctx.AddTableLock(lockTables)
  5021  	}
  5022  	err = d.callHookOnChanged(err)
  5023  	return errors.Trace(err)
  5024  }
  5025  
  5026  // UnlockTables uses to execute unlock blocks memex.
  5027  func (d *dbs) UnlockTables(ctx stochastikctx.Context, unlockTables []perceptron.TableLockTpInfo) error {
  5028  	if len(unlockTables) == 0 {
  5029  		return nil
  5030  	}
  5031  	arg := &lockTablesArg{
  5032  		UnlockTables: unlockTables,
  5033  		StochastikInfo: perceptron.StochastikInfo{
  5034  			ServerID:     d.GetID(),
  5035  			StochastikID: ctx.GetStochastikVars().ConnectionID,
  5036  		},
  5037  	}
  5038  	job := &perceptron.Job{
  5039  		SchemaID:   unlockTables[0].SchemaID,
  5040  		TableID:    unlockTables[0].TableID,
  5041  		Type:       perceptron.CausetActionUnlockTable,
  5042  		BinlogInfo: &perceptron.HistoryInfo{},
  5043  		Args:       []interface{}{arg},
  5044  	}
  5045  
  5046  	err := d.doDBSJob(ctx, job)
  5047  	if err == nil {
  5048  		ctx.ReleaseAllTableLocks()
  5049  	}
  5050  	err = d.callHookOnChanged(err)
  5051  	return errors.Trace(err)
  5052  }
  5053  
  5054  // CleanDeadTableLock uses to clean dead causet locks.
  5055  func (d *dbs) CleanDeadTableLock(unlockTables []perceptron.TableLockTpInfo, se perceptron.StochastikInfo) error {
  5056  	if len(unlockTables) == 0 {
  5057  		return nil
  5058  	}
  5059  	arg := &lockTablesArg{
  5060  		UnlockTables:   unlockTables,
  5061  		StochastikInfo: se,
  5062  	}
  5063  	job := &perceptron.Job{
  5064  		SchemaID:   unlockTables[0].SchemaID,
  5065  		TableID:    unlockTables[0].TableID,
  5066  		Type:       perceptron.CausetActionUnlockTable,
  5067  		BinlogInfo: &perceptron.HistoryInfo{},
  5068  		Args:       []interface{}{arg},
  5069  	}
  5070  
  5071  	ctx, err := d.sessPool.get()
  5072  	if err != nil {
  5073  		return err
  5074  	}
  5075  	defer d.sessPool.put(ctx)
  5076  	err = d.doDBSJob(ctx, job)
  5077  	err = d.callHookOnChanged(err)
  5078  	return errors.Trace(err)
  5079  }
  5080  
  5081  func throwErrIfInMemOrSysDB(ctx stochastikctx.Context, dbLowerName string) error {
  5082  	if soliton.IsMemOrSysDB(dbLowerName) {
  5083  		if ctx.GetStochastikVars().User != nil {
  5084  			return schemareplicant.ErrAccessDenied.GenWithStackByArgs(ctx.GetStochastikVars().User.Username, ctx.GetStochastikVars().User.Hostname)
  5085  		}
  5086  		return schemareplicant.ErrAccessDenied.GenWithStackByArgs("", "")
  5087  	}
  5088  	return nil
  5089  }
  5090  
  5091  func (d *dbs) CleanupTableLock(ctx stochastikctx.Context, blocks []*ast.TableName) error {
  5092  	uniqueTableID := make(map[int64]struct{})
  5093  	cleanupTables := make([]perceptron.TableLockTpInfo, 0, len(blocks))
  5094  	unlockedTablesNum := 0
  5095  	// Check whether the causet was already locked by another.
  5096  	for _, tb := range blocks {
  5097  		err := throwErrIfInMemOrSysDB(ctx, tb.Schema.L)
  5098  		if err != nil {
  5099  			return err
  5100  		}
  5101  		schemaReplicant, t, err := d.getSchemaAndTableByIdent(ctx, ast.Ident{Schema: tb.Schema, Name: tb.Name})
  5102  		if err != nil {
  5103  			return errors.Trace(err)
  5104  		}
  5105  		if t.Meta().IsView() || t.Meta().IsSequence() {
  5106  			return causet.ErrUnsupportedOp
  5107  		}
  5108  		// Maybe the causet t was not locked, but still try to unlock this causet.
  5109  		// If we skip unlock the causet here, the job maybe not consistent with the job.Query.
  5110  		// eg: unlock blocks t1,t2;  If t2 is not locked and skip here, then the job will only unlock causet t1,
  5111  		// and this behaviour is not consistent with the allegrosql query.
  5112  		if !t.Meta().IsLocked() {
  5113  			unlockedTablesNum++
  5114  		}
  5115  		if _, ok := uniqueTableID[t.Meta().ID]; ok {
  5116  			return schemareplicant.ErrNonuniqTable.GenWithStackByArgs(t.Meta().Name)
  5117  		}
  5118  		uniqueTableID[t.Meta().ID] = struct{}{}
  5119  		cleanupTables = append(cleanupTables, perceptron.TableLockTpInfo{SchemaID: schemaReplicant.ID, TableID: t.Meta().ID})
  5120  	}
  5121  	// If the num of cleanupTables is 0, or all cleanupTables is unlocked, just return here.
  5122  	if len(cleanupTables) == 0 || len(cleanupTables) == unlockedTablesNum {
  5123  		return nil
  5124  	}
  5125  
  5126  	arg := &lockTablesArg{
  5127  		UnlockTables: cleanupTables,
  5128  		IsCleanup:    true,
  5129  	}
  5130  	job := &perceptron.Job{
  5131  		SchemaID:   cleanupTables[0].SchemaID,
  5132  		TableID:    cleanupTables[0].TableID,
  5133  		Type:       perceptron.CausetActionUnlockTable,
  5134  		BinlogInfo: &perceptron.HistoryInfo{},
  5135  		Args:       []interface{}{arg},
  5136  	}
  5137  	err := d.doDBSJob(ctx, job)
  5138  	if err == nil {
  5139  		ctx.ReleaseTableLocks(cleanupTables)
  5140  	}
  5141  	err = d.callHookOnChanged(err)
  5142  	return errors.Trace(err)
  5143  }
  5144  
  5145  type lockTablesArg struct {
  5146  	LockTables     []perceptron.TableLockTpInfo
  5147  	IndexOfLock    int
  5148  	UnlockTables   []perceptron.TableLockTpInfo
  5149  	IndexOfUnlock  int
  5150  	StochastikInfo perceptron.StochastikInfo
  5151  	IsCleanup      bool
  5152  }
  5153  
  5154  func (d *dbs) RepairTable(ctx stochastikctx.Context, causet *ast.TableName, createStmt *ast.CreateTableStmt) error {
  5155  	// Existence of EDB and causet has been checked in the preprocessor.
  5156  	oldTableInfo, ok := (ctx.Value(petriutil.RepairedTable)).(*perceptron.TableInfo)
  5157  	if !ok || oldTableInfo == nil {
  5158  		return ErrRepairTableFail.GenWithStack("Failed to get the repaired causet")
  5159  	}
  5160  	oldDBInfo, ok := (ctx.Value(petriutil.RepairedDatabase)).(*perceptron.DBInfo)
  5161  	if !ok || oldDBInfo == nil {
  5162  		return ErrRepairTableFail.GenWithStack("Failed to get the repaired database")
  5163  	}
  5164  	// By now only support same EDB repair.
  5165  	if createStmt.Block.Schema.L != oldDBInfo.Name.L {
  5166  		return ErrRepairTableFail.GenWithStack("Repaired causet should in same database with the old one")
  5167  	}
  5168  
  5169  	// It is necessary to specify the causet.ID and partition.ID manually.
  5170  	newTableInfo, err := buildTableInfoWithCheck(ctx, createStmt, oldTableInfo.Charset, oldTableInfo.DefCauslate)
  5171  	if err != nil {
  5172  		return errors.Trace(err)
  5173  	}
  5174  	// Override newTableInfo with oldTableInfo's element necessary.
  5175  	// TODO: There may be more element assignments here, and the new TableInfo should be verified with the actual data.
  5176  	newTableInfo.ID = oldTableInfo.ID
  5177  	if err = checkAndOverridePartitionID(newTableInfo, oldTableInfo); err != nil {
  5178  		return err
  5179  	}
  5180  	newTableInfo.AutoIncID = oldTableInfo.AutoIncID
  5181  	// If any old defCausumnInfo has lost, that means the old defCausumn ID lost too, repair failed.
  5182  	for i, newOne := range newTableInfo.DeferredCausets {
  5183  		old := getDeferredCausetInfoByName(oldTableInfo, newOne.Name.L)
  5184  		if old == nil {
  5185  			return ErrRepairTableFail.GenWithStackByArgs("DeferredCauset " + newOne.Name.L + " has lost")
  5186  		}
  5187  		if newOne.Tp != old.Tp {
  5188  			return ErrRepairTableFail.GenWithStackByArgs("DeferredCauset " + newOne.Name.L + " type should be the same")
  5189  		}
  5190  		if newOne.Flen != old.Flen {
  5191  			logutil.BgLogger().Warn("[dbs] admin repair causet : DeferredCauset " + newOne.Name.L + " flen is not equal to the old one")
  5192  		}
  5193  		newTableInfo.DeferredCausets[i].ID = old.ID
  5194  	}
  5195  	// If any old indexInfo has lost, that means the index ID lost too, so did the data, repair failed.
  5196  	for i, newOne := range newTableInfo.Indices {
  5197  		old := getIndexInfoByNameAndDeferredCauset(oldTableInfo, newOne)
  5198  		if old == nil {
  5199  			return ErrRepairTableFail.GenWithStackByArgs("Index " + newOne.Name.L + " has lost")
  5200  		}
  5201  		if newOne.Tp != old.Tp {
  5202  			return ErrRepairTableFail.GenWithStackByArgs("Index " + newOne.Name.L + " type should be the same")
  5203  		}
  5204  		newTableInfo.Indices[i].ID = old.ID
  5205  	}
  5206  
  5207  	newTableInfo.State = perceptron.StatePublic
  5208  	err = checkTableInfoValid(newTableInfo)
  5209  	if err != nil {
  5210  		return err
  5211  	}
  5212  	newTableInfo.State = perceptron.StateNone
  5213  
  5214  	job := &perceptron.Job{
  5215  		SchemaID:   oldDBInfo.ID,
  5216  		TableID:    newTableInfo.ID,
  5217  		SchemaName: oldDBInfo.Name.L,
  5218  		Type:       perceptron.CausetActionRepairTable,
  5219  		BinlogInfo: &perceptron.HistoryInfo{},
  5220  		Args:       []interface{}{newTableInfo},
  5221  	}
  5222  	err = d.doDBSJob(ctx, job)
  5223  	if err == nil {
  5224  		// Remove the old TableInfo from repairInfo before petri reload.
  5225  		petriutil.RepairInfo.RemoveFromRepairInfo(oldDBInfo.Name.L, oldTableInfo.Name.L)
  5226  	}
  5227  	err = d.callHookOnChanged(err)
  5228  	return errors.Trace(err)
  5229  }
  5230  
  5231  func (d *dbs) OrderByDeferredCausets(ctx stochastikctx.Context, ident ast.Ident) error {
  5232  	_, tb, err := d.getSchemaAndTableByIdent(ctx, ident)
  5233  	if err != nil {
  5234  		return errors.Trace(err)
  5235  	}
  5236  	if tb.Meta().GetPkDefCausInfo() != nil {
  5237  		ctx.GetStochastikVars().StmtCtx.AppendWarning(errors.Errorf("ORDER BY ignored as there is a user-defined clustered index in the causet '%s'", ident.Name))
  5238  	}
  5239  	return nil
  5240  }
  5241  
  5242  func (d *dbs) CreateSequence(ctx stochastikctx.Context, stmt *ast.CreateSequenceStmt) error {
  5243  	ident := ast.Ident{Name: stmt.Name.Name, Schema: stmt.Name.Schema}
  5244  	sequenceInfo, err := buildSequenceInfo(stmt, ident)
  5245  	if err != nil {
  5246  		return err
  5247  	}
  5248  	// MilevaDB describe the sequence within a blockInfo, as a same-level object of a causet and view.
  5249  	tbInfo, err := buildTableInfo(ctx, ident.Name, nil, nil, "", "")
  5250  	if err != nil {
  5251  		return err
  5252  	}
  5253  	tbInfo.Sequence = sequenceInfo
  5254  
  5255  	onExist := OnExistError
  5256  	if stmt.IfNotExists {
  5257  		onExist = OnExistIgnore
  5258  	}
  5259  
  5260  	return d.CreateTableWithInfo(ctx, ident.Schema, tbInfo, onExist, false /*tryRetainID*/)
  5261  }
  5262  
  5263  func (d *dbs) DropSequence(ctx stochastikctx.Context, ti ast.Ident, ifExists bool) (err error) {
  5264  	schemaReplicant, tbl, err := d.getSchemaAndTableByIdent(ctx, ti)
  5265  	if err != nil {
  5266  		return errors.Trace(err)
  5267  	}
  5268  
  5269  	if !tbl.Meta().IsSequence() {
  5270  		err = ErrWrongObject.GenWithStackByArgs(ti.Schema, ti.Name, "SEQUENCE")
  5271  		if ifExists {
  5272  			ctx.GetStochastikVars().StmtCtx.AppendNote(err)
  5273  			return nil
  5274  		}
  5275  		return err
  5276  	}
  5277  
  5278  	job := &perceptron.Job{
  5279  		SchemaID:   schemaReplicant.ID,
  5280  		TableID:    tbl.Meta().ID,
  5281  		SchemaName: schemaReplicant.Name.L,
  5282  		Type:       perceptron.CausetActionDropSequence,
  5283  		BinlogInfo: &perceptron.HistoryInfo{},
  5284  	}
  5285  
  5286  	err = d.doDBSJob(ctx, job)
  5287  	err = d.callHookOnChanged(err)
  5288  	return errors.Trace(err)
  5289  }
  5290  
  5291  func (d *dbs) AlterIndexVisibility(ctx stochastikctx.Context, ident ast.Ident, indexName perceptron.CIStr, visibility ast.IndexVisibility) error {
  5292  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ident)
  5293  	if err != nil {
  5294  		return err
  5295  	}
  5296  
  5297  	invisible := false
  5298  	if visibility == ast.IndexVisibilityInvisible {
  5299  		invisible = true
  5300  	}
  5301  
  5302  	skip, err := validateAlterIndexVisibility(indexName, invisible, tb.Meta())
  5303  	if err != nil {
  5304  		return errors.Trace(err)
  5305  	}
  5306  	if skip {
  5307  		return nil
  5308  	}
  5309  
  5310  	job := &perceptron.Job{
  5311  		SchemaID:   schemaReplicant.ID,
  5312  		TableID:    tb.Meta().ID,
  5313  		SchemaName: schemaReplicant.Name.L,
  5314  		Type:       perceptron.CausetActionAlterIndexVisibility,
  5315  		BinlogInfo: &perceptron.HistoryInfo{},
  5316  		Args:       []interface{}{indexName, invisible},
  5317  	}
  5318  
  5319  	err = d.doDBSJob(ctx, job)
  5320  	err = d.callHookOnChanged(err)
  5321  	return errors.Trace(err)
  5322  }
  5323  
  5324  func buildPlacementSpecReplicasAndConstraint(rule *memristed.MemruleOp, replicas uint64, cnstr string) ([]*memristed.MemruleOp, error) {
  5325  	var err error
  5326  	cnstr = strings.TrimSpace(cnstr)
  5327  	rules := make([]*memristed.MemruleOp, 0, 1)
  5328  	if len(cnstr) > 0 && cnstr[0] == '[' {
  5329  		// can not emit REPLICAS with an array label
  5330  		if replicas == 0 {
  5331  			return rules, errors.Errorf("array CONSTRAINTS should be with a positive REPLICAS")
  5332  		}
  5333  		rule.Count = int(replicas)
  5334  
  5335  		constraints := []string{}
  5336  
  5337  		err = json.Unmarshal([]byte(cnstr), &constraints)
  5338  		if err != nil {
  5339  			return rules, err
  5340  		}
  5341  
  5342  		rule.LabelConstraints, err = memristed.CheckLabelConstraints(constraints)
  5343  		if err != nil {
  5344  			return rules, err
  5345  		}
  5346  
  5347  		rules = append(rules, rule)
  5348  	} else if len(cnstr) > 0 && cnstr[0] == '{' {
  5349  		constraints := map[string]int{}
  5350  		err = json.Unmarshal([]byte(cnstr), &constraints)
  5351  		if err != nil {
  5352  			return rules, err
  5353  		}
  5354  
  5355  		ruleCnt := int(replicas)
  5356  		for labels, cnt := range constraints {
  5357  			newMemrule := rule.Clone()
  5358  			if cnt <= 0 {
  5359  				err = errors.Errorf("count should be positive, but got %d", cnt)
  5360  				break
  5361  			}
  5362  
  5363  			if replicas != 0 {
  5364  				ruleCnt -= cnt
  5365  				if ruleCnt < 0 {
  5366  					err = errors.Errorf("REPLICAS should be larger or equal to the number of total replicas, but got %d", replicas)
  5367  					break
  5368  				}
  5369  			}
  5370  			newMemrule.Count = cnt
  5371  
  5372  			newMemrule.LabelConstraints, err = memristed.CheckLabelConstraints(strings.Split(strings.TrimSpace(labels), ","))
  5373  			if err != nil {
  5374  				break
  5375  			}
  5376  			rules = append(rules, newMemrule)
  5377  		}
  5378  		rule.Count = ruleCnt
  5379  
  5380  		if rule.Count > 0 {
  5381  			rules = append(rules, rule)
  5382  		}
  5383  	} else {
  5384  		err = errors.Errorf("constraint should be a JSON array or object, but got '%s'", cnstr)
  5385  	}
  5386  	return rules, err
  5387  }
  5388  
  5389  func buildPlacementSpecs(specs []*ast.PlacementSpec) ([]*memristed.MemruleOp, error) {
  5390  	rules := make([]*memristed.MemruleOp, 0, len(specs))
  5391  
  5392  	var err error
  5393  	var sb strings.Builder
  5394  	restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes
  5395  	restoreCtx := format.NewRestoreCtx(restoreFlags, &sb)
  5396  
  5397  	for _, spec := range specs {
  5398  		rule := &memristed.MemruleOp{
  5399  			Memrule: &memristed.Memrule{
  5400  				GroupID:  memristed.MemruleDefaultGroupID,
  5401  				Override: true,
  5402  			},
  5403  		}
  5404  
  5405  		switch spec.Role {
  5406  		case ast.PlacementRoleFollower:
  5407  			rule.Role = memristed.Follower
  5408  		case ast.PlacementRoleLeader:
  5409  			rule.Role = memristed.Leader
  5410  		case ast.PlacementRoleLearner:
  5411  			rule.Role = memristed.Learner
  5412  		case ast.PlacementRoleVoter:
  5413  			rule.Role = memristed.Voter
  5414  		default:
  5415  			err = errors.Errorf("unknown role: %d", spec.Role)
  5416  		}
  5417  
  5418  		if err == nil {
  5419  			switch spec.Tp {
  5420  			case ast.PlacementAdd:
  5421  				rule.CausetAction = memristed.MemruleOpAdd
  5422  			case ast.PlacementAlter, ast.PlacementDrop:
  5423  				rule.CausetAction = memristed.MemruleOpAdd
  5424  
  5425  				// alter will overwrite all things
  5426  				// drop all rules that will be overridden
  5427  				newMemrules := rules[:0]
  5428  
  5429  				for _, r := range rules {
  5430  					if r.Role != rule.Role {
  5431  						newMemrules = append(newMemrules, r)
  5432  					}
  5433  				}
  5434  
  5435  				rules = newMemrules
  5436  
  5437  				// delete previous definitions
  5438  				rules = append(rules, &memristed.MemruleOp{
  5439  					CausetAction:     memristed.MemruleOFIDelel,
  5440  					DeleteByIDPrefix: true,
  5441  					Memrule: &memristed.Memrule{
  5442  						GroupID: memristed.MemruleDefaultGroupID,
  5443  						// ROLE is useless for FIDel, prevent two alter memexs from coexisting
  5444  						Role: rule.Role,
  5445  					},
  5446  				})
  5447  
  5448  				// alter == drop + add new rules
  5449  				if spec.Tp == ast.PlacementDrop {
  5450  					continue
  5451  				}
  5452  			default:
  5453  				err = errors.Errorf("unknown action type: %d", spec.Tp)
  5454  			}
  5455  		}
  5456  
  5457  		if err == nil {
  5458  			var newMemrules []*memristed.MemruleOp
  5459  			newMemrules, err = buildPlacementSpecReplicasAndConstraint(rule, spec.Replicas, spec.Constraints)
  5460  			rules = append(rules, newMemrules...)
  5461  		}
  5462  
  5463  		if err != nil {
  5464  			sb.Reset()
  5465  			if e := spec.Restore(restoreCtx); e != nil {
  5466  				return rules, ErrInvalidPlacementSpec.GenWithStackByArgs("", err)
  5467  			}
  5468  			return rules, ErrInvalidPlacementSpec.GenWithStackByArgs(sb.String(), err)
  5469  		}
  5470  	}
  5471  	return rules, nil
  5472  }
  5473  
  5474  func (d *dbs) AlterTablePartition(ctx stochastikctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) (err error) {
  5475  	schemaReplicant, tb, err := d.getSchemaAndTableByIdent(ctx, ident)
  5476  	if err != nil {
  5477  		return errors.Trace(err)
  5478  	}
  5479  
  5480  	spacetime := tb.Meta()
  5481  	if spacetime.Partition == nil {
  5482  		return errors.Trace(ErrPartitionMgmtOnNonpartitioned)
  5483  	}
  5484  
  5485  	partitionID, err := blocks.FindPartitionByName(spacetime, spec.PartitionNames[0].L)
  5486  	if err != nil {
  5487  		return errors.Trace(err)
  5488  	}
  5489  
  5490  	rules, err := buildPlacementSpecs(spec.PlacementSpecs)
  5491  	if err != nil {
  5492  		return errors.Trace(err)
  5493  	}
  5494  
  5495  	startKey := hex.EncodeToString(codec.EncodeBytes(nil, blockcodec.GenTablePrefix(partitionID)))
  5496  	endKey := hex.EncodeToString(codec.EncodeBytes(nil, blockcodec.GenTablePrefix(partitionID+1)))
  5497  	for _, rule := range rules {
  5498  		rule.Index = memristed.MemruleIndexPartition
  5499  		rule.StartKeyHex = startKey
  5500  		rule.EndKeyHex = endKey
  5501  	}
  5502  
  5503  	job := &perceptron.Job{
  5504  		SchemaID:   schemaReplicant.ID,
  5505  		TableID:    spacetime.ID,
  5506  		SchemaName: schemaReplicant.Name.L,
  5507  		Type:       perceptron.CausetActionAlterTableAlterPartition,
  5508  		BinlogInfo: &perceptron.HistoryInfo{},
  5509  		Args:       []interface{}{partitionID, rules},
  5510  	}
  5511  
  5512  	err = d.doDBSJob(ctx, job)
  5513  	if err != nil {
  5514  		return errors.Trace(err)
  5515  	}
  5516  
  5517  	err = d.callHookOnChanged(err)
  5518  	return errors.Trace(err)
  5519  }