github.com/matrixorigin/matrixone@v0.7.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  	"encoding/json"
    19  	"fmt"
    20  	"strconv"
    21  	"strings"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/catalog"
    24  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    25  	"github.com/matrixorigin/matrixone/pkg/container/types"
    26  	"github.com/matrixorigin/matrixone/pkg/defines"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    28  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    29  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    30  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function/operator"
    31  	"github.com/matrixorigin/matrixone/pkg/sql/util"
    32  )
    33  
    34  func genViewTableDef(ctx CompilerContext, stmt *tree.Select) (*plan.TableDef, error) {
    35  	var tableDef plan.TableDef
    36  
    37  	// check view statement
    38  	stmtPlan, err := runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	query := stmtPlan.GetQuery()
    44  	cols := make([]*plan.ColDef, len(query.Nodes[query.Steps[len(query.Steps)-1]].ProjectList))
    45  	for idx, expr := range query.Nodes[query.Steps[len(query.Steps)-1]].ProjectList {
    46  		cols[idx] = &plan.ColDef{
    47  			Name: query.Headings[idx],
    48  			Alg:  plan.CompressType_Lz4,
    49  			Typ:  expr.Typ,
    50  			Default: &plan.Default{
    51  				NullAbility:  true,
    52  				Expr:         nil,
    53  				OriginString: "",
    54  			},
    55  		}
    56  	}
    57  	tableDef.Cols = cols
    58  
    59  	// Check alter and change the viewsql.
    60  	viewSql := ctx.GetRootSql()
    61  	if len(viewSql) != 0 {
    62  		if viewSql[0] == 'A' {
    63  			viewSql = strings.Replace(viewSql, "ALTER", "CREATE", 1)
    64  		}
    65  		if viewSql[0] == 'a' {
    66  			viewSql = strings.Replace(viewSql, "alter", "create", 1)
    67  		}
    68  	}
    69  
    70  	viewData, err := json.Marshal(ViewData{
    71  		Stmt:            viewSql,
    72  		DefaultDatabase: ctx.DefaultDatabase(),
    73  	})
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	tableDef.ViewSql = &plan.ViewDef{
    78  		View: string(viewData),
    79  	}
    80  	properties := []*plan.Property{
    81  		{
    82  			Key:   catalog.SystemRelAttr_Kind,
    83  			Value: catalog.SystemViewRel,
    84  		},
    85  		{
    86  			Key:   catalog.SystemRelAttr_CreateSQL,
    87  			Value: ctx.GetRootSql(),
    88  		},
    89  	}
    90  	tableDef.Defs = append(tableDef.Defs, &plan.TableDef_DefType{
    91  		Def: &plan.TableDef_DefType_Properties{
    92  			Properties: &plan.PropertiesDef{
    93  				Properties: properties,
    94  			},
    95  		},
    96  	})
    97  
    98  	return &tableDef, nil
    99  }
   100  
   101  func buildCreateView(stmt *tree.CreateView, ctx CompilerContext) (*Plan, error) {
   102  	viewName := stmt.Name.ObjectName
   103  	createTable := &plan.CreateTable{
   104  		IfNotExists: stmt.IfNotExists,
   105  		TableDef: &TableDef{
   106  			Name: string(viewName),
   107  		},
   108  	}
   109  
   110  	// get database name
   111  	if len(stmt.Name.SchemaName) == 0 {
   112  		createTable.Database = ""
   113  	} else {
   114  		createTable.Database = string(stmt.Name.SchemaName)
   115  	}
   116  
   117  	tableDef, err := genViewTableDef(ctx, stmt.AsSource)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	createTable.TableDef.Cols = tableDef.Cols
   123  	createTable.TableDef.ViewSql = tableDef.ViewSql
   124  	createTable.TableDef.Defs = tableDef.Defs
   125  
   126  	return &Plan{
   127  		Plan: &plan.Plan_Ddl{
   128  			Ddl: &plan.DataDefinition{
   129  				DdlType: plan.DataDefinition_CREATE_TABLE,
   130  				Definition: &plan.DataDefinition_CreateTable{
   131  					CreateTable: createTable,
   132  				},
   133  			},
   134  		},
   135  	}, nil
   136  }
   137  
   138  func buildCreateTable(stmt *tree.CreateTable, ctx CompilerContext) (*Plan, error) {
   139  	createTable := &plan.CreateTable{
   140  		IfNotExists: stmt.IfNotExists,
   141  		Temporary:   stmt.Temporary,
   142  		TableDef: &TableDef{
   143  			Name: string(stmt.Table.ObjectName),
   144  		},
   145  	}
   146  
   147  	// get database name
   148  	if len(stmt.Table.SchemaName) == 0 {
   149  		createTable.Database = ctx.DefaultDatabase()
   150  	} else {
   151  		createTable.Database = string(stmt.Table.SchemaName)
   152  	}
   153  
   154  	// set tableDef
   155  	err := buildTableDefs(stmt, ctx, createTable)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	// set option
   161  	for _, option := range stmt.Options {
   162  		switch opt := option.(type) {
   163  		case *tree.TableOptionProperties:
   164  			properties := make([]*plan.Property, len(opt.Preperties))
   165  			for idx, property := range opt.Preperties {
   166  				properties[idx] = &plan.Property{
   167  					Key:   property.Key,
   168  					Value: property.Value,
   169  				}
   170  			}
   171  			createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{
   172  				Def: &plan.TableDef_DefType_Properties{
   173  					Properties: &plan.PropertiesDef{
   174  						Properties: properties,
   175  					},
   176  				},
   177  			})
   178  		// todo confirm: option data store like this?
   179  		case *tree.TableOptionComment:
   180  			if getNumOfCharacters(opt.Comment) > maxLengthOfTableComment {
   181  				return nil, moerr.NewInvalidInput(ctx.GetContext(), "comment for field '%s' is too long", createTable.TableDef.Name)
   182  			}
   183  
   184  			properties := []*plan.Property{
   185  				{
   186  					Key:   catalog.SystemRelAttr_Comment,
   187  					Value: opt.Comment,
   188  				},
   189  			}
   190  			createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{
   191  				Def: &plan.TableDef_DefType_Properties{
   192  					Properties: &plan.PropertiesDef{
   193  						Properties: properties,
   194  					},
   195  				},
   196  			})
   197  		// these table options is not support in plan
   198  		// case *tree.TableOptionEngine, *tree.TableOptionSecondaryEngine, *tree.TableOptionCharset,
   199  		// 	*tree.TableOptionCollate, *tree.TableOptionAutoIncrement, *tree.TableOptionComment,
   200  		// 	*tree.TableOptionAvgRowLength, *tree.TableOptionChecksum, *tree.TableOptionCompression,
   201  		// 	*tree.TableOptionConnection, *tree.TableOptionPassword, *tree.TableOptionKeyBlockSize,
   202  		// 	*tree.TableOptionMaxRows, *tree.TableOptionMinRows, *tree.TableOptionDelayKeyWrite,
   203  		// 	*tree.TableOptionRowFormat, *tree.TableOptionStatsPersistent, *tree.TableOptionStatsAutoRecalc,
   204  		// 	*tree.TableOptionPackKeys, *tree.TableOptionTablespace, *tree.TableOptionDataDirectory,
   205  		// 	*tree.TableOptionIndexDirectory, *tree.TableOptionStorageMedia, *tree.TableOptionStatsSamplePages,
   206  		// 	*tree.TableOptionUnion, *tree.TableOptionEncryption:
   207  		// 	return nil, moerr.NewNotSupported("statement: '%v'", tree.String(stmt, dialect.MYSQL))
   208  		default:
   209  			return nil, moerr.NewNotSupported(ctx.GetContext(), "statement: '%v'", tree.String(stmt, dialect.MYSQL))
   210  		}
   211  	}
   212  
   213  	// After handleTableOptions, so begin the partitions processing depend on TableDef
   214  	if stmt.Param != nil {
   215  		for i := 0; i < len(stmt.Param.Option); i += 2 {
   216  			switch strings.ToLower(stmt.Param.Option[i]) {
   217  			case "endpoint", "region", "access_key_id", "secret_access_key", "bucket", "filepath", "compression", "format", "jsondata", "provider", "role_arn", "external_id":
   218  			default:
   219  				return nil, moerr.NewBadConfig(ctx.GetContext(), "the keyword '%s' is not support", strings.ToLower(stmt.Param.Option[i]))
   220  			}
   221  		}
   222  		if err := InitNullMap(stmt.Param, ctx); err != nil {
   223  			return nil, err
   224  		}
   225  		json_byte, err := json.Marshal(stmt.Param)
   226  		if err != nil {
   227  			return nil, err
   228  		}
   229  		properties := []*plan.Property{
   230  			{
   231  				Key:   catalog.SystemRelAttr_Kind,
   232  				Value: catalog.SystemExternalRel,
   233  			},
   234  			{
   235  				Key:   catalog.SystemRelAttr_CreateSQL,
   236  				Value: string(json_byte),
   237  			},
   238  		}
   239  		createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{
   240  			Def: &plan.TableDef_DefType_Properties{
   241  				Properties: &plan.PropertiesDef{
   242  					Properties: properties,
   243  				},
   244  			}})
   245  	} else {
   246  		kind := catalog.SystemOrdinaryRel
   247  		if stmt.IsClusterTable {
   248  			kind = catalog.SystemClusterRel
   249  		}
   250  		properties := []*plan.Property{
   251  			{
   252  				Key:   catalog.SystemRelAttr_Kind,
   253  				Value: kind,
   254  			},
   255  			{
   256  				Key:   catalog.SystemRelAttr_CreateSQL,
   257  				Value: ctx.GetRootSql(),
   258  			},
   259  		}
   260  		createTable.TableDef.Defs = append(createTable.TableDef.Defs, &plan.TableDef_DefType{
   261  			Def: &plan.TableDef_DefType_Properties{
   262  				Properties: &plan.PropertiesDef{
   263  					Properties: properties,
   264  				},
   265  			}})
   266  	}
   267  
   268  	builder := NewQueryBuilder(plan.Query_SELECT, ctx)
   269  	bindContext := NewBindContext(builder, nil)
   270  
   271  	// set partition(unsupport now)
   272  	if stmt.PartitionOption != nil {
   273  		nodeID := builder.appendNode(&plan.Node{
   274  			NodeType:    plan.Node_TABLE_SCAN,
   275  			Stats:       nil,
   276  			ObjRef:      nil,
   277  			TableDef:    createTable.TableDef,
   278  			BindingTags: []int32{builder.genNewTag()},
   279  		}, bindContext)
   280  
   281  		err = builder.addBinding(nodeID, tree.AliasClause{}, bindContext)
   282  		if err != nil {
   283  			return nil, err
   284  		}
   285  		partitionBinder := NewPartitionBinder(builder, bindContext)
   286  		err = buildPartitionByClause(partitionBinder, stmt, createTable.TableDef)
   287  		if err != nil {
   288  			return nil, err
   289  		}
   290  	}
   291  
   292  	return &Plan{
   293  		Plan: &plan.Plan_Ddl{
   294  			Ddl: &plan.DataDefinition{
   295  				DdlType: plan.DataDefinition_CREATE_TABLE,
   296  				Definition: &plan.DataDefinition_CreateTable{
   297  					CreateTable: createTable,
   298  				},
   299  			},
   300  		},
   301  	}, nil
   302  }
   303  
   304  // buildPartitionByClause build partition by clause info and semantic check.
   305  // Currently, sub partition and partition value verification are not supported
   306  func buildPartitionByClause(partitionBinder *PartitionBinder, stmt *tree.CreateTable, tableDef *TableDef) (err error) {
   307  	switch stmt.PartitionOption.PartBy.PType.(type) {
   308  	case *tree.HashType:
   309  		err = buildHashPartition(partitionBinder, stmt, tableDef)
   310  	case *tree.KeyType:
   311  		err = buildKeyPartition(partitionBinder, stmt, tableDef)
   312  	case *tree.RangeType:
   313  		err = buildRangePartition(partitionBinder, stmt, tableDef)
   314  	case *tree.ListType:
   315  		err = buildListPartitiion(partitionBinder, stmt, tableDef)
   316  	}
   317  	return err
   318  }
   319  
   320  func buildTableDefs(stmt *tree.CreateTable, ctx CompilerContext, createTable *plan.CreateTable) error {
   321  	var primaryKeys []string
   322  	var indexs []string
   323  	colMap := make(map[string]*ColDef)
   324  	uniqueIndexInfos := make([]*tree.UniqueIndex, 0)
   325  	secondaryIndexInfos := make([]*tree.Index, 0)
   326  	for _, item := range stmt.Defs {
   327  		switch def := item.(type) {
   328  		case *tree.ColumnTableDef:
   329  			colType, err := getTypeFromAst(ctx.GetContext(), def.Type)
   330  			if err != nil {
   331  				return err
   332  			}
   333  			if colType.Id == int32(types.T_char) || colType.Id == int32(types.T_varchar) {
   334  				if colType.GetWidth() > types.MaxStringSize {
   335  					return moerr.NewInvalidInput(ctx.GetContext(), "string width (%d) is too long", colType.GetWidth())
   336  				}
   337  			}
   338  			var pks []string
   339  			var comment string
   340  			var auto_incr bool
   341  			for _, attr := range def.Attributes {
   342  				switch attribute := attr.(type) {
   343  				case *tree.AttributePrimaryKey:
   344  					if colType.GetId() == int32(types.T_blob) {
   345  						return moerr.NewNotSupported(ctx.GetContext(), "blob type in primary key")
   346  					}
   347  					if colType.GetId() == int32(types.T_text) {
   348  						return moerr.NewNotSupported(ctx.GetContext(), "text type in primary key")
   349  					}
   350  					if colType.GetId() == int32(types.T_json) {
   351  						return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in primary key", def.Name.Parts[0]))
   352  					}
   353  					pks = append(pks, def.Name.Parts[0])
   354  				case *tree.AttributeComment:
   355  					comment = attribute.CMT.String()
   356  					if getNumOfCharacters(comment) > maxLengthOfColumnComment {
   357  						return moerr.NewInvalidInput(ctx.GetContext(), "comment for column '%s' is too long", def.Name.Parts[0])
   358  					}
   359  				case *tree.AttributeAutoIncrement:
   360  					auto_incr = true
   361  					if !operator.IsInteger(types.T(colType.GetId())) {
   362  						return moerr.NewNotSupported(ctx.GetContext(), "the auto_incr column is only support integer type now")
   363  					}
   364  				case *tree.AttributeUnique, *tree.AttributeUniqueKey:
   365  					uniqueIndexInfos = append(uniqueIndexInfos, &tree.UniqueIndex{
   366  						KeyParts: []*tree.KeyPart{
   367  							{
   368  								ColName: def.Name,
   369  							},
   370  						},
   371  					})
   372  					indexs = append(indexs, def.Name.Parts[0])
   373  				}
   374  			}
   375  			if len(pks) > 0 {
   376  				if len(primaryKeys) > 0 {
   377  					return moerr.NewInvalidInput(ctx.GetContext(), "more than one primary key defined")
   378  				}
   379  				primaryKeys = pks
   380  			}
   381  
   382  			defaultValue, err := buildDefaultExpr(def, colType, ctx.GetProcess())
   383  			if err != nil {
   384  				return err
   385  			}
   386  			if auto_incr && defaultValue.Expr != nil {
   387  				return moerr.NewInvalidInput(ctx.GetContext(), "invalid default value for '%s'", def.Name.Parts[0])
   388  			}
   389  
   390  			onUpdateExpr, err := buildOnUpdate(def, colType, ctx.GetProcess())
   391  			if err != nil {
   392  				return err
   393  			}
   394  
   395  			colType.AutoIncr = auto_incr
   396  			col := &ColDef{
   397  				Name:     def.Name.Parts[0],
   398  				Alg:      plan.CompressType_Lz4,
   399  				Typ:      colType,
   400  				Default:  defaultValue,
   401  				OnUpdate: onUpdateExpr,
   402  				Comment:  comment,
   403  			}
   404  			colMap[col.Name] = col
   405  			createTable.TableDef.Cols = append(createTable.TableDef.Cols, col)
   406  		case *tree.PrimaryKeyIndex:
   407  			if len(primaryKeys) > 0 {
   408  				return moerr.NewInvalidInput(ctx.GetContext(), "more than one primary key defined")
   409  			}
   410  			pksMap := map[string]bool{}
   411  			for _, key := range def.KeyParts {
   412  				name := key.ColName.Parts[0] // name of primary key column
   413  				if _, ok := pksMap[name]; ok {
   414  					return moerr.NewInvalidInput(ctx.GetContext(), "duplicate column name '%s' in primary key", name)
   415  				}
   416  				primaryKeys = append(primaryKeys, name)
   417  				pksMap[name] = true
   418  				indexs = append(indexs, name)
   419  			}
   420  		case *tree.Index:
   421  			secondaryIndexInfos = append(secondaryIndexInfos, def)
   422  			for _, key := range def.KeyParts {
   423  				name := key.ColName.Parts[0]
   424  				indexs = append(indexs, name)
   425  			}
   426  
   427  		case *tree.UniqueIndex:
   428  			uniqueIndexInfos = append(uniqueIndexInfos, def)
   429  			for _, key := range def.KeyParts {
   430  				name := key.ColName.Parts[0]
   431  				indexs = append(indexs, name)
   432  			}
   433  		case *tree.ForeignKey:
   434  			refer := def.Refer
   435  			fkDef := &plan.ForeignKeyDef{
   436  				Name:        def.Name,
   437  				Cols:        make([]uint64, len(def.KeyParts)),
   438  				OnDelete:    getRefAction(refer.OnDelete),
   439  				OnUpdate:    getRefAction(refer.OnUpdate),
   440  				ForeignCols: make([]uint64, len(refer.KeyParts)),
   441  			}
   442  
   443  			// get fk columns of create table
   444  			fkCols := &plan.CreateTable_FkColName{
   445  				Cols: make([]string, len(def.KeyParts)),
   446  			}
   447  			fkColTyp := make(map[int]*plan.Type)
   448  			fkColName := make(map[int]string)
   449  			for i, keyPart := range def.KeyParts {
   450  				getCol := false
   451  				colName := keyPart.ColName.Parts[0]
   452  				for _, col := range createTable.TableDef.Cols {
   453  					if col.Name == colName {
   454  						// need to reset to ColId after created.
   455  						fkDef.Cols[i] = 0
   456  						fkCols.Cols[i] = colName
   457  						fkColTyp[i] = col.Typ
   458  						fkColName[i] = colName
   459  						getCol = true
   460  						break
   461  					}
   462  				}
   463  				if !getCol {
   464  					return moerr.NewInternalError(ctx.GetContext(), "column '%v' no exists in the creating table '%v'", colName, createTable.TableDef.Name)
   465  				}
   466  			}
   467  			createTable.FkCols = append(createTable.FkCols, fkCols)
   468  
   469  			// get foreign table & their columns
   470  			fkTableName := string(refer.TableName.ObjectName)
   471  			fkDbName := string(refer.TableName.SchemaName)
   472  			if fkDbName == "" {
   473  				fkDbName = ctx.DefaultDatabase()
   474  			}
   475  			createTable.FkDbs = append(createTable.FkDbs, fkDbName)
   476  			createTable.FkTables = append(createTable.FkTables, fkTableName)
   477  
   478  			_, tableRef := ctx.Resolve(fkDbName, fkTableName)
   479  			if tableRef == nil {
   480  				return moerr.NewNoSuchTable(ctx.GetContext(), ctx.DefaultDatabase(), fkTableName)
   481  			}
   482  
   483  			fkDef.ForeignTbl = tableRef.TblId
   484  			columnIdPos := make(map[uint64]int)
   485  			columnNamePos := make(map[string]int)
   486  			uniqueColumn := make(map[string]uint64)
   487  			for i, col := range tableRef.Cols {
   488  				columnIdPos[col.ColId] = i
   489  				columnNamePos[col.Name] = i
   490  				if col.Primary {
   491  					uniqueColumn[col.Name] = col.ColId
   492  				}
   493  			}
   494  			if tableRef.Pkey != nil {
   495  				for _, colName := range tableRef.Pkey.Names {
   496  					uniqueColumn[colName] = tableRef.Cols[columnNamePos[colName]].ColId
   497  				}
   498  			}
   499  
   500  			// now tableRef.Indices is empty, you can not test it
   501  			for _, index := range tableRef.Indexes {
   502  				if index.Unique {
   503  					if len(index.Parts) == 1 {
   504  						uniqueColName := index.Parts[0]
   505  						colId := tableRef.Cols[columnNamePos[uniqueColName]].ColId
   506  						uniqueColumn[uniqueColName] = colId
   507  					}
   508  				}
   509  			}
   510  
   511  			for i, keyPart := range refer.KeyParts {
   512  				colName := keyPart.ColName.Parts[0]
   513  				if _, exists := columnNamePos[colName]; exists {
   514  					if colId, ok := uniqueColumn[colName]; ok {
   515  						// check column type
   516  						if tableRef.Cols[columnIdPos[colId]].Typ.Id != fkColTyp[i].Id {
   517  							return moerr.NewInternalError(ctx.GetContext(), "type of reference column '%v' is not match for column '%v'", colName, fkColName[i])
   518  						}
   519  						fkDef.ForeignCols[i] = colId
   520  					} else {
   521  						return moerr.NewInternalError(ctx.GetContext(), "reference column '%v' is not unique constraint(Unique index or Primary Key)", colName)
   522  					}
   523  				} else {
   524  					return moerr.NewInternalError(ctx.GetContext(), "column '%v' no exists in table '%v'", colName, fkTableName)
   525  				}
   526  			}
   527  			createTable.TableDef.Fkeys = append(createTable.TableDef.Fkeys, fkDef)
   528  
   529  		case *tree.CheckIndex, *tree.FullTextIndex:
   530  			// unsupport in plan. will support in next version.
   531  			return moerr.NewNYI(ctx.GetContext(), "table def: '%v'", def)
   532  		default:
   533  			return moerr.NewNYI(ctx.GetContext(), "table def: '%v'", def)
   534  		}
   535  	}
   536  
   537  	//add cluster table attribute
   538  	if stmt.IsClusterTable {
   539  		if _, ok := colMap[util.GetClusterTableAttributeName()]; ok {
   540  			return moerr.NewInvalidInput(ctx.GetContext(), "the attribute account_id in the cluster table can not be defined directly by the user")
   541  		}
   542  		colType, err := getTypeFromAst(ctx.GetContext(), util.GetClusterTableAttributeType())
   543  		if err != nil {
   544  			return err
   545  		}
   546  		colDef := &ColDef{
   547  			Name:    util.GetClusterTableAttributeName(),
   548  			Alg:     plan.CompressType_Lz4,
   549  			Typ:     colType,
   550  			NotNull: true,
   551  			Default: &plan.Default{
   552  				Expr: &Expr{
   553  					Expr: &plan.Expr_C{
   554  						C: &Const{
   555  							Isnull: false,
   556  							Value:  &plan.Const_U32Val{U32Val: catalog.System_Account},
   557  						},
   558  					},
   559  					Typ: &plan.Type{
   560  						Id:          colType.Id,
   561  						NotNullable: true,
   562  					},
   563  				},
   564  				NullAbility: false,
   565  			},
   566  			Comment: "the account_id added by the mo",
   567  		}
   568  		colMap[util.GetClusterTableAttributeName()] = colDef
   569  		createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef)
   570  	}
   571  
   572  	pkeyName := ""
   573  	if len(primaryKeys) > 0 {
   574  		pKeyParts := make([]*ColDef, len(primaryKeys))
   575  		for i, primaryKey := range primaryKeys {
   576  			if coldef, ok := colMap[primaryKey]; !ok {
   577  				return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' doesn't exist in table", primaryKey)
   578  			} else {
   579  				pKeyParts[i] = coldef
   580  			}
   581  		}
   582  		if len(primaryKeys) == 1 {
   583  			pkeyName = primaryKeys[0]
   584  			for _, col := range createTable.TableDef.Cols {
   585  				if col.Name == pkeyName {
   586  					col.Primary = true
   587  					createTable.TableDef.Pkey = &PrimaryKeyDef{
   588  						Names:       primaryKeys,
   589  						PkeyColName: pkeyName,
   590  					}
   591  					break
   592  				}
   593  			}
   594  		} else {
   595  			pkeyName = util.BuildCompositePrimaryKeyColumnName(primaryKeys)
   596  			colDef := &ColDef{
   597  				Name: pkeyName,
   598  				Alg:  plan.CompressType_Lz4,
   599  				Typ: &Type{
   600  					Id:    int32(types.T_varchar),
   601  					Size:  types.VarlenaSize,
   602  					Width: types.MaxVarcharLen,
   603  				},
   604  				Default: &plan.Default{
   605  					NullAbility:  false,
   606  					Expr:         nil,
   607  					OriginString: "",
   608  				},
   609  			}
   610  			colDef.Primary = true
   611  			createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef)
   612  			colMap[pkeyName] = colDef
   613  
   614  			pkeyDef := &PrimaryKeyDef{
   615  				Names:       primaryKeys,
   616  				PkeyColName: pkeyName,
   617  			}
   618  			createTable.TableDef.Pkey = pkeyDef
   619  		}
   620  		for _, primaryKey := range primaryKeys {
   621  			colMap[primaryKey].Default.NullAbility = false
   622  			colMap[primaryKey].NotNull = true
   623  		}
   624  	}
   625  
   626  	//handle cluster by keys
   627  	if stmt.ClusterByOption != nil {
   628  		if stmt.Temporary {
   629  			return moerr.NewNotSupported(ctx.GetContext(), "cluster by with temporary table is not support")
   630  		}
   631  		if len(primaryKeys) > 0 {
   632  			return moerr.NewNotSupported(ctx.GetContext(), "cluster by with primary key is not support")
   633  		}
   634  		lenClusterBy := len(stmt.ClusterByOption.ColumnList)
   635  		var clusterByKeys []string
   636  		for i := 0; i < lenClusterBy; i++ {
   637  			colName := stmt.ClusterByOption.ColumnList[i].Parts[0]
   638  			if _, ok := colMap[colName]; !ok {
   639  				return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' doesn't exist in table", colName)
   640  			}
   641  			clusterByKeys = append(clusterByKeys, colName)
   642  		}
   643  
   644  		clusterByColName := clusterByKeys[0]
   645  		if lenClusterBy == 1 {
   646  			for _, col := range createTable.TableDef.Cols {
   647  				if col.Name == clusterByColName {
   648  					col.ClusterBy = true
   649  				}
   650  			}
   651  		} else {
   652  			clusterByColName = util.BuildCompositeClusterByColumnName(clusterByKeys)
   653  			colDef := &ColDef{
   654  				Name:      clusterByColName,
   655  				Alg:       plan.CompressType_Lz4,
   656  				ClusterBy: true,
   657  				Typ: &Type{
   658  					Id:    int32(types.T_varchar),
   659  					Size:  types.VarlenaSize,
   660  					Width: types.MaxVarcharLen,
   661  				},
   662  				Default: &plan.Default{
   663  					NullAbility:  true,
   664  					Expr:         nil,
   665  					OriginString: "",
   666  				},
   667  			}
   668  			createTable.TableDef.Cols = append(createTable.TableDef.Cols, colDef)
   669  			colMap[clusterByColName] = colDef
   670  		}
   671  		createTable.TableDef.ClusterBy = &plan.ClusterByDef{
   672  			Name: clusterByColName,
   673  		}
   674  	}
   675  
   676  	// check index invalid on the type
   677  	// for example, the text type don't support index
   678  	for _, str := range indexs {
   679  		if _, ok := colMap[str]; !ok {
   680  			return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", str)
   681  		}
   682  		if colMap[str].Typ.Id == int32(types.T_blob) {
   683  			return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", str))
   684  		}
   685  		if colMap[str].Typ.Id == int32(types.T_text) {
   686  			return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", str))
   687  		}
   688  		if colMap[str].Typ.Id == int32(types.T_json) {
   689  			return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", str))
   690  		}
   691  	}
   692  
   693  	// build index table
   694  	if len(uniqueIndexInfos) != 0 {
   695  		err := buildUniqueIndexTable(createTable, uniqueIndexInfos, colMap, pkeyName, ctx)
   696  		if err != nil {
   697  			return err
   698  		}
   699  	}
   700  	if len(secondaryIndexInfos) != 0 {
   701  		err := buildSecondaryIndexDef(createTable, secondaryIndexInfos, colMap, ctx)
   702  		if err != nil {
   703  			return err
   704  		}
   705  	}
   706  	return nil
   707  }
   708  
   709  func getRefAction(typ tree.ReferenceOptionType) plan.ForeignKeyDef_RefAction {
   710  	switch typ {
   711  	case tree.REFERENCE_OPTION_CASCADE:
   712  		return plan.ForeignKeyDef_CASCADE
   713  	case tree.REFERENCE_OPTION_NO_ACTION:
   714  		return plan.ForeignKeyDef_NO_ACTION
   715  	case tree.REFERENCE_OPTION_RESTRICT:
   716  		return plan.ForeignKeyDef_RESTRICT
   717  	case tree.REFERENCE_OPTION_SET_NULL:
   718  		return plan.ForeignKeyDef_SET_NULL
   719  	case tree.REFERENCE_OPTION_SET_DEFAULT:
   720  		return plan.ForeignKeyDef_SET_DEFAULT
   721  	default:
   722  		return plan.ForeignKeyDef_RESTRICT
   723  	}
   724  }
   725  
   726  func buildUniqueIndexTable(createTable *plan.CreateTable, indexInfos []*tree.UniqueIndex, colMap map[string]*ColDef, pkeyName string, ctx CompilerContext) error {
   727  	nameCount := make(map[string]int)
   728  
   729  	for _, indexInfo := range indexInfos {
   730  		indexDef := &plan.IndexDef{}
   731  		indexDef.Unique = true
   732  
   733  		indexTableName, err := util.BuildIndexTableName(ctx.GetContext(), true)
   734  
   735  		if err != nil {
   736  			return err
   737  		}
   738  		tableDef := &TableDef{
   739  			Name: indexTableName,
   740  		}
   741  		indexParts := make([]string, 0)
   742  
   743  		for _, keyPart := range indexInfo.KeyParts {
   744  			name := keyPart.ColName.Parts[0]
   745  			if _, ok := colMap[name]; !ok {
   746  				return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", name)
   747  			}
   748  			if colMap[name].Typ.Id == int32(types.T_blob) {
   749  				return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", name))
   750  			}
   751  			if colMap[name].Typ.Id == int32(types.T_text) {
   752  				return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", name))
   753  			}
   754  			if colMap[name].Typ.Id == int32(types.T_json) {
   755  				return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", name))
   756  			}
   757  			indexParts = append(indexParts, name)
   758  		}
   759  
   760  		var keyName string
   761  		if len(indexInfo.KeyParts) == 1 {
   762  			keyName = catalog.IndexTableIndexColName
   763  			colDef := &ColDef{
   764  				Name: keyName,
   765  				Alg:  plan.CompressType_Lz4,
   766  				Typ: &Type{
   767  					Id:    colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Id,
   768  					Size:  colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Size,
   769  					Width: colMap[indexInfo.KeyParts[0].ColName.Parts[0]].Typ.Width,
   770  				},
   771  				Default: &plan.Default{
   772  					NullAbility:  false,
   773  					Expr:         nil,
   774  					OriginString: "",
   775  				},
   776  			}
   777  			tableDef.Cols = append(tableDef.Cols, colDef)
   778  			tableDef.Pkey = &PrimaryKeyDef{
   779  				Names:       []string{keyName},
   780  				PkeyColName: keyName,
   781  			}
   782  		} else {
   783  			keyName = catalog.IndexTableIndexColName
   784  			colDef := &ColDef{
   785  				Name: keyName,
   786  				Alg:  plan.CompressType_Lz4,
   787  				Typ: &Type{
   788  					Id:    int32(types.T_varchar),
   789  					Size:  types.VarlenaSize,
   790  					Width: types.MaxVarcharLen,
   791  				},
   792  				Default: &plan.Default{
   793  					NullAbility:  false,
   794  					Expr:         nil,
   795  					OriginString: "",
   796  				},
   797  			}
   798  			tableDef.Cols = append(tableDef.Cols, colDef)
   799  			tableDef.Pkey = &PrimaryKeyDef{
   800  				Names:       []string{keyName},
   801  				PkeyColName: keyName,
   802  			}
   803  		}
   804  		if pkeyName != "" {
   805  			colDef := &ColDef{
   806  				Name: catalog.IndexTablePrimaryColName,
   807  				Alg:  plan.CompressType_Lz4,
   808  				Typ:  colMap[pkeyName].Typ,
   809  				Default: &plan.Default{
   810  					NullAbility:  false,
   811  					Expr:         nil,
   812  					OriginString: "",
   813  				},
   814  			}
   815  			tableDef.Cols = append(tableDef.Cols, colDef)
   816  		}
   817  		if indexInfo.Name == "" {
   818  			firstPart := indexInfo.KeyParts[0].ColName.Parts[0]
   819  			nameCount[firstPart]++
   820  			count := nameCount[firstPart]
   821  			indexName := firstPart
   822  			if count > 1 {
   823  				indexName = firstPart + "_" + strconv.Itoa(count)
   824  			}
   825  			indexDef.IndexName = indexName
   826  		} else {
   827  			indexDef.IndexName = indexInfo.Name
   828  		}
   829  		indexDef.IndexTableName = indexTableName
   830  		indexDef.Parts = indexParts
   831  		indexDef.TableExist = true
   832  		if indexInfo.IndexOption != nil {
   833  			indexDef.Comment = indexInfo.IndexOption.Comment
   834  		} else {
   835  			indexDef.Comment = ""
   836  		}
   837  		createTable.IndexTables = append(createTable.IndexTables, tableDef)
   838  
   839  		createTable.TableDef.Indexes = append(createTable.TableDef.Indexes, indexDef)
   840  	}
   841  	return nil
   842  }
   843  
   844  func buildSecondaryIndexDef(createTable *plan.CreateTable, indexInfos []*tree.Index, colMap map[string]*ColDef, ctx CompilerContext) error {
   845  	nameCount := make(map[string]int)
   846  
   847  	for _, indexInfo := range indexInfos {
   848  		indexDef := &plan.IndexDef{}
   849  		indexDef.Unique = false
   850  
   851  		indexParts := make([]string, 0)
   852  
   853  		for _, keyPart := range indexInfo.KeyParts {
   854  			name := keyPart.ColName.Parts[0]
   855  			if _, ok := colMap[name]; !ok {
   856  				return moerr.NewInvalidInput(ctx.GetContext(), "column '%s' is not exist", name)
   857  			}
   858  			if colMap[name].Typ.Id == int32(types.T_blob) {
   859  				return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("BLOB column '%s' cannot be in index", name))
   860  			}
   861  			if colMap[name].Typ.Id == int32(types.T_text) {
   862  				return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("TEXT column '%s' cannot be in index", name))
   863  			}
   864  			if colMap[name].Typ.Id == int32(types.T_json) {
   865  				return moerr.NewNotSupported(ctx.GetContext(), fmt.Sprintf("JSON column '%s' cannot be in index", name))
   866  			}
   867  			indexParts = append(indexParts, name)
   868  		}
   869  
   870  		if indexInfo.Name == "" {
   871  			firstPart := indexInfo.KeyParts[0].ColName.Parts[0]
   872  			nameCount[firstPart]++
   873  			count := nameCount[firstPart]
   874  			indexName := firstPart
   875  			if count > 1 {
   876  				indexName = firstPart + "_" + strconv.Itoa(count)
   877  			}
   878  			indexDef.IndexName = indexName
   879  		} else {
   880  			indexDef.IndexName = indexInfo.Name
   881  		}
   882  		indexDef.IndexTableName = ""
   883  		indexDef.Parts = indexParts
   884  		indexDef.TableExist = false
   885  		if indexInfo.IndexOption != nil {
   886  			indexDef.Comment = indexInfo.IndexOption.Comment
   887  		} else {
   888  			indexDef.Comment = ""
   889  		}
   890  		createTable.TableDef.Indexes = append(createTable.TableDef.Indexes, indexDef)
   891  	}
   892  	return nil
   893  }
   894  
   895  func buildTruncateTable(stmt *tree.TruncateTable, ctx CompilerContext) (*Plan, error) {
   896  	truncateTable := &plan.TruncateTable{}
   897  
   898  	truncateTable.Database = string(stmt.Name.SchemaName)
   899  	if truncateTable.Database == "" {
   900  		truncateTable.Database = ctx.DefaultDatabase()
   901  	}
   902  	truncateTable.Table = string(stmt.Name.ObjectName)
   903  	_, tableDef := ctx.Resolve(truncateTable.Database, truncateTable.Table)
   904  	if tableDef == nil {
   905  		return nil, moerr.NewNoSuchTable(ctx.GetContext(), truncateTable.Database, truncateTable.Table)
   906  	} else {
   907  		if len(tableDef.RefChildTbls) > 0 {
   908  			return nil, moerr.NewInternalError(ctx.GetContext(), "can not truncate table '%v' referenced by some foreign key constraint", truncateTable.Table)
   909  		}
   910  
   911  		if tableDef.ViewSql != nil {
   912  			return nil, moerr.NewNoSuchTable(ctx.GetContext(), truncateTable.Database, truncateTable.Table)
   913  		}
   914  
   915  		truncateTable.TableId = tableDef.TblId
   916  		if tableDef.Fkeys != nil {
   917  			for _, fk := range tableDef.Fkeys {
   918  				truncateTable.ForeignTbl = append(truncateTable.ForeignTbl, fk.ForeignTbl)
   919  			}
   920  		}
   921  
   922  		truncateTable.ClusterTable = &plan.ClusterTable{
   923  			IsClusterTable: util.TableIsClusterTable(tableDef.GetTableType()),
   924  		}
   925  
   926  		//non-sys account can not truncate the cluster table
   927  		if truncateTable.GetClusterTable().GetIsClusterTable() && ctx.GetAccountId() != catalog.System_Account {
   928  			return nil, moerr.NewInternalError(ctx.GetContext(), "only the sys account can truncate the cluster table")
   929  		}
   930  
   931  		truncateTable.IndexTableNames = make([]string, 0)
   932  		if tableDef.Indexes != nil {
   933  			for _, indexdef := range tableDef.Indexes {
   934  				if indexdef.TableExist {
   935  					truncateTable.IndexTableNames = append(truncateTable.IndexTableNames, indexdef.IndexTableName)
   936  				}
   937  			}
   938  		}
   939  	}
   940  
   941  	return &Plan{
   942  		Plan: &plan.Plan_Ddl{
   943  			Ddl: &plan.DataDefinition{
   944  				DdlType: plan.DataDefinition_TRUNCATE_TABLE,
   945  				Definition: &plan.DataDefinition_TruncateTable{
   946  					TruncateTable: truncateTable,
   947  				},
   948  			},
   949  		},
   950  	}, nil
   951  }
   952  
   953  func buildDropTable(stmt *tree.DropTable, ctx CompilerContext) (*Plan, error) {
   954  	dropTable := &plan.DropTable{
   955  		IfExists: stmt.IfExists,
   956  	}
   957  	if len(stmt.Names) != 1 {
   958  		return nil, moerr.NewNotSupported(ctx.GetContext(), "drop multiple (%d) tables in one statement", len(stmt.Names))
   959  	}
   960  	dropTable.Database = string(stmt.Names[0].SchemaName)
   961  	if dropTable.Database == "" {
   962  		dropTable.Database = ctx.DefaultDatabase()
   963  	}
   964  	dropTable.Table = string(stmt.Names[0].ObjectName)
   965  
   966  	_, tableDef := ctx.Resolve(dropTable.Database, dropTable.Table)
   967  	if tableDef == nil {
   968  		if !dropTable.IfExists {
   969  			return nil, moerr.NewNoSuchTable(ctx.GetContext(), dropTable.Database, dropTable.Table)
   970  		}
   971  	} else {
   972  		if len(tableDef.RefChildTbls) > 0 {
   973  			return nil, moerr.NewInternalError(ctx.GetContext(), "can not drop table '%v' referenced by some foreign key constraint", dropTable.Table)
   974  		}
   975  
   976  		isView := (tableDef.ViewSql != nil)
   977  
   978  		if isView && !dropTable.IfExists {
   979  			// drop table v0, v0 is view
   980  			return nil, moerr.NewNoSuchTable(ctx.GetContext(), dropTable.Database, dropTable.Table)
   981  		} else if isView {
   982  			// drop table if exists v0, v0 is view
   983  			dropTable.Table = ""
   984  		}
   985  
   986  		dropTable.ClusterTable = &plan.ClusterTable{
   987  			IsClusterTable: util.TableIsClusterTable(tableDef.GetTableType()),
   988  		}
   989  
   990  		//non-sys account can not drop the cluster table
   991  		if dropTable.GetClusterTable().GetIsClusterTable() && ctx.GetAccountId() != catalog.System_Account {
   992  			return nil, moerr.NewInternalError(ctx.GetContext(), "only the sys account can drop the cluster table")
   993  		}
   994  
   995  		dropTable.TableId = tableDef.TblId
   996  		if tableDef.Fkeys != nil {
   997  			for _, fk := range tableDef.Fkeys {
   998  				dropTable.ForeignTbl = append(dropTable.ForeignTbl, fk.ForeignTbl)
   999  			}
  1000  		}
  1001  
  1002  		dropTable.IndexTableNames = make([]string, 0)
  1003  		if tableDef.Indexes != nil {
  1004  			for _, indexdef := range tableDef.Indexes {
  1005  				if indexdef.TableExist {
  1006  					dropTable.IndexTableNames = append(dropTable.IndexTableNames, indexdef.IndexTableName)
  1007  				}
  1008  			}
  1009  		}
  1010  	}
  1011  	return &Plan{
  1012  		Plan: &plan.Plan_Ddl{
  1013  			Ddl: &plan.DataDefinition{
  1014  				DdlType: plan.DataDefinition_DROP_TABLE,
  1015  				Definition: &plan.DataDefinition_DropTable{
  1016  					DropTable: dropTable,
  1017  				},
  1018  			},
  1019  		},
  1020  	}, nil
  1021  }
  1022  
  1023  func buildDropView(stmt *tree.DropView, ctx CompilerContext) (*Plan, error) {
  1024  	dropTable := &plan.DropTable{
  1025  		IfExists: stmt.IfExists,
  1026  	}
  1027  	if len(stmt.Names) != 1 {
  1028  		return nil, moerr.NewNotSupported(ctx.GetContext(), "drop multiple (%d) view", len(stmt.Names))
  1029  	}
  1030  	dropTable.Database = string(stmt.Names[0].SchemaName)
  1031  	if dropTable.Database == "" {
  1032  		dropTable.Database = ctx.DefaultDatabase()
  1033  	}
  1034  	dropTable.Table = string(stmt.Names[0].ObjectName)
  1035  
  1036  	_, tableDef := ctx.Resolve(dropTable.Database, dropTable.Table)
  1037  	if tableDef == nil {
  1038  		if !dropTable.IfExists {
  1039  			return nil, moerr.NewBadView(ctx.GetContext(), dropTable.Database, dropTable.Table)
  1040  		}
  1041  	} else {
  1042  		if tableDef.ViewSql == nil {
  1043  			return nil, moerr.NewBadView(ctx.GetContext(), dropTable.Database, dropTable.Table)
  1044  		}
  1045  	}
  1046  
  1047  	return &Plan{
  1048  		Plan: &plan.Plan_Ddl{
  1049  			Ddl: &plan.DataDefinition{
  1050  				DdlType: plan.DataDefinition_DROP_TABLE,
  1051  				Definition: &plan.DataDefinition_DropTable{
  1052  					DropTable: dropTable,
  1053  				},
  1054  			},
  1055  		},
  1056  	}, nil
  1057  }
  1058  
  1059  func buildCreateDatabase(stmt *tree.CreateDatabase, ctx CompilerContext) (*Plan, error) {
  1060  	if string(stmt.Name) == defines.TEMPORARY_DBNAME {
  1061  		return nil, moerr.NewInternalError(ctx.GetContext(), "this database name is used by mo temporary engine")
  1062  	}
  1063  	createDB := &plan.CreateDatabase{
  1064  		IfNotExists: stmt.IfNotExists,
  1065  		Database:    string(stmt.Name),
  1066  	}
  1067  
  1068  	return &Plan{
  1069  		Plan: &plan.Plan_Ddl{
  1070  			Ddl: &plan.DataDefinition{
  1071  				DdlType: plan.DataDefinition_CREATE_DATABASE,
  1072  				Definition: &plan.DataDefinition_CreateDatabase{
  1073  					CreateDatabase: createDB,
  1074  				},
  1075  			},
  1076  		},
  1077  	}, nil
  1078  }
  1079  
  1080  func buildDropDatabase(stmt *tree.DropDatabase, ctx CompilerContext) (*Plan, error) {
  1081  	dropDB := &plan.DropDatabase{
  1082  		IfExists: stmt.IfExists,
  1083  		Database: string(stmt.Name),
  1084  	}
  1085  
  1086  	return &Plan{
  1087  		Plan: &plan.Plan_Ddl{
  1088  			Ddl: &plan.DataDefinition{
  1089  				DdlType: plan.DataDefinition_DROP_DATABASE,
  1090  				Definition: &plan.DataDefinition_DropDatabase{
  1091  					DropDatabase: dropDB,
  1092  				},
  1093  			},
  1094  		},
  1095  	}, nil
  1096  }
  1097  
  1098  func buildCreateIndex(stmt *tree.CreateIndex, ctx CompilerContext) (*Plan, error) {
  1099  	createIndex := &plan.CreateIndex{}
  1100  	if len(stmt.Table.SchemaName) == 0 {
  1101  		createIndex.Database = ctx.DefaultDatabase()
  1102  	} else {
  1103  		createIndex.Database = string(stmt.Table.SchemaName)
  1104  	}
  1105  	// check table
  1106  	tableName := string(stmt.Table.ObjectName)
  1107  	_, tableDef := ctx.Resolve(createIndex.Database, tableName)
  1108  	if tableDef == nil {
  1109  		return nil, moerr.NewNoSuchTable(ctx.GetContext(), createIndex.Database, tableName)
  1110  	}
  1111  	// check index
  1112  	indexName := string(stmt.Name)
  1113  	for _, def := range tableDef.Indexes {
  1114  		if def.IndexName == indexName {
  1115  			return nil, moerr.NewDuplicateKey(ctx.GetContext(), indexName)
  1116  		}
  1117  	}
  1118  	// build index
  1119  	var uIdx *tree.UniqueIndex
  1120  	var sIdx *tree.Index
  1121  	switch stmt.IndexCat {
  1122  	case tree.INDEX_CATEGORY_UNIQUE:
  1123  		uIdx = &tree.UniqueIndex{
  1124  			Name:        indexName,
  1125  			KeyParts:    stmt.KeyParts,
  1126  			IndexOption: stmt.IndexOption,
  1127  		}
  1128  	case tree.INDEX_CATEGORY_NONE:
  1129  		sIdx = &tree.Index{
  1130  			Name:        indexName,
  1131  			KeyParts:    stmt.KeyParts,
  1132  			IndexOption: stmt.IndexOption,
  1133  		}
  1134  	default:
  1135  		return nil, moerr.NewNotSupported(ctx.GetContext(), "statement: '%v'", tree.String(stmt, dialect.MYSQL))
  1136  	}
  1137  	colMap := make(map[string]*ColDef)
  1138  	for _, col := range tableDef.Cols {
  1139  		colMap[col.Name] = col
  1140  	}
  1141  	// index.TableDef.Defs store info of index need to be modified
  1142  	// index.IndexTables store index table need to be created
  1143  	oriPriKeyName := GetTablePriKeyName(tableDef.Cols, tableDef.CompositePkey)
  1144  	createIndex.OriginTablePrimaryKey = oriPriKeyName
  1145  
  1146  	index := &plan.CreateTable{TableDef: &TableDef{}}
  1147  	if uIdx != nil {
  1148  		if err := buildUniqueIndexTable(index, []*tree.UniqueIndex{uIdx}, colMap, oriPriKeyName, ctx); err != nil {
  1149  			return nil, err
  1150  		}
  1151  		createIndex.TableExist = true
  1152  	}
  1153  	if sIdx != nil {
  1154  		if err := buildSecondaryIndexDef(index, []*tree.Index{sIdx}, colMap, ctx); err != nil {
  1155  			return nil, err
  1156  		}
  1157  		createIndex.TableExist = false
  1158  	}
  1159  	createIndex.Index = index
  1160  	createIndex.Table = tableName
  1161  
  1162  	return &Plan{
  1163  		Plan: &plan.Plan_Ddl{
  1164  			Ddl: &plan.DataDefinition{
  1165  				DdlType: plan.DataDefinition_CREATE_INDEX,
  1166  				Definition: &plan.DataDefinition_CreateIndex{
  1167  					CreateIndex: createIndex,
  1168  				},
  1169  			},
  1170  		},
  1171  	}, nil
  1172  }
  1173  
  1174  func buildDropIndex(stmt *tree.DropIndex, ctx CompilerContext) (*Plan, error) {
  1175  	dropIndex := &plan.DropIndex{}
  1176  	if len(stmt.TableName.SchemaName) == 0 {
  1177  		dropIndex.Database = ctx.DefaultDatabase()
  1178  	} else {
  1179  		dropIndex.Database = string(stmt.TableName.SchemaName)
  1180  	}
  1181  
  1182  	// check table
  1183  	dropIndex.Table = string(stmt.TableName.ObjectName)
  1184  	_, tableDef := ctx.Resolve(dropIndex.Database, dropIndex.Table)
  1185  	if tableDef == nil {
  1186  		return nil, moerr.NewNoSuchTable(ctx.GetContext(), dropIndex.Database, dropIndex.Table)
  1187  	}
  1188  
  1189  	// check index
  1190  	dropIndex.IndexName = string(stmt.Name)
  1191  	found := false
  1192  
  1193  	for _, indexdef := range tableDef.Indexes {
  1194  		if dropIndex.IndexName == indexdef.IndexName {
  1195  			dropIndex.IndexTableName = indexdef.IndexTableName
  1196  			found = true
  1197  			break
  1198  		}
  1199  	}
  1200  
  1201  	if !found {
  1202  		return nil, moerr.NewInternalError(ctx.GetContext(), "not found index: %s", dropIndex.IndexName)
  1203  	}
  1204  
  1205  	return &Plan{
  1206  		Plan: &plan.Plan_Ddl{
  1207  			Ddl: &plan.DataDefinition{
  1208  				DdlType: plan.DataDefinition_DROP_INDEX,
  1209  				Definition: &plan.DataDefinition_DropIndex{
  1210  					DropIndex: dropIndex,
  1211  				},
  1212  			},
  1213  		},
  1214  	}, nil
  1215  }
  1216  
  1217  // Get tabledef(col, viewsql, properties) for alterview.
  1218  func buildAlterView(stmt *tree.AlterView, ctx CompilerContext) (*Plan, error) {
  1219  	viewName := string(stmt.Name.ObjectName)
  1220  	alterView := &plan.AlterView{
  1221  		IfExists: stmt.IfExists,
  1222  		TableDef: &plan.TableDef{
  1223  			Name: viewName,
  1224  		},
  1225  	}
  1226  	// get database name
  1227  	if len(stmt.Name.SchemaName) == 0 {
  1228  		alterView.Database = ""
  1229  	} else {
  1230  		alterView.Database = string(stmt.Name.SchemaName)
  1231  	}
  1232  	if alterView.Database == "" {
  1233  		alterView.Database = ctx.DefaultDatabase()
  1234  	}
  1235  
  1236  	//step 1: check the view exists or not
  1237  	_, oldViewDef := ctx.Resolve(alterView.Database, viewName)
  1238  	if oldViewDef == nil {
  1239  		if !alterView.IfExists {
  1240  			return nil, moerr.NewBadView(ctx.GetContext(),
  1241  				alterView.Database,
  1242  				viewName)
  1243  		}
  1244  	} else {
  1245  		if oldViewDef.ViewSql == nil {
  1246  			return nil, moerr.NewBadView(ctx.GetContext(),
  1247  				alterView.Database,
  1248  				viewName)
  1249  		}
  1250  	}
  1251  
  1252  	//step 2: generate new view def
  1253  	ctx.SetBuildingAlterView(true, alterView.Database, viewName)
  1254  	//restore
  1255  	defer func() {
  1256  		ctx.SetBuildingAlterView(false, "", "")
  1257  	}()
  1258  	tableDef, err := genViewTableDef(ctx, stmt.AsSource)
  1259  	if err != nil {
  1260  		return nil, err
  1261  	}
  1262  
  1263  	alterView.TableDef.Cols = tableDef.Cols
  1264  	alterView.TableDef.ViewSql = tableDef.ViewSql
  1265  	alterView.TableDef.Defs = tableDef.Defs
  1266  
  1267  	return &Plan{
  1268  		Plan: &plan.Plan_Ddl{
  1269  			Ddl: &plan.DataDefinition{
  1270  				DdlType: plan.DataDefinition_ALTER_VIEW,
  1271  				Definition: &plan.DataDefinition_AlterView{
  1272  					AlterView: alterView,
  1273  				},
  1274  			},
  1275  		},
  1276  	}, nil
  1277  }