github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/auto_incr.go (about) 1 // Copyright 2022 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package colexec 16 17 import ( 18 "context" 19 "fmt" 20 "math" 21 22 "github.com/matrixorigin/matrixone/pkg/catalog" 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/common/mpool" 25 "github.com/matrixorigin/matrixone/pkg/container/batch" 26 "github.com/matrixorigin/matrixone/pkg/container/nulls" 27 "github.com/matrixorigin/matrixone/pkg/container/types" 28 "github.com/matrixorigin/matrixone/pkg/container/vector" 29 "github.com/matrixorigin/matrixone/pkg/defines" 30 "github.com/matrixorigin/matrixone/pkg/logutil" 31 "github.com/matrixorigin/matrixone/pkg/pb/plan" 32 "github.com/matrixorigin/matrixone/pkg/txn/client" 33 "github.com/matrixorigin/matrixone/pkg/vm/engine" 34 "github.com/matrixorigin/matrixone/pkg/vm/process" 35 "golang.org/x/exp/constraints" 36 ) 37 38 var AUTO_INCR_TABLE = "%!%mo_increment_columns" 39 var AUTO_INCR_TABLE_COLNAME []string = []string{catalog.Row_ID, "name", "offset", "step"} 40 41 type AutoIncrParam struct { 42 eg engine.Engine 43 // rel engine.Relation 44 ctx context.Context 45 proc *process.Process 46 dbName string 47 tblName string 48 colDefs []*plan.ColDef 49 } 50 51 func (aip *AutoIncrParam) SetLastInsertID(id uint64) { 52 aip.proc.SetLastInsertID(id) 53 } 54 55 func getNextAutoIncrNum(proc *process.Process, colDefs []*plan.ColDef, ctx context.Context, incrParam *AutoIncrParam, bat *batch.Batch, tableID uint64) ([]uint64, []uint64, error) { 56 autoIncrCaches := proc.SessionInfo.AutoIncrCaches 57 autoIncrCaches.Mu.Lock() 58 defer autoIncrCaches.Mu.Unlock() 59 offset, step := make([]uint64, 0), make([]uint64, 0) 60 for i, col := range colDefs { 61 if !col.Typ.AutoIncr { 62 continue 63 } 64 name := fmt.Sprintf("%d_%s", tableID, col.Name) 65 autoincrcache, ok := autoIncrCaches.AutoIncrCaches[name] 66 // Not cached yet or the cache is ran out. 67 // Need new txn for read from the table. 68 if !ok || autoincrcache.CurNum >= autoincrcache.MaxNum { 69 // Need return maxNum for correction. 70 cur := uint64(0) 71 if ok { 72 cur = autoincrcache.CurNum 73 } 74 curNum, maxNum, stp, err := getNextOneCache(ctx, incrParam, bat, tableID, i, name, proc.SessionInfo.AutoIncrCacheSize, cur) 75 if err != nil { 76 return nil, nil, err 77 } 78 autoIncrCaches.AutoIncrCaches[name] = defines.AutoIncrCache{CurNum: curNum, MaxNum: maxNum, Step: stp} 79 } 80 81 offset = append(offset, autoIncrCaches.AutoIncrCaches[name].CurNum) 82 step = append(step, autoIncrCaches.AutoIncrCaches[name].Step) 83 84 // Here got the most recent id in the cache. 85 // Need compare witch vec and get the maxNum. 86 maxNum, err := getMax(incrParam, bat, i, autoIncrCaches.AutoIncrCaches[name].Step, 1, autoIncrCaches.AutoIncrCaches[name].CurNum) 87 if err != nil { 88 return nil, nil, err 89 } 90 91 incrParam.SetLastInsertID(maxNum) 92 93 // Update the caches. 94 autoIncrCaches.AutoIncrCaches[name] = defines.AutoIncrCache{CurNum: maxNum, 95 MaxNum: autoIncrCaches.AutoIncrCaches[name].MaxNum, Step: autoIncrCaches.AutoIncrCaches[name].Step} 96 } 97 98 return offset, step, nil 99 } 100 101 func deleteAutoIncrCache(name string, proc *process.Process) { 102 autoIncrCaches := proc.SessionInfo.AutoIncrCaches 103 autoIncrCaches.Mu.Lock() 104 defer autoIncrCaches.Mu.Unlock() 105 _, ok := autoIncrCaches.AutoIncrCaches[name] 106 if ok { 107 delete(autoIncrCaches.AutoIncrCaches, name) 108 } 109 } 110 111 func renameAutoIncrCache(newname, oldname string, proc *process.Process) { 112 autoIncrCaches := proc.SessionInfo.AutoIncrCaches 113 autoIncrCaches.Mu.Lock() 114 defer autoIncrCaches.Mu.Unlock() 115 _, ok := autoIncrCaches.AutoIncrCaches[oldname] 116 if ok { 117 autoIncrCaches.AutoIncrCaches[newname] = defines.AutoIncrCache{CurNum: autoIncrCaches.AutoIncrCaches[oldname].CurNum, 118 MaxNum: autoIncrCaches.AutoIncrCaches[oldname].MaxNum, Step: autoIncrCaches.AutoIncrCaches[oldname].Step} 119 delete(autoIncrCaches.AutoIncrCaches, oldname) 120 } 121 } 122 123 func getNextOneCache(ctx context.Context, param *AutoIncrParam, bat *batch.Batch, tableID uint64, i int, name string, cachesize, curNum uint64) (uint64, uint64, uint64, error) { 124 var err error 125 loopCnt := 0 126 loop: 127 loopCnt += 1 128 if loopCnt >= 100 { 129 return 0, 0, 0, err 130 } 131 132 txn, err := NewTxn(param.eg, param.proc, param.ctx) 133 if err != nil { 134 goto loop 135 } 136 var d, m, s uint64 137 if d, m, s, err = getOneColRangeFromAutoIncrTable(param, bat, name, i, txn, cachesize, curNum); err != nil { // Get next 1000. 138 RolllbackTxn(param.eg, txn, param.ctx) 139 goto loop 140 } 141 142 if err = CommitTxn(param.eg, txn, param.ctx); err != nil { 143 goto loop 144 } 145 146 return d, m, s, nil 147 } 148 149 func UpdateInsertBatch(e engine.Engine, ctx context.Context, proc *process.Process, ColDefs []*plan.ColDef, bat *batch.Batch, tableID uint64, dbName, tblName string) error { 150 incrParam := &AutoIncrParam{ 151 eg: e, 152 ctx: ctx, 153 proc: proc, 154 colDefs: ColDefs, 155 dbName: dbName, 156 tblName: tblName, 157 } 158 159 offset, step, err := getNextAutoIncrNum(proc, ColDefs, ctx, incrParam, bat, tableID) 160 if err != nil { 161 return err 162 } 163 164 if err = updateBatchImpl(ctx, ColDefs, bat, offset, step); err != nil { 165 return err 166 } 167 return nil 168 } 169 170 // func UpdateInsertValueBatch(e engine.Engine, ctx context.Context, proc *process.Process, p *plan.InsertValues, bat *batch.Batch, dbName, tblName string) error { 171 // ColDefs := p.ExplicitCols 172 // orderColDefs(p.OrderAttrs, ColDefs, p.Columns) 173 // db, err := e.Database(ctx, p.DbName, proc.TxnOperator) 174 // if err != nil { 175 // return err 176 // } 177 // rel, err := db.Relation(ctx, p.TblName) 178 // if err != nil { 179 // return err 180 // } 181 182 // return UpdateInsertBatch(e, ctx, proc, ColDefs, bat, rel.GetTableID(ctx), dbName, tblName) 183 // } 184 185 // get autoincr columns values. This function updates the auto incr table. 186 // multiple txn may cause a conflicts, but we retry off band transactions. 187 // func getRangeFromAutoIncrTable(param *AutoIncrParam, bat *batch.Batch, tableID uint64) ([]uint64, []uint64, error) { 188 // var err error 189 // loopCnt := 0 190 // loop: 191 // // if fail 100 times, too bad, really unlucky one get aborted anyway. 192 // loopCnt += 1 193 // if loopCnt >= 100 { 194 // return nil, nil, err 195 // } 196 // txn, err := NewTxn(param.eg, param.proc, param.ctx) 197 // if err != nil { 198 // goto loop 199 // } 200 // offset, step := make([]uint64, 0), make([]uint64, 0) 201 // for i, col := range param.colDefs { 202 // if !col.Typ.AutoIncr { 203 // continue 204 // } 205 // var d, s uint64 206 // name := fmt.Sprintf("%d_%s", tableID, col.Name) 207 // if d, _, s, err = getOneColRangeFromAutoIncrTable(param, bat, name, i, txn, 1, 0); err != nil { 208 // RolllbackTxn(param.eg, txn, param.ctx) 209 // goto loop 210 // } 211 // offset = append(offset, d) 212 // step = append(step, s) 213 // } 214 // if err = CommitTxn(param.eg, txn, param.ctx); err != nil { 215 // goto loop 216 // } 217 // return offset, step, nil 218 // } 219 220 func getMaxnum[T constraints.Integer](vec *vector.Vector, length, maxNum, step, cacheSize uint64) uint64 { 221 vs := vector.MustTCols[T](vec) 222 rowIndex := uint64(0) 223 storeNum := maxNum 224 for rowIndex = 0; rowIndex < length; rowIndex++ { 225 if nulls.Contains(vec.Nsp, rowIndex) { 226 maxNum += step 227 } else { 228 if vs[rowIndex] < 0 { 229 continue 230 } 231 if uint64(vs[rowIndex]) > maxNum { 232 maxNum = uint64(vs[rowIndex]) 233 } 234 } 235 } 236 if cacheSize != 1 { 237 storeNum += step * cacheSize 238 if storeNum > maxNum { 239 maxNum = storeNum 240 } 241 } 242 return maxNum 243 } 244 245 func updateVector[T constraints.Integer](vec *vector.Vector, length, curNum, stepNum uint64) { 246 vs := vector.MustTCols[T](vec) 247 rowIndex := uint64(0) 248 for rowIndex = 0; rowIndex < length; rowIndex++ { 249 if nulls.Contains(vec.Nsp, uint64(rowIndex)) { 250 nulls.Del(vec.Nsp, rowIndex) 251 curNum += stepNum 252 vs[rowIndex] = T(curNum) 253 } else { 254 if vs[rowIndex] < 0 { 255 continue 256 } 257 if uint64(vs[rowIndex]) > curNum { 258 curNum = uint64(vs[rowIndex]) 259 } 260 } 261 } 262 } 263 264 // Get max get the max number of next ids and the vec number. 265 func getMax(param *AutoIncrParam, bat *batch.Batch, pos int, step, cachesize, oriNum uint64) (uint64, error) { 266 vec := bat.Vecs[pos] 267 maxNum := oriNum 268 maxNumStore := oriNum 269 270 switch vec.Typ.Oid { 271 case types.T_int8: 272 maxNum = getMaxnum[int8](vec, uint64(bat.Length()), maxNum, step, 1) 273 maxNumStore = getMaxnum[int8](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 274 if maxNum > math.MaxInt8 { 275 return 0, moerr.NewOutOfRange(param.ctx, "tinyint", "value %v", maxNum) 276 } 277 if maxNumStore > math.MaxInt8 { 278 maxNumStore = math.MaxInt8 279 } 280 case types.T_int16: 281 maxNum = getMaxnum[int16](vec, uint64(bat.Length()), maxNum, step, 1) 282 maxNumStore = getMaxnum[int16](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 283 if maxNum > math.MaxInt16 { 284 return 0, moerr.NewOutOfRange(param.ctx, "smallint", "value %v", maxNum) 285 } 286 if maxNumStore > math.MaxInt16 { 287 maxNumStore = math.MaxInt16 288 } 289 case types.T_int32: 290 maxNum = getMaxnum[int32](vec, uint64(bat.Length()), maxNum, step, 1) 291 maxNumStore = getMaxnum[int32](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 292 if maxNum > math.MaxInt32 { 293 return 0, moerr.NewOutOfRange(param.ctx, "int", "value %v", maxNum) 294 } 295 if maxNumStore > math.MaxInt32 { 296 maxNumStore = math.MaxInt32 297 } 298 case types.T_int64: 299 maxNum = getMaxnum[int64](vec, uint64(bat.Length()), maxNum, step, 1) 300 maxNumStore = getMaxnum[int64](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 301 if maxNum > math.MaxInt64 { 302 return 0, moerr.NewOutOfRange(param.ctx, "bigint", "value %v", maxNum) 303 } 304 if maxNumStore > math.MaxInt64 { 305 maxNumStore = math.MaxInt64 306 } 307 case types.T_uint8: 308 maxNum = getMaxnum[uint8](vec, uint64(bat.Length()), maxNum, step, 1) 309 maxNumStore = getMaxnum[uint8](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 310 if maxNum > math.MaxUint8 { 311 return 0, moerr.NewOutOfRange(param.ctx, "tinyint unsigned", "value %v", maxNum) 312 } 313 if maxNumStore > math.MaxUint8 { 314 maxNumStore = math.MaxUint8 315 } 316 case types.T_uint16: 317 maxNum = getMaxnum[uint16](vec, uint64(bat.Length()), maxNum, step, 1) 318 maxNumStore = getMaxnum[uint16](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 319 if maxNum > math.MaxUint16 { 320 return 0, moerr.NewOutOfRange(param.ctx, "smallint unsigned", "value %v", maxNum) 321 } 322 if maxNumStore > math.MaxUint16 { 323 maxNumStore = math.MaxUint16 324 } 325 case types.T_uint32: 326 maxNum = getMaxnum[uint32](vec, uint64(bat.Length()), maxNum, step, 1) 327 maxNumStore = getMaxnum[uint32](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 328 if maxNum > math.MaxUint32 { 329 return 0, moerr.NewOutOfRange(param.ctx, "int unsigned", "value %v", maxNum) 330 } 331 if maxNumStore > math.MaxUint32 { 332 maxNumStore = math.MaxUint32 333 } 334 case types.T_uint64: 335 maxNum = getMaxnum[uint64](vec, uint64(bat.Length()), maxNum, step, 1) 336 maxNumStore = getMaxnum[uint64](vec, uint64(bat.Length()), maxNumStore, step, cachesize) 337 if maxNum < oriNum { 338 return 0, moerr.NewOutOfRange(param.ctx, "bigint unsigned", "auto_incrment column constant value overflows bigint unsigned") 339 } 340 if maxNumStore < oriNum { 341 maxNumStore = math.MaxUint64 342 } 343 default: 344 return 0, moerr.NewInvalidInput(param.ctx, "the auto_incr col is not integer type") 345 } 346 347 return maxNumStore, nil 348 } 349 350 func getOneColRangeFromAutoIncrTable(param *AutoIncrParam, bat *batch.Batch, name string, pos int, txn client.TxnOperator, cachesize, curNum uint64) (uint64, uint64, uint64, error) { 351 oriNum, step, delBat, err := getCurrentIndex(param, name, txn, param.proc.Mp()) 352 if err != nil { 353 return 0, 0, 0, err 354 } 355 356 if curNum > oriNum { 357 oriNum = curNum 358 } 359 360 maxNum, err := getMax(param, bat, pos, step, cachesize, oriNum) 361 if err != nil { 362 return 0, 0, 0, err 363 } 364 365 if err := updateAutoIncrTable(param, delBat, maxNum, name, txn, param.proc.Mp()); err != nil { 366 return 0, 0, 0, err 367 } 368 return oriNum, maxNum, step, nil 369 } 370 371 func updateBatchImpl(ctx context.Context, ColDefs []*plan.ColDef, bat *batch.Batch, offset, step []uint64) error { 372 pos := 0 373 for i, col := range ColDefs { 374 if !col.Typ.AutoIncr { 375 continue 376 } 377 vec := bat.Vecs[i] 378 curNum := offset[pos] 379 stepNum := step[pos] 380 pos++ 381 switch vec.Typ.Oid { 382 case types.T_int8: 383 updateVector[int8](vec, uint64(bat.Length()), curNum, stepNum) 384 case types.T_int16: 385 updateVector[int16](vec, uint64(bat.Length()), curNum, stepNum) 386 case types.T_int32: 387 updateVector[int32](vec, uint64(bat.Length()), curNum, stepNum) 388 case types.T_int64: 389 updateVector[int64](vec, uint64(bat.Length()), curNum, stepNum) 390 case types.T_uint8: 391 updateVector[uint8](vec, uint64(bat.Length()), curNum, stepNum) 392 case types.T_uint16: 393 updateVector[uint16](vec, uint64(bat.Length()), curNum, stepNum) 394 case types.T_uint32: 395 updateVector[uint32](vec, uint64(bat.Length()), curNum, stepNum) 396 case types.T_uint64: 397 updateVector[uint64](vec, uint64(bat.Length()), curNum, stepNum) 398 default: 399 return moerr.NewInvalidInput(ctx, "invalid auto_increment type '%v'", vec.Typ.Oid) 400 } 401 } 402 return nil 403 } 404 405 func getRangeExpr(colName string) *plan.Expr { 406 return &plan.Expr{ 407 Expr: &plan.Expr_F{ 408 F: &plan.Function{ 409 Func: &plan.ObjectRef{ 410 Obj: 10, 411 ObjName: "=", 412 }, 413 Args: []*plan.Expr{ 414 { 415 Expr: &plan.Expr_Col{ 416 Col: &plan.ColRef{ 417 Name: AUTO_INCR_TABLE_COLNAME[1], 418 }, 419 }, 420 }, 421 { 422 Expr: &plan.Expr_C{ 423 C: &plan.Const{ 424 Value: &plan.Const_Sval{ 425 Sval: colName, 426 }, 427 }, 428 }, 429 }, 430 }, 431 }, 432 }, 433 } 434 } 435 436 func getCurrentIndex(param *AutoIncrParam, colName string, txn client.TxnOperator, mp *mpool.MPool) (uint64, uint64, *batch.Batch, error) { 437 var rds []engine.Reader 438 retbat := batch.NewWithSize(1) 439 440 rel, err := GetNewRelation(param.eg, param.dbName, AUTO_INCR_TABLE, txn, param.ctx) 441 if err != nil { 442 return 0, 0, nil, err 443 } 444 445 expr := getRangeExpr(colName) 446 // use expression to get ranges 447 ret, err := rel.Ranges(param.ctx, expr) 448 if err != nil { 449 return 0, 0, nil, err 450 } 451 switch { 452 case len(ret) == 0: 453 if rds, err = rel.NewReader(param.ctx, 1, expr, nil); err != nil { 454 return 0, 0, nil, err 455 } 456 case len(ret) == 1 && len(ret[0]) == 0: 457 if rds, err = rel.NewReader(param.ctx, 1, expr, nil); err != nil { 458 return 0, 0, nil, err 459 } 460 case len(ret[0]) == 0: 461 rds0, err := rel.NewReader(param.ctx, 1, expr, nil) 462 if err != nil { 463 return 0, 0, nil, err 464 } 465 rds1, err := rel.NewReader(param.ctx, 1, expr, ret[1:]) 466 if err != nil { 467 return 0, 0, nil, err 468 } 469 rds = append(rds, rds0...) 470 rds = append(rds, rds1...) 471 default: 472 rds, _ = rel.NewReader(param.ctx, 1, expr, ret) 473 } 474 475 for len(rds) > 0 { 476 bat, err := rds[0].Read(param.ctx, AUTO_INCR_TABLE_COLNAME, expr, param.proc.Mp()) 477 if err != nil { 478 return 0, 0, nil, moerr.NewInvalidInput(param.ctx, "can not find the auto col") 479 } 480 if bat == nil { 481 rds[0].Close() 482 rds = rds[1:] 483 continue 484 } 485 if len(bat.Vecs) < 2 { 486 return 0, 0, nil, moerr.NewInternalError(param.ctx, "the mo_increment_columns col num is not two") 487 } 488 489 vs2 := vector.MustTCols[uint64](bat.Vecs[2]) 490 vs3 := vector.MustTCols[uint64](bat.Vecs[3]) 491 var rowIndex int64 492 for rowIndex = 0; rowIndex < int64(bat.Length()); rowIndex++ { 493 str := bat.Vecs[1].GetString(rowIndex) 494 if str == colName { 495 break 496 } 497 } 498 if rowIndex < int64(bat.Length()) { 499 vec := vector.New(bat.GetVector(0).Typ) 500 rowid := vector.MustTCols[types.Rowid](bat.GetVector(0))[rowIndex] 501 if err := vec.Append(rowid, false, mp); err != nil { 502 panic(err) 503 } 504 retbat.SetVector(0, vec) 505 retbat.SetZs(1, mp) 506 bat.Clean(mp) 507 return vs2[rowIndex], vs3[rowIndex], retbat, nil 508 } 509 bat.Clean(mp) 510 } 511 return 0, 0, nil, nil 512 } 513 514 func updateAutoIncrTable(param *AutoIncrParam, delBat *batch.Batch, curNum uint64, name string, txn client.TxnOperator, mp *mpool.MPool) error { 515 rel, err := GetNewRelation(param.eg, param.dbName, AUTO_INCR_TABLE, txn, param.ctx) 516 if err != nil { 517 return err 518 } 519 520 err = rel.Delete(param.ctx, delBat, AUTO_INCR_TABLE_COLNAME[0]) 521 if err != nil { 522 delBat.Clean(mp) 523 return err 524 } 525 bat := makeAutoIncrBatch(name, curNum, 1, mp) 526 if err = rel.Write(param.ctx, bat); err != nil { 527 bat.Clean(mp) 528 return err 529 } 530 param.proc.SetLastInsertID(curNum) 531 return nil 532 } 533 534 func makeAutoIncrBatch(name string, num, step uint64, mp *mpool.MPool) *batch.Batch { 535 vec := vector.NewWithStrings(types.T_varchar.ToType(), []string{name}, nil, mp) 536 vec2 := vector.NewWithFixed(types.T_uint64.ToType(), []uint64{num}, nil, mp) 537 vec3 := vector.NewWithFixed(types.T_uint64.ToType(), []uint64{step}, nil, mp) 538 bat := batch.NewWithSize(3) 539 bat.SetAttributes(AUTO_INCR_TABLE_COLNAME[1:]) 540 bat.SetVector(0, vec) 541 bat.SetVector(1, vec2) 542 bat.SetVector(2, vec3) 543 bat.SetZs(1, mp) 544 return bat 545 } 546 547 func GetDeleteBatch(rel engine.Relation, ctx context.Context, colName string, mp *mpool.MPool) (*batch.Batch, uint64) { 548 var rds []engine.Reader 549 550 ret, err := rel.Ranges(ctx, nil) 551 if err != nil { 552 panic(err) 553 } 554 switch { 555 case len(ret) == 0: 556 rds, _ = rel.NewReader(ctx, 1, nil, nil) 557 case len(ret) == 1 && len(ret[0]) == 0: 558 rds, _ = rel.NewReader(ctx, 1, nil, nil) 559 case len(ret[0]) == 0: 560 rds0, _ := rel.NewReader(ctx, 1, nil, nil) 561 rds1, _ := rel.NewReader(ctx, 1, nil, ret[1:]) 562 rds = append(rds, rds0...) 563 rds = append(rds, rds1...) 564 default: 565 rds, _ = rel.NewReader(ctx, 1, nil, ret) 566 } 567 568 retbat := batch.NewWithSize(1) 569 for len(rds) > 0 { 570 bat, err := rds[0].Read(ctx, AUTO_INCR_TABLE_COLNAME, nil, mp) 571 if err != nil { 572 bat.Clean(mp) 573 return nil, 0 574 } 575 if bat == nil { 576 rds[0].Close() 577 rds = rds[1:] 578 continue 579 } 580 if len(bat.Vecs) < 2 { 581 panic(moerr.NewInternalError(ctx, "the mo_increment_columns col num is not two")) 582 } 583 var rowIndex int64 584 for rowIndex = 0; rowIndex < int64(bat.Length()); rowIndex++ { 585 str := bat.Vecs[1].GetString(rowIndex) 586 if str == colName { 587 currentNum := vector.MustTCols[uint64](bat.Vecs[2])[rowIndex : rowIndex+1] 588 vec := vector.New(bat.GetVector(0).Typ) 589 rowid := vector.MustTCols[types.Rowid](bat.GetVector(0))[rowIndex] 590 if err := vec.Append(rowid, false, mp); err != nil { 591 panic(err) 592 } 593 retbat.SetVector(0, vec) 594 retbat.SetZs(1, mp) 595 bat.Clean(mp) 596 return retbat, currentNum[0] 597 } 598 } 599 bat.Clean(mp) 600 } 601 return nil, 0 602 } 603 604 // for create database operation, add col in mo_increment_columns table 605 func CreateAutoIncrTable(e engine.Engine, ctx context.Context, proc *process.Process, dbName string) error { 606 dbSource, err := e.Database(ctx, dbName, proc.TxnOperator) 607 if err != nil { 608 return err 609 } 610 if err = dbSource.Create(ctx, AUTO_INCR_TABLE, getAutoIncrTableDef()); err != nil { 611 return err 612 } 613 return nil 614 } 615 616 // for create table operation, add col in mo_increment_columns table 617 func CreateAutoIncrCol(eg engine.Engine, ctx context.Context, db engine.Database, proc *process.Process, cols []*plan.ColDef, dbName, tblName string) error { 618 rel, err := db.Relation(ctx, tblName) 619 if err != nil { 620 return err 621 } 622 name := fmt.Sprintf("%d_", rel.GetTableID(ctx)) 623 624 txn, err := NewTxn(eg, proc, ctx) 625 if err != nil { 626 return err 627 } 628 629 for _, attr := range cols { 630 if !attr.Typ.AutoIncr { 631 continue 632 } 633 var rel2 engine.Relation 634 // Essentially, temporary table is not an operation of a transaction. 635 // Therefore, it is not possible to fetch the temporary table through the function GetNewRelation 636 if dbName == defines.TEMPORARY_DBNAME { 637 rel2, err = db.Relation(ctx, AUTO_INCR_TABLE) 638 } else { 639 rel2, err = GetNewRelation(eg, dbName, AUTO_INCR_TABLE, txn, ctx) 640 } 641 if err != nil { 642 return err 643 } 644 bat := makeAutoIncrBatch(name+attr.Name, 0, 1, proc.Mp()) 645 if err = rel2.Write(ctx, bat); err != nil { 646 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 647 return err2 648 } 649 return err 650 } 651 } 652 if err = CommitTxn(eg, txn, ctx); err != nil { 653 return err 654 } 655 return nil 656 } 657 658 // for delete table operation, delete col in mo_increment_columns table 659 func DeleteAutoIncrCol(eg engine.Engine, ctx context.Context, db engine.Database, rel engine.Relation, proc *process.Process, dbName string, tableID uint64) error { 660 txn, err := NewTxn(eg, proc, ctx) 661 if err != nil { 662 return err 663 } 664 665 var rel2 engine.Relation 666 // Essentially, temporary table is not an operation of a transaction. 667 // Therefore, it is not possible to fetch the temporary table through the function GetNewRelation 668 if dbName == defines.TEMPORARY_DBNAME { 669 rel2, err = db.Relation(ctx, AUTO_INCR_TABLE) 670 } else { 671 rel2, err = GetNewRelation(eg, dbName, AUTO_INCR_TABLE, txn, ctx) 672 } 673 674 if err != nil { 675 return err 676 } 677 678 defs, err := rel.TableDefs(ctx) 679 if err != nil { 680 return err 681 } 682 683 for _, def := range defs { 684 switch d := def.(type) { 685 case *engine.AttributeDef: 686 if !d.Attr.AutoIncrement { 687 continue 688 } 689 name := fmt.Sprintf("%d_%s", tableID, d.Attr.Name) 690 bat, _ := GetDeleteBatch(rel2, ctx, name, proc.Mp()) 691 if bat == nil { 692 return moerr.NewInternalError(ctx, "the deleted batch is nil") 693 } 694 if err = rel2.Delete(ctx, bat, AUTO_INCR_TABLE_COLNAME[0]); err != nil { 695 bat.Clean(proc.Mp()) 696 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 697 return err2 698 } 699 return err 700 } 701 bat.Clean(proc.Mp()) 702 703 // Delete the cache. 704 deleteAutoIncrCache(name, proc) 705 } 706 } 707 if err = CommitTxn(eg, txn, ctx); err != nil { 708 return err 709 } 710 return nil 711 } 712 713 // for delete table operation, move old col as new col in mo_increment_columns table 714 func MoveAutoIncrCol(eg engine.Engine, ctx context.Context, tblName string, db engine.Database, proc *process.Process, oldTableID, newId uint64, dbName string) error { 715 var err error 716 newRel, err := db.Relation(ctx, tblName) 717 if err != nil { 718 return err 719 } 720 defs, err := newRel.TableDefs(ctx) 721 if err != nil { 722 return err 723 } 724 725 txn, err := NewTxn(eg, proc, ctx) 726 if err != nil { 727 return err 728 } 729 730 var autoRel engine.Relation 731 // Essentially, temporary table is not an operation of a transaction. 732 // Therefore, it is not possible to fetch the temporary table through the function GetNewRelation 733 if dbName == defines.TEMPORARY_DBNAME { 734 autoRel, err = db.Relation(ctx, AUTO_INCR_TABLE) 735 } else { 736 autoRel, err = GetNewRelation(eg, dbName, AUTO_INCR_TABLE, txn, ctx) 737 } 738 739 if err != nil { 740 return err 741 } 742 743 newName := fmt.Sprintf("%d_", newId) 744 for _, def := range defs { 745 switch d := def.(type) { 746 case *engine.AttributeDef: 747 if !d.Attr.AutoIncrement { 748 continue 749 } 750 751 delName := fmt.Sprintf("%d_%s", oldTableID, d.Attr.Name) 752 bat, currentNum := GetDeleteBatch(autoRel, ctx, delName, proc.Mp()) 753 if bat == nil { 754 return moerr.NewInternalError(ctx, "the deleted batch is nil") 755 } 756 if err = autoRel.Delete(ctx, bat, AUTO_INCR_TABLE_COLNAME[0]); err != nil { 757 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 758 return err2 759 } 760 return err 761 } 762 763 // Rename the old cache. 764 renameAutoIncrCache(delName, newName+d.Attr.Name, proc) 765 766 // In cache implementation no update needed. 767 currentNum = currentNum - 1 768 769 bat2 := makeAutoIncrBatch(newName+d.Attr.Name, currentNum-1, 1, proc.Mp()) 770 if err = autoRel.Write(ctx, bat2); err != nil { 771 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 772 return err2 773 } 774 return err 775 } 776 } 777 } 778 if err = CommitTxn(eg, txn, ctx); err != nil { 779 return err 780 } 781 return nil 782 } 783 784 // for truncate table operation, reset col in mo_increment_columns table 785 func ResetAutoInsrCol(eg engine.Engine, ctx context.Context, tblName string, db engine.Database, proc *process.Process, tableID, newId uint64, dbName string) error { 786 rel, err := db.Relation(ctx, tblName) 787 if err != nil { 788 return err 789 } 790 defs, err := rel.TableDefs(ctx) 791 if err != nil { 792 return err 793 } 794 795 txn, err := NewTxn(eg, proc, ctx) 796 if err != nil { 797 return err 798 } 799 800 var autoRel engine.Relation 801 // Essentially, temporary table is not an operation of a transaction. 802 // Therefore, it is not possible to fetch the temporary table through the function GetNewRelation 803 if dbName == defines.TEMPORARY_DBNAME { 804 autoRel, err = db.Relation(ctx, AUTO_INCR_TABLE) 805 } else { 806 autoRel, err = GetNewRelation(eg, dbName, AUTO_INCR_TABLE, txn, ctx) 807 } 808 809 if err != nil { 810 return err 811 } 812 name := fmt.Sprintf("%d_", newId) 813 for _, def := range defs { 814 switch d := def.(type) { 815 case *engine.AttributeDef: 816 if !d.Attr.AutoIncrement { 817 continue 818 } 819 delName := fmt.Sprintf("%d_%s", tableID, d.Attr.Name) 820 bat, _ := GetDeleteBatch(autoRel, ctx, delName, proc.Mp()) 821 if bat == nil { 822 return moerr.NewInternalError(ctx, "the deleted batch is nil") 823 } 824 if err = autoRel.Delete(ctx, bat, AUTO_INCR_TABLE_COLNAME[0]); err != nil { 825 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 826 return err2 827 } 828 return err 829 } 830 831 // Delete the cache. 832 deleteAutoIncrCache(delName, proc) 833 834 bat2 := makeAutoIncrBatch(name+d.Attr.Name, 0, 1, proc.Mp()) 835 if err = autoRel.Write(ctx, bat2); err != nil { 836 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 837 return err2 838 } 839 return err 840 } 841 } 842 } 843 if err = CommitTxn(eg, txn, ctx); err != nil { 844 return err 845 } 846 return nil 847 } 848 849 // func orderColDefs(attrs []string, ColDefs []*plan.ColDef, cols []*plan.Column) { 850 // for i, name := range attrs { 851 // for j, def := range ColDefs { 852 // if name == def.Name { 853 // ColDefs[i], ColDefs[j] = ColDefs[j], ColDefs[i] 854 // cols[i], cols[j] = cols[j], cols[i] 855 // } 856 // } 857 // } 858 // } 859 860 func NewTxn(eg engine.Engine, proc *process.Process, ctx context.Context) (txn client.TxnOperator, err error) { 861 if proc.TxnClient == nil { 862 return nil, moerr.NewInternalError(ctx, "must set txn client") 863 } 864 txn, err = proc.TxnClient.New() 865 if err != nil { 866 return nil, err 867 } 868 if ctx == nil { 869 return nil, moerr.NewInternalError(ctx, "context should not be nil") 870 } 871 if err = eg.New(ctx, txn); err != nil { 872 return nil, err 873 } 874 return txn, nil 875 } 876 877 func CommitTxn(eg engine.Engine, txn client.TxnOperator, ctx context.Context) error { 878 if txn == nil { 879 return nil 880 } 881 if ctx == nil { 882 return moerr.NewInternalError(ctx, "context should not be nil") 883 } 884 ctx, cancel := context.WithTimeout( 885 ctx, 886 eg.Hints().CommitOrRollbackTimeout, 887 ) 888 defer cancel() 889 if err := eg.Commit(ctx, txn); err != nil { 890 if err2 := RolllbackTxn(eg, txn, ctx); err2 != nil { 891 logutil.Errorf("CommitTxn: txn operator rollback failed. error:%v", err2) 892 } 893 return err 894 } 895 err := txn.Commit(ctx) 896 txn = nil 897 return err 898 } 899 900 func RolllbackTxn(eg engine.Engine, txn client.TxnOperator, ctx context.Context) error { 901 if txn == nil { 902 return nil 903 } 904 if ctx == nil { 905 return moerr.NewInternalError(ctx, "context should not be nil") 906 } 907 ctx, cancel := context.WithTimeout( 908 ctx, 909 eg.Hints().CommitOrRollbackTimeout, 910 ) 911 defer cancel() 912 if err := eg.Rollback(ctx, txn); err != nil { 913 return err 914 } 915 err := txn.Rollback(ctx) 916 txn = nil 917 return err 918 } 919 920 func GetNewRelation(eg engine.Engine, dbName, tbleName string, txn client.TxnOperator, ctx context.Context) (engine.Relation, error) { 921 dbHandler, err := eg.Database(ctx, dbName, txn) 922 if err != nil { 923 return nil, err 924 } 925 tableHandler, err := dbHandler.Relation(ctx, tbleName) 926 if err != nil { 927 return nil, err 928 } 929 return tableHandler, nil 930 } 931 932 func getAutoIncrTableDef() []engine.TableDef { 933 /* 934 mo_increment_columns schema 935 | Attribute | Type | Primary Key | Note | 936 | ------- | ------------ | ----------- | ------------------------ | 937 | name | varchar(770) | | Name of the db_table_col | 938 | offset | uint64 | | current index number | 939 | step | uint64 | | every increase step | 940 */ 941 942 nameAttr := &engine.AttributeDef{Attr: engine.Attribute{ 943 Name: AUTO_INCR_TABLE_COLNAME[1], 944 Alg: 0, 945 Type: types.T_varchar.ToType(), 946 Default: &plan.Default{}, 947 Primary: true, 948 }} 949 950 numAttr := &engine.AttributeDef{Attr: engine.Attribute{ 951 Name: AUTO_INCR_TABLE_COLNAME[2], 952 Alg: 0, 953 Type: types.T_uint64.ToType(), 954 Default: &plan.Default{}, 955 Primary: false, 956 }} 957 958 stepAttr := &engine.AttributeDef{Attr: engine.Attribute{ 959 Name: AUTO_INCR_TABLE_COLNAME[3], 960 Alg: 0, 961 Type: types.T_uint64.ToType(), 962 Default: &plan.Default{}, 963 Primary: false, 964 }} 965 966 defs := make([]engine.TableDef, 0, 3) 967 defs = append(defs, nameAttr) 968 defs = append(defs, numAttr) 969 defs = append(defs, stepAttr) 970 971 constrains := &engine.ConstraintDef{Cts: make([]engine.Constraint, 0)} 972 constrains.Cts = append(constrains.Cts, &engine.PrimaryKeyDef{ 973 Pkey: &plan.PrimaryKeyDef{ 974 Names: []string{AUTO_INCR_TABLE_COLNAME[1]}, 975 PkeyColName: AUTO_INCR_TABLE_COLNAME[1], 976 }, 977 }) 978 defs = append(defs, constrains) 979 980 return defs 981 }