github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/build_ddl.go (about) 1 // Copyright 2021 - 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 plan 16 17 import ( 18 "context" 19 "encoding/json" 20 "fmt" 21 "slices" 22 "strconv" 23 "strings" 24 25 "github.com/matrixorigin/matrixone/pkg/catalog" 26 "github.com/matrixorigin/matrixone/pkg/common/moerr" 27 "github.com/matrixorigin/matrixone/pkg/container/types" 28 "github.com/matrixorigin/matrixone/pkg/defines" 29 "github.com/matrixorigin/matrixone/pkg/pb/plan" 30 "github.com/matrixorigin/matrixone/pkg/pb/timestamp" 31 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 32 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 33 "github.com/matrixorigin/matrixone/pkg/sql/util" 34 mokafka "github.com/matrixorigin/matrixone/pkg/stream/adapter/kafka" 35 ) 36 37 func genDynamicTableDef(ctx CompilerContext, stmt *tree.Select) (*plan.TableDef, error) { 38 var tableDef plan.TableDef 39 40 // check view statement 41 var stmtPlan *Plan 42 var err error 43 switch s := stmt.Select.(type) { 44 case *tree.ParenSelect: 45 stmtPlan, err = runBuildSelectByBinder(plan.Query_SELECT, ctx, s.Select, false) 46 if err != nil { 47 return nil, err 48 } 49 default: 50 stmtPlan, err = runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt, false) 51 if err != nil { 52 return nil, err 53 } 54 } 55 56 query := stmtPlan.GetQuery() 57 cols := make([]*plan.ColDef, len(query.Nodes[query.Steps[len(query.Steps)-1]].ProjectList)) 58 for idx, expr := range query.Nodes[query.Steps[len(query.Steps)-1]].ProjectList { 59 cols[idx] = &plan.ColDef{ 60 Name: strings.ToLower(query.Headings[idx]), 61 Alg: plan.CompressType_Lz4, 62 Typ: expr.Typ, 63 Default: &plan.Default{ 64 NullAbility: !expr.Typ.NotNullable, 65 Expr: nil, 66 OriginString: "", 67 }, 68 } 69 } 70 tableDef.Cols = cols 71 72 viewData, err := json.Marshal(ViewData{ 73 Stmt: ctx.GetRootSql(), 74 DefaultDatabase: ctx.DefaultDatabase(), 75 }) 76 if err != nil { 77 return nil, err 78 } 79 tableDef.ViewSql = &plan.ViewDef{ 80 View: string(viewData), 81 } 82 properties := []*plan.Property{ 83 { 84 Key: catalog.SystemRelAttr_CreateSQL, 85 Value: ctx.GetRootSql(), 86 }, 87 } 88 tableDef.Defs = append(tableDef.Defs, &plan.TableDef_DefType{ 89 Def: &plan.TableDef_DefType_Properties{ 90 Properties: &plan.PropertiesDef{ 91 Properties: properties, 92 }, 93 }, 94 }) 95 96 return &tableDef, nil 97 } 98 99 func genViewTableDef(ctx CompilerContext, stmt *tree.Select) (*plan.TableDef, error) { 100 var tableDef plan.TableDef 101 102 // check view statement 103 var stmtPlan *Plan 104 var err error 105 switch s := stmt.Select.(type) { 106 case *tree.ParenSelect: 107 stmtPlan, err = runBuildSelectByBinder(plan.Query_SELECT, ctx, s.Select, false) 108 if err != nil { 109 return nil, err 110 } 111 default: 112 stmtPlan, err = runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt, false) 113 if err != nil { 114 return nil, err 115 } 116 } 117 118 query := stmtPlan.GetQuery() 119 cols := make([]*plan.ColDef, len(query.Nodes[query.Steps[len(query.Steps)-1]].ProjectList)) 120 for idx, expr := range query.Nodes[query.Steps[len(query.Steps)-1]].ProjectList { 121 cols[idx] = &plan.ColDef{ 122 Name: strings.ToLower(query.Headings[idx]), 123 Alg: plan.CompressType_Lz4, 124 Typ: expr.Typ, 125 Default: &plan.Default{ 126 NullAbility: !expr.Typ.NotNullable, 127 Expr: nil, 128 OriginString: "", 129 }, 130 } 131 } 132 tableDef.Cols = cols 133 134 // Check alter and change the viewsql. 135 viewSql := ctx.GetRootSql() 136 if len(viewSql) != 0 { 137 if viewSql[0] == 'A' { 138 viewSql = strings.Replace(viewSql, "ALTER", "CREATE", 1) 139 } 140 if viewSql[0] == 'a' { 141 viewSql = strings.Replace(viewSql, "alter", "create", 1) 142 } 143 } 144 145 viewData, err := json.Marshal(ViewData{ 146 Stmt: viewSql, 147 DefaultDatabase: ctx.DefaultDatabase(), 148 }) 149 if err != nil { 150 return nil, err 151 } 152 tableDef.ViewSql = &plan.ViewDef{ 153 View: string(viewData), 154 } 155 properties := []*plan.Property{ 156 { 157 Key: catalog.SystemRelAttr_Kind, 158 Value: catalog.SystemViewRel, 159 }, 160 { 161 Key: catalog.SystemRelAttr_CreateSQL, 162 Value: ctx.GetRootSql(), 163 }, 164 } 165 tableDef.Defs = append(tableDef.Defs, &plan.TableDef_DefType{ 166 Def: &plan.TableDef_DefType_Properties{ 167 Properties: &plan.PropertiesDef{ 168 Properties: properties, 169 }, 170 }, 171 }) 172 173 return &tableDef, nil 174 } 175 176 func genAsSelectCols(ctx CompilerContext, stmt *tree.Select) ([]*ColDef, error) { 177 var err error 178 var rootId int32 179 builder := NewQueryBuilder(plan.Query_SELECT, ctx, false) 180 bindCtx := NewBindContext(builder, nil) 181 182 getTblAndColName := func(relPos, colPos int32) (string, string) { 183 name := builder.nameByColRef[[2]int32{relPos, colPos}] 184 // name pattern: tableName.colName 185 splits := strings.Split(name, ".") 186 if len(splits) < 2 { 187 return "", "" 188 } 189 return splits[0], splits[1] 190 } 191 192 if s, ok := stmt.Select.(*tree.ParenSelect); ok { 193 stmt = s.Select 194 } 195 if rootId, err = builder.buildSelect(stmt, bindCtx, true); err != nil { 196 return nil, err 197 } 198 rootNode := builder.qry.Nodes[rootId] 199 200 cols := make([]*plan.ColDef, len(rootNode.ProjectList)) 201 for i, expr := range rootNode.ProjectList { 202 defaultVal := "" 203 typ := &expr.Typ 204 switch e := expr.Expr.(type) { 205 case *plan.Expr_Col: 206 tblName, colName := getTblAndColName(e.Col.RelPos, e.Col.ColPos) 207 if binding, ok := bindCtx.bindingByTable[tblName]; ok { 208 defaultVal = binding.defaults[binding.colIdByName[colName]] 209 } 210 case *plan.Expr_F: 211 // enum 212 if e.F.Func.ObjName == moEnumCastIndexToValueFun { 213 // cast_index_to_value('apple,banana,orange', cast(col_name as T_uint16)) 214 colRef := e.F.Args[1].Expr.(*plan.Expr_F).F.Args[0].Expr.(*plan.Expr_Col).Col 215 tblName, colName := getTblAndColName(colRef.RelPos, colRef.ColPos) 216 if binding, ok := bindCtx.bindingByTable[tblName]; ok { 217 typ = binding.types[binding.colIdByName[colName]] 218 } 219 } 220 } 221 222 cols[i] = &plan.ColDef{ 223 Name: strings.ToLower(bindCtx.headings[i]), 224 Alg: plan.CompressType_Lz4, 225 Typ: *typ, 226 Default: &plan.Default{ 227 NullAbility: !expr.Typ.NotNullable, 228 Expr: nil, 229 OriginString: defaultVal, 230 }, 231 } 232 } 233 return cols, nil 234 } 235 236 func buildCreateSource(stmt *tree.CreateSource, ctx CompilerContext) (*Plan, error) { 237 streamName := string(stmt.SourceName.ObjectName) 238 createStream := &plan.CreateTable{ 239 IfNotExists: stmt.IfNotExists, 240 TableDef: &TableDef{ 241 TableType: catalog.SystemSourceRel, 242 Name: streamName, 243 }, 244 } 245 if len(stmt.SourceName.SchemaName) == 0 { 246 createStream.Database = ctx.DefaultDatabase() 247 } else { 248 createStream.Database = string(stmt.SourceName.SchemaName) 249 } 250 251 if sub, err := ctx.GetSubscriptionMeta(createStream.Database, Snapshot{TS: ×tamp.Timestamp{}}); err != nil { 252 return nil, err 253 } else if sub != nil { 254 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot create stream in subscription database") 255 } 256 257 if err := buildSourceDefs(stmt, ctx, createStream); err != nil { 258 return nil, err 259 } 260 261 var properties []*plan.Property 262 properties = append(properties, &plan.Property{ 263 Key: catalog.SystemRelAttr_Kind, 264 Value: catalog.SystemSourceRel, 265 }) 266 configs := make(map[string]interface{}) 267 for _, option := range stmt.Options { 268 switch opt := option.(type) { 269 case *tree.CreateSourceWithOption: 270 key := strings.ToLower(string(opt.Key)) 271 val := opt.Val.(*tree.NumVal).OrigString() 272 properties = append(properties, &plan.Property{ 273 Key: key, 274 Value: val, 275 }) 276 configs[key] = val 277 } 278 } 279 if err := mokafka.ValidateConfig(context.Background(), configs, mokafka.NewKafkaAdapter); err != nil { 280 return nil, err 281 } 282 createStream.TableDef.Defs = append(createStream.TableDef.Defs, &plan.TableDef_DefType{ 283 Def: &plan.TableDef_DefType_Properties{ 284 Properties: &plan.PropertiesDef{ 285 Properties: properties, 286 }, 287 }, 288 }) 289 return &Plan{ 290 Plan: &plan.Plan_Ddl{ 291 Ddl: &plan.DataDefinition{ 292 DdlType: plan.DataDefinition_CREATE_TABLE, 293 Definition: &plan.DataDefinition_CreateTable{ 294 CreateTable: createStream, 295 }, 296 }, 297 }, 298 }, nil 299 } 300 301 func buildSourceDefs(stmt *tree.CreateSource, ctx CompilerContext, createStream *plan.CreateTable) error { 302 colMap := make(map[string]*ColDef) 303 for _, item := range stmt.Defs { 304 switch def := item.(type) { 305 case *tree.ColumnTableDef: 306 colName := def.Name.Parts[0] 307 if _, ok := colMap[colName]; ok { 308 return moerr.NewInvalidInput(ctx.GetContext(), "duplicate column name: %s", colName) 309 } 310 colType, err := getTypeFromAst(ctx.GetContext(), def.Type) 311 if err != nil { 312 return err 313 } 314 if colType.Id == int32(types.T_char) || colType.Id == int32(types.T_varchar) || 315 colType.Id == int32(types.T_binary) || colType.Id == int32(types.T_varbinary) { 316 if colType.GetWidth() > types.MaxStringSize { 317 return moerr.NewInvalidInput(ctx.GetContext(), "string width (%d) is too long", colType.GetWidth()) 318 } 319 } 320 col := &ColDef{ 321 Name: colName, 322 Alg: plan.CompressType_Lz4, 323 Typ: colType, 324 } 325 colMap[colName] = col 326 for _, attr := range def.Attributes { 327 switch a := attr.(type) { 328 case *tree.AttributeKey: 329 col.Primary = true 330 case *tree.AttributeHeader: 331 col.Header = a.Key 332 case *tree.AttributeHeaders: 333 col.Headers = true 334 } 335 } 336 createStream.TableDef.Cols = append(createStream.TableDef.Cols, col) 337 case *tree.CreateSourceWithOption: 338 default: 339 return moerr.NewNYI(ctx.GetContext(), "stream def: '%v'", def) 340 } 341 } 342 return nil 343 } 344 345 func buildCreateView(stmt *tree.CreateView, ctx CompilerContext) (*Plan, error) { 346 viewName := stmt.Name.ObjectName 347 createTable := &plan.CreateTable{ 348 Replace: stmt.Replace, 349 IfNotExists: stmt.IfNotExists, 350 TableDef: &TableDef{ 351 Name: string(viewName), 352 }, 353 } 354 355 // get database name 356 if len(stmt.Name.SchemaName) == 0 { 357 createTable.Database = "" 358 } else { 359 createTable.Database = string(stmt.Name.SchemaName) 360 } 361 if len(createTable.Database) == 0 { 362 createTable.Database = ctx.DefaultDatabase() 363 } 364 365 snapshot := &Snapshot{TS: ×tamp.Timestamp{}} 366 if IsSnapshotValid(ctx.GetSnapshot()) { 367 snapshot = ctx.GetSnapshot() 368 } 369 370 if sub, err := ctx.GetSubscriptionMeta(createTable.Database, *snapshot); err != nil { 371 return nil, err 372 } else if sub != nil { 373 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot create view in subscription database") 374 } 375 376 tableDef, err := genViewTableDef(ctx, stmt.AsSource) 377 if err != nil { 378 return nil, err 379 } 380 381 createTable.TableDef.Cols = tableDef.Cols 382 createTable.TableDef.ViewSql = tableDef.ViewSql 383 createTable.TableDef.Defs = tableDef.Defs 384 385 return &Plan{ 386 Plan: &plan.Plan_Ddl{ 387 Ddl: &plan.DataDefinition{ 388 DdlType: plan.DataDefinition_CREATE_TABLE, 389 Definition: &plan.DataDefinition_CreateTable{ 390 CreateTable: createTable, 391 }, 392 }, 393 }, 394 }, nil 395 } 396 397 func buildSequenceTableDef(stmt *tree.CreateSequence, ctx CompilerContext, cs *plan.CreateSequence) error { 398 // Sequence table got 1 row and 7 col 399 // sequence_value, maxvalue,minvalue,startvalue,increment,cycleornot,iscalled. 400 cols := make([]*plan.ColDef, len(Sequence_cols_name)) 401 402 typ, err := getTypeFromAst(ctx.GetContext(), stmt.Type) 403 if err != nil { 404 return err 405 } 406 for i := range cols { 407 if i == 4 { 408 break 409 } 410 cols[i] = &plan.ColDef{ 411 Name: Sequence_cols_name[i], 412 Alg: plan.CompressType_Lz4, 413 Typ: typ, 414 Default: &plan.Default{ 415 NullAbility: true, 416 Expr: nil, 417 OriginString: "", 418 }, 419 } 420 } 421 cols[4] = &plan.ColDef{ 422 Name: Sequence_cols_name[4], 423 Alg: plan.CompressType_Lz4, 424 Typ: plan.Type{ 425 Id: int32(types.T_int64), 426 Width: 0, 427 Scale: 0, 428 }, 429 Primary: true, 430 Default: &plan.Default{ 431 NullAbility: true, 432 Expr: nil, 433 OriginString: "", 434 }, 435 } 436 cs.TableDef.Pkey = &PrimaryKeyDef{ 437 Names: []string{Sequence_cols_name[4]}, 438 PkeyColName: Sequence_cols_name[4], 439 } 440 for i := 5; i <= 6; i++ { 441 cols[i] = &plan.ColDef{ 442 Name: Sequence_cols_name[i], 443 Alg: plan.CompressType_Lz4, 444 Typ: plan.Type{ 445 Id: int32(types.T_bool), 446 Width: 0, 447 Scale: 0, 448 }, 449 Default: &plan.Default{ 450 NullAbility: true, 451 Expr: nil, 452 OriginString: "", 453 }, 454 } 455 } 456 457 cs.TableDef.Cols = cols 458 459 properties := []*plan.Property{ 460 { 461 Key: catalog.SystemRelAttr_Kind, 462 Value: catalog.SystemSequenceRel, 463 }, 464 { 465 Key: catalog.SystemRelAttr_CreateSQL, 466 Value: ctx.GetRootSql(), 467 }, 468 } 469 470 cs.TableDef.Defs = append(cs.TableDef.Defs, &plan.TableDef_DefType{ 471 Def: &plan.TableDef_DefType_Properties{ 472 Properties: &plan.PropertiesDef{ 473 Properties: properties, 474 }, 475 }, 476 }) 477 return nil 478 } 479 480 func buildAlterSequenceTableDef(stmt *tree.AlterSequence, ctx CompilerContext, as *plan.AlterSequence) error { 481 // Sequence table got 1 row and 7 col 482 // sequence_value, maxvalue,minvalue,startvalue,increment,cycleornot,iscalled. 483 cols := make([]*plan.ColDef, len(Sequence_cols_name)) 484 485 var typ plan.Type 486 var err error 487 if stmt.Type == nil { 488 _, tableDef := ctx.Resolve(as.GetDatabase(), as.TableDef.Name, Snapshot{TS: ×tamp.Timestamp{}}) 489 if tableDef == nil { 490 return moerr.NewInvalidInput(ctx.GetContext(), "no such sequence %s", as.TableDef.Name) 491 } else { 492 typ = tableDef.Cols[0].Typ 493 } 494 } else { 495 typ, err = getTypeFromAst(ctx.GetContext(), stmt.Type.Type) 496 if err != nil { 497 return err 498 } 499 } 500 501 for i := range cols { 502 if i == 4 { 503 break 504 } 505 cols[i] = &plan.ColDef{ 506 Name: Sequence_cols_name[i], 507 Alg: plan.CompressType_Lz4, 508 Typ: typ, 509 Default: &plan.Default{ 510 NullAbility: true, 511 Expr: nil, 512 OriginString: "", 513 }, 514 } 515 } 516 cols[4] = &plan.ColDef{ 517 Name: Sequence_cols_name[4], 518 Alg: plan.CompressType_Lz4, 519 Typ: plan.Type{ 520 Id: int32(types.T_int64), 521 Width: 0, 522 Scale: 0, 523 }, 524 Primary: true, 525 Default: &plan.Default{ 526 NullAbility: true, 527 Expr: nil, 528 OriginString: "", 529 }, 530 } 531 as.TableDef.Pkey = &PrimaryKeyDef{ 532 Names: []string{Sequence_cols_name[4]}, 533 PkeyColName: Sequence_cols_name[4], 534 } 535 for i := 5; i <= 6; i++ { 536 cols[i] = &plan.ColDef{ 537 Name: Sequence_cols_name[i], 538 Alg: plan.CompressType_Lz4, 539 Typ: plan.Type{ 540 Id: int32(types.T_bool), 541 Width: 0, 542 Scale: 0, 543 }, 544 Default: &plan.Default{ 545 NullAbility: true, 546 Expr: nil, 547 OriginString: "", 548 }, 549 } 550 } 551 552 as.TableDef.Cols = cols 553 554 properties := []*plan.Property{ 555 { 556 Key: catalog.SystemRelAttr_Kind, 557 Value: catalog.SystemSequenceRel, 558 }, 559 { 560 Key: catalog.SystemRelAttr_CreateSQL, 561 Value: ctx.GetRootSql(), 562 }, 563 } 564 565 as.TableDef.Defs = append(as.TableDef.Defs, &plan.TableDef_DefType{ 566 Def: &plan.TableDef_DefType_Properties{ 567 Properties: &plan.PropertiesDef{ 568 Properties: properties, 569 }, 570 }, 571 }) 572 return nil 573 574 } 575 576 func buildDropSequence(stmt *tree.DropSequence, ctx CompilerContext) (*Plan, error) { 577 dropSequence := &plan.DropSequence{ 578 IfExists: stmt.IfExists, 579 } 580 if len(stmt.Names) != 1 { 581 return nil, moerr.NewNotSupported(ctx.GetContext(), "drop multiple (%d) Sequence in one statement", len(stmt.Names)) 582 } 583 dropSequence.Database = string(stmt.Names[0].SchemaName) 584 if dropSequence.Database == "" { 585 dropSequence.Database = ctx.DefaultDatabase() 586 } 587 dropSequence.Table = string(stmt.Names[0].ObjectName) 588 589 obj, tableDef := ctx.Resolve(dropSequence.Database, dropSequence.Table, Snapshot{TS: ×tamp.Timestamp{}}) 590 if tableDef == nil || tableDef.TableType != catalog.SystemSequenceRel { 591 if !dropSequence.IfExists { 592 return nil, moerr.NewNoSuchSequence(ctx.GetContext(), dropSequence.Database, dropSequence.Table) 593 } 594 dropSequence.Table = "" 595 } 596 if obj != nil && obj.PubInfo != nil { 597 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot drop sequence in subscription database") 598 } 599 600 return &Plan{ 601 Plan: &plan.Plan_Ddl{ 602 Ddl: &plan.DataDefinition{ 603 DdlType: plan.DataDefinition_DROP_SEQUENCE, 604 Definition: &plan.DataDefinition_DropSequence{ 605 DropSequence: dropSequence, 606 }, 607 }, 608 }, 609 }, nil 610 } 611 612 func buildAlterSequence(stmt *tree.AlterSequence, ctx CompilerContext) (*Plan, error) { 613 if stmt.Type == nil && stmt.IncrementBy == nil && stmt.MaxValue == nil && stmt.MinValue == nil && stmt.StartWith == nil && stmt.Cycle == nil { 614 return nil, moerr.NewSyntaxError(ctx.GetContext(), "synatx error, %s has nothing to alter", string(stmt.Name.ObjectName)) 615 } 616 617 alterSequence := &plan.AlterSequence{ 618 IfExists: stmt.IfExists, 619 TableDef: &TableDef{ 620 Name: string(stmt.Name.ObjectName), 621 }, 622 } 623 // Get database name. 624 if len(stmt.Name.SchemaName) == 0 { 625 alterSequence.Database = ctx.DefaultDatabase() 626 } else { 627 alterSequence.Database = string(stmt.Name.SchemaName) 628 } 629 630 if sub, err := ctx.GetSubscriptionMeta(alterSequence.Database, Snapshot{TS: ×tamp.Timestamp{}}); err != nil { 631 return nil, err 632 } else if sub != nil { 633 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot alter sequence in subscription database") 634 } 635 636 err := buildAlterSequenceTableDef(stmt, ctx, alterSequence) 637 if err != nil { 638 return nil, err 639 } 640 641 return &Plan{ 642 Plan: &plan.Plan_Ddl{ 643 Ddl: &plan.DataDefinition{ 644 DdlType: plan.DataDefinition_ALTER_SEQUENCE, 645 Definition: &plan.DataDefinition_AlterSequence{ 646 AlterSequence: alterSequence, 647 }, 648 }, 649 }, 650 }, nil 651 } 652 653 func buildCreateSequence(stmt *tree.CreateSequence, ctx CompilerContext) (*Plan, error) { 654 createSequence := &plan.CreateSequence{ 655 IfNotExists: stmt.IfNotExists, 656 TableDef: &TableDef{ 657 Name: string(stmt.Name.ObjectName), 658 }, 659 } 660 // Get database name. 661 if len(stmt.Name.SchemaName) == 0 { 662 createSequence.Database = ctx.DefaultDatabase() 663 } else { 664 createSequence.Database = string(stmt.Name.SchemaName) 665 } 666 667 if sub, err := ctx.GetSubscriptionMeta(createSequence.Database, Snapshot{TS: ×tamp.Timestamp{}}); err != nil { 668 return nil, err 669 } else if sub != nil { 670 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot create sequence in subscription database") 671 } 672 673 err := buildSequenceTableDef(stmt, ctx, createSequence) 674 if err != nil { 675 return nil, err 676 } 677 678 return &Plan{ 679 Plan: &plan.Plan_Ddl{ 680 Ddl: &plan.DataDefinition{ 681 DdlType: plan.DataDefinition_CREATE_SEQUENCE, 682 Definition: &plan.DataDefinition_CreateSequence{ 683 CreateSequence: createSequence, 684 }, 685 }, 686 }, 687 }, nil 688 } 689 690 func buildCreateTable(stmt *tree.CreateTable, ctx CompilerContext) (*Plan, error) { 691 if stmt.IsAsLike { 692 newStmt, err := rewriteForCreateTableLike(stmt, ctx) 693 if err != nil { 694 return nil, err 695 } 696 if stmtLike, ok := newStmt.(*tree.CreateTable); ok { 697 return buildCreateTable(stmtLike, ctx) 698 } 699 return nil, moerr.NewInternalError(ctx.GetContext(), "rewrite for create table like failed") 700 } 701 702 createTable := &plan.CreateTable{ 703 IfNotExists: stmt.IfNotExists, 704 Temporary: stmt.Temporary, 705 TableDef: &TableDef{ 706 Name: string(stmt.Table.ObjectName), 707 }, 708 } 709 710 // get database name 711 if len(stmt.Table.SchemaName) == 0 { 712 createTable.Database = ctx.DefaultDatabase() 713 } else { 714 createTable.Database = string(stmt.Table.SchemaName) 715 } 716 717 if stmt.Temporary && stmt.PartitionOption != nil { 718 return nil, moerr.NewPartitionNoTemporary(ctx.GetContext()) 719 } 720 721 if sub, err := ctx.GetSubscriptionMeta(createTable.Database, Snapshot{TS: ×tamp.Timestamp{}}); err != nil { 722 return nil, err 723 } else if sub != nil { 724 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot create table in subscription database") 725 } 726 727 // set tableDef 728 var err error 729 if stmt.IsDynamicTable { 730 tableDef, err := genDynamicTableDef(ctx, stmt.AsSource) 731 if err != nil { 732 return nil, err 733 } 734 735 createTable.TableDef.Cols = tableDef.Cols 736 //createTable.TableDef.ViewSql = tableDef.ViewSql 737 //createTable.TableDef.Defs = tableDef.Defs 738 } 739 740 var asSelectCols []*ColDef 741 if stmt.IsAsSelect { 742 if asSelectCols, err = genAsSelectCols(ctx, stmt.AsSource); err != nil { 743 return nil, err 744 } 745 } 746 747 if err = buildTableDefs(stmt, ctx, createTable, asSelectCols); err != nil { 748 return nil, err 749 } 750 751 v, ok := getAutoIncrementOffsetFromVariables(ctx) 752 if ok { 753 createTable.TableDef.AutoIncrOffset = v 754 } 755 756 // set option 757 for _, option := range stmt.Options { 758 switch opt := option.(type) { 759 case *tree.TableOptionProperties: 760 properties := make([]*plan.Property, len(opt.Preperties)) 761 for idx, property := range opt.Preperties { 762 properties[idx] = &plan.Property{ 763 Key: property.Key, 764 Value: property.Value, 765 } 766 } 767 createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{ 768 Def: &plan.TableDef_DefType_Properties{ 769 Properties: &plan.PropertiesDef{ 770 Properties: properties, 771 }, 772 }, 773 }) 774 // todo confirm: option data store like this? 775 case *tree.TableOptionComment: 776 if getNumOfCharacters(opt.Comment) > maxLengthOfTableComment { 777 return nil, moerr.NewInvalidInput(ctx.GetContext(), "comment for field '%s' is too long", createTable.TableDef.Name) 778 } 779 780 properties := []*plan.Property{ 781 { 782 Key: catalog.SystemRelAttr_Comment, 783 Value: opt.Comment, 784 }, 785 } 786 createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{ 787 Def: &plan.TableDef_DefType_Properties{ 788 Properties: &plan.PropertiesDef{ 789 Properties: properties, 790 }, 791 }, 792 }) 793 case *tree.TableOptionAutoIncrement: 794 if opt.Value != 0 { 795 createTable.TableDef.AutoIncrOffset = opt.Value - 1 796 } 797 798 // these table options is not support in plan 799 // case *tree.TableOptionEngine, *tree.TableOptionSecondaryEngine, *tree.TableOptionCharset, 800 // *tree.TableOptionCollate, *tree.TableOptionAutoIncrement, *tree.TableOptionComment, 801 // *tree.TableOptionAvgRowLength, *tree.TableOptionChecksum, *tree.TableOptionCompression, 802 // *tree.TableOptionConnection, *tree.TableOptionPassword, *tree.TableOptionKeyBlockSize, 803 // *tree.TableOptionMaxRows, *tree.TableOptionMinRows, *tree.TableOptionDelayKeyWrite, 804 // *tree.TableOptionRowFormat, *tree.TableOptionStatsPersistent, *tree.TableOptionStatsAutoRecalc, 805 // *tree.TableOptionPackKeys, *tree.TableOptionTablespace, *tree.TableOptionDataDirectory, 806 // *tree.TableOptionIndexDirectory, *tree.TableOptionStorageMedia, *tree.TableOptionStatsSamplePages, 807 // *tree.TableOptionUnion, *tree.TableOptionEncryption: 808 // return nil, moerr.NewNotSupported("statement: '%v'", tree.String(stmt, dialect.MYSQL)) 809 case *tree.TableOptionAUTOEXTEND_SIZE, *tree.TableOptionAvgRowLength, 810 *tree.TableOptionCharset, *tree.TableOptionChecksum, *tree.TableOptionCollate, *tree.TableOptionCompression, 811 *tree.TableOptionConnection, *tree.TableOptionDataDirectory, *tree.TableOptionIndexDirectory, 812 *tree.TableOptionDelayKeyWrite, *tree.TableOptionEncryption, *tree.TableOptionEngine, *tree.TableOptionEngineAttr, 813 *tree.TableOptionKeyBlockSize, *tree.TableOptionMaxRows, *tree.TableOptionMinRows, *tree.TableOptionPackKeys, 814 *tree.TableOptionPassword, *tree.TableOptionRowFormat, *tree.TableOptionStartTrans, *tree.TableOptionSecondaryEngineAttr, 815 *tree.TableOptionStatsAutoRecalc, *tree.TableOptionStatsPersistent, *tree.TableOptionStatsSamplePages, 816 *tree.TableOptionTablespace, *tree.TableOptionUnion: 817 818 default: 819 return nil, moerr.NewNotSupported(ctx.GetContext(), "statement: '%v'", tree.String(stmt, dialect.MYSQL)) 820 } 821 } 822 823 // After handleTableOptions, so begin the partitions processing depend on TableDef 824 if stmt.Param != nil { 825 for i := 0; i < len(stmt.Param.Option); i += 2 { 826 switch strings.ToLower(stmt.Param.Option[i]) { 827 case "endpoint", "region", "access_key_id", "secret_access_key", "bucket", "filepath", "compression", "format", "jsondata", "provider", "role_arn", "external_id": 828 default: 829 return nil, moerr.NewBadConfig(ctx.GetContext(), "the keyword '%s' is not support", strings.ToLower(stmt.Param.Option[i])) 830 } 831 } 832 if err := InitNullMap(stmt.Param, ctx); err != nil { 833 return nil, err 834 } 835 json_byte, err := json.Marshal(stmt.Param) 836 if err != nil { 837 return nil, err 838 } 839 properties := []*plan.Property{ 840 { 841 Key: catalog.SystemRelAttr_Kind, 842 Value: catalog.SystemExternalRel, 843 }, 844 { 845 Key: catalog.SystemRelAttr_CreateSQL, 846 Value: string(json_byte), 847 }, 848 } 849 createTable.TableDef.TableType = catalog.SystemExternalRel 850 createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{ 851 Def: &plan.TableDef_DefType_Properties{ 852 Properties: &plan.PropertiesDef{ 853 Properties: properties, 854 }, 855 }}) 856 } else { 857 kind := catalog.SystemOrdinaryRel 858 if stmt.IsClusterTable { 859 kind = catalog.SystemClusterRel 860 } 861 // when create hidden talbe(like: auto_incr_table, index_table), we set relKind to empty 862 if catalog.IsHiddenTable(createTable.TableDef.Name) { 863 kind = "" 864 } 865 fmtCtx := tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 866 stmt.Format(fmtCtx) 867 properties := []*plan.Property{ 868 { 869 Key: catalog.SystemRelAttr_Kind, 870 Value: kind, 871 }, 872 { 873 Key: catalog.SystemRelAttr_CreateSQL, 874 Value: fmtCtx.String(), 875 }, 876 } 877 createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{ 878 Def: &plan.TableDef_DefType_Properties{ 879 Properties: &plan.PropertiesDef{ 880 Properties: properties, 881 }, 882 }}) 883 } 884 885 builder := NewQueryBuilder(plan.Query_SELECT, ctx, false) 886 bindContext := NewBindContext(builder, nil) 887 888 // set partition(unsupport now) 889 if stmt.PartitionOption != nil { 890 // Foreign keys are not yet supported in conjunction with partitioning 891 // see: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-14.html 892 if len(createTable.TableDef.Fkeys) > 0 { 893 return nil, moerr.NewErrForeignKeyOnPartitioned(ctx.GetContext()) 894 } 895 896 nodeID := builder.appendNode(&plan.Node{ 897 NodeType: plan.Node_TABLE_SCAN, 898 Stats: nil, 899 ObjRef: nil, 900 TableDef: createTable.TableDef, 901 BindingTags: []int32{builder.genNewTag()}, 902 }, bindContext) 903 904 err = builder.addBinding(nodeID, tree.AliasClause{}, bindContext) 905 if err != nil { 906 return nil, err 907 } 908 partitionBinder := NewPartitionBinder(builder, bindContext) 909 err = buildPartitionByClause(ctx.GetContext(), partitionBinder, stmt, createTable.TableDef) 910 if err != nil { 911 return nil, err 912 } 913 914 err = addPartitionTableDef(ctx.GetContext(), string(stmt.Table.ObjectName), createTable) 915 if err != nil { 916 return nil, err 917 } 918 } 919 920 return &Plan{ 921 Plan: &plan.Plan_Ddl{ 922 Ddl: &plan.DataDefinition{ 923 DdlType: plan.DataDefinition_CREATE_TABLE, 924 Definition: &plan.DataDefinition_CreateTable{ 925 CreateTable: createTable, 926 }, 927 }, 928 }, 929 }, nil 930 } 931 932 // addPartitionTableDef constructs the table def for the partition table 933 func addPartitionTableDef(ctx context.Context, mainTableName string, createTable *plan.CreateTable) error { 934 //add partition table 935 //there is no index for the partition table 936 //there is no foreign key for the partition table 937 if !util.IsValidNameForPartitionTable(mainTableName) { 938 return moerr.NewInvalidInput(ctx, "invalid main table name %s", mainTableName) 939 } 940 941 //common properties 942 partitionProps := []*plan.Property{ 943 { 944 Key: catalog.SystemRelAttr_Kind, 945 Value: catalog.SystemPartitionRel, 946 }, 947 { 948 Key: catalog.SystemRelAttr_CreateSQL, 949 Value: "", 950 }, 951 } 952 partitionPropsDef := &plan.TableDef_DefType{ 953 Def: &plan.TableDef_DefType_Properties{ 954 Properties: &plan.PropertiesDef{ 955 Properties: partitionProps, 956 }, 957 }} 958 959 partitionDef := createTable.TableDef.Partition 960 partitionTableDefs := make([]*TableDef, partitionDef.PartitionNum) 961 962 partitionTableNames := make([]string, partitionDef.PartitionNum) 963 for i := 0; i < int(partitionDef.PartitionNum); i++ { 964 part := partitionDef.Partitions[i] 965 ok, partitionTableName := util.MakeNameOfPartitionTable(part.GetPartitionName(), mainTableName) 966 if !ok { 967 return moerr.NewInvalidInput(ctx, "invalid partition table name %s", partitionTableName) 968 } 969 970 // save the table name for a partition 971 part.PartitionTableName = partitionTableName 972 partitionTableNames[i] = partitionTableName 973 974 partitionTableDefs[i] = &TableDef{ 975 Name: partitionTableName, 976 Cols: createTable.TableDef.Cols, //same as the main table's column defs 977 } 978 partitionTableDefs[i].Pkey = createTable.TableDef.GetPkey() 979 partitionTableDefs[i].Defs = append(partitionTableDefs[i].Defs, partitionPropsDef) 980 } 981 partitionDef.PartitionTableNames = partitionTableNames 982 createTable.PartitionTables = partitionTableDefs 983 return nil 984 } 985 986 // buildPartitionByClause build partition by clause info and semantic check. 987 // Currently, sub partition and partition value verification are not supported 988 func buildPartitionByClause(ctx context.Context, partitionBinder *PartitionBinder, stmt *tree.CreateTable, tableDef *TableDef) (err error) { 989 var builder partitionBuilder 990 switch stmt.PartitionOption.PartBy.PType.(type) { 991 case *tree.HashType: 992 builder = &hashPartitionBuilder{} 993 case *tree.KeyType: 994 builder = &keyPartitionBuilder{} 995 case *tree.RangeType: 996 builder = &rangePartitionBuilder{} 997 case *tree.ListType: 998 builder = &listPartitionBuilder{} 999 } 1000 return builder.build(ctx, partitionBinder, stmt, tableDef) 1001 } 1002 1003 func buildTableDefs(stmt *tree.CreateTable, ctx CompilerContext, createTable *plan.CreateTable, asSelectCols []*ColDef) error { 1004 var primaryKeys []string 1005 var indexs []string 1006 colMap := make(map[string]*ColDef) 1007 defaultMap := make(map[string]string) 1008 uniqueIndexInfos := make([]*tree.UniqueIndex, 0) 1009 secondaryIndexInfos := make([]*tree.Index, 0) 1010 fkDatasOfFKSelfRefer := make([]*FkData, 0) 1011 for _, item := range stmt.Defs { 1012 switch def := item.(type) { 1013 case *tree.ColumnTableDef: 1014 colType, err := getTypeFromAst(ctx.GetContext(), def.Type) 1015 if err != nil { 1016 return err 1017 } 1018 if colType.Id == int32(types.T_char) || colType.Id == int32(types.T_varchar) || 1019 colType.Id == int32(types.T_binary) || colType.Id == int32(types.T_varbinary) { 1020 if colType.GetWidth() > types.MaxStringSize { 1021 return moerr.NewInvalidInput(ctx.GetContext(), "string width (%d) is too long", colType.GetWidth()) 1022 } 1023 } 1024 if colType.Id == int32(types.T_array_float32) || colType.Id == int32(types.T_array_float64) { 1025 if colType.GetWidth() > types.MaxArrayDimension { 1026 return moerr.NewInvalidInput(ctx.GetContext(), "vector width (%d) is too long", colType.GetWidth()) 1027 } 1028 } 1029 if colType.Id == int32(types.T_bit) { 1030 if colType.Width == 0 { 1031 colType.Width = 1 1032 } 1033 if colType.Width > types.MaxBitLen { 1034 return moerr.NewInvalidInput(ctx.GetContext(), "bit width (%d) is too long (max = %d) ", colType.GetWidth(), types.MaxBitLen) 1035 } 1036 } 1037 var pks []string 1038 var comment string 1039 var auto_incr bool 1040 for _, attr := range def.Attributes { 1041 switch attribute := attr.(type) { 1042 case *tree.AttributePrimaryKey, *tree.AttributeKey: 1043 if colType.GetId() == int32(types.T_blob) { 1044 return moerr.NewNotSupported(ctx.GetContext(), "blob type in primary key") 1045 } 1046 if colType.GetId() == int32(types.T_text) { 1047 return moerr.NewNotSupported(ctx.GetContext(), "text type in primary key") 1048 } 1049 if colType.GetId() == int32(types.T_json) { 1050 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in primary key", def.Name.Parts[0])) 1051 } 1052 if colType.GetId() == int32(types.T_array_float32) || colType.GetId() == int32(types.T_array_float64) { 1053 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("VECTOR column '%s' cannot be in primary key", def.Name.Parts[0])) 1054 } 1055 if colType.GetId() == int32(types.T_enum) { 1056 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("ENUM column '%s' cannot be in primary key", def.Name.Parts[0])) 1057 1058 } 1059 pks = append(pks, def.Name.Parts[0]) 1060 case *tree.AttributeComment: 1061 comment = attribute.CMT.String() 1062 if getNumOfCharacters(comment) > maxLengthOfColumnComment { 1063 return moerr.NewInvalidInput(ctx.GetContext(), "comment for column '%s' is too long", def.Name.Parts[0]) 1064 } 1065 case *tree.AttributeAutoIncrement: 1066 auto_incr = true 1067 if !types.T(colType.GetId()).IsInteger() { 1068 return moerr.NewNotSupported(ctx.GetContext(), "the auto_incr column is only support integer type now") 1069 } 1070 case *tree.AttributeUnique, *tree.AttributeUniqueKey: 1071 uniqueIndexInfos = append(uniqueIndexInfos, &tree.UniqueIndex{ 1072 KeyParts: []*tree.KeyPart{ 1073 { 1074 ColName: def.Name, 1075 }, 1076 }, 1077 Name: def.Name.Parts[0], 1078 }) 1079 indexs = append(indexs, def.Name.Parts[0]) 1080 } 1081 } 1082 if len(pks) > 0 { 1083 if len(primaryKeys) > 0 { 1084 return moerr.NewInvalidInput(ctx.GetContext(), "more than one primary key defined") 1085 } 1086 primaryKeys = pks 1087 } 1088 1089 defaultValue, err := buildDefaultExpr(def, colType, ctx.GetProcess()) 1090 if err != nil { 1091 return err 1092 } 1093 if auto_incr && defaultValue.Expr != nil { 1094 return moerr.NewInvalidInput(ctx.GetContext(), "invalid default value for '%s'", def.Name.Parts[0]) 1095 } 1096 1097 onUpdateExpr, err := buildOnUpdate(def, colType, ctx.GetProcess()) 1098 if err != nil { 1099 return err 1100 } 1101 1102 if !checkTableColumnNameValid(def.Name.Parts[0]) { 1103 return moerr.NewInvalidInput(ctx.GetContext(), "table column name '%s' is illegal and conflicts with internal keyword", def.Name.Parts[0]) 1104 } 1105 1106 colType.AutoIncr = auto_incr 1107 col := &ColDef{ 1108 Name: def.Name.Parts[0], 1109 Alg: plan.CompressType_Lz4, 1110 Typ: colType, 1111 Default: defaultValue, 1112 OnUpdate: onUpdateExpr, 1113 Comment: comment, 1114 } 1115 // if same name col in asSelectCols, overwrite it; add into colMap && createTable.TableDef.Cols later 1116 if idx := slices.IndexFunc(asSelectCols, func(c *ColDef) bool { return c.Name == col.Name }); idx != -1 { 1117 asSelectCols[idx] = col 1118 } else { 1119 colMap[col.Name] = col 1120 createTable.TableDef.Cols = append(createTable.TableDef.Cols, col) 1121 1122 // get default val from ast node 1123 attrIdx := slices.IndexFunc(def.Attributes, func(a tree.ColumnAttribute) bool { 1124 _, ok := a.(*tree.AttributeDefault) 1125 return ok 1126 }) 1127 if attrIdx != -1 { 1128 defaultAttr := def.Attributes[attrIdx].(*tree.AttributeDefault) 1129 fmtCtx := tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 1130 defaultAttr.Format(fmtCtx) 1131 // defaultAttr.Format start with "default ", trim first 8 chars 1132 defaultMap[col.Name] = fmtCtx.String()[8:] 1133 } else { 1134 defaultMap[col.Name] = "NULL" 1135 } 1136 } 1137 case *tree.PrimaryKeyIndex: 1138 if len(primaryKeys) > 0 { 1139 return moerr.NewInvalidInput(ctx.GetContext(), "more than one primary key defined") 1140 } 1141 pksMap := map[string]bool{} 1142 for _, key := range def.KeyParts { 1143 name := key.ColName.Parts[0] // name of primary key column 1144 if _, ok := pksMap[name]; ok { 1145 return moerr.NewInvalidInput(ctx.GetContext(), "duplicate column name '%s' in primary key", name) 1146 } 1147 primaryKeys = append(primaryKeys, name) 1148 pksMap[name] = true 1149 indexs = append(indexs, name) 1150 } 1151 case *tree.Index: 1152 err := checkIndexKeypartSupportability(ctx.GetContext(), def.KeyParts) 1153 if err != nil { 1154 return err 1155 } 1156 1157 secondaryIndexInfos = append(secondaryIndexInfos, def) 1158 for _, key := range def.KeyParts { 1159 name := key.ColName.Parts[0] 1160 indexs = append(indexs, name) 1161 } 1162 case *tree.UniqueIndex: 1163 err := checkIndexKeypartSupportability(ctx.GetContext(), def.KeyParts) 1164 if err != nil { 1165 return err 1166 } 1167 1168 uniqueIndexInfos = append(uniqueIndexInfos, def) 1169 for _, key := range def.KeyParts { 1170 name := key.ColName.Parts[0] 1171 indexs = append(indexs, name) 1172 } 1173 case *tree.ForeignKey: 1174 if createTable.Temporary { 1175 return moerr.NewNYI(ctx.GetContext(), "add foreign key for temporary table") 1176 } 1177 if len(asSelectCols) != 0 { 1178 return moerr.NewNYI(ctx.GetContext(), "add foreign key in create table ... as select statement") 1179 } 1180 if IsFkBannedDatabase(createTable.Database) { 1181 return moerr.NewInternalError(ctx.GetContext(), "can not create foreign keys in %s", createTable.Database) 1182 } 1183 err := adjustConstraintName(ctx.GetContext(), def) 1184 if err != nil { 1185 return err 1186 } 1187 fkData, err := getForeignKeyData(ctx, createTable.Database, createTable.TableDef, def) 1188 if err != nil { 1189 return err 1190 } 1191 //only setups foreign key without forward reference 1192 if !fkData.ForwardRefer { 1193 createTable.FkDbs = append(createTable.FkDbs, fkData.ParentDbName) 1194 createTable.FkTables = append(createTable.FkTables, fkData.ParentTableName) 1195 createTable.FkCols = append(createTable.FkCols, fkData.Cols) 1196 createTable.TableDef.Fkeys = append(createTable.TableDef.Fkeys, fkData.Def) 1197 } 1198 1199 createTable.UpdateFkSqls = append(createTable.UpdateFkSqls, fkData.UpdateSql) 1200 1201 //save self reference foreign keys 1202 if fkData.IsSelfRefer { 1203 fkDatasOfFKSelfRefer = append(fkDatasOfFKSelfRefer, fkData) 1204 } 1205 case *tree.CheckIndex, *tree.FullTextIndex: 1206 // unsupport in plan. will support in next version. 1207 // return moerr.NewNYI(ctx.GetContext(), "table def: '%v'", def) 1208 default: 1209 return moerr.NewNYI(ctx.GetContext(), "table def: '%v'", def) 1210 } 1211 } 1212 1213 if stmt.IsAsSelect { 1214 // add as select cols 1215 for _, col := range asSelectCols { 1216 colMap[col.Name] = col 1217 createTable.TableDef.Cols = append(createTable.TableDef.Cols, col) 1218 } 1219 1220 // insert into new_table select default_val1, default_val2, ..., * from (select clause); 1221 var insertSqlBuilder strings.Builder 1222 insertSqlBuilder.WriteString(fmt.Sprintf("insert into `%s` select ", createTable.TableDef.Name)) 1223 1224 cols := createTable.TableDef.Cols 1225 firstCol := true 1226 for i := range cols { 1227 // insert default values if col[i] only in create clause 1228 if !slices.ContainsFunc(asSelectCols, func(c *ColDef) bool { return c.Name == cols[i].Name }) { 1229 if !firstCol { 1230 insertSqlBuilder.WriteString(", ") 1231 } 1232 insertSqlBuilder.WriteString(defaultMap[cols[i].Name]) 1233 firstCol = false 1234 } 1235 } 1236 if !firstCol { 1237 insertSqlBuilder.WriteString(", ") 1238 } 1239 // add all cols from select clause 1240 insertSqlBuilder.WriteString("*") 1241 1242 // from 1243 fmtCtx := tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true)) 1244 stmt.AsSource.Format(fmtCtx) 1245 insertSqlBuilder.WriteString(fmt.Sprintf(" from (%s)", fmtCtx.String())) 1246 1247 createTable.CreateAsSelectSql = insertSqlBuilder.String() 1248 } 1249 1250 //add cluster table attribute 1251 if stmt.IsClusterTable { 1252 if _, ok := colMap[util.GetClusterTableAttributeName()]; ok { 1253 return moerr.NewInvalidInput(ctx.GetContext(), "the attribute account_id in the cluster table can not be defined directly by the user") 1254 } 1255 colType, err := getTypeFromAst(ctx.GetContext(), util.GetClusterTableAttributeType()) 1256 if err != nil { 1257 return err 1258 } 1259 colDef := &ColDef{ 1260 Name: util.GetClusterTableAttributeName(), 1261 Alg: plan.CompressType_Lz4, 1262 Typ: colType, 1263 NotNull: true, 1264 Default: &plan.Default{ 1265 Expr: &Expr{ 1266 Expr: &plan.Expr_Lit{ 1267 Lit: &Const{ 1268 Isnull: false, 1269 Value: &plan.Literal_U32Val{U32Val: catalog.System_Account}, 1270 }, 1271 }, 1272 Typ: plan.Type{ 1273 Id: colType.Id, 1274 NotNullable: true, 1275 }, 1276 }, 1277 NullAbility: false, 1278 }, 1279 Comment: "the account_id added by the mo", 1280 } 1281 colMap[util.GetClusterTableAttributeName()] = colDef 1282 createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef) 1283 } 1284 1285 pkeyName := "" 1286 // If the primary key is explicitly defined in the ddl statement 1287 if len(primaryKeys) > 0 { 1288 for _, primaryKey := range primaryKeys { 1289 if _, ok := colMap[primaryKey]; !ok { 1290 return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' doesn't exist in table", primaryKey) 1291 } 1292 } 1293 if len(primaryKeys) == 1 { 1294 pkeyName = primaryKeys[0] 1295 for _, col := range createTable.TableDef.Cols { 1296 if col.Name == pkeyName { 1297 col.Primary = true 1298 createTable.TableDef.Pkey = &PrimaryKeyDef{ 1299 Names: primaryKeys, 1300 PkeyColName: pkeyName, 1301 } 1302 break 1303 } 1304 } 1305 } else { 1306 //pkeyName = util.BuildCompositePrimaryKeyColumnName(primaryKeys) 1307 pkeyName = catalog.CPrimaryKeyColName 1308 colDef := MakeHiddenColDefByName(pkeyName) 1309 colDef.Primary = true 1310 createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef) 1311 colMap[pkeyName] = colDef 1312 1313 pkeyDef := &PrimaryKeyDef{ 1314 Names: primaryKeys, 1315 PkeyColName: pkeyName, 1316 CompPkeyCol: colDef, 1317 } 1318 createTable.TableDef.Pkey = pkeyDef 1319 } 1320 for _, primaryKey := range primaryKeys { 1321 colMap[primaryKey].Default.NullAbility = false 1322 colMap[primaryKey].NotNull = true 1323 } 1324 } else { 1325 // If table does not have a explicit primary key in the ddl statement, a new hidden primary key column will be add, 1326 // which will not be sorted or used for any other purpose, but will only be used to add 1327 // locks to the Lock operator in pessimistic transaction mode. 1328 if !createTable.IsSystemExternalRel() { 1329 pkeyName = catalog.FakePrimaryKeyColName 1330 colDef := &ColDef{ 1331 ColId: uint64(len(createTable.TableDef.Cols)), 1332 Name: pkeyName, 1333 Hidden: true, 1334 Typ: Type{ 1335 Id: int32(types.T_uint64), 1336 AutoIncr: true, 1337 }, 1338 Default: &plan.Default{ 1339 NullAbility: false, 1340 Expr: nil, 1341 OriginString: "", 1342 }, 1343 NotNull: true, 1344 Primary: true, 1345 } 1346 1347 createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef) 1348 colMap[pkeyName] = colDef 1349 1350 createTable.TableDef.Pkey = &PrimaryKeyDef{ 1351 Names: []string{pkeyName}, 1352 PkeyColName: pkeyName, 1353 } 1354 1355 idx := len(createTable.TableDef.Cols) - 1 1356 // FIXME: due to the special treatment of insert and update for composite primary key, cluster-by, the 1357 // hidden primary key cannot be placed in the last column, otherwise it will cause the columns sent to 1358 // tae will not match the definition of schema, resulting in panic. 1359 if createTable.TableDef.ClusterBy != nil && 1360 len(stmt.ClusterByOption.ColumnList) > 1 { 1361 // we must swap hide pk and cluster_by 1362 createTable.TableDef.Cols[idx-1], createTable.TableDef.Cols[idx] = createTable.TableDef.Cols[idx], createTable.TableDef.Cols[idx-1] 1363 } 1364 } 1365 } 1366 1367 //handle cluster by keys 1368 if stmt.ClusterByOption != nil { 1369 if stmt.Temporary { 1370 return moerr.NewNotSupported(ctx.GetContext(), "cluster by with temporary table is not support") 1371 } 1372 if len(primaryKeys) > 0 { 1373 return moerr.NewNotSupported(ctx.GetContext(), "cluster by with primary key is not support") 1374 } 1375 lenClusterBy := len(stmt.ClusterByOption.ColumnList) 1376 var clusterByKeys []string 1377 for i := 0; i < lenClusterBy; i++ { 1378 colName := stmt.ClusterByOption.ColumnList[i].Parts[0] 1379 if _, ok := colMap[colName]; !ok { 1380 return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' doesn't exist in table", colName) 1381 } 1382 clusterByKeys = append(clusterByKeys, colName) 1383 } 1384 1385 if lenClusterBy == 1 { 1386 clusterByColName := clusterByKeys[0] 1387 for _, col := range createTable.TableDef.Cols { 1388 if col.Name == clusterByColName { 1389 col.ClusterBy = true 1390 } 1391 } 1392 1393 createTable.TableDef.ClusterBy = &plan.ClusterByDef{ 1394 Name: clusterByColName, 1395 } 1396 } else { 1397 clusterByColName := util.BuildCompositeClusterByColumnName(clusterByKeys) 1398 colDef := MakeHiddenColDefByName(clusterByColName) 1399 createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef) 1400 colMap[clusterByColName] = colDef 1401 1402 createTable.TableDef.ClusterBy = &plan.ClusterByDef{ 1403 Name: clusterByColName, 1404 CompCbkeyCol: colDef, 1405 } 1406 } 1407 } 1408 1409 // check index invalid on the type 1410 // for example, the text type don't support index 1411 for _, str := range indexs { 1412 if _, ok := colMap[str]; !ok { 1413 return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", str) 1414 } 1415 if colMap[str].Typ.Id == int32(types.T_blob) { 1416 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", str)) 1417 } 1418 if colMap[str].Typ.Id == int32(types.T_text) { 1419 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", str)) 1420 } 1421 if colMap[str].Typ.Id == int32(types.T_json) { 1422 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", str)) 1423 } 1424 } 1425 1426 // check Constraint Name (include index/ unique) 1427 err := checkConstraintNames(uniqueIndexInfos, secondaryIndexInfos, ctx.GetContext()) 1428 if err != nil { 1429 return err 1430 } 1431 1432 // build index table 1433 if len(uniqueIndexInfos) != 0 { 1434 err = buildUniqueIndexTable(createTable, uniqueIndexInfos, colMap, pkeyName, ctx) 1435 if err != nil { 1436 return err 1437 } 1438 } 1439 if len(secondaryIndexInfos) != 0 { 1440 err = buildSecondaryIndexDef(createTable, secondaryIndexInfos, colMap, pkeyName, ctx) 1441 if err != nil { 1442 return err 1443 } 1444 } 1445 1446 //process self reference foreign keys after colDefs and indexes are processed. 1447 if len(fkDatasOfFKSelfRefer) > 0 { 1448 //for fk self refer. the column id of the tableDef is not ready. 1449 //setup fake column id to distinguish the columns 1450 for i, def := range createTable.TableDef.Cols { 1451 def.ColId = uint64(i) 1452 } 1453 for _, selfRefer := range fkDatasOfFKSelfRefer { 1454 if err := checkFkColsAreValid(ctx, selfRefer, createTable.TableDef); err != nil { 1455 return err 1456 } 1457 } 1458 } 1459 1460 skip := IsFkBannedDatabase(createTable.Database) 1461 if !skip { 1462 fks, err := GetFkReferredTo(ctx, createTable.Database, createTable.TableDef.Name) 1463 if err != nil { 1464 return err 1465 } 1466 //for fk forward reference. the column id of the tableDef is not ready. 1467 //setup fake column id to distinguish the columns 1468 for i, def := range createTable.TableDef.Cols { 1469 def.ColId = uint64(i) 1470 } 1471 for rkey, fkDefs := range fks { 1472 for constraintName, defs := range fkDefs { 1473 data, err := buildFkDataOfForwardRefer(ctx, constraintName, defs, createTable) 1474 if err != nil { 1475 return err 1476 } 1477 info := &plan.ForeignKeyInfo{ 1478 Db: rkey.Db, 1479 Table: rkey.Tbl, 1480 ColsReferred: data.ColsReferred, 1481 Def: data.Def, 1482 } 1483 createTable.FksReferToMe = append(createTable.FksReferToMe, info) 1484 } 1485 } 1486 } 1487 1488 return nil 1489 } 1490 1491 func getRefAction(typ tree.ReferenceOptionType) plan.ForeignKeyDef_RefAction { 1492 switch typ { 1493 case tree.REFERENCE_OPTION_CASCADE: 1494 return plan.ForeignKeyDef_CASCADE 1495 case tree.REFERENCE_OPTION_NO_ACTION: 1496 return plan.ForeignKeyDef_NO_ACTION 1497 case tree.REFERENCE_OPTION_RESTRICT: 1498 return plan.ForeignKeyDef_RESTRICT 1499 case tree.REFERENCE_OPTION_SET_NULL: 1500 return plan.ForeignKeyDef_SET_NULL 1501 case tree.REFERENCE_OPTION_SET_DEFAULT: 1502 return plan.ForeignKeyDef_SET_DEFAULT 1503 default: 1504 return plan.ForeignKeyDef_RESTRICT 1505 } 1506 } 1507 1508 func buildUniqueIndexTable(createTable *plan.CreateTable, indexInfos []*tree.UniqueIndex, colMap map[string]*ColDef, pkeyName string, ctx CompilerContext) error { 1509 for _, indexInfo := range indexInfos { 1510 indexDef := &plan.IndexDef{} 1511 indexDef.Unique = true 1512 1513 indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), true) 1514 1515 if err != nil { 1516 return err 1517 } 1518 tableDef := &TableDef{ 1519 Name: indexTableName, 1520 } 1521 indexParts := make([]string, 0) 1522 1523 for _, keyPart := range indexInfo.KeyParts { 1524 name := keyPart.ColName.Parts[0] 1525 if _, ok := colMap[name]; !ok { 1526 return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", name) 1527 } 1528 if colMap[name].Typ.Id == int32(types.T_blob) { 1529 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", name)) 1530 } 1531 if colMap[name].Typ.Id == int32(types.T_text) { 1532 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", name)) 1533 } 1534 if colMap[name].Typ.Id == int32(types.T_json) { 1535 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", name)) 1536 } 1537 if colMap[name].Typ.Id == int32(types.T_array_float32) || colMap[name].Typ.Id == int32(types.T_array_float64) { 1538 return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("VECTOR column '%s' cannot be in index", name)) 1539 } 1540 1541 indexParts = append(indexParts, name) 1542 } 1543 1544 var keyName string 1545 if len(indexInfo.KeyParts) == 1 { 1546 keyName = catalog.IndexTableIndexColName 1547 colDef := &ColDef{ 1548 Name: keyName, 1549 Alg: plan.CompressType_Lz4, 1550 Typ: Type{ 1551 Id: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Id, 1552 Width: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Width, 1553 }, 1554 Default: &plan.Default{ 1555 NullAbility: false, 1556 Expr: nil, 1557 OriginString: "", 1558 }, 1559 } 1560 tableDef.Cols = append(tableDef.Cols, colDef) 1561 tableDef.Pkey = &PrimaryKeyDef{ 1562 Names: []string{keyName}, 1563 PkeyColName: keyName, 1564 } 1565 } else { 1566 keyName = catalog.IndexTableIndexColName 1567 colDef := &ColDef{ 1568 Name: keyName, 1569 Alg: plan.CompressType_Lz4, 1570 Typ: Type{ 1571 Id: int32(types.T_varchar), 1572 Width: types.MaxVarcharLen, 1573 }, 1574 Default: &plan.Default{ 1575 NullAbility: false, 1576 Expr: nil, 1577 OriginString: "", 1578 }, 1579 } 1580 tableDef.Cols = append(tableDef.Cols, colDef) 1581 tableDef.Pkey = &PrimaryKeyDef{ 1582 Names: []string{keyName}, 1583 PkeyColName: keyName, 1584 } 1585 } 1586 if pkeyName != "" { 1587 colDef := &ColDef{ 1588 Name: catalog.IndexTablePrimaryColName, 1589 Alg: plan.CompressType_Lz4, 1590 Typ: plan.Type{ 1591 // don't copy auto increment 1592 Id: colMap[pkeyName].Typ.Id, 1593 Width: colMap[pkeyName].Typ.Width, 1594 Scale: colMap[pkeyName].Typ.Scale, 1595 }, 1596 Default: &plan.Default{ 1597 NullAbility: false, 1598 Expr: nil, 1599 OriginString: "", 1600 }, 1601 } 1602 tableDef.Cols = append(tableDef.Cols, colDef) 1603 } 1604 1605 //indexDef.IndexName = indexInfo.Name 1606 indexDef.IndexName = indexInfo.GetIndexName() 1607 indexDef.IndexTableName = indexTableName 1608 indexDef.Parts = indexParts 1609 indexDef.TableExist = true 1610 if indexInfo.IndexOption != nil { 1611 indexDef.Comment = indexInfo.IndexOption.Comment 1612 } else { 1613 indexDef.Comment = "" 1614 } 1615 createTable.IndexTables = append(createTable.IndexTables, tableDef) 1616 createTable.TableDef.Indexes = append(createTable.TableDef.Indexes, indexDef) 1617 } 1618 return nil 1619 } 1620 1621 func buildSecondaryIndexDef(createTable *plan.CreateTable, indexInfos []*tree.Index, colMap map[string]*ColDef, pkeyName string, ctx CompilerContext) (err error) { 1622 1623 if len(pkeyName) == 0 { 1624 return moerr.NewInternalErrorNoCtx("primary key cannot be empty for secondary index") 1625 } 1626 1627 for _, indexInfo := range indexInfos { 1628 err = checkIndexKeypartSupportability(ctx.GetContext(), indexInfo.KeyParts) 1629 if err != nil { 1630 return err 1631 } 1632 1633 var indexDef []*plan.IndexDef 1634 var tableDef []*TableDef 1635 switch indexInfo.KeyType { 1636 case tree.INDEX_TYPE_BTREE, tree.INDEX_TYPE_INVALID: 1637 indexDef, tableDef, err = buildRegularSecondaryIndexDef(ctx, indexInfo, colMap, pkeyName) 1638 case tree.INDEX_TYPE_IVFFLAT: 1639 indexDef, tableDef, err = buildIvfFlatSecondaryIndexDef(ctx, indexInfo, colMap, pkeyName) 1640 case tree.INDEX_TYPE_MASTER: 1641 indexDef, tableDef, err = buildMasterSecondaryIndexDef(ctx, indexInfo, colMap, pkeyName) 1642 default: 1643 return moerr.NewInvalidInputNoCtx("unsupported index type: %s", indexInfo.KeyType.ToString()) 1644 } 1645 1646 if err != nil { 1647 return err 1648 } 1649 createTable.IndexTables = append(createTable.IndexTables, tableDef...) 1650 createTable.TableDef.Indexes = append(createTable.TableDef.Indexes, indexDef...) 1651 1652 } 1653 return nil 1654 } 1655 1656 func buildMasterSecondaryIndexDef(ctx CompilerContext, indexInfo *tree.Index, colMap map[string]*ColDef, pkeyName string) ([]*plan.IndexDef, []*TableDef, error) { 1657 // 1. indexDef init 1658 indexDef := &plan.IndexDef{} 1659 indexDef.Unique = false 1660 1661 // 2. tableDef init 1662 indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), false) 1663 if err != nil { 1664 return nil, nil, err 1665 } 1666 tableDef := &TableDef{ 1667 Name: indexTableName, 1668 } 1669 1670 nameCount := make(map[string]int) 1671 // Note: Index Parts will store the ColName, as Parts is used to populate mo_index_table. 1672 // However, when inserting Index, we convert Parts (ie ColName) to ColIdx. 1673 indexParts := make([]string, 0) 1674 1675 for _, keyPart := range indexInfo.KeyParts { 1676 name := keyPart.ColName.Parts[0] 1677 if _, ok := colMap[name]; !ok { 1678 return nil, nil, moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", name) 1679 } 1680 if colMap[name].Typ.Id != int32(types.T_varchar) { 1681 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("column '%s' is not varchar type.", name)) 1682 } 1683 indexParts = append(indexParts, name) 1684 } 1685 1686 var keyName = catalog.MasterIndexTableIndexColName 1687 colDef := &ColDef{ 1688 Name: keyName, 1689 Alg: plan.CompressType_Lz4, 1690 Typ: Type{ 1691 Id: int32(types.T_varchar), 1692 Width: types.MaxVarcharLen, 1693 }, 1694 Default: &plan.Default{ 1695 NullAbility: false, 1696 Expr: nil, 1697 OriginString: "", 1698 }, 1699 } 1700 tableDef.Cols = append(tableDef.Cols, colDef) 1701 tableDef.Pkey = &PrimaryKeyDef{ 1702 Names: []string{keyName}, 1703 PkeyColName: keyName, 1704 } 1705 if pkeyName != "" { 1706 pkColDef := &ColDef{ 1707 Name: catalog.MasterIndexTablePrimaryColName, 1708 Alg: plan.CompressType_Lz4, 1709 Typ: plan.Type{ 1710 // don't copy auto increment 1711 Id: colMap[pkeyName].Typ.Id, 1712 Width: colMap[pkeyName].Typ.Width, 1713 Scale: colMap[pkeyName].Typ.Scale, 1714 }, 1715 Default: &plan.Default{ 1716 NullAbility: false, 1717 Expr: nil, 1718 OriginString: "", 1719 }, 1720 } 1721 tableDef.Cols = append(tableDef.Cols, pkColDef) 1722 } 1723 if indexInfo.Name == "" { 1724 firstPart := indexInfo.KeyParts[0].ColName.Parts[0] 1725 nameCount[firstPart]++ 1726 count := nameCount[firstPart] 1727 indexName := firstPart 1728 if count > 1 { 1729 indexName = firstPart + "_" + strconv.Itoa(count) 1730 } 1731 indexDef.IndexName = indexName 1732 } else { 1733 indexDef.IndexName = indexInfo.Name 1734 } 1735 1736 indexDef.IndexTableName = indexTableName 1737 indexDef.Parts = indexParts 1738 indexDef.TableExist = true 1739 indexDef.IndexAlgo = indexInfo.KeyType.ToString() 1740 indexDef.IndexAlgoTableType = "" 1741 1742 if indexInfo.IndexOption != nil { 1743 indexDef.Comment = indexInfo.IndexOption.Comment 1744 1745 params, err := catalog.IndexParamsToJsonString(indexInfo) 1746 if err != nil { 1747 return nil, nil, err 1748 } 1749 indexDef.IndexAlgoParams = params 1750 } else { 1751 indexDef.Comment = "" 1752 indexDef.IndexAlgoParams = "" 1753 } 1754 return []*plan.IndexDef{indexDef}, []*TableDef{tableDef}, nil 1755 } 1756 1757 func buildRegularSecondaryIndexDef(ctx CompilerContext, indexInfo *tree.Index, colMap map[string]*ColDef, pkeyName string) ([]*plan.IndexDef, []*TableDef, error) { 1758 1759 // 1. indexDef init 1760 indexDef := &plan.IndexDef{} 1761 indexDef.Unique = false 1762 1763 // 2. tableDef init 1764 indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), false) 1765 if err != nil { 1766 return nil, nil, err 1767 } 1768 tableDef := &TableDef{ 1769 Name: indexTableName, 1770 } 1771 1772 nameCount := make(map[string]int) 1773 indexParts := make([]string, 0) 1774 1775 isPkAlreadyPresentInIndexParts := false 1776 for _, keyPart := range indexInfo.KeyParts { 1777 name := keyPart.ColName.Parts[0] 1778 if _, ok := colMap[name]; !ok { 1779 return nil, nil, moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", name) 1780 } 1781 if colMap[name].Typ.Id == int32(types.T_blob) { 1782 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", name)) 1783 } 1784 if colMap[name].Typ.Id == int32(types.T_text) { 1785 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", name)) 1786 } 1787 if colMap[name].Typ.Id == int32(types.T_json) { 1788 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", name)) 1789 } 1790 if colMap[name].Typ.Id == int32(types.T_array_float32) || colMap[name].Typ.Id == int32(types.T_array_float64) { 1791 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("VECTOR column '%s' cannot be in index", name)) 1792 } 1793 1794 if strings.Compare(name, pkeyName) == 0 || catalog.IsAlias(name) { 1795 isPkAlreadyPresentInIndexParts = true 1796 } 1797 indexParts = append(indexParts, name) 1798 } 1799 1800 if !isPkAlreadyPresentInIndexParts { 1801 indexParts = append(indexParts, catalog.CreateAlias(pkeyName)) 1802 } 1803 1804 var keyName string 1805 if len(indexParts) == 1 { 1806 // This means indexParts only contains the primary key column 1807 keyName = catalog.IndexTableIndexColName 1808 colDef := &ColDef{ 1809 Name: keyName, 1810 Alg: plan.CompressType_Lz4, 1811 Typ: plan.Type{ 1812 // don't copy auto increment 1813 Id: colMap[pkeyName].Typ.Id, 1814 Width: colMap[pkeyName].Typ.Width, 1815 Scale: colMap[pkeyName].Typ.Scale, 1816 }, 1817 Default: &plan.Default{ 1818 NullAbility: false, 1819 Expr: nil, 1820 OriginString: "", 1821 }, 1822 } 1823 tableDef.Cols = append(tableDef.Cols, colDef) 1824 tableDef.Pkey = &PrimaryKeyDef{ 1825 Names: []string{keyName}, 1826 PkeyColName: keyName, 1827 } 1828 } else { 1829 keyName = catalog.IndexTableIndexColName 1830 colDef := &ColDef{ 1831 Name: keyName, 1832 Alg: plan.CompressType_Lz4, 1833 Typ: Type{ 1834 Id: int32(types.T_varchar), 1835 Width: types.MaxVarcharLen, 1836 }, 1837 Default: &plan.Default{ 1838 NullAbility: false, 1839 Expr: nil, 1840 OriginString: "", 1841 }, 1842 } 1843 tableDef.Cols = append(tableDef.Cols, colDef) 1844 tableDef.Pkey = &PrimaryKeyDef{ 1845 Names: []string{keyName}, 1846 PkeyColName: keyName, 1847 } 1848 } 1849 if pkeyName != "" { 1850 colDef := &ColDef{ 1851 Name: catalog.IndexTablePrimaryColName, 1852 Alg: plan.CompressType_Lz4, 1853 Typ: plan.Type{ 1854 // don't copy auto increment 1855 Id: colMap[pkeyName].Typ.Id, 1856 Width: colMap[pkeyName].Typ.Width, 1857 Scale: colMap[pkeyName].Typ.Scale, 1858 }, 1859 Default: &plan.Default{ 1860 NullAbility: false, 1861 Expr: nil, 1862 OriginString: "", 1863 }, 1864 } 1865 tableDef.Cols = append(tableDef.Cols, colDef) 1866 } 1867 1868 if indexInfo.Name == "" { 1869 firstPart := indexInfo.KeyParts[0].ColName.Parts[0] 1870 nameCount[firstPart]++ 1871 count := nameCount[firstPart] 1872 indexName := firstPart 1873 if count > 1 { 1874 indexName = firstPart + "_" + strconv.Itoa(count) 1875 } 1876 indexDef.IndexName = indexName 1877 } else { 1878 indexDef.IndexName = indexInfo.Name 1879 } 1880 1881 indexDef.IndexTableName = indexTableName 1882 indexDef.Parts = indexParts 1883 indexDef.TableExist = true 1884 indexDef.IndexAlgo = indexInfo.KeyType.ToString() 1885 indexDef.IndexAlgoTableType = "" 1886 1887 if indexInfo.IndexOption != nil { 1888 indexDef.Comment = indexInfo.IndexOption.Comment 1889 1890 params, err := catalog.IndexParamsToJsonString(indexInfo) 1891 if err != nil { 1892 return nil, nil, err 1893 } 1894 indexDef.IndexAlgoParams = params 1895 } else { 1896 indexDef.Comment = "" 1897 indexDef.IndexAlgoParams = "" 1898 } 1899 return []*plan.IndexDef{indexDef}, []*TableDef{tableDef}, nil 1900 } 1901 1902 func buildIvfFlatSecondaryIndexDef(ctx CompilerContext, indexInfo *tree.Index, colMap map[string]*ColDef, pkeyName string) ([]*plan.IndexDef, []*TableDef, error) { 1903 1904 indexParts := make([]string, 1) 1905 1906 // 0. Validate: We only support 1 column of either VECF32 or VECF64 type 1907 { 1908 if len(indexInfo.KeyParts) != 1 { 1909 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), "don't support multi column IVF vector index") 1910 } 1911 1912 name := indexInfo.KeyParts[0].ColName.Parts[0] 1913 indexParts[0] = name 1914 1915 if _, ok := colMap[name]; !ok { 1916 return nil, nil, moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", name) 1917 } 1918 if colMap[name].Typ.Id != int32(types.T_array_float32) && colMap[name].Typ.Id != int32(types.T_array_float64) { 1919 return nil, nil, moerr.NewNotSupported(ctx.GetContext(), "IVFFLAT only supports VECFXX column types") 1920 } 1921 1922 } 1923 1924 indexDefs := make([]*plan.IndexDef, 3) 1925 tableDefs := make([]*TableDef, 3) 1926 1927 // 1. create ivf-flat `metadata` table 1928 { 1929 // 1.a tableDef1 init 1930 indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), false) 1931 if err != nil { 1932 return nil, nil, err 1933 } 1934 tableDefs[0] = &TableDef{ 1935 Name: indexTableName, 1936 TableType: catalog.SystemSI_IVFFLAT_TblType_Metadata, 1937 Cols: make([]*ColDef, 2), 1938 } 1939 1940 // 1.b indexDef1 init 1941 indexDefs[0], err = CreateIndexDef(indexInfo, indexTableName, catalog.SystemSI_IVFFLAT_TblType_Metadata, indexParts, false) 1942 if err != nil { 1943 return nil, nil, err 1944 } 1945 1946 // 1.c columns: key (PK), val 1947 tableDefs[0].Cols[0] = &ColDef{ 1948 Name: catalog.SystemSI_IVFFLAT_TblCol_Metadata_key, 1949 Alg: plan.CompressType_Lz4, 1950 Typ: Type{ 1951 Id: int32(types.T_varchar), 1952 Width: types.MaxVarcharLen, 1953 }, 1954 Primary: true, 1955 Default: &plan.Default{ 1956 NullAbility: false, 1957 Expr: nil, 1958 OriginString: "", 1959 }, 1960 } 1961 tableDefs[0].Cols[1] = &ColDef{ 1962 Name: catalog.SystemSI_IVFFLAT_TblCol_Metadata_val, 1963 Alg: plan.CompressType_Lz4, 1964 Typ: Type{ 1965 Id: int32(types.T_varchar), 1966 Width: types.MaxVarcharLen, 1967 }, 1968 Default: &plan.Default{ 1969 NullAbility: false, 1970 Expr: nil, 1971 OriginString: "", 1972 }, 1973 } 1974 1975 // 1.d PK def 1976 tableDefs[0].Pkey = &PrimaryKeyDef{ 1977 Names: []string{catalog.SystemSI_IVFFLAT_TblCol_Metadata_key}, 1978 PkeyColName: catalog.SystemSI_IVFFLAT_TblCol_Metadata_key, 1979 } 1980 } 1981 1982 // 2. create ivf-flat `centroids` table 1983 { 1984 // 2.a tableDefs[1] init 1985 indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), false) 1986 if err != nil { 1987 return nil, nil, err 1988 } 1989 tableDefs[1] = &TableDef{ 1990 Name: indexTableName, 1991 TableType: catalog.SystemSI_IVFFLAT_TblType_Centroids, 1992 Cols: make([]*ColDef, 4), 1993 } 1994 1995 // 2.b indexDefs[1] init 1996 indexDefs[1], err = CreateIndexDef(indexInfo, indexTableName, catalog.SystemSI_IVFFLAT_TblType_Centroids, indexParts, false) 1997 if err != nil { 1998 return nil, nil, err 1999 } 2000 2001 // 2.c columns: version, id, centroid, PRIMARY KEY (version,id) 2002 tableDefs[1].Cols[0] = &ColDef{ 2003 Name: catalog.SystemSI_IVFFLAT_TblCol_Centroids_version, 2004 Alg: plan.CompressType_Lz4, 2005 Typ: plan.Type{ 2006 Id: int32(types.T_int64), 2007 Width: 0, 2008 Scale: 0, 2009 }, 2010 Default: &plan.Default{ 2011 NullAbility: false, 2012 Expr: nil, 2013 OriginString: "", 2014 }, 2015 } 2016 tableDefs[1].Cols[1] = &ColDef{ 2017 Name: catalog.SystemSI_IVFFLAT_TblCol_Centroids_id, 2018 Alg: plan.CompressType_Lz4, 2019 Typ: plan.Type{ 2020 Id: int32(types.T_int64), 2021 Width: 0, 2022 Scale: 0, 2023 }, 2024 Default: &plan.Default{ 2025 NullAbility: false, 2026 Expr: nil, 2027 OriginString: "", 2028 }, 2029 } 2030 tableDefs[1].Cols[2] = &ColDef{ 2031 Name: catalog.SystemSI_IVFFLAT_TblCol_Centroids_centroid, 2032 Alg: plan.CompressType_Lz4, 2033 Typ: Type{ 2034 Id: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Id, 2035 Width: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Width, 2036 }, 2037 Default: &plan.Default{ 2038 NullAbility: true, 2039 Expr: nil, 2040 OriginString: "", 2041 }, 2042 } 2043 tableDefs[1].Cols[3] = MakeHiddenColDefByName(catalog.CPrimaryKeyColName) 2044 tableDefs[1].Cols[3].Alg = plan.CompressType_Lz4 2045 tableDefs[1].Cols[3].Primary = true 2046 2047 // 2.d PK def 2048 tableDefs[1].Pkey = &PrimaryKeyDef{ 2049 Names: []string{ 2050 catalog.SystemSI_IVFFLAT_TblCol_Centroids_version, 2051 catalog.SystemSI_IVFFLAT_TblCol_Centroids_id, 2052 }, 2053 PkeyColName: catalog.CPrimaryKeyColName, 2054 CompPkeyCol: tableDefs[1].Cols[3], 2055 } 2056 } 2057 2058 // 3. create ivf-flat `entries` table 2059 { 2060 // 3.a tableDefs[2] init 2061 indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), false) 2062 if err != nil { 2063 return nil, nil, err 2064 } 2065 tableDefs[2] = &TableDef{ 2066 Name: indexTableName, 2067 TableType: catalog.SystemSI_IVFFLAT_TblType_Entries, 2068 Cols: make([]*ColDef, 5), 2069 } 2070 2071 // 3.b indexDefs[2] init 2072 indexDefs[2], err = CreateIndexDef(indexInfo, indexTableName, catalog.SystemSI_IVFFLAT_TblType_Entries, indexParts, false) 2073 if err != nil { 2074 return nil, nil, err 2075 } 2076 2077 // 3.c columns: version, id, origin_pk, PRIMARY KEY (version,origin_pk) 2078 tableDefs[2].Cols[0] = &ColDef{ 2079 Name: catalog.SystemSI_IVFFLAT_TblCol_Entries_version, 2080 Alg: plan.CompressType_Lz4, 2081 Typ: plan.Type{ 2082 Id: int32(types.T_int64), 2083 Width: 0, 2084 Scale: 0, 2085 }, 2086 Default: &plan.Default{ 2087 NullAbility: false, 2088 Expr: nil, 2089 OriginString: "", 2090 }, 2091 } 2092 tableDefs[2].Cols[1] = &ColDef{ 2093 Name: catalog.SystemSI_IVFFLAT_TblCol_Entries_id, 2094 Alg: plan.CompressType_Lz4, 2095 Typ: plan.Type{ 2096 Id: int32(types.T_int64), 2097 Width: 0, 2098 Scale: 0, 2099 }, 2100 Default: &plan.Default{ 2101 NullAbility: false, 2102 Expr: nil, 2103 OriginString: "", 2104 }, 2105 } 2106 2107 tableDefs[2].Cols[2] = &ColDef{ 2108 Name: catalog.SystemSI_IVFFLAT_TblCol_Entries_pk, 2109 Alg: plan.CompressType_Lz4, 2110 Typ: plan.Type{ 2111 //NOTE: don't directly copy the Type from Original Table's PK column. 2112 // If you do that, we can get the AutoIncrement property from the original table's PK column. 2113 // This results in a bug when you try to insert data into entries table. 2114 Id: colMap[pkeyName].Typ.Id, 2115 Width: colMap[pkeyName].Typ.Width, 2116 Scale: colMap[pkeyName].Typ.Scale, 2117 }, 2118 Default: &plan.Default{ 2119 NullAbility: false, 2120 Expr: nil, 2121 OriginString: "", 2122 }, 2123 } 2124 tableDefs[2].Cols[3] = &ColDef{ 2125 Name: catalog.SystemSI_IVFFLAT_TblCol_Entries_entry, 2126 Alg: plan.CompressType_Lz4, 2127 Typ: Type{ 2128 Id: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Id, 2129 Width: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Width, 2130 }, 2131 Default: &plan.Default{ 2132 NullAbility: true, 2133 Expr: nil, 2134 OriginString: "", 2135 }, 2136 } 2137 2138 tableDefs[2].Cols[4] = MakeHiddenColDefByName(catalog.CPrimaryKeyColName) 2139 tableDefs[2].Cols[4].Alg = plan.CompressType_Lz4 2140 tableDefs[2].Cols[4].Primary = true 2141 2142 // 3.d PK def 2143 tableDefs[2].Pkey = &PrimaryKeyDef{ 2144 Names: []string{ 2145 catalog.SystemSI_IVFFLAT_TblCol_Entries_version, 2146 catalog.SystemSI_IVFFLAT_TblCol_Entries_id, 2147 catalog.SystemSI_IVFFLAT_TblCol_Entries_pk, // added to make this unique 2148 }, 2149 PkeyColName: catalog.CPrimaryKeyColName, 2150 CompPkeyCol: tableDefs[2].Cols[4], 2151 } 2152 } 2153 2154 return indexDefs, tableDefs, nil 2155 } 2156 2157 func CreateIndexDef(indexInfo *tree.Index, 2158 indexTableName, indexAlgoTableType string, 2159 indexParts []string, isUnique bool) (*plan.IndexDef, error) { 2160 2161 //TODO: later use this function for RegularSecondaryIndex and UniqueIndex. 2162 2163 indexDef := &plan.IndexDef{} 2164 2165 indexDef.IndexTableName = indexTableName 2166 indexDef.Parts = indexParts 2167 2168 indexDef.Unique = isUnique 2169 indexDef.TableExist = true 2170 2171 // Algorithm related fields 2172 indexDef.IndexAlgo = indexInfo.KeyType.ToString() 2173 indexDef.IndexAlgoTableType = indexAlgoTableType 2174 if indexInfo.IndexOption != nil { 2175 // Copy Comment as it is 2176 indexDef.Comment = indexInfo.IndexOption.Comment 2177 2178 // Create params JSON string and set it 2179 params, err := catalog.IndexParamsToJsonString(indexInfo) 2180 if err != nil { 2181 return nil, err 2182 } 2183 indexDef.IndexAlgoParams = params 2184 } else { 2185 // default indexInfo.IndexOption values 2186 switch indexInfo.KeyType { 2187 case catalog.MoIndexDefaultAlgo, catalog.MoIndexBTreeAlgo: 2188 indexDef.Comment = "" 2189 indexDef.IndexAlgoParams = "" 2190 case catalog.MOIndexMasterAlgo: 2191 indexDef.Comment = "" 2192 indexDef.IndexAlgoParams = "" 2193 case catalog.MoIndexIvfFlatAlgo: 2194 var err error 2195 indexDef.IndexAlgoParams, err = catalog.IndexParamsMapToJsonString(catalog.DefaultIvfIndexAlgoOptions()) 2196 if err != nil { 2197 return nil, err 2198 } 2199 } 2200 2201 } 2202 2203 nameCount := make(map[string]int) 2204 if indexInfo.Name == "" { 2205 firstPart := indexInfo.KeyParts[0].ColName.Parts[0] 2206 nameCount[firstPart]++ 2207 count := nameCount[firstPart] 2208 indexName := firstPart 2209 if count > 1 { 2210 indexName = firstPart + "_" + strconv.Itoa(count) 2211 } 2212 indexDef.IndexName = indexName 2213 } else { 2214 indexDef.IndexName = indexInfo.Name 2215 } 2216 2217 return indexDef, nil 2218 } 2219 2220 func buildTruncateTable(stmt *tree.TruncateTable, ctx CompilerContext) (*Plan, error) { 2221 truncateTable := &plan.TruncateTable{} 2222 2223 truncateTable.Database = string(stmt.Name.SchemaName) 2224 if truncateTable.Database == "" { 2225 truncateTable.Database = ctx.DefaultDatabase() 2226 } 2227 truncateTable.Table = string(stmt.Name.ObjectName) 2228 obj, tableDef := ctx.Resolve(truncateTable.Database, truncateTable.Table, Snapshot{TS: ×tamp.Timestamp{}}) 2229 if tableDef == nil { 2230 return nil, moerr.NewNoSuchTable(ctx.GetContext(), truncateTable.Database, truncateTable.Table) 2231 } else { 2232 if tableDef.TableType == catalog.SystemSourceRel { 2233 return nil, moerr.NewInternalError(ctx.GetContext(), "can not truncate source '%v' ", truncateTable.Table) 2234 } 2235 2236 if len(tableDef.RefChildTbls) > 0 { 2237 //if all children tables are self reference, we can drop the table 2238 if !HasFkSelfReferOnly(tableDef) { 2239 return nil, moerr.NewInternalError(ctx.GetContext(), "can not truncate table '%v' referenced by some foreign key constraint", truncateTable.Table) 2240 } 2241 } 2242 2243 if tableDef.ViewSql != nil { 2244 return nil, moerr.NewNoSuchTable(ctx.GetContext(), truncateTable.Database, truncateTable.Table) 2245 } 2246 2247 truncateTable.TableId = tableDef.TblId 2248 if tableDef.Fkeys != nil { 2249 for _, fk := range tableDef.Fkeys { 2250 truncateTable.ForeignTbl = append(truncateTable.ForeignTbl, fk.ForeignTbl) 2251 } 2252 } 2253 2254 truncateTable.ClusterTable = &plan.ClusterTable{ 2255 IsClusterTable: util.TableIsClusterTable(tableDef.GetTableType()), 2256 } 2257 2258 //non-sys account can not truncate the cluster table 2259 accountId, err := ctx.GetAccountId() 2260 if err != nil { 2261 return nil, err 2262 } 2263 if truncateTable.GetClusterTable().GetIsClusterTable() && accountId != catalog.System_Account { 2264 return nil, moerr.NewInternalError(ctx.GetContext(), "only the sys account can truncate the cluster table") 2265 } 2266 2267 if obj.PubInfo != nil { 2268 return nil, moerr.NewInternalError(ctx.GetContext(), "can not truncate table '%v' which is published by other account", truncateTable.Table) 2269 } 2270 2271 truncateTable.IndexTableNames = make([]string, 0) 2272 if tableDef.Indexes != nil { 2273 for _, indexdef := range tableDef.Indexes { 2274 // We only handle truncate on regular index. For other indexes such as IVF, we don't handle truncate now. 2275 if indexdef.TableExist && catalog.IsRegularIndexAlgo(indexdef.IndexAlgo) { 2276 truncateTable.IndexTableNames = append(truncateTable.IndexTableNames, indexdef.IndexTableName) 2277 } else if indexdef.TableExist && catalog.IsIvfIndexAlgo(indexdef.IndexAlgo) { 2278 if indexdef.IndexAlgoTableType == catalog.SystemSI_IVFFLAT_TblType_Entries { 2279 //TODO: check with @feng on how to handle truncate on IVF index 2280 // Right now, we are only clearing the entries. Should we empty the centroids and metadata as well? 2281 // Ideally, after truncate the user is expected to run re-index. 2282 truncateTable.IndexTableNames = append(truncateTable.IndexTableNames, indexdef.IndexTableName) 2283 } 2284 } else if indexdef.TableExist && catalog.IsMasterIndexAlgo(indexdef.IndexAlgo) { 2285 truncateTable.IndexTableNames = append(truncateTable.IndexTableNames, indexdef.IndexTableName) 2286 } 2287 } 2288 } 2289 2290 if tableDef.Partition != nil { 2291 truncateTable.PartitionTableNames = make([]string, len(tableDef.Partition.PartitionTableNames)) 2292 copy(truncateTable.PartitionTableNames, tableDef.Partition.PartitionTableNames) 2293 } 2294 } 2295 2296 return &Plan{ 2297 Plan: &plan.Plan_Ddl{ 2298 Ddl: &plan.DataDefinition{ 2299 DdlType: plan.DataDefinition_TRUNCATE_TABLE, 2300 Definition: &plan.DataDefinition_TruncateTable{ 2301 TruncateTable: truncateTable, 2302 }, 2303 }, 2304 }, 2305 }, nil 2306 } 2307 2308 func buildDropTable(stmt *tree.DropTable, ctx CompilerContext) (*Plan, error) { 2309 dropTable := &plan.DropTable{ 2310 IfExists: stmt.IfExists, 2311 } 2312 if len(stmt.Names) != 1 { 2313 return nil, moerr.NewNotSupported(ctx.GetContext(), "drop multiple (%d) tables in one statement", len(stmt.Names)) 2314 } 2315 2316 dropTable.Database = string(stmt.Names[0].SchemaName) 2317 2318 // If the database name is empty, attempt to get default database name 2319 if dropTable.Database == "" { 2320 dropTable.Database = ctx.DefaultDatabase() 2321 } 2322 2323 // If the final database name is still empty, return an error 2324 if dropTable.Database == "" { 2325 return nil, moerr.NewNoDB(ctx.GetContext()) 2326 } 2327 2328 dropTable.Table = string(stmt.Names[0].ObjectName) 2329 2330 obj, tableDef := ctx.Resolve(dropTable.Database, dropTable.Table, Snapshot{TS: ×tamp.Timestamp{}}) 2331 2332 if tableDef == nil { 2333 if !dropTable.IfExists { 2334 return nil, moerr.NewNoSuchTable(ctx.GetContext(), dropTable.Database, dropTable.Table) 2335 } 2336 } else { 2337 enabled, err := IsForeignKeyChecksEnabled(ctx) 2338 if err != nil { 2339 return nil, err 2340 } 2341 if enabled && len(tableDef.RefChildTbls) > 0 { 2342 //if all children tables are self reference, we can drop the table 2343 if !HasFkSelfReferOnly(tableDef) { 2344 return nil, moerr.NewInternalError(ctx.GetContext(), "can not drop table '%v' referenced by some foreign key constraint", dropTable.Table) 2345 } 2346 } 2347 2348 isView := (tableDef.ViewSql != nil) 2349 dropTable.IsView = isView 2350 2351 if isView && !dropTable.IfExists { 2352 // drop table v0, v0 is view 2353 return nil, moerr.NewNoSuchTable(ctx.GetContext(), dropTable.Database, dropTable.Table) 2354 } else if isView { 2355 // drop table if exists v0, v0 is view 2356 dropTable.Table = "" 2357 } 2358 2359 // Can not use drop table to drop sequence. 2360 if tableDef.TableType == catalog.SystemSequenceRel && !dropTable.IfExists { 2361 return nil, moerr.NewInternalError(ctx.GetContext(), "Should use 'drop sequence' to drop a sequence") 2362 } else if tableDef.TableType == catalog.SystemSequenceRel { 2363 // If exists, don't drop anything. 2364 dropTable.Table = "" 2365 } 2366 2367 dropTable.ClusterTable = &plan.ClusterTable{ 2368 IsClusterTable: util.TableIsClusterTable(tableDef.GetTableType()), 2369 } 2370 2371 //non-sys account can not drop the cluster table 2372 accountId, err := ctx.GetAccountId() 2373 if err != nil { 2374 return nil, err 2375 } 2376 if dropTable.GetClusterTable().GetIsClusterTable() && accountId != catalog.System_Account { 2377 return nil, moerr.NewInternalError(ctx.GetContext(), "only the sys account can drop the cluster table") 2378 } 2379 2380 if obj.PubInfo != nil { 2381 return nil, moerr.NewInternalError(ctx.GetContext(), "can not drop subscription table %s", dropTable.Table) 2382 } 2383 2384 dropTable.TableId = tableDef.TblId 2385 if tableDef.Fkeys != nil { 2386 for _, fk := range tableDef.Fkeys { 2387 if fk.ForeignTbl == 0 { 2388 continue 2389 } 2390 dropTable.ForeignTbl = append(dropTable.ForeignTbl, fk.ForeignTbl) 2391 } 2392 } 2393 2394 // collect child tables that needs remove fk relationships 2395 // with the table 2396 if tableDef.RefChildTbls != nil { 2397 for _, childTbl := range tableDef.RefChildTbls { 2398 if childTbl == 0 { 2399 continue 2400 } 2401 dropTable.FkChildTblsReferToMe = append(dropTable.FkChildTblsReferToMe, childTbl) 2402 } 2403 } 2404 2405 dropTable.IndexTableNames = make([]string, 0) 2406 if tableDef.Indexes != nil { 2407 for _, indexdef := range tableDef.Indexes { 2408 if indexdef.TableExist { 2409 dropTable.IndexTableNames = append(dropTable.IndexTableNames, indexdef.IndexTableName) 2410 } 2411 } 2412 } 2413 2414 if tableDef.GetPartition() != nil { 2415 dropTable.PartitionTableNames = tableDef.GetPartition().GetPartitionTableNames() 2416 } 2417 2418 dropTable.TableDef = tableDef 2419 dropTable.UpdateFkSqls = []string{getSqlForDeleteTable(dropTable.Database, dropTable.Table)} 2420 } 2421 return &Plan{ 2422 Plan: &plan.Plan_Ddl{ 2423 Ddl: &plan.DataDefinition{ 2424 DdlType: plan.DataDefinition_DROP_TABLE, 2425 Definition: &plan.DataDefinition_DropTable{ 2426 DropTable: dropTable, 2427 }, 2428 }, 2429 }, 2430 }, nil 2431 } 2432 2433 func buildDropView(stmt *tree.DropView, ctx CompilerContext) (*Plan, error) { 2434 dropTable := &plan.DropTable{ 2435 IfExists: stmt.IfExists, 2436 } 2437 if len(stmt.Names) != 1 { 2438 return nil, moerr.NewNotSupported(ctx.GetContext(), "drop multiple (%d) view", len(stmt.Names)) 2439 } 2440 2441 dropTable.Database = string(stmt.Names[0].SchemaName) 2442 2443 // If the database name is empty, attempt to get default database name 2444 if dropTable.Database == "" { 2445 dropTable.Database = ctx.DefaultDatabase() 2446 } 2447 // If the final database name is still empty, return an error 2448 if dropTable.Database == "" { 2449 return nil, moerr.NewNoDB(ctx.GetContext()) 2450 } 2451 2452 dropTable.Table = string(stmt.Names[0].ObjectName) 2453 2454 obj, tableDef := ctx.Resolve(dropTable.Database, dropTable.Table, Snapshot{TS: ×tamp.Timestamp{}}) 2455 if tableDef == nil { 2456 if !dropTable.IfExists { 2457 return nil, moerr.NewBadView(ctx.GetContext(), dropTable.Database, dropTable.Table) 2458 } 2459 } else { 2460 if tableDef.ViewSql == nil { 2461 return nil, moerr.NewBadView(ctx.GetContext(), dropTable.Database, dropTable.Table) 2462 } 2463 if obj.PubInfo != nil { 2464 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot drop view in subscription database") 2465 } 2466 } 2467 dropTable.IsView = true 2468 2469 return &Plan{ 2470 Plan: &plan.Plan_Ddl{ 2471 Ddl: &plan.DataDefinition{ 2472 DdlType: plan.DataDefinition_DROP_TABLE, 2473 Definition: &plan.DataDefinition_DropTable{ 2474 DropTable: dropTable, 2475 }, 2476 }, 2477 }, 2478 }, nil 2479 } 2480 2481 func buildCreateDatabase(stmt *tree.CreateDatabase, ctx CompilerContext) (*Plan, error) { 2482 if string(stmt.Name) == defines.TEMPORARY_DBNAME { 2483 return nil, moerr.NewInternalError(ctx.GetContext(), "this database name is used by mo temporary engine") 2484 } 2485 createDB := &plan.CreateDatabase{ 2486 IfNotExists: stmt.IfNotExists, 2487 Database: string(stmt.Name), 2488 } 2489 2490 if stmt.SubscriptionOption != nil { 2491 accName := string(stmt.SubscriptionOption.From) 2492 pubName := string(stmt.SubscriptionOption.Publication) 2493 subName := string(stmt.Name) 2494 if err := ctx.CheckSubscriptionValid(subName, accName, pubName); err != nil { 2495 return nil, err 2496 } 2497 createDB.SubscriptionOption = &plan.SubscriptionOption{ 2498 From: string(stmt.SubscriptionOption.From), 2499 Publication: string(stmt.SubscriptionOption.Publication), 2500 } 2501 } 2502 createDB.Sql = stmt.Sql 2503 2504 return &Plan{ 2505 Plan: &plan.Plan_Ddl{ 2506 Ddl: &plan.DataDefinition{ 2507 DdlType: plan.DataDefinition_CREATE_DATABASE, 2508 Definition: &plan.DataDefinition_CreateDatabase{ 2509 CreateDatabase: createDB, 2510 }, 2511 }, 2512 }, 2513 }, nil 2514 } 2515 2516 func buildDropDatabase(stmt *tree.DropDatabase, ctx CompilerContext) (*Plan, error) { 2517 dropDB := &plan.DropDatabase{ 2518 IfExists: stmt.IfExists, 2519 Database: string(stmt.Name), 2520 } 2521 if publishing, err := ctx.IsPublishing(dropDB.Database); err != nil { 2522 return nil, err 2523 } else if publishing { 2524 return nil, moerr.NewInternalError(ctx.GetContext(), "can not drop database '%v' which is publishing", dropDB.Database) 2525 } 2526 2527 if ctx.DatabaseExists(string(stmt.Name), Snapshot{TS: ×tamp.Timestamp{}}) { 2528 databaseId, err := ctx.GetDatabaseId(string(stmt.Name), Snapshot{TS: ×tamp.Timestamp{}}) 2529 if err != nil { 2530 return nil, err 2531 } 2532 dropDB.DatabaseId = databaseId 2533 2534 //check foreign keys exists or not 2535 enabled, err := IsForeignKeyChecksEnabled(ctx) 2536 if err != nil { 2537 return nil, err 2538 } 2539 if enabled { 2540 dropDB.CheckFKSql = getSqlForCheckHasDBRefersTo(dropDB.Database) 2541 } 2542 } 2543 2544 dropDB.UpdateFkSql = getSqlForDeleteDB(dropDB.Database) 2545 2546 return &Plan{ 2547 Plan: &plan.Plan_Ddl{ 2548 Ddl: &plan.DataDefinition{ 2549 DdlType: plan.DataDefinition_DROP_DATABASE, 2550 Definition: &plan.DataDefinition_DropDatabase{ 2551 DropDatabase: dropDB, 2552 }, 2553 }, 2554 }, 2555 }, nil 2556 } 2557 2558 func buildCreateIndex(stmt *tree.CreateIndex, ctx CompilerContext) (*Plan, error) { 2559 createIndex := &plan.CreateIndex{} 2560 if len(stmt.Table.SchemaName) == 0 { 2561 createIndex.Database = ctx.DefaultDatabase() 2562 } else { 2563 createIndex.Database = string(stmt.Table.SchemaName) 2564 } 2565 // check table 2566 tableName := string(stmt.Table.ObjectName) 2567 obj, tableDef := ctx.Resolve(createIndex.Database, tableName, Snapshot{TS: ×tamp.Timestamp{}}) 2568 if tableDef == nil { 2569 return nil, moerr.NewNoSuchTable(ctx.GetContext(), createIndex.Database, tableName) 2570 } 2571 if obj.PubInfo != nil { 2572 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot create index in subscription database") 2573 } 2574 // check index 2575 indexName := string(stmt.Name) 2576 for _, def := range tableDef.Indexes { 2577 if def.IndexName == indexName { 2578 return nil, moerr.NewDuplicateKey(ctx.GetContext(), indexName) 2579 } 2580 } 2581 // build index 2582 var uIdx *tree.UniqueIndex 2583 var sIdx *tree.Index 2584 switch stmt.IndexCat { 2585 case tree.INDEX_CATEGORY_UNIQUE: 2586 uIdx = &tree.UniqueIndex{ 2587 Name: indexName, 2588 KeyParts: stmt.KeyParts, 2589 IndexOption: stmt.IndexOption, 2590 } 2591 case tree.INDEX_CATEGORY_NONE: 2592 sIdx = &tree.Index{ 2593 Name: indexName, 2594 KeyParts: stmt.KeyParts, 2595 IndexOption: stmt.IndexOption, 2596 KeyType: stmt.IndexOption.IType, 2597 } 2598 default: 2599 return nil, moerr.NewNotSupported(ctx.GetContext(), "statement: '%v'", tree.String(stmt, dialect.MYSQL)) 2600 } 2601 colMap := make(map[string]*ColDef) 2602 for _, col := range tableDef.Cols { 2603 colMap[col.Name] = col 2604 } 2605 2606 // Check whether the composite primary key column is included 2607 if tableDef.Pkey != nil && tableDef.Pkey.CompPkeyCol != nil { 2608 colMap[tableDef.Pkey.CompPkeyCol.Name] = tableDef.Pkey.CompPkeyCol 2609 } 2610 2611 // index.TableDef.Defs store info of index need to be modified 2612 // index.IndexTables store index table need to be created 2613 oriPriKeyName := getTablePriKeyName(tableDef.Pkey) 2614 createIndex.OriginTablePrimaryKey = oriPriKeyName 2615 2616 indexInfo := &plan.CreateTable{TableDef: &TableDef{}} 2617 if uIdx != nil { 2618 if err := buildUniqueIndexTable(indexInfo, []*tree.UniqueIndex{uIdx}, colMap, oriPriKeyName, ctx); err != nil { 2619 return nil, err 2620 } 2621 createIndex.TableExist = true 2622 } 2623 if sIdx != nil { 2624 if err := buildSecondaryIndexDef(indexInfo, []*tree.Index{sIdx}, colMap, oriPriKeyName, ctx); err != nil { 2625 return nil, err 2626 } 2627 createIndex.TableExist = true 2628 } 2629 createIndex.Index = indexInfo 2630 createIndex.Table = tableName 2631 createIndex.TableDef = tableDef 2632 2633 return &Plan{ 2634 Plan: &plan.Plan_Ddl{ 2635 Ddl: &plan.DataDefinition{ 2636 DdlType: plan.DataDefinition_CREATE_INDEX, 2637 Definition: &plan.DataDefinition_CreateIndex{ 2638 CreateIndex: createIndex, 2639 }, 2640 }, 2641 }, 2642 }, nil 2643 } 2644 2645 func buildDropIndex(stmt *tree.DropIndex, ctx CompilerContext) (*Plan, error) { 2646 dropIndex := &plan.DropIndex{} 2647 if len(stmt.TableName.SchemaName) == 0 { 2648 dropIndex.Database = ctx.DefaultDatabase() 2649 } else { 2650 dropIndex.Database = string(stmt.TableName.SchemaName) 2651 } 2652 2653 // If the final database name is still empty, return an error 2654 if dropIndex.Database == "" { 2655 return nil, moerr.NewNoDB(ctx.GetContext()) 2656 } 2657 2658 // check table 2659 dropIndex.Table = string(stmt.TableName.ObjectName) 2660 obj, tableDef := ctx.Resolve(dropIndex.Database, dropIndex.Table, Snapshot{TS: ×tamp.Timestamp{}}) 2661 if tableDef == nil { 2662 return nil, moerr.NewNoSuchTable(ctx.GetContext(), dropIndex.Database, dropIndex.Table) 2663 } 2664 2665 if obj.PubInfo != nil { 2666 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot drop index in subscription database") 2667 } 2668 2669 // check index 2670 dropIndex.IndexName = string(stmt.Name) 2671 found := false 2672 2673 for _, indexdef := range tableDef.Indexes { 2674 if dropIndex.IndexName == indexdef.IndexName { 2675 dropIndex.IndexTableName = indexdef.IndexTableName 2676 found = true 2677 break 2678 } 2679 } 2680 2681 if !found { 2682 return nil, moerr.NewInternalError(ctx.GetContext(), "not found index: %s", dropIndex.IndexName) 2683 } 2684 2685 return &Plan{ 2686 Plan: &plan.Plan_Ddl{ 2687 Ddl: &plan.DataDefinition{ 2688 DdlType: plan.DataDefinition_DROP_INDEX, 2689 Definition: &plan.DataDefinition_DropIndex{ 2690 DropIndex: dropIndex, 2691 }, 2692 }, 2693 }, 2694 }, nil 2695 } 2696 2697 // Get tabledef(col, viewsql, properties) for alterview. 2698 func buildAlterView(stmt *tree.AlterView, ctx CompilerContext) (*Plan, error) { 2699 viewName := string(stmt.Name.ObjectName) 2700 alterView := &plan.AlterView{ 2701 IfExists: stmt.IfExists, 2702 TableDef: &plan.TableDef{ 2703 Name: viewName, 2704 }, 2705 } 2706 // get database name 2707 if len(stmt.Name.SchemaName) == 0 { 2708 alterView.Database = "" 2709 } else { 2710 alterView.Database = string(stmt.Name.SchemaName) 2711 } 2712 if alterView.Database == "" { 2713 alterView.Database = ctx.DefaultDatabase() 2714 } 2715 2716 //step 1: check the view exists or not 2717 obj, oldViewDef := ctx.Resolve(alterView.Database, viewName, Snapshot{TS: ×tamp.Timestamp{}}) 2718 if oldViewDef == nil { 2719 if !alterView.IfExists { 2720 return nil, moerr.NewBadView(ctx.GetContext(), 2721 alterView.Database, 2722 viewName) 2723 } 2724 } else { 2725 if obj.PubInfo != nil { 2726 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot alter view in subscription database") 2727 } 2728 if oldViewDef.ViewSql == nil { 2729 return nil, moerr.NewBadView(ctx.GetContext(), 2730 alterView.Database, 2731 viewName) 2732 } 2733 } 2734 2735 //step 2: generate new view def 2736 ctx.SetBuildingAlterView(true, alterView.Database, viewName) 2737 //restore 2738 defer func() { 2739 ctx.SetBuildingAlterView(false, "", "") 2740 }() 2741 tableDef, err := genViewTableDef(ctx, stmt.AsSource) 2742 if err != nil { 2743 return nil, err 2744 } 2745 2746 alterView.TableDef.Cols = tableDef.Cols 2747 alterView.TableDef.ViewSql = tableDef.ViewSql 2748 alterView.TableDef.Defs = tableDef.Defs 2749 2750 return &Plan{ 2751 Plan: &plan.Plan_Ddl{ 2752 Ddl: &plan.DataDefinition{ 2753 DdlType: plan.DataDefinition_ALTER_VIEW, 2754 Definition: &plan.DataDefinition_AlterView{ 2755 AlterView: alterView, 2756 }, 2757 }, 2758 }, 2759 }, nil 2760 } 2761 2762 func getTableComment(tableDef *plan.TableDef) string { 2763 var comment string 2764 for _, def := range tableDef.Defs { 2765 if proDef, ok := def.Def.(*plan.TableDef_DefType_Properties); ok { 2766 for _, kv := range proDef.Properties.Properties { 2767 if kv.Key == catalog.SystemRelAttr_Comment { 2768 comment = kv.Value 2769 } 2770 } 2771 } 2772 } 2773 return comment 2774 } 2775 2776 func buildAlterTableInplace(stmt *tree.AlterTable, ctx CompilerContext) (*Plan, error) { 2777 tableName := string(stmt.Table.ObjectName) 2778 databaseName := string(stmt.Table.SchemaName) 2779 if databaseName == "" { 2780 databaseName = ctx.DefaultDatabase() 2781 } 2782 2783 _, tableDef := ctx.Resolve(databaseName, tableName, Snapshot{TS: ×tamp.Timestamp{}}) 2784 if tableDef == nil { 2785 return nil, moerr.NewNoSuchTable(ctx.GetContext(), databaseName, tableName) 2786 } 2787 2788 alterTable := &plan.AlterTable{ 2789 Actions: make([]*plan.AlterTable_Action, len(stmt.Options)), 2790 AlgorithmType: plan.AlterTable_INPLACE, 2791 Database: databaseName, 2792 TableDef: tableDef, 2793 IsClusterTable: util.TableIsClusterTable(tableDef.GetTableType()), 2794 } 2795 accountId, err := ctx.GetAccountId() 2796 if err != nil { 2797 return nil, err 2798 } 2799 if alterTable.IsClusterTable && accountId != catalog.System_Account { 2800 return nil, moerr.NewInternalError(ctx.GetContext(), "only the sys account can alter the cluster table") 2801 } 2802 2803 comment := getTableComment(tableDef) 2804 colMap := make(map[string]*ColDef) 2805 for _, col := range tableDef.Cols { 2806 colMap[col.Name] = col 2807 } 2808 // Check whether the composite primary key column is included 2809 if tableDef.Pkey != nil && tableDef.Pkey.CompPkeyCol != nil { 2810 colMap[tableDef.Pkey.CompPkeyCol.Name] = tableDef.Pkey.CompPkeyCol 2811 } 2812 2813 var primaryKeys []string 2814 var indexs []string 2815 var detectSqls []string 2816 var updateSqls []string 2817 uniqueIndexInfos := make([]*tree.UniqueIndex, 0) 2818 secondaryIndexInfos := make([]*tree.Index, 0) 2819 for i, option := range stmt.Options { 2820 switch opt := option.(type) { 2821 case *tree.AlterOptionDrop: 2822 alterTableDrop := new(plan.AlterTableDrop) 2823 constraintName := string(opt.Name) 2824 if constraintNameAreWhiteSpaces(constraintName) { 2825 return nil, moerr.NewInternalError(ctx.GetContext(), "Can't DROP '%s'; check that column/key exists", constraintName) 2826 } 2827 alterTableDrop.Name = constraintName 2828 name_not_found := true 2829 switch opt.Typ { 2830 case tree.AlterTableDropColumn: 2831 alterTableDrop.Typ = plan.AlterTableDrop_COLUMN 2832 err := checkIsDroppableColumn(tableDef, constraintName, ctx) 2833 if err != nil { 2834 return nil, err 2835 } 2836 for _, col := range tableDef.Cols { 2837 if col.Name == constraintName { 2838 name_not_found = false 2839 break 2840 } 2841 } 2842 case tree.AlterTableDropIndex: 2843 alterTableDrop.Typ = plan.AlterTableDrop_INDEX 2844 // check index 2845 for _, indexdef := range tableDef.Indexes { 2846 if constraintName == indexdef.IndexName { 2847 name_not_found = false 2848 break 2849 } 2850 } 2851 case tree.AlterTableDropKey: 2852 alterTableDrop.Typ = plan.AlterTableDrop_KEY 2853 case tree.AlterTableDropPrimaryKey: 2854 alterTableDrop.Typ = plan.AlterTableDrop_PRIMARY_KEY 2855 if tableDef.Pkey.PkeyColName == catalog.FakePrimaryKeyColName { 2856 return nil, moerr.NewErrCantDropFieldOrKey(ctx.GetContext(), "PRIMARY") 2857 } 2858 return nil, moerr.NewInternalError(ctx.GetContext(), "Can't DROP exists Primary Key") 2859 case tree.AlterTableDropForeignKey: 2860 alterTableDrop.Typ = plan.AlterTableDrop_FOREIGN_KEY 2861 for _, fk := range tableDef.Fkeys { 2862 if fk.Name == constraintName { 2863 name_not_found = false 2864 updateSqls = append(updateSqls, getSqlForDeleteConstraint(databaseName, tableName, constraintName)) 2865 break 2866 } 2867 } 2868 } 2869 if name_not_found { 2870 return nil, moerr.NewInternalError(ctx.GetContext(), "Can't DROP '%s'; check that column/key exists", constraintName) 2871 } 2872 alterTable.Actions[i] = &plan.AlterTable_Action{ 2873 Action: &plan.AlterTable_Action_Drop{ 2874 Drop: alterTableDrop, 2875 }, 2876 } 2877 2878 case *tree.AlterOptionAdd: 2879 switch def := opt.Def.(type) { 2880 case *tree.ForeignKey: 2881 err = adjustConstraintName(ctx.GetContext(), def) 2882 if err != nil { 2883 return nil, err 2884 } 2885 2886 fkData, err := getForeignKeyData(ctx, databaseName, tableDef, def) 2887 if err != nil { 2888 return nil, err 2889 } 2890 alterTable.Actions[i] = &plan.AlterTable_Action{ 2891 Action: &plan.AlterTable_Action_AddFk{ 2892 AddFk: &plan.AlterTableAddFk{ 2893 DbName: fkData.ParentDbName, 2894 TableName: fkData.ParentTableName, 2895 Cols: fkData.Cols.Cols, 2896 Fkey: fkData.Def, 2897 }, 2898 }, 2899 } 2900 //for new fk in this alter table, the data in the table must 2901 //be checked to confirm that it is compliant with foreign key constraints. 2902 if fkData.IsSelfRefer { 2903 //fk self refer. 2904 //check columns of fk self refer are valid 2905 err = checkFkColsAreValid(ctx, fkData, tableDef) 2906 if err != nil { 2907 return nil, err 2908 } 2909 sqls, err := genSqlsForCheckFKSelfRefer(ctx.GetContext(), databaseName, tableDef.Name, tableDef.Cols, []*plan.ForeignKeyDef{fkData.Def}) 2910 if err != nil { 2911 return nil, err 2912 } 2913 detectSqls = append(detectSqls, sqls...) 2914 } else { 2915 //get table def of parent table 2916 _, parentTableDef := ctx.Resolve(fkData.ParentDbName, fkData.ParentTableName, Snapshot{TS: ×tamp.Timestamp{}}) 2917 if parentTableDef == nil { 2918 return nil, moerr.NewNoSuchTable(ctx.GetContext(), fkData.ParentDbName, fkData.ParentTableName) 2919 } 2920 sql, err := genSqlForCheckFKConstraints(ctx.GetContext(), fkData.Def, 2921 databaseName, tableDef.Name, tableDef.Cols, 2922 fkData.ParentDbName, fkData.ParentTableName, parentTableDef.Cols) 2923 if err != nil { 2924 return nil, err 2925 } 2926 detectSqls = append(detectSqls, sql) 2927 } 2928 updateSqls = append(updateSqls, fkData.UpdateSql) 2929 case *tree.UniqueIndex: 2930 err := checkIndexKeypartSupportability(ctx.GetContext(), def.KeyParts) 2931 if err != nil { 2932 return nil, err 2933 } 2934 2935 indexName := def.GetIndexName() 2936 constrNames := map[string]bool{} 2937 // Check not empty constraint name whether is duplicated. 2938 for _, idx := range tableDef.Indexes { 2939 nameLower := strings.ToLower(idx.IndexName) 2940 constrNames[nameLower] = true 2941 } 2942 2943 err = checkDuplicateConstraint(constrNames, indexName, false, ctx.GetContext()) 2944 if err != nil { 2945 return nil, err 2946 } 2947 if len(indexName) == 0 { 2948 // set empty constraint names(index and unique index) 2949 setEmptyUniqueIndexName(constrNames, def) 2950 } 2951 2952 oriPriKeyName := getTablePriKeyName(tableDef.Pkey) 2953 indexInfo := &plan.CreateTable{TableDef: &TableDef{}} 2954 if err = buildUniqueIndexTable(indexInfo, []*tree.UniqueIndex{def}, colMap, oriPriKeyName, ctx); err != nil { 2955 return nil, err 2956 } 2957 2958 alterTable.Actions[i] = &plan.AlterTable_Action{ 2959 Action: &plan.AlterTable_Action_AddIndex{ 2960 AddIndex: &plan.AlterTableAddIndex{ 2961 DbName: databaseName, 2962 TableName: tableName, 2963 OriginTablePrimaryKey: oriPriKeyName, 2964 IndexInfo: indexInfo, 2965 IndexTableExist: true, 2966 }, 2967 }, 2968 } 2969 case *tree.Index: 2970 err := checkIndexKeypartSupportability(ctx.GetContext(), def.KeyParts) 2971 if err != nil { 2972 return nil, err 2973 } 2974 2975 indexName := def.Name 2976 2977 constrNames := map[string]bool{} 2978 // Check not empty constraint name whether is duplicated. 2979 for _, idx := range tableDef.Indexes { 2980 nameLower := strings.ToLower(idx.IndexName) 2981 constrNames[nameLower] = true 2982 } 2983 2984 err = checkDuplicateConstraint(constrNames, indexName, false, ctx.GetContext()) 2985 if err != nil { 2986 return nil, err 2987 } 2988 2989 if len(indexName) == 0 { 2990 // set empty constraint names(index and unique index) 2991 setEmptyIndexName(constrNames, def) 2992 } 2993 2994 oriPriKeyName := getTablePriKeyName(tableDef.Pkey) 2995 2996 indexInfo := &plan.CreateTable{TableDef: &TableDef{}} 2997 if err := buildSecondaryIndexDef(indexInfo, []*tree.Index{def}, colMap, oriPriKeyName, ctx); err != nil { 2998 return nil, err 2999 } 3000 3001 alterTable.Actions[i] = &plan.AlterTable_Action{ 3002 Action: &plan.AlterTable_Action_AddIndex{ 3003 AddIndex: &plan.AlterTableAddIndex{ 3004 DbName: databaseName, 3005 TableName: tableName, 3006 OriginTablePrimaryKey: oriPriKeyName, 3007 IndexInfo: indexInfo, 3008 IndexTableExist: true, 3009 }, 3010 }, 3011 } 3012 case *tree.CheckIndex: 3013 alterTable.Actions[i] = &plan.AlterTable_Action{ 3014 Action: &plan.AlterTable_Action_AlterComment{ 3015 AlterComment: &plan.AlterTableComment{ 3016 NewComment: comment, 3017 }, 3018 }, 3019 } 3020 default: 3021 return nil, moerr.NewInternalError(ctx.GetContext(), "unsupported alter option: %T", def) 3022 } 3023 3024 case *tree.AlterOptionAlterIndex: 3025 alterTableIndex := new(plan.AlterTableAlterIndex) 3026 constraintName := string(opt.Name) 3027 alterTableIndex.IndexName = constraintName 3028 3029 if opt.Visibility == tree.VISIBLE_TYPE_VISIBLE { 3030 alterTableIndex.Visible = true 3031 } else { 3032 alterTableIndex.Visible = false 3033 } 3034 3035 name_not_found := true 3036 // check index 3037 for _, indexdef := range tableDef.Indexes { 3038 if constraintName == indexdef.IndexName { 3039 name_not_found = false 3040 break 3041 } 3042 } 3043 if name_not_found { 3044 return nil, moerr.NewInternalError(ctx.GetContext(), "Can't ALTER '%s'; check that column/key exists", constraintName) 3045 } 3046 alterTable.Actions[i] = &plan.AlterTable_Action{ 3047 Action: &plan.AlterTable_Action_AlterIndex{ 3048 AlterIndex: alterTableIndex, 3049 }, 3050 } 3051 3052 case *tree.AlterOptionAlterReIndex: 3053 alterTableReIndex := new(plan.AlterTableAlterReIndex) 3054 constraintName := string(opt.Name) 3055 alterTableReIndex.IndexName = constraintName 3056 3057 switch opt.KeyType { 3058 case tree.INDEX_TYPE_IVFFLAT: 3059 if opt.AlgoParamList <= 0 { 3060 return nil, moerr.NewInternalError(ctx.GetContext(), "lists should be > 0.") 3061 } 3062 alterTableReIndex.IndexAlgoParamList = opt.AlgoParamList 3063 default: 3064 return nil, moerr.NewInternalError(ctx.GetContext(), "unsupported index type: %v", opt.KeyType) 3065 } 3066 3067 name_not_found := true 3068 // check index 3069 for _, indexdef := range tableDef.Indexes { 3070 if constraintName == indexdef.IndexName { 3071 name_not_found = false 3072 break 3073 } 3074 } 3075 if name_not_found { 3076 return nil, moerr.NewInternalError(ctx.GetContext(), "Can't REINDEX '%s'; check that column/key exists", constraintName) 3077 } 3078 alterTable.Actions[i] = &plan.AlterTable_Action{ 3079 Action: &plan.AlterTable_Action_AlterReindex{ 3080 AlterReindex: alterTableReIndex, 3081 }, 3082 } 3083 3084 case *tree.TableOptionComment: 3085 if getNumOfCharacters(opt.Comment) > maxLengthOfTableComment { 3086 return nil, moerr.NewInvalidInput(ctx.GetContext(), "comment for field '%s' is too long", alterTable.TableDef.Name) 3087 } 3088 comment = opt.Comment 3089 alterTable.Actions[i] = &plan.AlterTable_Action{ 3090 Action: &plan.AlterTable_Action_AlterComment{ 3091 AlterComment: &plan.AlterTableComment{ 3092 NewComment: opt.Comment, 3093 }, 3094 }, 3095 } 3096 case *tree.AlterOptionTableName: 3097 oldName := tableDef.Name 3098 newName := string(opt.Name.ToTableName().ObjectName) 3099 alterTable.Actions[i] = &plan.AlterTable_Action{ 3100 Action: &plan.AlterTable_Action_AlterName{ 3101 AlterName: &plan.AlterTableName{ 3102 OldName: oldName, 3103 NewName: newName, 3104 }, 3105 }, 3106 } 3107 updateSqls = append(updateSqls, getSqlForRenameTable(databaseName, oldName, newName)...) 3108 case *tree.AlterAddCol: 3109 colType, err := getTypeFromAst(ctx.GetContext(), opt.Column.Type) 3110 if err != nil { 3111 return nil, err 3112 } 3113 if colType.Id == int32(types.T_char) || colType.Id == int32(types.T_varchar) || 3114 colType.Id == int32(types.T_binary) || colType.Id == int32(types.T_varbinary) { 3115 if colType.GetWidth() > types.MaxStringSize { 3116 return nil, moerr.NewInvalidInput(ctx.GetContext(), "string width (%d) is too long", colType.GetWidth()) 3117 } 3118 } 3119 3120 if colType.Id == int32(types.T_array_float32) || colType.Id == int32(types.T_array_float64) { 3121 if colType.GetWidth() > types.MaxArrayDimension { 3122 return nil, moerr.NewInvalidInput(ctx.GetContext(), "vector width (%d) is too long", colType.GetWidth()) 3123 } 3124 } 3125 var pks []string 3126 var comment string 3127 var auto_incr bool 3128 for _, attr := range opt.Column.Attributes { 3129 switch attribute := attr.(type) { 3130 case *tree.AttributePrimaryKey, *tree.AttributeKey: 3131 if colType.GetId() == int32(types.T_blob) { 3132 return nil, moerr.NewNotSupported(ctx.GetContext(), "blob type in primary key") 3133 } 3134 if colType.GetId() == int32(types.T_text) { 3135 return nil, moerr.NewNotSupported(ctx.GetContext(), "text type in primary key") 3136 } 3137 if colType.GetId() == int32(types.T_json) { 3138 return nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in primary key", opt.Column.Name.Parts[0])) 3139 } 3140 if colType.GetId() == int32(types.T_array_float32) || colType.GetId() == int32(types.T_array_float64) { 3141 return nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("VECTOR column '%s' cannot be in primary key", opt.Column.Name.Parts[0])) 3142 } 3143 pks = append(pks, opt.Column.Name.Parts[0]) 3144 case *tree.AttributeComment: 3145 comment = attribute.CMT.String() 3146 if getNumOfCharacters(comment) > maxLengthOfColumnComment { 3147 return nil, moerr.NewInvalidInput(ctx.GetContext(), "comment for column '%s' is too long", opt.Column.Name.Parts[0]) 3148 } 3149 case *tree.AttributeAutoIncrement: 3150 auto_incr = true 3151 if !types.T(colType.GetId()).IsInteger() { 3152 return nil, moerr.NewNotSupported(ctx.GetContext(), "the auto_incr column is only support integer type now") 3153 } 3154 case *tree.AttributeUnique, *tree.AttributeUniqueKey: 3155 return nil, moerr.NewNotSupported(ctx.GetContext(), "unsupport add unique index constraints when adding new column") 3156 //uniqueIndexInfos = append(uniqueIndexInfos, &tree.UniqueIndex{ 3157 // KeyParts: []*tree.KeyPart{ 3158 // { 3159 // ColName: opt.Column.Name, 3160 // }, 3161 // }, 3162 // Name: opt.Column.Name.Parts[0], 3163 //}) 3164 //indexs = append(indexs, opt.Column.Name.Parts[0]) 3165 } 3166 } 3167 if len(pks) > 0 { 3168 if len(primaryKeys) > 0 { 3169 return nil, moerr.NewInvalidInput(ctx.GetContext(), "more than one primary key defined") 3170 } 3171 primaryKeys = pks 3172 } 3173 3174 defaultValue, err := buildDefaultExpr(opt.Column, colType, ctx.GetProcess()) 3175 if err != nil { 3176 return nil, err 3177 } 3178 if auto_incr && defaultValue.Expr != nil { 3179 return nil, moerr.NewInvalidInput(ctx.GetContext(), "invalid default value for '%s'", opt.Column.Name.Parts[0]) 3180 } 3181 3182 onUpdateExpr, err := buildOnUpdate(opt.Column, colType, ctx.GetProcess()) 3183 if err != nil { 3184 return nil, err 3185 } 3186 3187 if !checkTableColumnNameValid(opt.Column.Name.Parts[0]) { 3188 return nil, moerr.NewInvalidInput(ctx.GetContext(), "table column name '%s' is illegal and conflicts with internal keyword", opt.Column.Name.Parts[0]) 3189 } 3190 3191 colType.AutoIncr = auto_incr 3192 col := &ColDef{ 3193 Name: opt.Column.Name.Parts[0], 3194 Alg: plan.CompressType_Lz4, 3195 Typ: colType, 3196 Default: defaultValue, 3197 OnUpdate: onUpdateExpr, 3198 Comment: comment, 3199 } 3200 colMap[col.Name] = col 3201 preName := "" 3202 if opt.Position.RelativeColumn != nil { 3203 preName = opt.Position.RelativeColumn.Parts[0] 3204 } 3205 err = checkIsAddableColumn(tableDef, opt.Column.Name.Parts[0], &colType, ctx) 3206 if err != nil { 3207 return nil, err 3208 } 3209 alterTable.Actions[i] = &plan.AlterTable_Action{ 3210 Action: &plan.AlterTable_Action_AddColumn{ 3211 AddColumn: &plan.AlterAddColumn{ 3212 Name: opt.Column.Name.Parts[0], 3213 PreName: preName, 3214 Type: colType, 3215 Pos: int32(opt.Position.Typ), 3216 }, 3217 }, 3218 } 3219 case *tree.TableOptionAutoIncrement: 3220 return nil, moerr.NewInvalidInput(ctx.GetContext(), "Can't set AutoIncr column value.") 3221 case *tree.AlterOptionAlterCheck, *tree.TableOptionCharset: 3222 alterTable.Actions[i] = &plan.AlterTable_Action{ 3223 Action: &plan.AlterTable_Action_AlterComment{ 3224 AlterComment: &plan.AlterTableComment{ 3225 NewComment: comment, 3226 }, 3227 }, 3228 } 3229 default: 3230 return nil, moerr.NewInvalidInput(ctx.GetContext(), "Do not support this stmt now.") 3231 } 3232 } 3233 3234 if stmt.PartitionOption != nil { 3235 alterPartitionOption := stmt.PartitionOption 3236 switch partitionOption := alterPartitionOption.(type) { 3237 case *tree.AlterPartitionAddPartitionClause: 3238 alterTableAddPartition, err := AddTablePartitions(ctx, alterTable, partitionOption) 3239 if err != nil { 3240 return nil, err 3241 } 3242 3243 alterTable.Actions = append(alterTable.Actions, &plan.AlterTable_Action{ 3244 Action: &plan.AlterTable_Action_AddPartition{ 3245 AddPartition: alterTableAddPartition, 3246 }, 3247 }) 3248 case *tree.AlterPartitionDropPartitionClause: 3249 return nil, moerr.NewNotSupported(ctx.GetContext(), "alter table drop partition clause") 3250 case *tree.AlterPartitionTruncatePartitionClause: 3251 return nil, moerr.NewNotSupported(ctx.GetContext(), "alter table truncate partition clause") 3252 case *tree.AlterPartitionRedefinePartitionClause: 3253 return nil, moerr.NewNotSupported(ctx.GetContext(), "alter table partition by clause") 3254 } 3255 } 3256 3257 for _, str := range indexs { 3258 if _, ok := colMap[str]; !ok { 3259 return nil, moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", str) 3260 } 3261 if colMap[str].Typ.Id == int32(types.T_blob) { 3262 return nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", str)) 3263 } 3264 if colMap[str].Typ.Id == int32(types.T_text) { 3265 return nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", str)) 3266 } 3267 if colMap[str].Typ.Id == int32(types.T_json) { 3268 return nil, moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", str)) 3269 } 3270 } 3271 3272 // check Constraint Name (include index/ unique) 3273 err = checkConstraintNames(uniqueIndexInfos, secondaryIndexInfos, ctx.GetContext()) 3274 if err != nil { 3275 return nil, err 3276 } 3277 alterTable.DetectSqls = detectSqls 3278 alterTable.UpdateFkSqls = updateSqls 3279 return &Plan{ 3280 Plan: &plan.Plan_Ddl{ 3281 Ddl: &plan.DataDefinition{ 3282 DdlType: plan.DataDefinition_ALTER_TABLE, 3283 Definition: &plan.DataDefinition_AlterTable{ 3284 AlterTable: alterTable, 3285 }, 3286 }, 3287 }, 3288 }, nil 3289 } 3290 3291 func buildLockTables(stmt *tree.LockTableStmt, ctx CompilerContext) (*Plan, error) { 3292 lockTables := make([]*plan.TableLockInfo, 0, len(stmt.TableLocks)) 3293 uniqueTableName := make(map[string]bool) 3294 3295 //Check table locks 3296 for _, tableLock := range stmt.TableLocks { 3297 tb := tableLock.Table 3298 3299 //get table name 3300 tblName := string(tb.ObjectName) 3301 3302 // get database name 3303 var schemaName string 3304 if len(tb.SchemaName) == 0 { 3305 schemaName = ctx.DefaultDatabase() 3306 } else { 3307 schemaName = string(tb.SchemaName) 3308 } 3309 3310 //check table whether exist 3311 obj, tableDef := ctx.Resolve(schemaName, tblName, Snapshot{TS: ×tamp.Timestamp{}}) 3312 if tableDef == nil { 3313 return nil, moerr.NewNoSuchTable(ctx.GetContext(), schemaName, tblName) 3314 } 3315 3316 if obj.PubInfo != nil { 3317 return nil, moerr.NewInternalError(ctx.GetContext(), "cannot lock table in subscription database") 3318 } 3319 3320 // check the stmt whether locks the same table 3321 if _, ok := uniqueTableName[tblName]; ok { 3322 return nil, moerr.NewInvalidInput(ctx.GetContext(), "Not unique table %s", tblName) 3323 } 3324 3325 uniqueTableName[tblName] = true 3326 3327 tableLockInfo := &plan.TableLockInfo{ 3328 LockType: plan.TableLockType(tableLock.LockType), 3329 TableDef: tableDef, 3330 } 3331 lockTables = append(lockTables, tableLockInfo) 3332 } 3333 3334 LockTables := &plan.LockTables{ 3335 TableLocks: lockTables, 3336 } 3337 3338 return &Plan{ 3339 Plan: &plan.Plan_Ddl{ 3340 Ddl: &plan.DataDefinition{ 3341 DdlType: plan.DataDefinition_LOCK_TABLES, 3342 Definition: &plan.DataDefinition_LockTables{ 3343 LockTables: LockTables, 3344 }, 3345 }, 3346 }, 3347 }, nil 3348 } 3349 3350 func buildUnLockTables(stmt *tree.UnLockTableStmt, ctx CompilerContext) (*Plan, error) { 3351 unLockTables := &plan.UnLockTables{} 3352 return &Plan{ 3353 Plan: &plan.Plan_Ddl{ 3354 Ddl: &plan.DataDefinition{ 3355 DdlType: plan.DataDefinition_UNLOCK_TABLES, 3356 Definition: &plan.DataDefinition_UnlockTables{ 3357 UnlockTables: unLockTables, 3358 }, 3359 }, 3360 }, 3361 }, nil 3362 } 3363 3364 type FkData struct { 3365 // fk reference to itself 3366 IsSelfRefer bool 3367 // the database that the fk refers to 3368 ParentDbName string 3369 // the table that the fk refers to 3370 ParentTableName string 3371 //the columns in foreign key 3372 Cols *plan.FkColName 3373 // the columns referred 3374 ColsReferred *plan.FkColName 3375 //fk definition 3376 Def *plan.ForeignKeyDef 3377 //the column typs in foreign key 3378 ColTyps map[int]*plan.Type 3379 // update foreign keys relations 3380 UpdateSql string 3381 // forward reference 3382 ForwardRefer bool 3383 } 3384 3385 // getForeignKeyData prepares the foreign key data. 3386 // for fk refer except the self refer, it is same as the previous one. 3387 // but for fk self refer, it is different in not checking fk self refer instantly. 3388 // because it is not ready. It should be checked after the pk,uk has been ready. 3389 func getForeignKeyData(ctx CompilerContext, dbName string, tableDef *TableDef, def *tree.ForeignKey) (*FkData, error) { 3390 refer := def.Refer 3391 fkData := FkData{ 3392 Def: &plan.ForeignKeyDef{ 3393 Name: def.ConstraintSymbol, 3394 Cols: make([]uint64, len(def.KeyParts)), 3395 OnDelete: getRefAction(refer.OnDelete), 3396 OnUpdate: getRefAction(refer.OnUpdate), 3397 ForeignCols: make([]uint64, len(refer.KeyParts)), 3398 }, 3399 } 3400 3401 // get fk columns of create table 3402 fkData.Cols = &plan.FkColName{ 3403 Cols: make([]string, len(def.KeyParts)), 3404 } 3405 fkData.ColTyps = make(map[int]*plan.Type) 3406 name2ColDef := make(map[string]*ColDef) 3407 for _, colDef := range tableDef.Cols { 3408 name2ColDef[colDef.Name] = colDef 3409 } 3410 //get the column (id,name,type) from tableDef for the foreign key 3411 for i, keyPart := range def.KeyParts { 3412 colName := keyPart.ColName.Parts[0] 3413 if colDef, has := name2ColDef[colName]; has { 3414 //column id from tableDef 3415 fkData.Def.Cols[i] = colDef.ColId 3416 //column name from tableDef 3417 fkData.Cols.Cols[i] = colDef.Name 3418 //column type from tableDef 3419 fkData.ColTyps[i] = &colDef.Typ 3420 } else { 3421 return nil, moerr.NewInternalError(ctx.GetContext(), "column '%v' no exists in the creating table '%v'", colName, tableDef.Name) 3422 } 3423 } 3424 3425 fkData.ColsReferred = &plan.FkColName{ 3426 Cols: make([]string, len(refer.KeyParts)), 3427 } 3428 for i, part := range refer.KeyParts { 3429 fkData.ColsReferred.Cols[i] = part.ColName.Parts[0] 3430 } 3431 3432 // get foreign table & their columns 3433 parentTableName := string(refer.TableName.ObjectName) 3434 parentDbName := string(refer.TableName.SchemaName) 3435 if parentDbName == "" { 3436 parentDbName = ctx.DefaultDatabase() 3437 } 3438 3439 if IsFkBannedDatabase(parentDbName) { 3440 return nil, moerr.NewInternalError(ctx.GetContext(), "can not refer foreign keys in %s", parentDbName) 3441 } 3442 3443 //foreign key reference to itself 3444 if IsFkSelfRefer(parentDbName, parentTableName, dbName, tableDef.Name) { 3445 //should be handled later for fk self reference 3446 //PK and unique key may not be processed now 3447 //check fk columns can not reference to themselves 3448 //In self refer, the parent table is the table itself 3449 parentColumnsMap := make(map[string]int8) 3450 for _, part := range refer.KeyParts { 3451 parentColumnsMap[part.ColName.Parts[0]] = 0 3452 } 3453 for _, name := range fkData.Cols.Cols { 3454 if _, ok := parentColumnsMap[name]; ok { 3455 return nil, moerr.NewInternalError(ctx.GetContext(), "foreign key %s can not reference to itself", name) 3456 } 3457 } 3458 //for fk self refer. column id may be not ready. 3459 fkData.IsSelfRefer = true 3460 fkData.ParentDbName = parentDbName 3461 fkData.ParentTableName = parentTableName 3462 fkData.Def.ForeignTbl = 0 3463 fkData.UpdateSql = getSqlForAddFk(dbName, tableDef.Name, &fkData) 3464 return &fkData, nil 3465 } 3466 3467 fkData.ParentDbName = parentDbName 3468 fkData.ParentTableName = parentTableName 3469 3470 //make insert mo_foreign_keys 3471 fkData.UpdateSql = getSqlForAddFk(dbName, tableDef.Name, &fkData) 3472 3473 _, parentTableDef := ctx.Resolve(parentDbName, parentTableName, Snapshot{TS: ×tamp.Timestamp{}}) 3474 if parentTableDef == nil { 3475 enabled, err := IsForeignKeyChecksEnabled(ctx) 3476 if err != nil { 3477 return nil, err 3478 } 3479 if !enabled { 3480 fkData.ForwardRefer = true 3481 return &fkData, nil 3482 } 3483 return nil, moerr.NewNoSuchTable(ctx.GetContext(), ctx.DefaultDatabase(), parentTableName) 3484 } 3485 3486 if parentTableDef.IsTemporary { 3487 return nil, moerr.NewNYI(ctx.GetContext(), "add foreign key for temporary table") 3488 } 3489 3490 fkData.Def.ForeignTbl = parentTableDef.TblId 3491 3492 //separate the rest of the logic in previous version 3493 //into an independent function checkFkColsAreValid 3494 //for reusing it in fk self refer that checks the 3495 //columns in fk definition are valid or not. 3496 if err := checkFkColsAreValid(ctx, &fkData, parentTableDef); err != nil { 3497 return nil, err 3498 } 3499 3500 return &fkData, nil 3501 } 3502 3503 /* 3504 checkFkColsAreValid check foreign key columns is valid or not, then it saves them. 3505 the columns referred by the foreign key in the children table must appear in the unique keys or primary key 3506 in the parent table. 3507 3508 For instance: 3509 create table f1 (a int ,b int, c int ,d int ,e int, 3510 3511 primary key(a,b), unique key(c,d), unique key (e)) 3512 3513 Case 1: 3514 3515 single column like "a" ,"b", "c", "d", "e" can be used as the column in foreign key of the child table 3516 due to they are the member of the primary key or some Unique key. 3517 3518 Case 2: 3519 3520 "a, b" can be used as the columns in the foreign key of the child table 3521 due to they are the member of the primary key. 3522 3523 "c, d" can be used as the columns in the foreign key of the child table 3524 due to they are the member of some unique key. 3525 3526 Case 3: 3527 3528 "a, c" can not be used due to they belong to the different primary key / unique key 3529 */ 3530 func checkFkColsAreValid(ctx CompilerContext, fkData *FkData, parentTableDef *TableDef) error { 3531 //colId in parent table-> position in parent table 3532 columnIdPos := make(map[uint64]int) 3533 //columnName in parent table -> position in parent table 3534 columnNamePos := make(map[string]int) 3535 //columnName of index and pk of parent table -> colId in parent table 3536 uniqueColumns := make([]map[string]uint64, 0, len(parentTableDef.Cols)) 3537 3538 //1. collect parent column info 3539 for i, col := range parentTableDef.Cols { 3540 columnIdPos[col.ColId] = i 3541 columnNamePos[col.Name] = i 3542 } 3543 3544 //2. check if the referred column does not exist in the parent table 3545 for _, colName := range fkData.ColsReferred.Cols { 3546 if _, exists := columnNamePos[colName]; !exists { // column exists in parent table 3547 return moerr.NewInternalError(ctx.GetContext(), "column '%v' no exists in table '%v'", colName, fkData.ParentTableName) 3548 } 3549 } 3550 3551 //columnName in uk or pk -> its colId in the parent table 3552 collectIndexColumn := func(names []string) { 3553 ret := make(map[string]uint64) 3554 //columnName -> its colId in the parent table 3555 for _, colName := range names { 3556 ret[colName] = parentTableDef.Cols[columnNamePos[colName]].ColId 3557 } 3558 uniqueColumns = append(uniqueColumns, ret) 3559 } 3560 3561 //3. collect pk column info of the parent table 3562 if parentTableDef.Pkey != nil { 3563 collectIndexColumn(parentTableDef.Pkey.Names) 3564 } 3565 3566 //4. collect index column info of the parent table 3567 //secondary key? 3568 // now tableRef.Indices are empty, you can not test it 3569 for _, index := range parentTableDef.Indexes { 3570 if index.Unique { 3571 collectIndexColumn(index.Parts) 3572 } 3573 } 3574 3575 //5. check if there is at least one unique key or primary key should have 3576 //the columns referenced by the foreign keys in the children tables. 3577 matchCol := make([]uint64, 0, len(fkData.ColsReferred.Cols)) 3578 //iterate on every pk or uk 3579 for _, uniqueColumn := range uniqueColumns { 3580 //iterate on the referred column of fk 3581 for i, colName := range fkData.ColsReferred.Cols { 3582 //check if the referred column exists in this pk or uk 3583 if colId, ok := uniqueColumn[colName]; ok { 3584 // check column type 3585 // left part of expr: column type in parent table 3586 // right part of expr: column type in child table 3587 if parentTableDef.Cols[columnIdPos[colId]].Typ.Id != fkData.ColTyps[i].Id { 3588 return moerr.NewInternalError(ctx.GetContext(), "type of reference column '%v' is not match for column '%v'", colName, fkData.Cols.Cols[i]) 3589 } 3590 matchCol = append(matchCol, colId) 3591 } else { 3592 // column in fk does not exist in this pk or uk 3593 matchCol = matchCol[:0] 3594 break 3595 } 3596 } 3597 3598 if len(matchCol) > 0 { 3599 break 3600 } 3601 } 3602 3603 if len(matchCol) == 0 { 3604 return moerr.NewInternalError(ctx.GetContext(), "failed to add the foreign key constraint") 3605 } else { 3606 fkData.Def.ForeignCols = matchCol 3607 } 3608 return nil 3609 } 3610 3611 // buildFkDataOfForwardRefer rebuilds the fk relationships based on 3612 // the mo_catalog.mo_foreign_keys. 3613 func buildFkDataOfForwardRefer(ctx CompilerContext, 3614 constraintName string, 3615 fkDefs []*FkReferDef, 3616 createTable *plan.CreateTable) (*FkData, error) { 3617 fkData := FkData{ 3618 Def: &plan.ForeignKeyDef{ 3619 Name: constraintName, 3620 Cols: make([]uint64, len(fkDefs)), 3621 OnDelete: convertIntoReferAction(fkDefs[0].OnDelete), 3622 OnUpdate: convertIntoReferAction(fkDefs[0].OnUpdate), 3623 ForeignCols: make([]uint64, len(fkDefs)), 3624 }, 3625 } 3626 //1. get tableDef of the child table 3627 _, childTableDef := ctx.Resolve(fkDefs[0].Db, fkDefs[0].Tbl, Snapshot{TS: ×tamp.Timestamp{}}) 3628 if childTableDef == nil { 3629 return nil, moerr.NewNoSuchTable(ctx.GetContext(), fkDefs[0].Db, fkDefs[0].Tbl) 3630 } 3631 //2. fill fkdata 3632 fkData.Cols = &plan.FkColName{ 3633 Cols: make([]string, len(fkDefs)), 3634 } 3635 fkData.ColTyps = make(map[int]*plan.Type) 3636 3637 name2ColDef := make(map[string]*ColDef) 3638 for _, def := range childTableDef.Cols { 3639 name2ColDef[def.Name] = def 3640 } 3641 for i, fkDef := range fkDefs { 3642 if colDef, has := name2ColDef[fkDef.Col]; has { 3643 //column id from tableDef 3644 fkData.Def.Cols[i] = colDef.ColId 3645 //column name from tableDef 3646 fkData.Cols.Cols[i] = colDef.Name 3647 //column type from tableDef 3648 fkData.ColTyps[i] = &colDef.Typ 3649 } else { 3650 return nil, moerr.NewInternalError(ctx.GetContext(), "column '%v' no exists in table '%v'", fkDef.Col, fkDefs[0].Tbl) 3651 } 3652 } 3653 3654 fkData.ColsReferred = &plan.FkColName{ 3655 Cols: make([]string, len(fkDefs)), 3656 } 3657 for i, def := range fkDefs { 3658 fkData.ColsReferred.Cols[i] = def.ReferCol 3659 } 3660 3661 //3. check fk valid or not 3662 if err := checkFkColsAreValid(ctx, &fkData, createTable.TableDef); err != nil { 3663 return nil, err 3664 } 3665 return &fkData, nil 3666 } 3667 3668 func getAutoIncrementOffsetFromVariables(ctx CompilerContext) (uint64, bool) { 3669 v, err := ctx.ResolveVariable("auto_increment_offset", true, false) 3670 if err == nil { 3671 if offset, ok := v.(int64); ok && offset > 1 { 3672 return uint64(offset - 1), true 3673 } 3674 } 3675 v, err = ctx.ResolveVariable("auto_increment_offset", true, true) 3676 if err == nil { 3677 if offset, ok := v.(int64); ok && offset > 1 { 3678 return uint64(offset - 1), true 3679 } 3680 } 3681 return 0, false 3682 }