github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/defcaus.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 dbs
    15  
    16  import (
    17  	"fmt"
    18  	"math"
    19  	"math/bits"
    20  	"strings"
    21  	"sync/atomic"
    22  	"time"
    23  
    24  	"github.com/cznic/mathutil"
    25  	"github.com/prometheus/client_golang/prometheus"
    26  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    27  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    28  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    29  	"github.com/whtcorpsinc/errors"
    30  	"github.com/whtcorpsinc/failpoint"
    31  	"github.com/whtcorpsinc/milevadb/blockcodec"
    32  	"github.com/whtcorpsinc/milevadb/causet"
    33  	dbsutil "github.com/whtcorpsinc/milevadb/dbs/soliton"
    34  	"github.com/whtcorpsinc/milevadb/ekv"
    35  	"github.com/whtcorpsinc/milevadb/metrics"
    36  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    37  	"github.com/whtcorpsinc/milevadb/soliton"
    38  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    39  	causetDecoder "github.com/whtcorpsinc/milevadb/soliton/rowCausetDecoder"
    40  	"github.com/whtcorpsinc/milevadb/soliton/sqlexec"
    41  	"github.com/whtcorpsinc/milevadb/soliton/timeutil"
    42  	"github.com/whtcorpsinc/milevadb/spacetime"
    43  	"github.com/whtcorpsinc/milevadb/spacetime/autoid"
    44  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    45  	"github.com/whtcorpsinc/milevadb/types"
    46  	"go.uber.org/zap"
    47  )
    48  
    49  
    50  func adjustDeferredCausetInfoInAddDeferredCauset(tblInfo *perceptron.BlockInfo, offset int) {
    51  	oldDefCauss := tblInfo.DeferredCausets
    52  	newDefCauss := make([]*perceptron.DeferredCausetInfo, 0, len(oldDefCauss))
    53  	newDefCauss = append(newDefCauss, oldDefCauss[:offset]...)
    54  	newDefCauss = append(newDefCauss, oldDefCauss[len(oldDefCauss)-1])
    55  	newDefCauss = append(newDefCauss, oldDefCauss[offset:len(oldDefCauss)-1]...)
    56  	// Adjust defCausumn offset.
    57  	offsetChanged := make(map[int]int, len(newDefCauss)-offset-1)
    58  	for i := offset + 1; i < len(newDefCauss); i++ {
    59  		offsetChanged[newDefCauss[i].Offset] = i
    60  		newDefCauss[i].Offset = i
    61  	}
    62  	newDefCauss[offset].Offset = offset
    63  	// UFIDelate index defCausumn offset info.
    64  	// TODO: There may be some corner cases for index defCausumn offsets, we may check this later.
    65  	for _, idx := range tblInfo.Indices {
    66  		for _, defCaus := range idx.DeferredCausets {
    67  			newOffset, ok := offsetChanged[defCaus.Offset]
    68  			if ok {
    69  				defCaus.Offset = newOffset
    70  			}
    71  		}
    72  	}
    73  	tblInfo.DeferredCausets = newDefCauss
    74  }
    75  
    76  
    77  func adjustDeferredCausetInfoInDropDeferredCauset(tblInfo *perceptron.BlockInfo, offset int) {
    78  	oldDefCauss := tblInfo.DeferredCausets
    79  	// Adjust defCausumn offset.
    80  	offsetChanged := make(map[int]int, len(oldDefCauss)-offset-1)
    81  	for i := offset + 1; i < len(oldDefCauss); i++ {
    82  		offsetChanged[oldDefCauss[i].Offset] = i - 1
    83  		oldDefCauss[i].Offset = i - 1
    84  	}
    85  	oldDefCauss[offset].Offset = len(oldDefCauss) - 1
    86  	// For memex index, we drop hidden defCausumns and index simultaneously.
    87  	// So we need to change the offset of memex index.
    88  	offsetChanged[offset] = len(oldDefCauss) - 1
    89  	// UFIDelate index defCausumn offset info.
    90  	// TODO: There may be some corner cases for index defCausumn offsets, we may check this later.
    91  	for _, idx := range tblInfo.Indices {
    92  		for _, defCaus := range idx.DeferredCausets {
    93  			newOffset, ok := offsetChanged[defCaus.Offset]
    94  			if ok {
    95  				defCaus.Offset = newOffset
    96  			}
    97  		}
    98  	}
    99  	newDefCauss := make([]*perceptron.DeferredCausetInfo, 0, len(oldDefCauss))
   100  	newDefCauss = append(newDefCauss, oldDefCauss[:offset]...)
   101  	newDefCauss = append(newDefCauss, oldDefCauss[offset+1:]...)
   102  	newDefCauss = append(newDefCauss, oldDefCauss[offset])
   103  	tblInfo.DeferredCausets = newDefCauss
   104  }
   105  
   106  func createDeferredCausetInfo(tblInfo *perceptron.BlockInfo, defCausInfo *perceptron.DeferredCausetInfo, pos *ast.DeferredCausetPosition) (*perceptron.DeferredCausetInfo, *ast.DeferredCausetPosition, int, error) {
   107  	// Check defCausumn name duplicate.
   108  	defcaus := tblInfo.DeferredCausets
   109  	offset := len(defcaus)
   110  	// Should initialize pos when it is nil.
   111  	if pos == nil {
   112  		pos = &ast.DeferredCausetPosition{}
   113  	}
   114  	// Get defCausumn offset.
   115  	if pos.Tp == ast.DeferredCausetPositionFirst {
   116  		offset = 0
   117  	} else if pos.Tp == ast.DeferredCausetPositionAfter {
   118  		c := perceptron.FindDeferredCausetInfo(defcaus, pos.RelativeDeferredCauset.Name.L)
   119  		if c == nil {
   120  			return nil, pos, 0, schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(pos.RelativeDeferredCauset, tblInfo.Name)
   121  		}
   122  
   123  		// Insert offset is after the mentioned defCausumn.
   124  		offset = c.Offset + 1
   125  	}
   126  	defCausInfo.ID = allocateDeferredCausetID(tblInfo)
   127  	defCausInfo.State = perceptron.StateNone
   128  	// To support add defCausumn asynchronous, we should mark its offset as the last defCausumn.
   129  	// So that we can use origin defCausumn offset to get value from event.
   130  	defCausInfo.Offset = len(defcaus)
   131  
   132  	// Append the defCausumn info to the end of the tblInfo.DeferredCausets.
   133  	// It will reorder to the right offset in "DeferredCausets" when it state change to public.
   134  	tblInfo.DeferredCausets = append(defcaus, defCausInfo)
   135  	return defCausInfo, pos, offset, nil
   136  }
   137  
   138  func checkAddDeferredCauset(t *spacetime.Meta, job *perceptron.Job) (*perceptron.BlockInfo, *perceptron.DeferredCausetInfo, *perceptron.DeferredCausetInfo, *ast.DeferredCausetPosition, int, error) {
   139  	schemaID := job.SchemaID
   140  	tblInfo, err := getBlockInfoAndCancelFaultJob(t, job, schemaID)
   141  	if err != nil {
   142  		return nil, nil, nil, nil, 0, errors.Trace(err)
   143  	}
   144  	defCaus := &perceptron.DeferredCausetInfo{}
   145  	pos := &ast.DeferredCausetPosition{}
   146  	offset := 0
   147  	err = job.DecodeArgs(defCaus, pos, &offset)
   148  	if err != nil {
   149  		job.State = perceptron.JobStateCancelled
   150  		return nil, nil, nil, nil, 0, errors.Trace(err)
   151  	}
   152  
   153  	defCausumnInfo := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, defCaus.Name.L)
   154  	if defCausumnInfo != nil {
   155  		if defCausumnInfo.State == perceptron.StatePublic {
   156  			// We already have a defCausumn with the same defCausumn name.
   157  			job.State = perceptron.JobStateCancelled
   158  			return nil, nil, nil, nil, 0, schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(defCaus.Name)
   159  		}
   160  	}
   161  	return tblInfo, defCausumnInfo, defCaus, pos, offset, nil
   162  }
   163  
   164  func onAddDeferredCauset(d *dbsCtx, t *spacetime.Meta, job *perceptron.Job) (ver int64, err error) {
   165  	// Handle the rolling back job.
   166  	if job.IsRollingback() {
   167  		ver, err = onDropDeferredCauset(t, job)
   168  		if err != nil {
   169  			return ver, errors.Trace(err)
   170  		}
   171  		return ver, nil
   172  	}
   173  
   174  	failpoint.Inject("errorBeforeDecodeArgs", func(val failpoint.Value) {
   175  		if val.(bool) {
   176  			failpoint.Return(ver, errors.New("occur an error before decode args"))
   177  		}
   178  	})
   179  
   180  	tblInfo, defCausumnInfo, defCaus, pos, offset, err := checkAddDeferredCauset(t, job)
   181  	if err != nil {
   182  		return ver, errors.Trace(err)
   183  	}
   184  	if defCausumnInfo == nil {
   185  		defCausumnInfo, _, offset, err = createDeferredCausetInfo(tblInfo, defCaus, pos)
   186  		if err != nil {
   187  			job.State = perceptron.JobStateCancelled
   188  			return ver, errors.Trace(err)
   189  		}
   190  		logutil.BgLogger().Info("[dbs] run add defCausumn job", zap.String("job", job.String()), zap.Reflect("defCausumnInfo", *defCausumnInfo), zap.Int("offset", offset))
   191  		// Set offset arg to job.
   192  		if offset != 0 {
   193  			job.Args = []interface{}{defCausumnInfo, pos, offset}
   194  		}
   195  		if err = checkAddDeferredCausetTooManyDeferredCausets(len(tblInfo.DeferredCausets)); err != nil {
   196  			job.State = perceptron.JobStateCancelled
   197  			return ver, errors.Trace(err)
   198  		}
   199  	}
   200  
   201  	originalState := defCausumnInfo.State
   202  	switch defCausumnInfo.State {
   203  	case perceptron.StateNone:
   204  		// none -> delete only
   205  		job.SchemaState = perceptron.StateDeleteOnly
   206  		defCausumnInfo.State = perceptron.StateDeleteOnly
   207  		ver, err = uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, originalState != defCausumnInfo.State)
   208  	case perceptron.StateDeleteOnly:
   209  		// delete only -> write only
   210  		job.SchemaState = perceptron.StateWriteOnly
   211  		defCausumnInfo.State = perceptron.StateWriteOnly
   212  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausumnInfo.State)
   213  	case perceptron.StateWriteOnly:
   214  		// write only -> reorganization
   215  		job.SchemaState = perceptron.StateWriteReorganization
   216  		defCausumnInfo.State = perceptron.StateWriteReorganization
   217  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausumnInfo.State)
   218  	case perceptron.StateWriteReorganization:
   219  		// reorganization -> public
   220  		// Adjust causet defCausumn offset.
   221  		adjustDeferredCausetInfoInAddDeferredCauset(tblInfo, offset)
   222  		defCausumnInfo.State = perceptron.StatePublic
   223  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausumnInfo.State)
   224  		if err != nil {
   225  			return ver, errors.Trace(err)
   226  		}
   227  
   228  		// Finish this job.
   229  		job.FinishBlockJob(perceptron.JobStateDone, perceptron.StatePublic, ver, tblInfo)
   230  		asyncNotifyEvent(d, &dbsutil.Event{Tp: perceptron.CausetActionAddDeferredCauset, BlockInfo: tblInfo, DeferredCausetInfos: []*perceptron.DeferredCausetInfo{defCausumnInfo}})
   231  	default:
   232  		err = ErrInvalidDBSState.GenWithStackByArgs("defCausumn", defCausumnInfo.State)
   233  	}
   234  
   235  	return ver, errors.Trace(err)
   236  }
   237  
   238  func checkAddDeferredCausets(t *spacetime.Meta, job *perceptron.Job) (*perceptron.BlockInfo, []*perceptron.DeferredCausetInfo, []*perceptron.DeferredCausetInfo, []*ast.DeferredCausetPosition, []int, []bool, error) {
   239  	schemaID := job.SchemaID
   240  	tblInfo, err := getBlockInfoAndCancelFaultJob(t, job, schemaID)
   241  	if err != nil {
   242  		return nil, nil, nil, nil, nil, nil, errors.Trace(err)
   243  	}
   244  	defCausumns := []*perceptron.DeferredCausetInfo{}
   245  	positions := []*ast.DeferredCausetPosition{}
   246  	offsets := []int{}
   247  	ifNotExists := []bool{}
   248  	err = job.DecodeArgs(&defCausumns, &positions, &offsets, &ifNotExists)
   249  	if err != nil {
   250  		job.State = perceptron.JobStateCancelled
   251  		return nil, nil, nil, nil, nil, nil, errors.Trace(err)
   252  	}
   253  
   254  	defCausumnInfos := make([]*perceptron.DeferredCausetInfo, 0, len(defCausumns))
   255  	newDeferredCausets := make([]*perceptron.DeferredCausetInfo, 0, len(defCausumns))
   256  	newPositions := make([]*ast.DeferredCausetPosition, 0, len(defCausumns))
   257  	newOffsets := make([]int, 0, len(defCausumns))
   258  	newIfNotExists := make([]bool, 0, len(defCausumns))
   259  	for i, defCaus := range defCausumns {
   260  		defCausumnInfo := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, defCaus.Name.L)
   261  		if defCausumnInfo != nil {
   262  			if defCausumnInfo.State == perceptron.StatePublic {
   263  				// We already have a defCausumn with the same defCausumn name.
   264  				if ifNotExists[i] {
   265  					// TODO: Should return a warning.
   266  					logutil.BgLogger().Warn("[dbs] check add defCausumns, duplicate defCausumn", zap.Stringer("defCaus", defCaus.Name))
   267  					continue
   268  				}
   269  				job.State = perceptron.JobStateCancelled
   270  				return nil, nil, nil, nil, nil, nil, schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(defCaus.Name)
   271  			}
   272  			defCausumnInfos = append(defCausumnInfos, defCausumnInfo)
   273  		}
   274  		newDeferredCausets = append(newDeferredCausets, defCausumns[i])
   275  		newPositions = append(newPositions, positions[i])
   276  		newOffsets = append(newOffsets, offsets[i])
   277  		newIfNotExists = append(newIfNotExists, ifNotExists[i])
   278  	}
   279  	return tblInfo, defCausumnInfos, newDeferredCausets, newPositions, newOffsets, newIfNotExists, nil
   280  }
   281  
   282  func setDeferredCausetsState(defCausumnInfos []*perceptron.DeferredCausetInfo, state perceptron.SchemaState) {
   283  	for i := range defCausumnInfos {
   284  		defCausumnInfos[i].State = state
   285  	}
   286  }
   287  
   288  func setIndicesState(indexInfos []*perceptron.IndexInfo, state perceptron.SchemaState) {
   289  	for _, indexInfo := range indexInfos {
   290  		indexInfo.State = state
   291  	}
   292  }
   293  
   294  func onAddDeferredCausets(d *dbsCtx, t *spacetime.Meta, job *perceptron.Job) (ver int64, err error) {
   295  	// Handle the rolling back job.
   296  	if job.IsRollingback() {
   297  		ver, err = onDropDeferredCausets(t, job)
   298  		if err != nil {
   299  			return ver, errors.Trace(err)
   300  		}
   301  		return ver, nil
   302  	}
   303  
   304  	failpoint.Inject("errorBeforeDecodeArgs", func(val failpoint.Value) {
   305  		if val.(bool) {
   306  			failpoint.Return(ver, errors.New("occur an error before decode args"))
   307  		}
   308  	})
   309  
   310  	tblInfo, defCausumnInfos, defCausumns, positions, offsets, ifNotExists, err := checkAddDeferredCausets(t, job)
   311  	if err != nil {
   312  		return ver, errors.Trace(err)
   313  	}
   314  	if len(defCausumnInfos) == 0 {
   315  		if len(defCausumns) == 0 {
   316  			job.State = perceptron.JobStateCancelled
   317  			return ver, nil
   318  		}
   319  		for i := range defCausumns {
   320  			defCausumnInfo, pos, offset, err := createDeferredCausetInfo(tblInfo, defCausumns[i], positions[i])
   321  			if err != nil {
   322  				job.State = perceptron.JobStateCancelled
   323  				return ver, errors.Trace(err)
   324  			}
   325  			logutil.BgLogger().Info("[dbs] run add defCausumns job", zap.String("job", job.String()), zap.Reflect("defCausumnInfo", *defCausumnInfo), zap.Int("offset", offset))
   326  			positions[i] = pos
   327  			offsets[i] = offset
   328  			if err = checkAddDeferredCausetTooManyDeferredCausets(len(tblInfo.DeferredCausets)); err != nil {
   329  				job.State = perceptron.JobStateCancelled
   330  				return ver, errors.Trace(err)
   331  			}
   332  			defCausumnInfos = append(defCausumnInfos, defCausumnInfo)
   333  		}
   334  		// Set arg to job.
   335  		job.Args = []interface{}{defCausumnInfos, positions, offsets, ifNotExists}
   336  	}
   337  
   338  	originalState := defCausumnInfos[0].State
   339  	switch defCausumnInfos[0].State {
   340  	case perceptron.StateNone:
   341  		// none -> delete only
   342  		job.SchemaState = perceptron.StateDeleteOnly
   343  		setDeferredCausetsState(defCausumnInfos, perceptron.StateDeleteOnly)
   344  		ver, err = uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, originalState != defCausumnInfos[0].State)
   345  	case perceptron.StateDeleteOnly:
   346  		// delete only -> write only
   347  		job.SchemaState = perceptron.StateWriteOnly
   348  		setDeferredCausetsState(defCausumnInfos, perceptron.StateWriteOnly)
   349  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausumnInfos[0].State)
   350  	case perceptron.StateWriteOnly:
   351  		// write only -> reorganization
   352  		job.SchemaState = perceptron.StateWriteReorganization
   353  		setDeferredCausetsState(defCausumnInfos, perceptron.StateWriteReorganization)
   354  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausumnInfos[0].State)
   355  	case perceptron.StateWriteReorganization:
   356  		// reorganization -> public
   357  		// Adjust causet defCausumn offsets.
   358  		oldDefCauss := tblInfo.DeferredCausets[:len(tblInfo.DeferredCausets)-len(offsets)]
   359  		newDefCauss := tblInfo.DeferredCausets[len(tblInfo.DeferredCausets)-len(offsets):]
   360  		tblInfo.DeferredCausets = oldDefCauss
   361  		for i := range offsets {
   362  			// For multiple defCausumns with after position, should adjust offsets.
   363  			// e.g. create causet t(a int);
   364  			// alter causet t add defCausumn b int after a, add defCausumn c int after a;
   365  			// alter causet t add defCausumn a1 int after a, add defCausumn b1 int after b, add defCausumn c1 int after c;
   366  			// alter causet t add defCausumn a1 int after a, add defCausumn b1 int first;
   367  			if positions[i].Tp == ast.DeferredCausetPositionAfter {
   368  				for j := 0; j < i; j++ {
   369  					if (positions[j].Tp == ast.DeferredCausetPositionAfter && offsets[j] < offsets[i]) || positions[j].Tp == ast.DeferredCausetPositionFirst {
   370  						offsets[i]++
   371  					}
   372  				}
   373  			}
   374  			tblInfo.DeferredCausets = append(tblInfo.DeferredCausets, newDefCauss[i])
   375  			adjustDeferredCausetInfoInAddDeferredCauset(tblInfo, offsets[i])
   376  		}
   377  		setDeferredCausetsState(defCausumnInfos, perceptron.StatePublic)
   378  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausumnInfos[0].State)
   379  		if err != nil {
   380  			return ver, errors.Trace(err)
   381  		}
   382  		// Finish this job.
   383  		job.FinishBlockJob(perceptron.JobStateDone, perceptron.StatePublic, ver, tblInfo)
   384  		asyncNotifyEvent(d, &dbsutil.Event{Tp: perceptron.CausetActionAddDeferredCausets, BlockInfo: tblInfo, DeferredCausetInfos: defCausumnInfos})
   385  	default:
   386  		err = ErrInvalidDBSState.GenWithStackByArgs("defCausumn", defCausumnInfos[0].State)
   387  	}
   388  
   389  	return ver, errors.Trace(err)
   390  }
   391  
   392  func onDropDeferredCausets(t *spacetime.Meta, job *perceptron.Job) (ver int64, _ error) {
   393  	tblInfo, defCausInfos, delCount, idxInfos, err := checkDropDeferredCausets(t, job)
   394  	if err != nil {
   395  		return ver, errors.Trace(err)
   396  	}
   397  	if len(defCausInfos) == 0 {
   398  		job.State = perceptron.JobStateCancelled
   399  		return ver, nil
   400  	}
   401  
   402  	originalState := defCausInfos[0].State
   403  	switch defCausInfos[0].State {
   404  	case perceptron.StatePublic:
   405  		// public -> write only
   406  		job.SchemaState = perceptron.StateWriteOnly
   407  		setDeferredCausetsState(defCausInfos, perceptron.StateWriteOnly)
   408  		setIndicesState(idxInfos, perceptron.StateWriteOnly)
   409  		for _, defCausInfo := range defCausInfos {
   410  			err = checkDropDeferredCausetForStatePublic(tblInfo, defCausInfo)
   411  			if err != nil {
   412  				return ver, errors.Trace(err)
   413  			}
   414  		}
   415  		ver, err = uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, originalState != defCausInfos[0].State)
   416  	case perceptron.StateWriteOnly:
   417  		// write only -> delete only
   418  		job.SchemaState = perceptron.StateDeleteOnly
   419  		setDeferredCausetsState(defCausInfos, perceptron.StateDeleteOnly)
   420  		setIndicesState(idxInfos, perceptron.StateDeleteOnly)
   421  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausInfos[0].State)
   422  	case perceptron.StateDeleteOnly:
   423  		// delete only -> reorganization
   424  		job.SchemaState = perceptron.StateDeleteReorganization
   425  		setDeferredCausetsState(defCausInfos, perceptron.StateDeleteReorganization)
   426  		setIndicesState(idxInfos, perceptron.StateDeleteReorganization)
   427  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausInfos[0].State)
   428  	case perceptron.StateDeleteReorganization:
   429  		// reorganization -> absent
   430  		// All reorganization jobs are done, drop this defCausumn.
   431  		if len(idxInfos) > 0 {
   432  			newIndices := make([]*perceptron.IndexInfo, 0, len(tblInfo.Indices))
   433  			for _, idx := range tblInfo.Indices {
   434  				if !indexInfoContains(idx.ID, idxInfos) {
   435  					newIndices = append(newIndices, idx)
   436  				}
   437  			}
   438  			tblInfo.Indices = newIndices
   439  		}
   440  
   441  		indexIDs := indexInfosToIDList(idxInfos)
   442  		tblInfo.DeferredCausets = tblInfo.DeferredCausets[:len(tblInfo.DeferredCausets)-delCount]
   443  		setDeferredCausetsState(defCausInfos, perceptron.StateNone)
   444  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausInfos[0].State)
   445  		if err != nil {
   446  			return ver, errors.Trace(err)
   447  		}
   448  
   449  		// Finish this job.
   450  		if job.IsRollingback() {
   451  			job.FinishBlockJob(perceptron.JobStateRollbackDone, perceptron.StateNone, ver, tblInfo)
   452  		} else {
   453  			job.FinishBlockJob(perceptron.JobStateDone, perceptron.StateNone, ver, tblInfo)
   454  			job.Args = append(job.Args, indexIDs, getPartitionIDs(tblInfo))
   455  		}
   456  	default:
   457  		err = errInvalidDBSJob.GenWithStackByArgs("causet", tblInfo.State)
   458  	}
   459  	return ver, errors.Trace(err)
   460  }
   461  
   462  func checkDropDeferredCausets(t *spacetime.Meta, job *perceptron.Job) (*perceptron.BlockInfo, []*perceptron.DeferredCausetInfo, int, []*perceptron.IndexInfo, error) {
   463  	schemaID := job.SchemaID
   464  	tblInfo, err := getBlockInfoAndCancelFaultJob(t, job, schemaID)
   465  	if err != nil {
   466  		return nil, nil, 0, nil, errors.Trace(err)
   467  	}
   468  
   469  	var defCausNames []perceptron.CIStr
   470  	var ifExists []bool
   471  	err = job.DecodeArgs(&defCausNames, &ifExists)
   472  	if err != nil {
   473  		job.State = perceptron.JobStateCancelled
   474  		return nil, nil, 0, nil, errors.Trace(err)
   475  	}
   476  
   477  	newDefCausNames := make([]perceptron.CIStr, 0, len(defCausNames))
   478  	defCausInfos := make([]*perceptron.DeferredCausetInfo, 0, len(defCausNames))
   479  	newIfExists := make([]bool, 0, len(defCausNames))
   480  	indexInfos := make([]*perceptron.IndexInfo, 0)
   481  	for i, defCausName := range defCausNames {
   482  		defCausInfo := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, defCausName.L)
   483  		if defCausInfo == nil || defCausInfo.Hidden {
   484  			if ifExists[i] {
   485  				// TODO: Should return a warning.
   486  				logutil.BgLogger().Warn(fmt.Sprintf("defCausumn %s doesn't exist", defCausName))
   487  				continue
   488  			}
   489  			job.State = perceptron.JobStateCancelled
   490  			return nil, nil, 0, nil, ErrCantDropFieldOrKey.GenWithStack("defCausumn %s doesn't exist", defCausName)
   491  		}
   492  		if err = isDroppableDeferredCauset(tblInfo, defCausName); err != nil {
   493  			job.State = perceptron.JobStateCancelled
   494  			return nil, nil, 0, nil, errors.Trace(err)
   495  		}
   496  		newDefCausNames = append(newDefCausNames, defCausName)
   497  		newIfExists = append(newIfExists, ifExists[i])
   498  		defCausInfos = append(defCausInfos, defCausInfo)
   499  		idxInfos := listIndicesWithDeferredCauset(defCausName.L, tblInfo.Indices)
   500  		indexInfos = append(indexInfos, idxInfos...)
   501  	}
   502  	job.Args = []interface{}{newDefCausNames, newIfExists}
   503  	return tblInfo, defCausInfos, len(defCausInfos), indexInfos, nil
   504  }
   505  
   506  func checkDropDeferredCausetForStatePublic(tblInfo *perceptron.BlockInfo, defCausInfo *perceptron.DeferredCausetInfo) (err error) {
   507  	// Set this defCausumn's offset to the last and reset all following defCausumns' offsets.
   508  	adjustDeferredCausetInfoInDropDeferredCauset(tblInfo, defCausInfo.Offset)
   509  	// When the dropping defCausumn has not-null flag and it hasn't the default value, we can backfill the defCausumn value like "add defCausumn".
   510  	// NOTE: If the state of StateWriteOnly can be rollbacked, we'd better reconsider the original default value.
   511  	// And we need consider the defCausumn without not-null flag.
   512  	if defCausInfo.OriginDefaultValue == nil && allegrosql.HasNotNullFlag(defCausInfo.Flag) {
   513  		// If the defCausumn is timestamp default current_timestamp, and DBS tenant is new version MilevaDB that set defCausumn.Version to 1,
   514  		// then old MilevaDB uFIDelate record in the defCausumn write only stage will uses the wrong default value of the dropping defCausumn.
   515  		// Because new version of the defCausumn default value is UTC time, but old version MilevaDB will think the default value is the time in system timezone.
   516  		// But currently will be ok, because we can't cancel the drop defCausumn job when the job is running,
   517  		// so the defCausumn will be dropped succeed and client will never see the wrong default value of the dropped defCausumn.
   518  		// More info about this problem, see PR#9115.
   519  		defCausInfo.OriginDefaultValue, err = generateOriginDefaultValue(defCausInfo)
   520  		if err != nil {
   521  			return err
   522  		}
   523  	}
   524  	return nil
   525  }
   526  
   527  func onDropDeferredCauset(t *spacetime.Meta, job *perceptron.Job) (ver int64, _ error) {
   528  	tblInfo, defCausInfo, idxInfos, err := checkDropDeferredCauset(t, job)
   529  	if err != nil {
   530  		return ver, errors.Trace(err)
   531  	}
   532  
   533  	originalState := defCausInfo.State
   534  	switch defCausInfo.State {
   535  	case perceptron.StatePublic:
   536  		// public -> write only
   537  		job.SchemaState = perceptron.StateWriteOnly
   538  		defCausInfo.State = perceptron.StateWriteOnly
   539  		setIndicesState(idxInfos, perceptron.StateWriteOnly)
   540  		err = checkDropDeferredCausetForStatePublic(tblInfo, defCausInfo)
   541  		if err != nil {
   542  			return ver, errors.Trace(err)
   543  		}
   544  		ver, err = uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, originalState != defCausInfo.State)
   545  	case perceptron.StateWriteOnly:
   546  		// write only -> delete only
   547  		job.SchemaState = perceptron.StateDeleteOnly
   548  		defCausInfo.State = perceptron.StateDeleteOnly
   549  		setIndicesState(idxInfos, perceptron.StateDeleteOnly)
   550  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausInfo.State)
   551  	case perceptron.StateDeleteOnly:
   552  		// delete only -> reorganization
   553  		job.SchemaState = perceptron.StateDeleteReorganization
   554  		defCausInfo.State = perceptron.StateDeleteReorganization
   555  		setIndicesState(idxInfos, perceptron.StateDeleteReorganization)
   556  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausInfo.State)
   557  	case perceptron.StateDeleteReorganization:
   558  		// reorganization -> absent
   559  		// All reorganization jobs are done, drop this defCausumn.
   560  		if len(idxInfos) > 0 {
   561  			newIndices := make([]*perceptron.IndexInfo, 0, len(tblInfo.Indices))
   562  			for _, idx := range tblInfo.Indices {
   563  				if !indexInfoContains(idx.ID, idxInfos) {
   564  					newIndices = append(newIndices, idx)
   565  				}
   566  			}
   567  			tblInfo.Indices = newIndices
   568  		}
   569  
   570  		indexIDs := indexInfosToIDList(idxInfos)
   571  		tblInfo.DeferredCausets = tblInfo.DeferredCausets[:len(tblInfo.DeferredCausets)-1]
   572  		defCausInfo.State = perceptron.StateNone
   573  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != defCausInfo.State)
   574  		if err != nil {
   575  			return ver, errors.Trace(err)
   576  		}
   577  
   578  		// Finish this job.
   579  		if job.IsRollingback() {
   580  			job.FinishBlockJob(perceptron.JobStateRollbackDone, perceptron.StateNone, ver, tblInfo)
   581  		} else {
   582  			// We should set related index IDs for job
   583  			job.FinishBlockJob(perceptron.JobStateDone, perceptron.StateNone, ver, tblInfo)
   584  			job.Args = append(job.Args, indexIDs, getPartitionIDs(tblInfo))
   585  		}
   586  	default:
   587  		err = errInvalidDBSJob.GenWithStackByArgs("causet", tblInfo.State)
   588  	}
   589  	return ver, errors.Trace(err)
   590  }
   591  
   592  func checkDropDeferredCauset(t *spacetime.Meta, job *perceptron.Job) (*perceptron.BlockInfo, *perceptron.DeferredCausetInfo, []*perceptron.IndexInfo, error) {
   593  	schemaID := job.SchemaID
   594  	tblInfo, err := getBlockInfoAndCancelFaultJob(t, job, schemaID)
   595  	if err != nil {
   596  		return nil, nil, nil, errors.Trace(err)
   597  	}
   598  
   599  	var defCausName perceptron.CIStr
   600  	err = job.DecodeArgs(&defCausName)
   601  	if err != nil {
   602  		job.State = perceptron.JobStateCancelled
   603  		return nil, nil, nil, errors.Trace(err)
   604  	}
   605  
   606  	defCausInfo := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, defCausName.L)
   607  	if defCausInfo == nil || defCausInfo.Hidden {
   608  		job.State = perceptron.JobStateCancelled
   609  		return nil, nil, nil, ErrCantDropFieldOrKey.GenWithStack("defCausumn %s doesn't exist", defCausName)
   610  	}
   611  	if err = isDroppableDeferredCauset(tblInfo, defCausName); err != nil {
   612  		job.State = perceptron.JobStateCancelled
   613  		return nil, nil, nil, errors.Trace(err)
   614  	}
   615  	idxInfos := listIndicesWithDeferredCauset(defCausName.L, tblInfo.Indices)
   616  	if len(idxInfos) > 0 {
   617  		for _, idxInfo := range idxInfos {
   618  			err = checkDropIndexOnAutoIncrementDeferredCauset(tblInfo, idxInfo)
   619  			if err != nil {
   620  				job.State = perceptron.JobStateCancelled
   621  				return nil, nil, nil, err
   622  			}
   623  		}
   624  	}
   625  	return tblInfo, defCausInfo, idxInfos, nil
   626  }
   627  
   628  func onSetDefaultValue(t *spacetime.Meta, job *perceptron.Job) (ver int64, _ error) {
   629  	newDefCaus := &perceptron.DeferredCausetInfo{}
   630  	err := job.DecodeArgs(newDefCaus)
   631  	if err != nil {
   632  		job.State = perceptron.JobStateCancelled
   633  		return ver, errors.Trace(err)
   634  	}
   635  
   636  	return uFIDelateDeferredCausetDefaultValue(t, job, newDefCaus, &newDefCaus.Name)
   637  }
   638  
   639  func needChangeDeferredCausetData(oldDefCaus, newDefCaus *perceptron.DeferredCausetInfo) bool {
   640  	toUnsigned := allegrosql.HasUnsignedFlag(newDefCaus.Flag)
   641  	originUnsigned := allegrosql.HasUnsignedFlag(oldDefCaus.Flag)
   642  	if newDefCaus.Flen > 0 && newDefCaus.Flen < oldDefCaus.Flen || toUnsigned != originUnsigned {
   643  		return true
   644  	}
   645  
   646  	return false
   647  }
   648  
   649  type modifyDeferredCausetJobParameter struct {
   650  	newDefCaus               *perceptron.DeferredCausetInfo
   651  	oldDefCausName           *perceptron.CIStr
   652  	modifyDeferredCausetTp   byte
   653  	uFIDelatedAutoRandomBits uint64
   654  	changingDefCaus          *perceptron.DeferredCausetInfo
   655  	changingIdxs             []*perceptron.IndexInfo
   656  	pos                      *ast.DeferredCausetPosition
   657  }
   658  
   659  func getModifyDeferredCausetInfo(t *spacetime.Meta, job *perceptron.Job) (*perceptron.DBInfo, *perceptron.BlockInfo, *perceptron.DeferredCausetInfo, *modifyDeferredCausetJobParameter, error) {
   660  	jobParam := &modifyDeferredCausetJobParameter{pos: &ast.DeferredCausetPosition{}}
   661  	err := job.DecodeArgs(&jobParam.newDefCaus, &jobParam.oldDefCausName, jobParam.pos, &jobParam.modifyDeferredCausetTp, &jobParam.uFIDelatedAutoRandomBits, &jobParam.changingDefCaus, &jobParam.changingIdxs)
   662  	if err != nil {
   663  		job.State = perceptron.JobStateCancelled
   664  		return nil, nil, nil, jobParam, errors.Trace(err)
   665  	}
   666  
   667  	dbInfo, err := checkSchemaExistAndCancelNotExistJob(t, job)
   668  	if err != nil {
   669  		return nil, nil, nil, jobParam, errors.Trace(err)
   670  	}
   671  
   672  	tblInfo, err := getBlockInfoAndCancelFaultJob(t, job, job.SchemaID)
   673  	if err != nil {
   674  		return nil, nil, nil, jobParam, errors.Trace(err)
   675  	}
   676  
   677  	oldDefCaus := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, jobParam.oldDefCausName.L)
   678  	if oldDefCaus == nil || oldDefCaus.State != perceptron.StatePublic {
   679  		job.State = perceptron.JobStateCancelled
   680  		return nil, nil, nil, jobParam, errors.Trace(schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(*(jobParam.oldDefCausName), tblInfo.Name))
   681  	}
   682  
   683  	return dbInfo, tblInfo, oldDefCaus, jobParam, errors.Trace(err)
   684  }
   685  
   686  func (w *worker) onModifyDeferredCauset(d *dbsCtx, t *spacetime.Meta, job *perceptron.Job) (ver int64, _ error) {
   687  	dbInfo, tblInfo, oldDefCaus, jobParam, err := getModifyDeferredCausetInfo(t, job)
   688  	if err != nil {
   689  		return ver, err
   690  	}
   691  
   692  	if job.IsRollingback() {
   693  		// For those defCausumn-type-change jobs which don't reorg the data.
   694  		if !needChangeDeferredCausetData(oldDefCaus, jobParam.newDefCaus) {
   695  			return rollbackModifyDeferredCausetJob(t, tblInfo, job, oldDefCaus, jobParam.modifyDeferredCausetTp)
   696  		}
   697  		// For those defCausumn-type-change jobs which reorg the data.
   698  		return rollbackModifyDeferredCausetJobWithData(t, tblInfo, job, oldDefCaus, jobParam)
   699  	}
   700  
   701  	// If we want to rename the defCausumn name, we need to check whether it already exists.
   702  	if jobParam.newDefCaus.Name.L != jobParam.oldDefCausName.L {
   703  		c := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, jobParam.newDefCaus.Name.L)
   704  		if c != nil {
   705  			job.State = perceptron.JobStateCancelled
   706  			return ver, errors.Trace(schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs(jobParam.newDefCaus.Name))
   707  		}
   708  	}
   709  
   710  	failpoint.Inject("uninitializedOffsetAndState", func(val failpoint.Value) {
   711  		if val.(bool) {
   712  			if jobParam.newDefCaus.State != perceptron.StatePublic {
   713  				failpoint.Return(ver, errors.New("the defCausumn state is wrong"))
   714  			}
   715  		}
   716  	})
   717  
   718  	if jobParam.uFIDelatedAutoRandomBits > 0 {
   719  		if err := checkAndApplyNewAutoRandomBits(job, t, tblInfo, jobParam.newDefCaus, jobParam.oldDefCausName, jobParam.uFIDelatedAutoRandomBits); err != nil {
   720  			return ver, errors.Trace(err)
   721  		}
   722  	}
   723  
   724  	if !needChangeDeferredCausetData(oldDefCaus, jobParam.newDefCaus) {
   725  		return w.doModifyDeferredCauset(t, job, dbInfo, tblInfo, jobParam.newDefCaus, oldDefCaus, jobParam.pos)
   726  	}
   727  
   728  	if jobParam.changingDefCaus == nil {
   729  		changingDefCausPos := &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}
   730  		newDefCausName := perceptron.NewCIStr(fmt.Sprintf("%s%s", changingDeferredCausetPrefix, oldDefCaus.Name.O))
   731  		if allegrosql.HasPriKeyFlag(oldDefCaus.Flag) {
   732  			job.State = perceptron.JobStateCancelled
   733  			msg := "milevadb_enable_change_defCausumn_type is true and this defCausumn has primary key flag"
   734  			return ver, errUnsupportedModifyDeferredCauset.GenWithStackByArgs(msg)
   735  		}
   736  		// TODO: Check whether we need to check OriginDefaultValue.
   737  		jobParam.changingDefCaus = jobParam.newDefCaus.Clone()
   738  		jobParam.changingDefCaus.Name = newDefCausName
   739  		jobParam.changingDefCaus.ChangeStateInfo = &perceptron.ChangeStateInfo{DependencyDeferredCausetOffset: oldDefCaus.Offset}
   740  		_, _, _, err := createDeferredCausetInfo(tblInfo, jobParam.changingDefCaus, changingDefCausPos)
   741  		if err != nil {
   742  			job.State = perceptron.JobStateCancelled
   743  			return ver, errors.Trace(err)
   744  		}
   745  
   746  		idxInfos, offsets := findIndexesByDefCausName(tblInfo.Indices, oldDefCaus.Name.L)
   747  		jobParam.changingIdxs = make([]*perceptron.IndexInfo, 0, len(idxInfos))
   748  		for i, idxInfo := range idxInfos {
   749  			newIdxInfo := idxInfo.Clone()
   750  			newIdxInfo.Name = perceptron.NewCIStr(fmt.Sprintf("%s%s", changingIndexPrefix, newIdxInfo.Name.O))
   751  			newIdxInfo.ID = allocateIndexID(tblInfo)
   752  			newIdxInfo.DeferredCausets[offsets[i]].Name = newDefCausName
   753  			newIdxInfo.DeferredCausets[offsets[i]].Offset = jobParam.changingDefCaus.Offset
   754  			jobParam.changingIdxs = append(jobParam.changingIdxs, newIdxInfo)
   755  		}
   756  		tblInfo.Indices = append(tblInfo.Indices, jobParam.changingIdxs...)
   757  	} else {
   758  		tblInfo.DeferredCausets[len(tblInfo.DeferredCausets)-1] = jobParam.changingDefCaus
   759  		copy(tblInfo.Indices[len(tblInfo.Indices)-len(jobParam.changingIdxs):], jobParam.changingIdxs)
   760  	}
   761  
   762  	return w.doModifyDeferredCausetTypeWithData(d, t, job, dbInfo, tblInfo, jobParam.changingDefCaus, oldDefCaus, jobParam.newDefCaus.Name, jobParam.pos, jobParam.changingIdxs)
   763  }
   764  
   765  // rollbackModifyDeferredCausetJobWithData is used to rollback modify-defCausumn job which need to reorg the data.
   766  func rollbackModifyDeferredCausetJobWithData(t *spacetime.Meta, tblInfo *perceptron.BlockInfo, job *perceptron.Job, oldDefCaus *perceptron.DeferredCausetInfo, jobParam *modifyDeferredCausetJobParameter) (ver int64, err error) {
   767  	// If the not-null change is included, we should clean the flag info in oldDefCaus.
   768  	if jobParam.modifyDeferredCausetTp == allegrosql.TypeNull {
   769  		// Reset NotNullFlag flag.
   770  		tblInfo.DeferredCausets[oldDefCaus.Offset].Flag = oldDefCaus.Flag &^ allegrosql.NotNullFlag
   771  		// Reset PreventNullInsertFlag flag.
   772  		tblInfo.DeferredCausets[oldDefCaus.Offset].Flag = oldDefCaus.Flag &^ allegrosql.PreventNullInsertFlag
   773  	}
   774  	if jobParam.changingDefCaus != nil {
   775  		// changingDefCaus isn't nil means the job has been in the mid state. These appended changingDefCaus and changingIndex should
   776  		// be removed from the blockInfo as well.
   777  		tblInfo.DeferredCausets = tblInfo.DeferredCausets[:len(tblInfo.DeferredCausets)-1]
   778  		tblInfo.Indices = tblInfo.Indices[:len(tblInfo.Indices)-len(jobParam.changingIdxs)]
   779  	}
   780  	ver, err = uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, true)
   781  	if err != nil {
   782  		return ver, errors.Trace(err)
   783  	}
   784  	job.FinishBlockJob(perceptron.JobStateRollbackDone, perceptron.StateNone, ver, tblInfo)
   785  	// Refactor the job args to add the abandoned temporary index ids into delete range causet.
   786  	idxIDs := make([]int64, 0, len(jobParam.changingIdxs))
   787  	for _, idx := range jobParam.changingIdxs {
   788  		idxIDs = append(idxIDs, idx.ID)
   789  	}
   790  	job.Args = []interface{}{idxIDs, getPartitionIDs(tblInfo)}
   791  	return ver, nil
   792  }
   793  
   794  func (w *worker) doModifyDeferredCausetTypeWithData(
   795  	d *dbsCtx, t *spacetime.Meta, job *perceptron.Job,
   796  	dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, changingDefCaus, oldDefCaus *perceptron.DeferredCausetInfo,
   797  	defCausName perceptron.CIStr, pos *ast.DeferredCausetPosition, changingIdxs []*perceptron.IndexInfo) (ver int64, _ error) {
   798  	var err error
   799  	originalState := changingDefCaus.State
   800  	switch changingDefCaus.State {
   801  	case perceptron.StateNone:
   802  		// DeferredCauset from null to not null.
   803  		if !allegrosql.HasNotNullFlag(oldDefCaus.Flag) && allegrosql.HasNotNullFlag(changingDefCaus.Flag) {
   804  			// Introduce the `allegrosql.PreventNullInsertFlag` flag to prevent users from inserting or uFIDelating null values.
   805  			err := modifyDefCaussFromNull2NotNull(w, dbInfo, tblInfo, []*perceptron.DeferredCausetInfo{oldDefCaus}, oldDefCaus.Name, oldDefCaus.Tp != changingDefCaus.Tp)
   806  			if err != nil {
   807  				if ErrWarnDataTruncated.Equal(err) || errInvalidUseOfNull.Equal(err) {
   808  					job.State = perceptron.JobStateRollingback
   809  				}
   810  				return ver, err
   811  			}
   812  		}
   813  		// none -> delete only
   814  		uFIDelateChangingInfo(changingDefCaus, changingIdxs, perceptron.StateDeleteOnly)
   815  		failpoint.Inject("mockInsertValueAfterCheckNull", func(val failpoint.Value) {
   816  			if valStr, ok := val.(string); ok {
   817  				var ctx stochastikctx.Context
   818  				ctx, err := w.sessPool.get()
   819  				if err != nil {
   820  					failpoint.Return(ver, err)
   821  				}
   822  				defer w.sessPool.put(ctx)
   823  
   824  				_, _, err = ctx.(sqlexec.RestrictedALLEGROSQLInterlockingDirectorate).InterDircRestrictedALLEGROSQL(valStr)
   825  				if err != nil {
   826  					job.State = perceptron.JobStateCancelled
   827  					failpoint.Return(ver, err)
   828  				}
   829  			}
   830  		})
   831  		ver, err = uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, originalState != changingDefCaus.State)
   832  		if err != nil {
   833  			return ver, errors.Trace(err)
   834  		}
   835  		// Make sure job args change after `uFIDelateVersionAndBlockInfoWithCheck`, otherwise, the job args will
   836  		// be uFIDelated in `uFIDelateDBSJob` even if it meets an error in `uFIDelateVersionAndBlockInfoWithCheck`.
   837  		job.SchemaState = perceptron.StateDeleteOnly
   838  		job.Args = append(job.Args, changingDefCaus, changingIdxs)
   839  	case perceptron.StateDeleteOnly:
   840  		// DeferredCauset from null to not null.
   841  		if !allegrosql.HasNotNullFlag(oldDefCaus.Flag) && allegrosql.HasNotNullFlag(changingDefCaus.Flag) {
   842  			// Introduce the `allegrosql.PreventNullInsertFlag` flag to prevent users from inserting or uFIDelating null values.
   843  			err := modifyDefCaussFromNull2NotNull(w, dbInfo, tblInfo, []*perceptron.DeferredCausetInfo{oldDefCaus}, oldDefCaus.Name, oldDefCaus.Tp != changingDefCaus.Tp)
   844  			if err != nil {
   845  				if ErrWarnDataTruncated.Equal(err) || errInvalidUseOfNull.Equal(err) {
   846  					job.State = perceptron.JobStateRollingback
   847  				}
   848  				return ver, err
   849  			}
   850  		}
   851  		// delete only -> write only
   852  		uFIDelateChangingInfo(changingDefCaus, changingIdxs, perceptron.StateWriteOnly)
   853  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != changingDefCaus.State)
   854  		if err != nil {
   855  			return ver, errors.Trace(err)
   856  		}
   857  		job.SchemaState = perceptron.StateWriteOnly
   858  	case perceptron.StateWriteOnly:
   859  		// write only -> reorganization
   860  		uFIDelateChangingInfo(changingDefCaus, changingIdxs, perceptron.StateWriteReorganization)
   861  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != changingDefCaus.State)
   862  		if err != nil {
   863  			return ver, errors.Trace(err)
   864  		}
   865  		job.SchemaState = perceptron.StateWriteReorganization
   866  	case perceptron.StateWriteReorganization:
   867  		tbl, err := getBlock(d.causetstore, dbInfo.ID, tblInfo)
   868  		if err != nil {
   869  			return ver, errors.Trace(err)
   870  		}
   871  		reorgInfo, err := getReorgInfo(d, t, job, tbl)
   872  		if err != nil || reorgInfo.first {
   873  			// If we run reorg firstly, we should uFIDelate the job snapshot version
   874  			// and then run the reorg next time.
   875  			return ver, errors.Trace(err)
   876  		}
   877  
   878  		err = w.runReorgJob(t, reorgInfo, tbl.Meta(), d.lease, func() (addIndexErr error) {
   879  			defer soliton.Recover(metrics.LabelDBS, "onModifyDeferredCauset",
   880  				func() {
   881  					addIndexErr = errCancelledDBSJob.GenWithStack("modify causet `%v` defCausumn `%v` panic", tblInfo.Name, oldDefCaus.Name)
   882  				}, false)
   883  			return w.uFIDelateDeferredCausetAndIndexes(tbl, oldDefCaus, changingDefCaus, changingIdxs, reorgInfo)
   884  		})
   885  		if err != nil {
   886  			if errWaitReorgTimeout.Equal(err) {
   887  				// If timeout, we should return, check for the tenant and re-wait job done.
   888  				return ver, nil
   889  			}
   890  			if ekv.ErrKeyExists.Equal(err) || errCancelledDBSJob.Equal(err) || errCantDecodeRecord.Equal(err) || types.ErrOverflow.Equal(err) {
   891  				logutil.BgLogger().Warn("[dbs] run modify defCausumn job failed, convert job to rollback", zap.String("job", job.String()), zap.Error(err))
   892  				// When encounter these error above, we change the job to rolling back job directly.
   893  				job.State = perceptron.JobStateRollingback
   894  				return ver, errors.Trace(err)
   895  			}
   896  			// Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs.
   897  			w.reorgCtx.cleanNotifyReorgCancel()
   898  			return ver, errors.Trace(err)
   899  		}
   900  		// Clean up the channel of notifyCancelReorgJob. Make sure it can't affect other jobs.
   901  		w.reorgCtx.cleanNotifyReorgCancel()
   902  
   903  		// Remove the old defCausumn and indexes. UFIDelate the relative defCausumn name and index names.
   904  		oldIdxIDs := make([]int64, 0, len(changingIdxs))
   905  		tblInfo.DeferredCausets = tblInfo.DeferredCausets[:len(tblInfo.DeferredCausets)-1]
   906  		for _, cIdx := range changingIdxs {
   907  			idxName := strings.TrimPrefix(cIdx.Name.O, changingIndexPrefix)
   908  			for i, idx := range tblInfo.Indices {
   909  				if strings.EqualFold(idxName, idx.Name.L) {
   910  					cIdx.Name = perceptron.NewCIStr(idxName)
   911  					tblInfo.Indices[i] = cIdx
   912  					oldIdxIDs = append(oldIdxIDs, idx.ID)
   913  					break
   914  				}
   915  			}
   916  		}
   917  		changingDefCaus.Name = defCausName
   918  		changingDefCaus.ChangeStateInfo = nil
   919  		tblInfo.Indices = tblInfo.Indices[:len(tblInfo.Indices)-len(changingIdxs)]
   920  		// Adjust causet defCausumn offset.
   921  		if err = adjustDeferredCausetInfoInModifyDeferredCauset(job, tblInfo, changingDefCaus, oldDefCaus, pos); err != nil {
   922  			// TODO: Do rollback.
   923  			return ver, errors.Trace(err)
   924  		}
   925  		uFIDelateChangingInfo(changingDefCaus, changingIdxs, perceptron.StatePublic)
   926  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, originalState != changingDefCaus.State)
   927  		if err != nil {
   928  			return ver, errors.Trace(err)
   929  		}
   930  
   931  		// Finish this job.
   932  		job.FinishBlockJob(perceptron.JobStateDone, perceptron.StatePublic, ver, tblInfo)
   933  		// Refactor the job args to add the old index ids into delete range causet.
   934  		job.Args = []interface{}{oldIdxIDs, getPartitionIDs(tblInfo)}
   935  		// TODO: Change defCausumn ID.
   936  		// asyncNotifyEvent(d, &soliton.Event{Tp: perceptron.CausetActionAddDeferredCauset, BlockInfo: tblInfo, DeferredCausetInfos: []*perceptron.DeferredCausetInfo{changingDefCaus}})
   937  	default:
   938  		err = ErrInvalidDBSState.GenWithStackByArgs("defCausumn", changingDefCaus.State)
   939  	}
   940  
   941  	return ver, errors.Trace(err)
   942  }
   943  
   944  func (w *worker) uFIDelatePhysicalBlockRow(t causet.PhysicalBlock, oldDefCausInfo, defCausInfo *perceptron.DeferredCausetInfo, reorgInfo *reorgInfo) error {
   945  	logutil.BgLogger().Info("[dbs] start to uFIDelate causet event", zap.String("job", reorgInfo.Job.String()), zap.String("reorgInfo", reorgInfo.String()))
   946  	return w.writePhysicalBlockRecord(t.(causet.PhysicalBlock), typeUFIDelateDeferredCausetWorker, nil, oldDefCausInfo, defCausInfo, reorgInfo)
   947  }
   948  
   949  // uFIDelateDeferredCausetAndIndexes handles the modify defCausumn reorganization state for a causet.
   950  func (w *worker) uFIDelateDeferredCausetAndIndexes(t causet.Block, oldDefCaus, defCaus *perceptron.DeferredCausetInfo, idxes []*perceptron.IndexInfo, reorgInfo *reorgInfo) error {
   951  	// TODO: Consider rebuild ReorgInfo key to mDBSJobReorgKey_jobID_elementID(defCausID/idxID).
   952  	// TODO: Support partition blocks.
   953  	err := w.uFIDelatePhysicalBlockRow(t.(causet.PhysicalBlock), oldDefCaus, defCaus, reorgInfo)
   954  	if err != nil {
   955  		return errors.Trace(err)
   956  	}
   957  
   958  	for _, idx := range idxes {
   959  		err = w.addBlockIndex(t, idx, reorgInfo)
   960  		if err != nil {
   961  			return errors.Trace(err)
   962  		}
   963  	}
   964  	return nil
   965  }
   966  
   967  type uFIDelateDeferredCausetWorker struct {
   968  	*backfillWorker
   969  	oldDefCausInfo *perceptron.DeferredCausetInfo
   970  	newDefCausInfo *perceptron.DeferredCausetInfo
   971  	metricCounter  prometheus.Counter
   972  
   973  	// The following attributes are used to reduce memory allocation.
   974  	rowRecords       []*rowRecord
   975  	rowCausetDecoder *causetDecoder.RowCausetDecoder
   976  
   977  	rowMap map[int64]types.Causet
   978  }
   979  
   980  func newUFIDelateDeferredCausetWorker(sessCtx stochastikctx.Context, worker *worker, id int, t causet.PhysicalBlock, oldDefCaus, newDefCaus *perceptron.DeferredCausetInfo, decodeDefCausMap map[int64]causetDecoder.DeferredCauset) *uFIDelateDeferredCausetWorker {
   981  	rowCausetDecoder := causetDecoder.NewRowCausetDecoder(t, t.WriblockDefCauss(), decodeDefCausMap)
   982  	return &uFIDelateDeferredCausetWorker{
   983  		backfillWorker:   newBackfillWorker(sessCtx, worker, id, t),
   984  		oldDefCausInfo:   oldDefCaus,
   985  		newDefCausInfo:   newDefCaus,
   986  		metricCounter:    metrics.BackfillTotalCounter.WithLabelValues("uFIDelate_defCaus_speed"),
   987  		rowCausetDecoder: rowCausetDecoder,
   988  		rowMap:           make(map[int64]types.Causet, len(decodeDefCausMap)),
   989  	}
   990  }
   991  
   992  func (w *uFIDelateDeferredCausetWorker) AddMetricInfo(cnt float64) {
   993  	w.metricCounter.Add(cnt)
   994  }
   995  
   996  type rowRecord struct {
   997  	key  []byte // It's used to dagger a record. Record it to reduce the encoding time.
   998  	vals []byte // It's the record.
   999  }
  1000  
  1001  // getNextHandle gets next handle of entry that we are going to process.
  1002  func (w *uFIDelateDeferredCausetWorker) getNextHandle(taskRange reorgBackfillTask, taskDone bool, lastAccessedHandle ekv.Handle) (nextHandle ekv.Handle) {
  1003  	if !taskDone {
  1004  		// The task is not done. So we need to pick the last processed entry's handle and add one.
  1005  		return lastAccessedHandle.Next()
  1006  	}
  1007  
  1008  	// The task is done. So we need to choose a handle outside this range.
  1009  	// Some corner cases should be considered:
  1010  	// - The end of task range is MaxInt64.
  1011  	// - The end of the task is excluded in the range.
  1012  	if (taskRange.endHandle.IsInt() && taskRange.endHandle.IntValue() == math.MaxInt64) || !taskRange.endIncluded {
  1013  		return taskRange.endHandle
  1014  	}
  1015  
  1016  	return taskRange.endHandle.Next()
  1017  }
  1018  
  1019  func (w *uFIDelateDeferredCausetWorker) fetchRowDefCausVals(txn ekv.Transaction, taskRange reorgBackfillTask) ([]*rowRecord, ekv.Handle, bool, error) {
  1020  	w.rowRecords = w.rowRecords[:0]
  1021  	startTime := time.Now()
  1022  
  1023  	// taskDone means that the added handle is out of taskRange.endHandle.
  1024  	taskDone := false
  1025  	var lastAccessedHandle ekv.Handle
  1026  	oprStartTime := startTime
  1027  	err := iterateSnapshotRows(w.sessCtx.GetStore(), w.priority, w.causet, txn.StartTS(), taskRange.startHandle, taskRange.endHandle, taskRange.endIncluded,
  1028  		func(handle ekv.Handle, recordKey ekv.Key, rawRow []byte) (bool, error) {
  1029  			oprEndTime := time.Now()
  1030  			logSlowOperations(oprEndTime.Sub(oprStartTime), "iterateSnapshotRows in uFIDelateDeferredCausetWorker fetchRowDefCausVals", 0)
  1031  			oprStartTime = oprEndTime
  1032  
  1033  			if !taskRange.endIncluded {
  1034  				taskDone = handle.Compare(taskRange.endHandle) >= 0
  1035  			} else {
  1036  				taskDone = handle.Compare(taskRange.endHandle) > 0
  1037  			}
  1038  
  1039  			if taskDone || len(w.rowRecords) >= w.batchCnt {
  1040  				return false, nil
  1041  			}
  1042  
  1043  			if err1 := w.getRowRecord(handle, recordKey, rawRow); err1 != nil {
  1044  				return false, errors.Trace(err1)
  1045  			}
  1046  			lastAccessedHandle = handle
  1047  			if handle.Equal(taskRange.endHandle) {
  1048  				// If taskRange.endIncluded == false, we will not reach here when handle == taskRange.endHandle.
  1049  				taskDone = true
  1050  				return false, nil
  1051  			}
  1052  			return true, nil
  1053  		})
  1054  
  1055  	if len(w.rowRecords) == 0 {
  1056  		taskDone = true
  1057  	}
  1058  
  1059  	logutil.BgLogger().Debug("[dbs] txn fetches handle info", zap.Uint64("txnStartTS", txn.StartTS()), zap.String("taskRange", taskRange.String()), zap.Duration("takeTime", time.Since(startTime)))
  1060  	return w.rowRecords, w.getNextHandle(taskRange, taskDone, lastAccessedHandle), taskDone, errors.Trace(err)
  1061  }
  1062  
  1063  func (w *uFIDelateDeferredCausetWorker) getRowRecord(handle ekv.Handle, recordKey []byte, rawRow []byte) error {
  1064  	_, err := w.rowCausetDecoder.DecodeAndEvalRowWithMap(w.sessCtx, handle, rawRow, time.UTC, timeutil.SystemLocation(), w.rowMap)
  1065  	if err != nil {
  1066  		return errors.Trace(errCantDecodeRecord.GenWithStackByArgs("defCausumn", err))
  1067  	}
  1068  
  1069  	if _, ok := w.rowMap[w.newDefCausInfo.ID]; ok {
  1070  		// The defCausumn is already added by uFIDelate or insert memex, skip it.
  1071  		w.cleanRowMap()
  1072  		return nil
  1073  	}
  1074  
  1075  	newDefCausVal, err := causet.CastValue(w.sessCtx, w.rowMap[w.oldDefCausInfo.ID], w.newDefCausInfo, false, false)
  1076  	// TODO: Consider sql_mode and the error msg(encounter this error check whether to rollback).
  1077  	if err != nil {
  1078  		return errors.Trace(err)
  1079  	}
  1080  	w.rowMap[w.newDefCausInfo.ID] = newDefCausVal
  1081  	newDeferredCausetIDs := make([]int64, 0, len(w.rowMap))
  1082  	newRow := make([]types.Causet, 0, len(w.rowMap))
  1083  	for defCausID, val := range w.rowMap {
  1084  		newDeferredCausetIDs = append(newDeferredCausetIDs, defCausID)
  1085  		newRow = append(newRow, val)
  1086  	}
  1087  	sctx, rd := w.sessCtx.GetStochastikVars().StmtCtx, &w.sessCtx.GetStochastikVars().RowCausetEncoder
  1088  	newRowVal, err := blockcodec.EncodeRow(sctx, newRow, newDeferredCausetIDs, nil, nil, rd)
  1089  	if err != nil {
  1090  		return errors.Trace(err)
  1091  	}
  1092  
  1093  	w.rowRecords = append(w.rowRecords, &rowRecord{key: recordKey, vals: newRowVal})
  1094  	w.cleanRowMap()
  1095  	return nil
  1096  }
  1097  
  1098  func (w *uFIDelateDeferredCausetWorker) cleanRowMap() {
  1099  	for id := range w.rowMap {
  1100  		delete(w.rowMap, id)
  1101  	}
  1102  }
  1103  
  1104  // BackfillDataInTxn will backfill the causet record in a transaction, dagger corresponding rowKey, if the value of rowKey is changed.
  1105  func (w *uFIDelateDeferredCausetWorker) BackfillDataInTxn(handleRange reorgBackfillTask) (taskCtx backfillTaskContext, errInTxn error) {
  1106  	oprStartTime := time.Now()
  1107  	errInTxn = ekv.RunInNewTxn(w.sessCtx.GetStore(), true, func(txn ekv.Transaction) error {
  1108  		taskCtx.addedCount = 0
  1109  		taskCtx.scanCount = 0
  1110  		txn.SetOption(ekv.Priority, w.priority)
  1111  
  1112  		rowRecords, nextHandle, taskDone, err := w.fetchRowDefCausVals(txn, handleRange)
  1113  		if err != nil {
  1114  			return errors.Trace(err)
  1115  		}
  1116  		taskCtx.nextHandle = nextHandle
  1117  		taskCtx.done = taskDone
  1118  
  1119  		for _, rowRecord := range rowRecords {
  1120  			taskCtx.scanCount++
  1121  
  1122  			err = txn.Set(rowRecord.key, rowRecord.vals)
  1123  			if err != nil {
  1124  				return errors.Trace(err)
  1125  			}
  1126  			taskCtx.addedCount++
  1127  		}
  1128  
  1129  		return nil
  1130  	})
  1131  	logSlowOperations(time.Since(oprStartTime), "BackfillDataInTxn", 3000)
  1132  
  1133  	return
  1134  }
  1135  
  1136  func uFIDelateChangingInfo(changingDefCaus *perceptron.DeferredCausetInfo, changingIdxs []*perceptron.IndexInfo, schemaState perceptron.SchemaState) {
  1137  	changingDefCaus.State = schemaState
  1138  	for _, idx := range changingIdxs {
  1139  		idx.State = schemaState
  1140  	}
  1141  }
  1142  
  1143  // doModifyDeferredCauset uFIDelates the defCausumn information and reorders all defCausumns. It does not support modifying defCausumn data.
  1144  func (w *worker) doModifyDeferredCauset(
  1145  	t *spacetime.Meta, job *perceptron.Job, dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo,
  1146  	newDefCaus, oldDefCaus *perceptron.DeferredCausetInfo, pos *ast.DeferredCausetPosition) (ver int64, _ error) {
  1147  	// DeferredCauset from null to not null.
  1148  	if !allegrosql.HasNotNullFlag(oldDefCaus.Flag) && allegrosql.HasNotNullFlag(newDefCaus.Flag) {
  1149  		noPreventNullFlag := !allegrosql.HasPreventNullInsertFlag(oldDefCaus.Flag)
  1150  		// Introduce the `allegrosql.PreventNullInsertFlag` flag to prevent users from inserting or uFIDelating null values.
  1151  		err := modifyDefCaussFromNull2NotNull(w, dbInfo, tblInfo, []*perceptron.DeferredCausetInfo{oldDefCaus}, newDefCaus.Name, oldDefCaus.Tp != newDefCaus.Tp)
  1152  		if err != nil {
  1153  			if ErrWarnDataTruncated.Equal(err) || errInvalidUseOfNull.Equal(err) {
  1154  				job.State = perceptron.JobStateRollingback
  1155  			}
  1156  			return ver, err
  1157  		}
  1158  		// The defCausumn should get into prevent null status first.
  1159  		if noPreventNullFlag {
  1160  			return uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, true)
  1161  		}
  1162  	}
  1163  
  1164  	if err := adjustDeferredCausetInfoInModifyDeferredCauset(job, tblInfo, newDefCaus, oldDefCaus, pos); err != nil {
  1165  		return ver, errors.Trace(err)
  1166  	}
  1167  
  1168  	ver, err := uFIDelateVersionAndBlockInfoWithCheck(t, job, tblInfo, true)
  1169  	if err != nil {
  1170  		// Modified the type definition of 'null' to 'not null' before this, so rollBack the job when an error occurs.
  1171  		job.State = perceptron.JobStateRollingback
  1172  		return ver, errors.Trace(err)
  1173  	}
  1174  
  1175  	job.FinishBlockJob(perceptron.JobStateDone, perceptron.StatePublic, ver, tblInfo)
  1176  	// For those defCausumn-type-change type which doesn't need reorg data, we should also mock the job args for delete range.
  1177  	job.Args = []interface{}{[]int64{}, []int64{}}
  1178  	return ver, nil
  1179  }
  1180  
  1181  func adjustDeferredCausetInfoInModifyDeferredCauset(
  1182  	job *perceptron.Job, tblInfo *perceptron.BlockInfo, newDefCaus, oldDefCaus *perceptron.DeferredCausetInfo, pos *ast.DeferredCausetPosition) error {
  1183  	// We need the latest defCausumn's offset and state. This information can be obtained from the causetstore.
  1184  	newDefCaus.Offset = oldDefCaus.Offset
  1185  	newDefCaus.State = oldDefCaus.State
  1186  	// Calculate defCausumn's new position.
  1187  	oldPos, newPos := oldDefCaus.Offset, oldDefCaus.Offset
  1188  	if pos.Tp == ast.DeferredCausetPositionAfter {
  1189  		// TODO: The check of "RelativeDeferredCauset" can be checked in advance. When "EnableChangeDeferredCausetType" is true, unnecessary state changes can be reduced.
  1190  		if oldDefCaus.Name.L == pos.RelativeDeferredCauset.Name.L {
  1191  			// `alter causet blockName modify defCausumn b int after b` will return ver,ErrDeferredCausetNotExists.
  1192  			// Modified the type definition of 'null' to 'not null' before this, so rollback the job when an error occurs.
  1193  			job.State = perceptron.JobStateRollingback
  1194  			return schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(oldDefCaus.Name, tblInfo.Name)
  1195  		}
  1196  
  1197  		relative := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, pos.RelativeDeferredCauset.Name.L)
  1198  		if relative == nil || relative.State != perceptron.StatePublic {
  1199  			job.State = perceptron.JobStateRollingback
  1200  			return schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(pos.RelativeDeferredCauset, tblInfo.Name)
  1201  		}
  1202  
  1203  		if relative.Offset < oldPos {
  1204  			newPos = relative.Offset + 1
  1205  		} else {
  1206  			newPos = relative.Offset
  1207  		}
  1208  	} else if pos.Tp == ast.DeferredCausetPositionFirst {
  1209  		newPos = 0
  1210  	}
  1211  
  1212  	defCausumnChanged := make(map[string]*perceptron.DeferredCausetInfo)
  1213  	defCausumnChanged[oldDefCaus.Name.L] = newDefCaus
  1214  
  1215  	if newPos == oldPos {
  1216  		tblInfo.DeferredCausets[newPos] = newDefCaus
  1217  	} else {
  1218  		defcaus := tblInfo.DeferredCausets
  1219  
  1220  		// Reorder defCausumns in place.
  1221  		if newPos < oldPos {
  1222  			// ******** +(new) ****** -(old) ********
  1223  			// [newPos:old-1] should shift one step to the right.
  1224  			copy(defcaus[newPos+1:], defcaus[newPos:oldPos])
  1225  		} else {
  1226  			// ******** -(old) ****** +(new) ********
  1227  			// [old+1:newPos] should shift one step to the left.
  1228  			copy(defcaus[oldPos:], defcaus[oldPos+1:newPos+1])
  1229  		}
  1230  		defcaus[newPos] = newDefCaus
  1231  
  1232  		for i, defCaus := range tblInfo.DeferredCausets {
  1233  			if defCaus.Offset != i {
  1234  				defCausumnChanged[defCaus.Name.L] = defCaus
  1235  				defCaus.Offset = i
  1236  			}
  1237  		}
  1238  	}
  1239  
  1240  	// Change offset and name in indices.
  1241  	for _, idx := range tblInfo.Indices {
  1242  		for _, c := range idx.DeferredCausets {
  1243  			cName := strings.ToLower(strings.TrimPrefix(c.Name.O, changingDeferredCausetPrefix))
  1244  			if newDefCaus, ok := defCausumnChanged[cName]; ok {
  1245  				c.Name = newDefCaus.Name
  1246  				c.Offset = newDefCaus.Offset
  1247  			}
  1248  		}
  1249  	}
  1250  	return nil
  1251  }
  1252  
  1253  func checkAndApplyNewAutoRandomBits(job *perceptron.Job, t *spacetime.Meta, tblInfo *perceptron.BlockInfo,
  1254  	newDefCaus *perceptron.DeferredCausetInfo, oldName *perceptron.CIStr, newAutoRandBits uint64) error {
  1255  	schemaID := job.SchemaID
  1256  	newLayout := autoid.NewAutoRandomIDLayout(&newDefCaus.FieldType, newAutoRandBits)
  1257  
  1258  	// GenAutoRandomID first to prevent concurrent uFIDelate.
  1259  	_, err := t.GenAutoRandomID(schemaID, tblInfo.ID, 1)
  1260  	if err != nil {
  1261  		return err
  1262  	}
  1263  	currentIncBitsVal, err := t.GetAutoRandomID(schemaID, tblInfo.ID)
  1264  	if err != nil {
  1265  		return err
  1266  	}
  1267  	// Find the max number of available shard bits by
  1268  	// counting leading zeros in current inc part of auto_random ID.
  1269  	availableBits := bits.LeadingZeros64(uint64(currentIncBitsVal))
  1270  	isOccupyingIncBits := newLayout.TypeBitsLength-newLayout.IncrementalBits > uint64(availableBits)
  1271  	if isOccupyingIncBits {
  1272  		availableBits := mathutil.Min(autoid.MaxAutoRandomBits, availableBits)
  1273  		errMsg := fmt.Sprintf(autoid.AutoRandomOverflowErrMsg, availableBits, newAutoRandBits, oldName.O)
  1274  		job.State = perceptron.JobStateCancelled
  1275  		return ErrInvalidAutoRandom.GenWithStackByArgs(errMsg)
  1276  	}
  1277  	tblInfo.AutoRandomBits = newAutoRandBits
  1278  	return nil
  1279  }
  1280  
  1281  // checkForNullValue ensure there are no null values of the defCausumn of this causet.
  1282  // `isDataTruncated` indicates whether the new field and the old field type are the same, in order to be compatible with allegrosql.
  1283  func checkForNullValue(ctx stochastikctx.Context, isDataTruncated bool, schemaReplicant, causet, newDefCaus perceptron.CIStr, oldDefCauss ...*perceptron.DeferredCausetInfo) error {
  1284  	defcausStr := ""
  1285  	for i, defCaus := range oldDefCauss {
  1286  		if i == 0 {
  1287  			defcausStr += "`" + defCaus.Name.L + "` is null"
  1288  		} else {
  1289  			defcausStr += " or `" + defCaus.Name.L + "` is null"
  1290  		}
  1291  	}
  1292  	allegrosql := fmt.Sprintf("select 1 from `%s`.`%s` where %s limit 1;", schemaReplicant.L, causet.L, defcausStr)
  1293  	rows, _, err := ctx.(sqlexec.RestrictedALLEGROSQLInterlockingDirectorate).InterDircRestrictedALLEGROSQL(allegrosql)
  1294  	if err != nil {
  1295  		return errors.Trace(err)
  1296  	}
  1297  	rowCount := len(rows)
  1298  	if rowCount != 0 {
  1299  		if isDataTruncated {
  1300  			return ErrWarnDataTruncated.GenWithStackByArgs(newDefCaus.L, rowCount)
  1301  		}
  1302  		return errInvalidUseOfNull
  1303  	}
  1304  	return nil
  1305  }
  1306  
  1307  func uFIDelateDeferredCausetDefaultValue(t *spacetime.Meta, job *perceptron.Job, newDefCaus *perceptron.DeferredCausetInfo, oldDefCausName *perceptron.CIStr) (ver int64, _ error) {
  1308  	tblInfo, err := getBlockInfoAndCancelFaultJob(t, job, job.SchemaID)
  1309  	if err != nil {
  1310  		return ver, errors.Trace(err)
  1311  	}
  1312  	oldDefCaus := perceptron.FindDeferredCausetInfo(tblInfo.DeferredCausets, oldDefCausName.L)
  1313  	if oldDefCaus == nil || oldDefCaus.State != perceptron.StatePublic {
  1314  		job.State = perceptron.JobStateCancelled
  1315  		return ver, schemareplicant.ErrDeferredCausetNotExists.GenWithStackByArgs(newDefCaus.Name, tblInfo.Name)
  1316  	}
  1317  	// The newDefCaus's offset may be the value of the old schemaReplicant version, so we can't use newDefCaus directly.
  1318  	oldDefCaus.DefaultValue = newDefCaus.DefaultValue
  1319  	oldDefCaus.DefaultValueBit = newDefCaus.DefaultValueBit
  1320  	oldDefCaus.Flag = newDefCaus.Flag
  1321  
  1322  	ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, true)
  1323  	if err != nil {
  1324  		job.State = perceptron.JobStateCancelled
  1325  		return ver, errors.Trace(err)
  1326  	}
  1327  
  1328  	job.FinishBlockJob(perceptron.JobStateDone, perceptron.StatePublic, ver, tblInfo)
  1329  	return ver, nil
  1330  }
  1331  
  1332  func isDeferredCausetWithIndex(defCausName string, indices []*perceptron.IndexInfo) bool {
  1333  	for _, indexInfo := range indices {
  1334  		for _, defCaus := range indexInfo.DeferredCausets {
  1335  			if defCaus.Name.L == defCausName {
  1336  				return true
  1337  			}
  1338  		}
  1339  	}
  1340  	return false
  1341  }
  1342  
  1343  func isDeferredCausetCanDropWithIndex(defCausName string, indices []*perceptron.IndexInfo) bool {
  1344  	for _, indexInfo := range indices {
  1345  		if indexInfo.Primary || len(indexInfo.DeferredCausets) > 1 {
  1346  			for _, defCaus := range indexInfo.DeferredCausets {
  1347  				if defCaus.Name.L == defCausName {
  1348  					return false
  1349  				}
  1350  			}
  1351  		}
  1352  	}
  1353  	return true
  1354  }
  1355  
  1356  func listIndicesWithDeferredCauset(defCausName string, indices []*perceptron.IndexInfo) []*perceptron.IndexInfo {
  1357  	ret := make([]*perceptron.IndexInfo, 0)
  1358  	for _, indexInfo := range indices {
  1359  		if len(indexInfo.DeferredCausets) == 1 && defCausName == indexInfo.DeferredCausets[0].Name.L {
  1360  			ret = append(ret, indexInfo)
  1361  		}
  1362  	}
  1363  	return ret
  1364  }
  1365  
  1366  func getDeferredCausetForeignKeyInfo(defCausName string, fkInfos []*perceptron.FKInfo) *perceptron.FKInfo {
  1367  	for _, fkInfo := range fkInfos {
  1368  		for _, defCaus := range fkInfo.DefCauss {
  1369  			if defCaus.L == defCausName {
  1370  				return fkInfo
  1371  			}
  1372  		}
  1373  	}
  1374  	return nil
  1375  }
  1376  
  1377  func allocateDeferredCausetID(tblInfo *perceptron.BlockInfo) int64 {
  1378  	tblInfo.MaxDeferredCausetID++
  1379  	return tblInfo.MaxDeferredCausetID
  1380  }
  1381  
  1382  func checkAddDeferredCausetTooManyDeferredCausets(defCausNum int) error {
  1383  	if uint32(defCausNum) > atomic.LoadUint32(&BlockDeferredCausetCountLimit) {
  1384  		return errTooManyFields
  1385  	}
  1386  	return nil
  1387  }
  1388  
  1389  // rollbackModifyDeferredCausetJob rollbacks the job when an error occurs.
  1390  func rollbackModifyDeferredCausetJob(t *spacetime.Meta, tblInfo *perceptron.BlockInfo, job *perceptron.Job, oldDefCaus *perceptron.DeferredCausetInfo, modifyDeferredCausetTp byte) (ver int64, _ error) {
  1391  	var err error
  1392  	if modifyDeferredCausetTp == allegrosql.TypeNull {
  1393  		// field NotNullFlag flag reset.
  1394  		tblInfo.DeferredCausets[oldDefCaus.Offset].Flag = oldDefCaus.Flag &^ allegrosql.NotNullFlag
  1395  		// field PreventNullInsertFlag flag reset.
  1396  		tblInfo.DeferredCausets[oldDefCaus.Offset].Flag = oldDefCaus.Flag &^ allegrosql.PreventNullInsertFlag
  1397  		ver, err = uFIDelateVersionAndBlockInfo(t, job, tblInfo, true)
  1398  		if err != nil {
  1399  			return ver, errors.Trace(err)
  1400  		}
  1401  	}
  1402  	job.FinishBlockJob(perceptron.JobStateRollbackDone, perceptron.StateNone, ver, tblInfo)
  1403  	// For those defCausumn-type-change type which doesn't need reorg data, we should also mock the job args for delete range.
  1404  	job.Args = []interface{}{[]int64{}, []int64{}}
  1405  	return ver, nil
  1406  }
  1407  
  1408  // modifyDefCaussFromNull2NotNull modifies the type definitions of 'null' to 'not null'.
  1409  // Introduce the `allegrosql.PreventNullInsertFlag` flag to prevent users from inserting or uFIDelating null values.
  1410  func modifyDefCaussFromNull2NotNull(w *worker, dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defcaus []*perceptron.DeferredCausetInfo,
  1411  	newDefCausName perceptron.CIStr, isModifiedType bool) error {
  1412  	// Get stochastikctx from context resource pool.
  1413  	var ctx stochastikctx.Context
  1414  	ctx, err := w.sessPool.get()
  1415  	if err != nil {
  1416  		return errors.Trace(err)
  1417  	}
  1418  	defer w.sessPool.put(ctx)
  1419  
  1420  	skipCheck := false
  1421  	failpoint.Inject("skipMockContextDoInterDirc", func(val failpoint.Value) {
  1422  		if val.(bool) {
  1423  			skipCheck = true
  1424  		}
  1425  	})
  1426  	if !skipCheck {
  1427  		// If there is a null value inserted, it cannot be modified and needs to be rollback.
  1428  		err = checkForNullValue(ctx, isModifiedType, dbInfo.Name, tblInfo.Name, newDefCausName, defcaus...)
  1429  		if err != nil {
  1430  			return errors.Trace(err)
  1431  		}
  1432  	}
  1433  
  1434  	// Prevent this field from inserting null values.
  1435  	for _, defCaus := range defcaus {
  1436  		defCaus.Flag |= allegrosql.PreventNullInsertFlag
  1437  	}
  1438  	return nil
  1439  }
  1440  
  1441  func generateOriginDefaultValue(defCaus *perceptron.DeferredCausetInfo) (interface{}, error) {
  1442  	var err error
  1443  	odValue := defCaus.GetDefaultValue()
  1444  	if odValue == nil && allegrosql.HasNotNullFlag(defCaus.Flag) {
  1445  		zeroVal := causet.GetZeroValue(defCaus)
  1446  		odValue, err = zeroVal.ToString()
  1447  		if err != nil {
  1448  			return nil, errors.Trace(err)
  1449  		}
  1450  	}
  1451  
  1452  	if odValue == strings.ToUpper(ast.CurrentTimestamp) {
  1453  		if defCaus.Tp == allegrosql.TypeTimestamp {
  1454  			odValue = time.Now().UTC().Format(types.TimeFormat)
  1455  		} else if defCaus.Tp == allegrosql.TypeDatetime {
  1456  			odValue = time.Now().Format(types.TimeFormat)
  1457  		}
  1458  	}
  1459  	return odValue, nil
  1460  }
  1461  
  1462  func findDeferredCausetInIndexDefCauss(c string, defcaus []*perceptron.IndexDeferredCauset) *perceptron.IndexDeferredCauset {
  1463  	for _, c1 := range defcaus {
  1464  		if c == c1.Name.L {
  1465  			return c1
  1466  		}
  1467  	}
  1468  	return nil
  1469  }
  1470  
  1471  func getDeferredCausetInfoByName(tbInfo *perceptron.BlockInfo, defCausumn string) *perceptron.DeferredCausetInfo {
  1472  	for _, defCausInfo := range tbInfo.DefCauss() {
  1473  		if defCausInfo.Name.L == defCausumn {
  1474  			return defCausInfo
  1475  		}
  1476  	}
  1477  	return nil
  1478  }
  1479  
  1480  // isVirtualGeneratedDeferredCauset checks the defCausumn if it is virtual.
  1481  func isVirtualGeneratedDeferredCauset(defCaus *perceptron.DeferredCausetInfo) bool {
  1482  	if defCaus.IsGenerated() && !defCaus.GeneratedStored {
  1483  		return true
  1484  	}
  1485  	return false
  1486  }
  1487  
  1488  func indexInfoContains(idxID int64, idxInfos []*perceptron.IndexInfo) bool {
  1489  	for _, idxInfo := range idxInfos {
  1490  		if idxID == idxInfo.ID {
  1491  			return true
  1492  		}
  1493  	}
  1494  	return false
  1495  }
  1496  
  1497  func indexInfosToIDList(idxInfos []*perceptron.IndexInfo) []int64 {
  1498  	ids := make([]int64, 0, len(idxInfos))
  1499  	for _, idxInfo := range idxInfos {
  1500  		ids = append(ids, idxInfo.ID)
  1501  	}
  1502  	return ids
  1503  }