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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.Timestamp{}}) {
  2528  		databaseId, err := ctx.GetDatabaseId(string(stmt.Name), Snapshot{TS: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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: &timestamp.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  }