github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/insert_common.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package interlock
    15  
    16  import (
    17  	"context"
    18  	"math"
    19  
    20  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    21  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    22  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    23  	"github.com/whtcorpsinc/errors"
    24  	"github.com/whtcorpsinc/milevadb/causet"
    25  	"github.com/whtcorpsinc/milevadb/causet/blocks"
    26  	"github.com/whtcorpsinc/milevadb/causetstore/einsteindb"
    27  	"github.com/whtcorpsinc/milevadb/config"
    28  	"github.com/whtcorpsinc/milevadb/dbs"
    29  	"github.com/whtcorpsinc/milevadb/ekv"
    30  	"github.com/whtcorpsinc/milevadb/memex"
    31  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    32  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    33  	"github.com/whtcorpsinc/milevadb/soliton/memory"
    34  	"github.com/whtcorpsinc/milevadb/spacetime/autoid"
    35  	"github.com/whtcorpsinc/milevadb/types"
    36  	"go.uber.org/zap"
    37  )
    38  
    39  // InsertValues is the data to insert.
    40  type InsertValues struct {
    41  	baseInterlockingDirectorate
    42  
    43  	rowCount         uint64
    44  	curBatchCnt      uint64
    45  	maxEventsInBatch uint64
    46  	lastInsertID     uint64
    47  
    48  	SelectInterDirc InterlockingDirectorate
    49  
    50  	Block           causet.Block
    51  	DeferredCausets []*ast.DeferredCausetName
    52  	Lists           [][]memex.Expression
    53  	SetList         []*memex.Assignment
    54  
    55  	GenExprs []memex.Expression
    56  
    57  	insertDeferredCausets []*causet.DeferredCauset
    58  
    59  	// defCausDefaultVals is used to causetstore casted default value.
    60  	// Because not every insert memex needs defCausDefaultVals, so we will init the buffer lazily.
    61  	defCausDefaultVals []defaultVal
    62  	evalBuffer         chunk.MutEvent
    63  	evalBufferTypes    []*types.FieldType
    64  
    65  	allAssignmentsAreConstant bool
    66  
    67  	hasRefDefCauss bool
    68  	hasExtraHandle bool
    69  
    70  	// Fill the autoID lazily to causet. This is used for being compatible with JDBC using getGeneratedKeys().
    71  	// `insert|replace values` can guarantee consecutive autoID in a batch.
    72  	// Other memexs like `insert select from` don't guarantee consecutive autoID.
    73  	// https://dev.allegrosql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html
    74  	lazyFillAutoID bool
    75  	memTracker     *memory.Tracker
    76  
    77  	stats *runtimeStatsWithSnapshot
    78  }
    79  
    80  type defaultVal struct {
    81  	val types.Causet
    82  	// valid indicates whether the val is evaluated. We evaluate the default value lazily.
    83  	valid bool
    84  }
    85  
    86  type insertCommon interface {
    87  	insertCommon() *InsertValues
    88  	exec(ctx context.Context, rows [][]types.Causet) error
    89  }
    90  
    91  func (e *InsertValues) insertCommon() *InsertValues {
    92  	return e
    93  }
    94  
    95  func (e *InsertValues) exec(_ context.Context, _ [][]types.Causet) error {
    96  	panic("derived should overload exec function")
    97  }
    98  
    99  // initInsertDeferredCausets sets the explicitly specified defCausumns of an insert memex. There are three cases:
   100  // There are three types of insert memexs:
   101  // 1 insert ... values(...)  --> name type defCausumn
   102  // 2 insert ... set x=y...   --> set type defCausumn
   103  // 3 insert ... (select ..)  --> name type defCausumn
   104  // See https://dev.allegrosql.com/doc/refman/5.7/en/insert.html
   105  func (e *InsertValues) initInsertDeferredCausets() error {
   106  	var defcaus []*causet.DeferredCauset
   107  	var missingDefCausName string
   108  	var err error
   109  
   110  	blockDefCauss := e.Block.DefCauss()
   111  
   112  	if len(e.SetList) > 0 {
   113  		// Process `set` type defCausumn.
   114  		defCausumns := make([]string, 0, len(e.SetList))
   115  		for _, v := range e.SetList {
   116  			defCausumns = append(defCausumns, v.DefCausName.O)
   117  		}
   118  		defcaus, missingDefCausName = causet.FindDefCauss(blockDefCauss, defCausumns, e.Block.Meta().PKIsHandle)
   119  		if missingDefCausName != "" {
   120  			return errors.Errorf("INSERT INTO %s: unknown defCausumn %s", e.Block.Meta().Name.O, missingDefCausName)
   121  		}
   122  		if len(defcaus) == 0 {
   123  			return errors.Errorf("INSERT INTO %s: empty defCausumn", e.Block.Meta().Name.O)
   124  		}
   125  	} else if len(e.DeferredCausets) > 0 {
   126  		// Process `name` type defCausumn.
   127  		defCausumns := make([]string, 0, len(e.DeferredCausets))
   128  		for _, v := range e.DeferredCausets {
   129  			defCausumns = append(defCausumns, v.Name.O)
   130  		}
   131  		defcaus, missingDefCausName = causet.FindDefCauss(blockDefCauss, defCausumns, e.Block.Meta().PKIsHandle)
   132  		if missingDefCausName != "" {
   133  			return errors.Errorf("INSERT INTO %s: unknown defCausumn %s", e.Block.Meta().Name.O, missingDefCausName)
   134  		}
   135  	} else {
   136  		// If e.DeferredCausets are empty, use all defCausumns instead.
   137  		defcaus = blockDefCauss
   138  	}
   139  	for _, defCaus := range defcaus {
   140  		if !defCaus.IsGenerated() {
   141  			e.insertDeferredCausets = append(e.insertDeferredCausets, defCaus)
   142  		}
   143  		if defCaus.Name.L == perceptron.ExtraHandleName.L {
   144  			if !e.ctx.GetStochastikVars().AllowWriteEventID {
   145  				return errors.Errorf("insert, uFIDelate and replace memexs for _milevadb_rowid are not supported.")
   146  			}
   147  			e.hasExtraHandle = true
   148  			break
   149  		}
   150  	}
   151  
   152  	// Check defCausumn whether is specified only once.
   153  	err = causet.CheckOnce(defcaus)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	return nil
   158  }
   159  
   160  func (e *InsertValues) initEvalBuffer() {
   161  	numDefCauss := len(e.Block.DefCauss())
   162  	if e.hasExtraHandle {
   163  		numDefCauss++
   164  	}
   165  	e.evalBufferTypes = make([]*types.FieldType, numDefCauss)
   166  	for i, defCaus := range e.Block.DefCauss() {
   167  		e.evalBufferTypes[i] = &defCaus.FieldType
   168  	}
   169  	if e.hasExtraHandle {
   170  		e.evalBufferTypes[len(e.evalBufferTypes)-1] = types.NewFieldType(allegrosql.TypeLonglong)
   171  	}
   172  	e.evalBuffer = chunk.MutEventFromTypes(e.evalBufferTypes)
   173  }
   174  
   175  func (e *InsertValues) lazilyInitDefCausDefaultValBuf() (ok bool) {
   176  	if e.defCausDefaultVals != nil {
   177  		return true
   178  	}
   179  
   180  	// only if values count of insert memex is more than one, use defCausDefaultVals to causetstore
   181  	// casted default values has benefits.
   182  	if len(e.Lists) > 1 {
   183  		e.defCausDefaultVals = make([]defaultVal, len(e.Block.DefCauss()))
   184  		return true
   185  	}
   186  
   187  	return false
   188  }
   189  
   190  func (e *InsertValues) processSetList() error {
   191  	if len(e.SetList) > 0 {
   192  		if len(e.Lists) > 0 {
   193  			return errors.Errorf("INSERT INTO %s: set type should not use values", e.Block)
   194  		}
   195  		l := make([]memex.Expression, 0, len(e.SetList))
   196  		for _, v := range e.SetList {
   197  			l = append(l, v.Expr)
   198  		}
   199  		e.Lists = append(e.Lists, l)
   200  	}
   201  	return nil
   202  }
   203  
   204  // insertEvents processes `insert|replace into values ()` or `insert|replace into set x=y`
   205  func insertEvents(ctx context.Context, base insertCommon) (err error) {
   206  	e := base.insertCommon()
   207  	// For `insert|replace into set x=y`, process the set list here.
   208  	if err = e.processSetList(); err != nil {
   209  		return err
   210  	}
   211  	sessVars := e.ctx.GetStochastikVars()
   212  	batchSize := sessVars.DMLBatchSize
   213  	batchInsert := sessVars.BatchInsert && !sessVars.InTxn() && config.GetGlobalConfig().EnableBatchDML && batchSize > 0
   214  
   215  	e.lazyFillAutoID = true
   216  	evalEventFunc := e.fastEvalEvent
   217  	if !e.allAssignmentsAreConstant {
   218  		evalEventFunc = e.evalEvent
   219  	}
   220  
   221  	rows := make([][]types.Causet, 0, len(e.Lists))
   222  	memUsageOfEvents := int64(0)
   223  	memTracker := e.memTracker
   224  	for i, list := range e.Lists {
   225  		e.rowCount++
   226  		var event []types.Causet
   227  		event, err = evalEventFunc(ctx, list, i)
   228  		if err != nil {
   229  			return err
   230  		}
   231  		rows = append(rows, event)
   232  		if batchInsert && e.rowCount%uint64(batchSize) == 0 {
   233  			memUsageOfEvents = types.EstimatedMemUsage(rows[0], len(rows))
   234  			memTracker.Consume(memUsageOfEvents)
   235  			// Before batch insert, fill the batch allocated autoIDs.
   236  			rows, err = e.lazyAdjustAutoIncrementCauset(ctx, rows)
   237  			if err != nil {
   238  				return err
   239  			}
   240  			if err = base.exec(ctx, rows); err != nil {
   241  				return err
   242  			}
   243  			rows = rows[:0]
   244  			memTracker.Consume(-memUsageOfEvents)
   245  			memUsageOfEvents = 0
   246  			if err = e.doBatchInsert(ctx); err != nil {
   247  				return err
   248  			}
   249  		}
   250  	}
   251  	if len(rows) != 0 {
   252  		memUsageOfEvents = types.EstimatedMemUsage(rows[0], len(rows))
   253  		memTracker.Consume(memUsageOfEvents)
   254  	}
   255  	// Fill the batch allocated autoIDs.
   256  	rows, err = e.lazyAdjustAutoIncrementCauset(ctx, rows)
   257  	if err != nil {
   258  		return err
   259  	}
   260  	err = base.exec(ctx, rows)
   261  	if err != nil {
   262  		return err
   263  	}
   264  	memTracker.Consume(-memUsageOfEvents)
   265  	return nil
   266  }
   267  
   268  func (e *InsertValues) handleErr(defCaus *causet.DeferredCauset, val *types.Causet, rowIdx int, err error) error {
   269  	if err == nil {
   270  		return nil
   271  	}
   272  
   273  	// Convert the error with full messages.
   274  	var (
   275  		defCausTp   byte
   276  		defCausName string
   277  	)
   278  	if defCaus != nil {
   279  		defCausTp = defCaus.Tp
   280  		defCausName = defCaus.Name.String()
   281  	}
   282  
   283  	if types.ErrDataTooLong.Equal(err) {
   284  		err = resetErrDataTooLong(defCausName, rowIdx+1, err)
   285  	} else if types.ErrOverflow.Equal(err) {
   286  		err = types.ErrWarnDataOutOfRange.GenWithStackByArgs(defCausName, rowIdx+1)
   287  	} else if types.ErrTruncated.Equal(err) {
   288  		err = types.ErrTruncated.GenWithStackByArgs(defCausName, rowIdx+1)
   289  	} else if types.ErrTruncatedWrongVal.Equal(err) || types.ErrWrongValue.Equal(err) {
   290  		valStr, err1 := val.ToString()
   291  		if err1 != nil {
   292  			logutil.BgLogger().Warn("truncate value failed", zap.Error(err1))
   293  		}
   294  		err = causet.ErrTruncatedWrongValueForField.GenWithStackByArgs(types.TypeStr(defCausTp), valStr, defCausName, rowIdx+1)
   295  	}
   296  
   297  	if !e.ctx.GetStochastikVars().StmtCtx.DupKeyAsWarning {
   298  		return err
   299  	}
   300  	// TODO: should not filter all types of errors here.
   301  	e.handleWarning(err)
   302  	return nil
   303  }
   304  
   305  // evalEvent evaluates a to-be-inserted event. The value of the defCausumn may base on another defCausumn,
   306  // so we use setValueForRefDeferredCauset to fill the empty event some default values when needFillDefaultValues is true.
   307  func (e *InsertValues) evalEvent(ctx context.Context, list []memex.Expression, rowIdx int) ([]types.Causet, error) {
   308  	rowLen := len(e.Block.DefCauss())
   309  	if e.hasExtraHandle {
   310  		rowLen++
   311  	}
   312  	event := make([]types.Causet, rowLen)
   313  	hasValue := make([]bool, rowLen)
   314  
   315  	// For memexs like `insert into t set a = b + 1`.
   316  	if e.hasRefDefCauss {
   317  		if err := e.setValueForRefDeferredCauset(event, hasValue); err != nil {
   318  			return nil, err
   319  		}
   320  	}
   321  
   322  	e.evalBuffer.SetCausets(event...)
   323  	for i, expr := range list {
   324  		val, err := expr.Eval(e.evalBuffer.ToEvent())
   325  		if err = e.handleErr(e.insertDeferredCausets[i], &val, rowIdx, err); err != nil {
   326  			return nil, err
   327  		}
   328  		val1, err := causet.CastValue(e.ctx, val, e.insertDeferredCausets[i].ToInfo(), false, false)
   329  		if err = e.handleErr(e.insertDeferredCausets[i], &val, rowIdx, err); err != nil {
   330  			return nil, err
   331  		}
   332  
   333  		offset := e.insertDeferredCausets[i].Offset
   334  		val1.Copy(&event[offset])
   335  		hasValue[offset] = true
   336  		e.evalBuffer.SetCauset(offset, val1)
   337  	}
   338  	// Event may lack of generated defCausumn, autoIncrement defCausumn, empty defCausumn here.
   339  	return e.fillEvent(ctx, event, hasValue)
   340  }
   341  
   342  var emptyEvent chunk.Event
   343  
   344  func (e *InsertValues) fastEvalEvent(ctx context.Context, list []memex.Expression, rowIdx int) ([]types.Causet, error) {
   345  	rowLen := len(e.Block.DefCauss())
   346  	if e.hasExtraHandle {
   347  		rowLen++
   348  	}
   349  	event := make([]types.Causet, rowLen)
   350  	hasValue := make([]bool, rowLen)
   351  	for i, expr := range list {
   352  		con := expr.(*memex.Constant)
   353  		val, err := con.Eval(emptyEvent)
   354  		if err = e.handleErr(e.insertDeferredCausets[i], &val, rowIdx, err); err != nil {
   355  			return nil, err
   356  		}
   357  		val1, err := causet.CastValue(e.ctx, val, e.insertDeferredCausets[i].ToInfo(), false, false)
   358  		if err = e.handleErr(e.insertDeferredCausets[i], &val, rowIdx, err); err != nil {
   359  			return nil, err
   360  		}
   361  		offset := e.insertDeferredCausets[i].Offset
   362  		event[offset], hasValue[offset] = val1, true
   363  	}
   364  	return e.fillEvent(ctx, event, hasValue)
   365  }
   366  
   367  // setValueForRefDeferredCauset set some default values for the event to eval the event value with other defCausumns,
   368  // it follows these rules:
   369  //     1. for nullable and no default value defCausumn, use NULL.
   370  //     2. for nullable and have default value defCausumn, use it's default value.
   371  //     3. for not null defCausumn, use zero value even in strict mode.
   372  //     4. for auto_increment defCausumn, use zero value.
   373  //     5. for generated defCausumn, use NULL.
   374  func (e *InsertValues) setValueForRefDeferredCauset(event []types.Causet, hasValue []bool) error {
   375  	for i, c := range e.Block.DefCauss() {
   376  		d, err := e.getDefCausDefaultValue(i, c)
   377  		if err == nil {
   378  			event[i] = d
   379  			if !allegrosql.HasAutoIncrementFlag(c.Flag) {
   380  				// It is an interesting behavior in MyALLEGROSQL.
   381  				// If the value of auto ID is not explicit, MyALLEGROSQL use 0 value for auto ID when it is
   382  				// evaluated by another defCausumn, but it should be used once only.
   383  				// When we fill it as an auto ID defCausumn, it should be set as it used to be.
   384  				// So just keep `hasValue` false for auto ID, and the others set true.
   385  				hasValue[c.Offset] = true
   386  			}
   387  		} else if causet.ErrNoDefaultValue.Equal(err) {
   388  			event[i] = causet.GetZeroValue(c.ToInfo())
   389  			hasValue[c.Offset] = false
   390  		} else if e.handleErr(c, &d, 0, err) != nil {
   391  			return err
   392  		}
   393  	}
   394  	return nil
   395  }
   396  
   397  func insertEventsFromSelect(ctx context.Context, base insertCommon) error {
   398  	// process `insert|replace into ... select ... from ...`
   399  	e := base.insertCommon()
   400  	selectInterDirc := e.children[0]
   401  	fields := retTypes(selectInterDirc)
   402  	chk := newFirstChunk(selectInterDirc)
   403  	iter := chunk.NewIterator4Chunk(chk)
   404  	rows := make([][]types.Causet, 0, chk.Capacity())
   405  
   406  	sessVars := e.ctx.GetStochastikVars()
   407  	if !sessVars.StrictALLEGROSQLMode {
   408  		// If StrictALLEGROSQLMode is disabled and it is a insert-select memex, it also handle BadNullAsWarning.
   409  		sessVars.StmtCtx.BadNullAsWarning = true
   410  	}
   411  	batchSize := sessVars.DMLBatchSize
   412  	batchInsert := sessVars.BatchInsert && !sessVars.InTxn() && config.GetGlobalConfig().EnableBatchDML && batchSize > 0
   413  	memUsageOfEvents := int64(0)
   414  	memTracker := e.memTracker
   415  	for {
   416  		err := Next(ctx, selectInterDirc, chk)
   417  		if err != nil {
   418  			return err
   419  		}
   420  		if chk.NumEvents() == 0 {
   421  			break
   422  		}
   423  		chkMemUsage := chk.MemoryUsage()
   424  		memTracker.Consume(chkMemUsage)
   425  		for innerChunkEvent := iter.Begin(); innerChunkEvent != iter.End(); innerChunkEvent = iter.Next() {
   426  			innerEvent := innerChunkEvent.GetCausetEvent(fields)
   427  			e.rowCount++
   428  			event, err := e.getEvent(ctx, innerEvent)
   429  			if err != nil {
   430  				return err
   431  			}
   432  			rows = append(rows, event)
   433  			if batchInsert && e.rowCount%uint64(batchSize) == 0 {
   434  				memUsageOfEvents = types.EstimatedMemUsage(rows[0], len(rows))
   435  				memTracker.Consume(memUsageOfEvents)
   436  				if err = base.exec(ctx, rows); err != nil {
   437  					return err
   438  				}
   439  				rows = rows[:0]
   440  				memTracker.Consume(-memUsageOfEvents)
   441  				memUsageOfEvents = 0
   442  				if err = e.doBatchInsert(ctx); err != nil {
   443  					return err
   444  				}
   445  			}
   446  		}
   447  
   448  		if len(rows) != 0 {
   449  			memUsageOfEvents = types.EstimatedMemUsage(rows[0], len(rows))
   450  			memTracker.Consume(memUsageOfEvents)
   451  		}
   452  		err = base.exec(ctx, rows)
   453  		if err != nil {
   454  			return err
   455  		}
   456  		rows = rows[:0]
   457  		memTracker.Consume(-memUsageOfEvents)
   458  		memTracker.Consume(-chkMemUsage)
   459  	}
   460  	return nil
   461  }
   462  
   463  func (e *InsertValues) doBatchInsert(ctx context.Context) error {
   464  	e.ctx.StmtCommit()
   465  	if err := e.ctx.NewTxn(ctx); err != nil {
   466  		// We should return a special error for batch insert.
   467  		return ErrBatchInsertFail.GenWithStack("BatchInsert failed with error: %v", err)
   468  	}
   469  	return nil
   470  }
   471  
   472  // getEvent gets the event which from `insert into select from` or `load data`.
   473  // The input values from these two memexs are datums instead of
   474  // memexs which are used in `insert into set x=y`.
   475  func (e *InsertValues) getEvent(ctx context.Context, vals []types.Causet) ([]types.Causet, error) {
   476  	event := make([]types.Causet, len(e.Block.DefCauss()))
   477  	hasValue := make([]bool, len(e.Block.DefCauss()))
   478  	for i, v := range vals {
   479  		casted, err := causet.CastValue(e.ctx, v, e.insertDeferredCausets[i].ToInfo(), false, false)
   480  		if e.handleErr(nil, &v, 0, err) != nil {
   481  			return nil, err
   482  		}
   483  
   484  		offset := e.insertDeferredCausets[i].Offset
   485  		event[offset] = casted
   486  		hasValue[offset] = true
   487  	}
   488  
   489  	return e.fillEvent(ctx, event, hasValue)
   490  }
   491  
   492  // getDefCausDefaultValue gets the defCausumn default value.
   493  func (e *InsertValues) getDefCausDefaultValue(idx int, defCaus *causet.DeferredCauset) (d types.Causet, err error) {
   494  	if !defCaus.DefaultIsExpr && e.defCausDefaultVals != nil && e.defCausDefaultVals[idx].valid {
   495  		return e.defCausDefaultVals[idx].val, nil
   496  	}
   497  
   498  	var defaultVal types.Causet
   499  	if defCaus.DefaultIsExpr && defCaus.DefaultExpr != nil {
   500  		defaultVal, err = causet.EvalDefCausDefaultExpr(e.ctx, defCaus.ToInfo(), defCaus.DefaultExpr)
   501  	} else {
   502  		defaultVal, err = causet.GetDefCausDefaultValue(e.ctx, defCaus.ToInfo())
   503  	}
   504  	if err != nil {
   505  		return types.Causet{}, err
   506  	}
   507  	if initialized := e.lazilyInitDefCausDefaultValBuf(); initialized && !defCaus.DefaultIsExpr {
   508  		e.defCausDefaultVals[idx].val = defaultVal
   509  		e.defCausDefaultVals[idx].valid = true
   510  	}
   511  
   512  	return defaultVal, nil
   513  }
   514  
   515  // fillDefCausValue fills the defCausumn value if it is not set in the insert memex.
   516  func (e *InsertValues) fillDefCausValue(ctx context.Context, causet types.Causet, idx int, defCausumn *causet.DeferredCauset, hasValue bool) (types.Causet,
   517  	error) {
   518  	if allegrosql.HasAutoIncrementFlag(defCausumn.Flag) {
   519  		if e.lazyFillAutoID {
   520  			// Handle hasValue info in autoIncrement defCausumn previously for lazy handle.
   521  			if !hasValue {
   522  				causet.SetNull()
   523  			}
   524  			// CausetStore the plain causet of autoIncrement defCausumn directly for lazy handle.
   525  			return causet, nil
   526  		}
   527  		d, err := e.adjustAutoIncrementCauset(ctx, causet, hasValue, defCausumn)
   528  		if err != nil {
   529  			return types.Causet{}, err
   530  		}
   531  		return d, nil
   532  	}
   533  	tblInfo := e.Block.Meta()
   534  	if dbs.IsAutoRandomDeferredCausetID(tblInfo, defCausumn.ID) {
   535  		d, err := e.adjustAutoRandomCauset(ctx, causet, hasValue, defCausumn)
   536  		if err != nil {
   537  			return types.Causet{}, err
   538  		}
   539  		return d, nil
   540  	}
   541  	if !hasValue {
   542  		d, err := e.getDefCausDefaultValue(idx, defCausumn)
   543  		if e.handleErr(defCausumn, &causet, 0, err) != nil {
   544  			return types.Causet{}, err
   545  		}
   546  		return d, nil
   547  	}
   548  	return causet, nil
   549  }
   550  
   551  // fillEvent fills generated defCausumns, auto_increment defCausumn and empty defCausumn.
   552  // For NOT NULL defCausumn, it will return error or use zero value based on sql_mode.
   553  // When lazyFillAutoID is true, fill event will lazily handle auto increment causet for lazy batch allocation.
   554  // `insert|replace values` can guarantee consecutive autoID in a batch.
   555  // Other memexs like `insert select from` don't guarantee consecutive autoID.
   556  // https://dev.allegrosql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html
   557  func (e *InsertValues) fillEvent(ctx context.Context, event []types.Causet, hasValue []bool) ([]types.Causet, error) {
   558  	gDefCauss := make([]*causet.DeferredCauset, 0)
   559  	for i, c := range e.Block.DefCauss() {
   560  		var err error
   561  		// Evaluate the generated defCausumns later after real defCausumns set
   562  		if c.IsGenerated() {
   563  			gDefCauss = append(gDefCauss, c)
   564  		} else {
   565  			// Get the default value for all no value defCausumns, the auto increment defCausumn is different from the others.
   566  			if event[i], err = e.fillDefCausValue(ctx, event[i], i, c, hasValue[i]); err != nil {
   567  				return nil, err
   568  			}
   569  			if !e.lazyFillAutoID || (e.lazyFillAutoID && !allegrosql.HasAutoIncrementFlag(c.Flag)) {
   570  				if err = c.HandleBadNull(&event[i], e.ctx.GetStochastikVars().StmtCtx); err != nil {
   571  					return nil, err
   572  				}
   573  			}
   574  		}
   575  	}
   576  	for i, gDefCaus := range gDefCauss {
   577  		defCausIdx := gDefCaus.DeferredCausetInfo.Offset
   578  		val, err := e.GenExprs[i].Eval(chunk.MutEventFromCausets(event).ToEvent())
   579  		if e.handleErr(gDefCaus, &val, 0, err) != nil {
   580  			return nil, err
   581  		}
   582  		event[defCausIdx], err = causet.CastValue(e.ctx, val, gDefCaus.ToInfo(), false, false)
   583  		if err != nil {
   584  			return nil, err
   585  		}
   586  		// Handle the bad null error.
   587  		if err = gDefCaus.HandleBadNull(&event[defCausIdx], e.ctx.GetStochastikVars().StmtCtx); err != nil {
   588  			return nil, err
   589  		}
   590  	}
   591  	return event, nil
   592  }
   593  
   594  // isAutoNull can help judge whether a causet is AutoIncrement Null quickly.
   595  // This used to help lazyFillAutoIncrement to find consecutive N causet backwards for batch autoID alloc.
   596  func (e *InsertValues) isAutoNull(ctx context.Context, d types.Causet, defCaus *causet.DeferredCauset) bool {
   597  	var err error
   598  	var recordID int64
   599  	if !d.IsNull() {
   600  		recordID, err = getAutoRecordID(d, &defCaus.FieldType, true)
   601  		if err != nil {
   602  			return false
   603  		}
   604  	}
   605  	// Use the value if it's not null and not 0.
   606  	if recordID != 0 {
   607  		return false
   608  	}
   609  	// Change NULL to auto id.
   610  	// Change value 0 to auto id, if NoAutoValueOnZero ALLEGROALLEGROSQL mode is not set.
   611  	if d.IsNull() || e.ctx.GetStochastikVars().ALLEGROSQLMode&allegrosql.ModeNoAutoValueOnZero == 0 {
   612  		return true
   613  	}
   614  	return false
   615  }
   616  
   617  func (e *InsertValues) hasAutoIncrementDeferredCauset() (int, bool) {
   618  	defCausIdx := -1
   619  	for i, c := range e.Block.DefCauss() {
   620  		if allegrosql.HasAutoIncrementFlag(c.Flag) {
   621  			defCausIdx = i
   622  			break
   623  		}
   624  	}
   625  	return defCausIdx, defCausIdx != -1
   626  }
   627  
   628  func (e *InsertValues) lazyAdjustAutoIncrementCausetInRetry(ctx context.Context, rows [][]types.Causet, defCausIdx int) ([][]types.Causet, error) {
   629  	// Get the autoIncrement defCausumn.
   630  	defCaus := e.Block.DefCauss()[defCausIdx]
   631  	// Consider the defCausIdx of autoIncrement in event are the same.
   632  	length := len(rows)
   633  	for i := 0; i < length; i++ {
   634  		autoCauset := rows[i][defCausIdx]
   635  
   636  		// autoID can be found in RetryInfo.
   637  		retryInfo := e.ctx.GetStochastikVars().RetryInfo
   638  		if retryInfo.Retrying {
   639  			id, err := retryInfo.GetCurrAutoIncrementID()
   640  			if err != nil {
   641  				return nil, err
   642  			}
   643  			autoCauset.SetAutoID(id, defCaus.Flag)
   644  
   645  			if err = defCaus.HandleBadNull(&autoCauset, e.ctx.GetStochastikVars().StmtCtx); err != nil {
   646  				return nil, err
   647  			}
   648  			rows[i][defCausIdx] = autoCauset
   649  		}
   650  	}
   651  	return rows, nil
   652  }
   653  
   654  // lazyAdjustAutoIncrementCauset is quite similar to adjustAutoIncrementCauset
   655  // except it will cache auto increment causet previously for lazy batch allocation of autoID.
   656  func (e *InsertValues) lazyAdjustAutoIncrementCauset(ctx context.Context, rows [][]types.Causet) ([][]types.Causet, error) {
   657  	// Not in lazyFillAutoID mode means no need to fill.
   658  	if !e.lazyFillAutoID {
   659  		return rows, nil
   660  	}
   661  	// No autoIncrement defCausumn means no need to fill.
   662  	defCausIdx, ok := e.hasAutoIncrementDeferredCauset()
   663  	if !ok {
   664  		return rows, nil
   665  	}
   666  	// autoID can be found in RetryInfo.
   667  	retryInfo := e.ctx.GetStochastikVars().RetryInfo
   668  	if retryInfo.Retrying {
   669  		return e.lazyAdjustAutoIncrementCausetInRetry(ctx, rows, defCausIdx)
   670  	}
   671  	// Get the autoIncrement defCausumn.
   672  	defCaus := e.Block.DefCauss()[defCausIdx]
   673  	// Consider the defCausIdx of autoIncrement in event are the same.
   674  	length := len(rows)
   675  	for i := 0; i < length; i++ {
   676  		autoCauset := rows[i][defCausIdx]
   677  
   678  		var err error
   679  		var recordID int64
   680  		if !autoCauset.IsNull() {
   681  			recordID, err = getAutoRecordID(autoCauset, &defCaus.FieldType, true)
   682  			if err != nil {
   683  				return nil, err
   684  			}
   685  		}
   686  		// Use the value if it's not null and not 0.
   687  		if recordID != 0 {
   688  			err = e.Block.RebaseAutoID(e.ctx, recordID, true, autoid.EventIDAllocType)
   689  			if err != nil {
   690  				return nil, err
   691  			}
   692  			e.ctx.GetStochastikVars().StmtCtx.InsertID = uint64(recordID)
   693  			retryInfo.AddAutoIncrementID(recordID)
   694  			rows[i][defCausIdx] = autoCauset
   695  			continue
   696  		}
   697  
   698  		// Change NULL to auto id.
   699  		// Change value 0 to auto id, if NoAutoValueOnZero ALLEGROALLEGROSQL mode is not set.
   700  		if autoCauset.IsNull() || e.ctx.GetStochastikVars().ALLEGROSQLMode&allegrosql.ModeNoAutoValueOnZero == 0 {
   701  			// Find consecutive num.
   702  			start := i
   703  			cnt := 1
   704  			for i+1 < length && e.isAutoNull(ctx, rows[i+1][defCausIdx], defCaus) {
   705  				i++
   706  				cnt++
   707  			}
   708  			// AllocBatchAutoIncrementValue allocates batch N consecutive autoIDs.
   709  			// The max value can be derived from adding the increment value to min for cnt-1 times.
   710  			min, increment, err := causet.AllocBatchAutoIncrementValue(ctx, e.Block, e.ctx, cnt)
   711  			if e.handleErr(defCaus, &autoCauset, cnt, err) != nil {
   712  				return nil, err
   713  			}
   714  			// It's compatible with allegrosql setting the first allocated autoID to lastInsertID.
   715  			// Cause autoID may be specified by user, judge only the first event is not suiblock.
   716  			if e.lastInsertID == 0 {
   717  				e.lastInsertID = uint64(min)
   718  			}
   719  			// Assign autoIDs to rows.
   720  			for j := 0; j < cnt; j++ {
   721  				offset := j + start
   722  				d := rows[offset][defCausIdx]
   723  
   724  				id := int64(uint64(min) + uint64(j)*uint64(increment))
   725  				d.SetAutoID(id, defCaus.Flag)
   726  				retryInfo.AddAutoIncrementID(id)
   727  
   728  				// The value of d is adjusted by auto ID, so we need to cast it again.
   729  				d, err := causet.CastValue(e.ctx, d, defCaus.ToInfo(), false, false)
   730  				if err != nil {
   731  					return nil, err
   732  				}
   733  				rows[offset][defCausIdx] = d
   734  			}
   735  			continue
   736  		}
   737  
   738  		autoCauset.SetAutoID(recordID, defCaus.Flag)
   739  		retryInfo.AddAutoIncrementID(recordID)
   740  
   741  		// the value of d is adjusted by auto ID, so we need to cast it again.
   742  		autoCauset, err = causet.CastValue(e.ctx, autoCauset, defCaus.ToInfo(), false, false)
   743  		if err != nil {
   744  			return nil, err
   745  		}
   746  		rows[i][defCausIdx] = autoCauset
   747  	}
   748  	return rows, nil
   749  }
   750  
   751  func (e *InsertValues) adjustAutoIncrementCauset(ctx context.Context, d types.Causet, hasValue bool, c *causet.DeferredCauset) (types.Causet, error) {
   752  	retryInfo := e.ctx.GetStochastikVars().RetryInfo
   753  	if retryInfo.Retrying {
   754  		id, err := retryInfo.GetCurrAutoIncrementID()
   755  		if err != nil {
   756  			return types.Causet{}, err
   757  		}
   758  		d.SetAutoID(id, c.Flag)
   759  		return d, nil
   760  	}
   761  
   762  	var err error
   763  	var recordID int64
   764  	if !hasValue {
   765  		d.SetNull()
   766  	}
   767  	if !d.IsNull() {
   768  		recordID, err = getAutoRecordID(d, &c.FieldType, true)
   769  		if err != nil {
   770  			return types.Causet{}, err
   771  		}
   772  	}
   773  	// Use the value if it's not null and not 0.
   774  	if recordID != 0 {
   775  		err = e.Block.RebaseAutoID(e.ctx, recordID, true, autoid.EventIDAllocType)
   776  		if err != nil {
   777  			return types.Causet{}, err
   778  		}
   779  		e.ctx.GetStochastikVars().StmtCtx.InsertID = uint64(recordID)
   780  		retryInfo.AddAutoIncrementID(recordID)
   781  		return d, nil
   782  	}
   783  
   784  	// Change NULL to auto id.
   785  	// Change value 0 to auto id, if NoAutoValueOnZero ALLEGROALLEGROSQL mode is not set.
   786  	if d.IsNull() || e.ctx.GetStochastikVars().ALLEGROSQLMode&allegrosql.ModeNoAutoValueOnZero == 0 {
   787  		recordID, err = causet.AllocAutoIncrementValue(ctx, e.Block, e.ctx)
   788  		if e.handleErr(c, &d, 0, err) != nil {
   789  			return types.Causet{}, err
   790  		}
   791  		// It's compatible with allegrosql setting the first allocated autoID to lastInsertID.
   792  		// Cause autoID may be specified by user, judge only the first event is not suiblock.
   793  		if e.lastInsertID == 0 {
   794  			e.lastInsertID = uint64(recordID)
   795  		}
   796  	}
   797  
   798  	d.SetAutoID(recordID, c.Flag)
   799  	retryInfo.AddAutoIncrementID(recordID)
   800  
   801  	// the value of d is adjusted by auto ID, so we need to cast it again.
   802  	casted, err := causet.CastValue(e.ctx, d, c.ToInfo(), false, false)
   803  	if err != nil {
   804  		return types.Causet{}, err
   805  	}
   806  	return casted, nil
   807  }
   808  
   809  func getAutoRecordID(d types.Causet, target *types.FieldType, isInsert bool) (int64, error) {
   810  	var recordID int64
   811  
   812  	switch target.Tp {
   813  	case allegrosql.TypeFloat, allegrosql.TypeDouble:
   814  		f := d.GetFloat64()
   815  		if isInsert {
   816  			recordID = int64(math.Round(f))
   817  		} else {
   818  			recordID = int64(f)
   819  		}
   820  	case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong:
   821  		recordID = d.GetInt64()
   822  	default:
   823  		return 0, errors.Errorf("unexpected field type [%v]", target.Tp)
   824  	}
   825  
   826  	return recordID, nil
   827  }
   828  
   829  func (e *InsertValues) adjustAutoRandomCauset(ctx context.Context, d types.Causet, hasValue bool, c *causet.DeferredCauset) (types.Causet, error) {
   830  	retryInfo := e.ctx.GetStochastikVars().RetryInfo
   831  	if retryInfo.Retrying {
   832  		autoRandomID, err := retryInfo.GetCurrAutoRandomID()
   833  		if err != nil {
   834  			return types.Causet{}, err
   835  		}
   836  		d.SetAutoID(autoRandomID, c.Flag)
   837  		return d, nil
   838  	}
   839  
   840  	var err error
   841  	var recordID int64
   842  	if !hasValue {
   843  		d.SetNull()
   844  	}
   845  	if !d.IsNull() {
   846  		recordID, err = getAutoRecordID(d, &c.FieldType, true)
   847  		if err != nil {
   848  			return types.Causet{}, err
   849  		}
   850  	}
   851  	// Use the value if it's not null and not 0.
   852  	if recordID != 0 {
   853  		if !e.ctx.GetStochastikVars().AllowAutoRandExplicitInsert {
   854  			return types.Causet{}, dbs.ErrInvalidAutoRandom.GenWithStackByArgs(autoid.AutoRandomExplicitInsertDisabledErrMsg)
   855  		}
   856  		err = e.rebaseAutoRandomID(recordID, &c.FieldType)
   857  		if err != nil {
   858  			return types.Causet{}, err
   859  		}
   860  		e.ctx.GetStochastikVars().StmtCtx.InsertID = uint64(recordID)
   861  		d.SetAutoID(recordID, c.Flag)
   862  		retryInfo.AddAutoRandomID(recordID)
   863  		return d, nil
   864  	}
   865  
   866  	// Change NULL to auto id.
   867  	// Change value 0 to auto id, if NoAutoValueOnZero ALLEGROALLEGROSQL mode is not set.
   868  	if d.IsNull() || e.ctx.GetStochastikVars().ALLEGROSQLMode&allegrosql.ModeNoAutoValueOnZero == 0 {
   869  		_, err := e.ctx.Txn(true)
   870  		if err != nil {
   871  			return types.Causet{}, errors.Trace(err)
   872  		}
   873  		recordID, err = e.allocAutoRandomID(&c.FieldType)
   874  		if err != nil {
   875  			return types.Causet{}, err
   876  		}
   877  		// It's compatible with allegrosql setting the first allocated autoID to lastInsertID.
   878  		// Cause autoID may be specified by user, judge only the first event is not suiblock.
   879  		if e.lastInsertID == 0 {
   880  			e.lastInsertID = uint64(recordID)
   881  		}
   882  	}
   883  
   884  	d.SetAutoID(recordID, c.Flag)
   885  	retryInfo.AddAutoRandomID(recordID)
   886  
   887  	casted, err := causet.CastValue(e.ctx, d, c.ToInfo(), false, false)
   888  	if err != nil {
   889  		return types.Causet{}, err
   890  	}
   891  	return casted, nil
   892  }
   893  
   894  // allocAutoRandomID allocates a random id for primary key defCausumn. It assumes blockInfo.AutoRandomBits > 0.
   895  func (e *InsertValues) allocAutoRandomID(fieldType *types.FieldType) (int64, error) {
   896  	alloc := e.Block.SlabPredictors(e.ctx).Get(autoid.AutoRandomType)
   897  	blockInfo := e.Block.Meta()
   898  	increment := e.ctx.GetStochastikVars().AutoIncrementIncrement
   899  	offset := e.ctx.GetStochastikVars().AutoIncrementOffset
   900  	_, autoRandomID, err := alloc.Alloc(blockInfo.ID, 1, int64(increment), int64(offset))
   901  	if err != nil {
   902  		return 0, err
   903  	}
   904  
   905  	layout := autoid.NewAutoRandomIDLayout(fieldType, blockInfo.AutoRandomBits)
   906  	if blocks.OverflowShardBits(autoRandomID, blockInfo.AutoRandomBits, layout.TypeBitsLength, layout.HasSignBit) {
   907  		return 0, autoid.ErrAutoRandReadFailed
   908  	}
   909  	shard := e.ctx.GetStochastikVars().TxnCtx.GetShard(blockInfo.AutoRandomBits, layout.TypeBitsLength, layout.HasSignBit, 1)
   910  	autoRandomID |= shard
   911  	return autoRandomID, nil
   912  }
   913  
   914  func (e *InsertValues) rebaseAutoRandomID(recordID int64, fieldType *types.FieldType) error {
   915  	if recordID < 0 {
   916  		return nil
   917  	}
   918  	alloc := e.Block.SlabPredictors(e.ctx).Get(autoid.AutoRandomType)
   919  	blockInfo := e.Block.Meta()
   920  
   921  	layout := autoid.NewAutoRandomIDLayout(fieldType, blockInfo.AutoRandomBits)
   922  	autoRandomID := layout.IncrementalMask() & recordID
   923  
   924  	return alloc.Rebase(blockInfo.ID, autoRandomID, true)
   925  }
   926  
   927  func (e *InsertValues) handleWarning(err error) {
   928  	sc := e.ctx.GetStochastikVars().StmtCtx
   929  	sc.AppendWarning(err)
   930  }
   931  
   932  func (e *InsertValues) defCauslectRuntimeStatsEnabled() bool {
   933  	if e.runtimeStats != nil {
   934  		if e.stats == nil {
   935  			snapshotStats := &einsteindb.SnapshotRuntimeStats{}
   936  			e.stats = &runtimeStatsWithSnapshot{
   937  				SnapshotRuntimeStats: snapshotStats,
   938  			}
   939  			e.ctx.GetStochastikVars().StmtCtx.RuntimeStatsDefCausl.RegisterStats(e.id, e.stats)
   940  		}
   941  		return true
   942  	}
   943  	return false
   944  }
   945  
   946  // batchCheckAndInsert checks rows with duplicate errors.
   947  // All duplicate rows will be ignored and appended as duplicate warnings.
   948  func (e *InsertValues) batchCheckAndInsert(ctx context.Context, rows [][]types.Causet, addRecord func(ctx context.Context, event []types.Causet) error) error {
   949  	// all the rows will be checked, so it is safe to set BatchCheck = true
   950  	e.ctx.GetStochastikVars().StmtCtx.BatchCheck = true
   951  
   952  	// Get keys need to be checked.
   953  	toBeCheckedEvents, err := getKeysNeedCheck(ctx, e.ctx, e.Block, rows)
   954  	if err != nil {
   955  		return err
   956  	}
   957  
   958  	txn, err := e.ctx.Txn(true)
   959  	if err != nil {
   960  		return err
   961  	}
   962  
   963  	if e.defCauslectRuntimeStatsEnabled() {
   964  		if snapshot := txn.GetSnapshot(); snapshot != nil {
   965  			snapshot.SetOption(ekv.DefCauslectRuntimeStats, e.stats.SnapshotRuntimeStats)
   966  			defer snapshot.DelOption(ekv.DefCauslectRuntimeStats)
   967  		}
   968  	}
   969  
   970  	// Fill cache using BatchGet, the following Get requests don't need to visit EinsteinDB.
   971  	if _, err = prefetchUniqueIndices(ctx, txn, toBeCheckedEvents); err != nil {
   972  		return err
   973  	}
   974  
   975  	// append warnings and get no duplicated error rows
   976  	for i, r := range toBeCheckedEvents {
   977  		skip := false
   978  		if r.handleKey != nil {
   979  			_, err := txn.Get(ctx, r.handleKey.newKey)
   980  			if err == nil {
   981  				e.ctx.GetStochastikVars().StmtCtx.AppendWarning(r.handleKey.dupErr)
   982  				continue
   983  			}
   984  			if !ekv.IsErrNotFound(err) {
   985  				return err
   986  			}
   987  		}
   988  		for _, uk := range r.uniqueKeys {
   989  			_, err := txn.Get(ctx, uk.newKey)
   990  			if err == nil {
   991  				// If duplicate keys were found in BatchGet, mark event = nil.
   992  				e.ctx.GetStochastikVars().StmtCtx.AppendWarning(uk.dupErr)
   993  				skip = true
   994  				break
   995  			}
   996  			if !ekv.IsErrNotFound(err) {
   997  				return err
   998  			}
   999  		}
  1000  		// If event was checked with no duplicate keys,
  1001  		// it should be add to values map for the further event check.
  1002  		// There may be duplicate keys inside the insert memex.
  1003  		if !skip {
  1004  			e.ctx.GetStochastikVars().StmtCtx.AddCopiedEvents(1)
  1005  			err = addRecord(ctx, rows[i])
  1006  			if err != nil {
  1007  				return err
  1008  			}
  1009  		}
  1010  	}
  1011  	return nil
  1012  }
  1013  
  1014  func (e *InsertValues) addRecord(ctx context.Context, event []types.Causet) error {
  1015  	return e.addRecordWithAutoIDHint(ctx, event, 0)
  1016  }
  1017  
  1018  func (e *InsertValues) addRecordWithAutoIDHint(ctx context.Context, event []types.Causet, reserveAutoIDCount int) (err error) {
  1019  	vars := e.ctx.GetStochastikVars()
  1020  	if !vars.ConstraintCheckInPlace {
  1021  		vars.PresumeKeyNotExists = true
  1022  	}
  1023  	if reserveAutoIDCount > 0 {
  1024  		_, err = e.Block.AddRecord(e.ctx, event, causet.WithCtx(ctx), causet.WithReserveAutoIDHint(reserveAutoIDCount))
  1025  	} else {
  1026  		_, err = e.Block.AddRecord(e.ctx, event, causet.WithCtx(ctx))
  1027  	}
  1028  	vars.PresumeKeyNotExists = false
  1029  	if err != nil {
  1030  		return err
  1031  	}
  1032  	if e.lastInsertID != 0 {
  1033  		vars.SetLastInsertID(e.lastInsertID)
  1034  	}
  1035  	return nil
  1036  }