Skip to content

Commit

Permalink
ddl: support create table with expression index (pingcap#18125)
Browse files Browse the repository at this point in the history
* done

Signed-off-by: wjhuang2016 <[email protected]>

* fix

Signed-off-by: wjhuang2016 <[email protected]>

* add

Signed-off-by: wjhuang2016 <[email protected]>

* save

Signed-off-by: wjhuang2016 <[email protected]>

* done

Signed-off-by: wjhuang2016 <[email protected]>

* Update ddl/ddl_api.go

Co-authored-by: Lynn <[email protected]>

* 2

Signed-off-by: wjhuang2016 <[email protected]>

* done

Signed-off-by: wjhuang2016 <[email protected]>

* fix

Signed-off-by: wjhuang2016 <[email protected]>

Co-authored-by: Lynn <[email protected]>
Co-authored-by: ti-srebot <[email protected]>
  • Loading branch information
3 people authored Sep 10, 2020
1 parent 71d7262 commit c7a836b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 15 deletions.
5 changes: 3 additions & 2 deletions ddl/db_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2080,8 +2080,6 @@ func (s *testIntegrationSuite7) TestAddExpressionIndex(c *C) {
tk.MustExec("use test")
tk.MustExec("drop table if exists t;")

tk.MustGetErrCode("create table t(a int, b int, index((a+b)));", errno.ErrNotSupportedYet)

tk.MustExec("create table t (a int, b real);")
tk.MustExec("insert into t values (1, 2.1);")
tk.MustExec("alter table t add index idx((a+b));")
Expand Down Expand Up @@ -2126,6 +2124,9 @@ func (s *testIntegrationSuite7) TestAddExpressionIndex(c *C) {
tk.MustExec("alter table t1 add unique index ei_ab ((concat(a, b)));")
tk.MustExec("alter table t1 alter index ei_ab invisible;")

tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, key((a+1)), key((a+2)), key idx((a+3)), key((a+4)));")

// Test experiment switch.
config.UpdateGlobal(func(conf *config.Config) {
conf.Experimental.AllowsExpressionIndex = false
Expand Down
47 changes: 40 additions & 7 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constra
switch v.Tp {
case ast.ConstraintPrimaryKey:
for _, key := range v.Keys {
if key.Expr != nil {
continue
}
c, ok := colMap[key.Column.Name.L]
if !ok {
continue
Expand All @@ -251,6 +254,9 @@ func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constra
}
case ast.ConstraintUniq, ast.ConstraintUniqIndex, ast.ConstraintUniqKey:
for i, key := range v.Keys {
if key.Expr != nil {
continue
}
c, ok := colMap[key.Column.Name.L]
if !ok {
continue
Expand All @@ -269,6 +275,9 @@ func setColumnFlagWithConstraint(colMap map[string]*table.Column, v *ast.Constra
}
case ast.ConstraintKey, ast.ConstraintIndex:
for i, key := range v.Keys {
if key.Expr != nil {
continue
}
c, ok := colMap[key.Column.Name.L]
if !ok {
continue
Expand Down Expand Up @@ -888,7 +897,7 @@ func checkPriKeyConstraint(col *table.Column, hasDefaultValue, hasNullFlag bool,
// Such as: create table t1 (id int , age int, primary key(id))
if !mysql.HasPriKeyFlag(col.Flag) && outPriKeyConstraint != nil {
for _, key := range outPriKeyConstraint.Keys {
if key.Column.Name.L != col.Name.L {
if key.Expr == nil && key.Column.Name.L != col.Name.L {
continue
}
col.Flag |= mysql.PriKeyFlag
Expand Down Expand Up @@ -1079,7 +1088,15 @@ func checkDuplicateConstraint(namesMap map[string]bool, name string, foreign boo

func setEmptyConstraintName(namesMap map[string]bool, constr *ast.Constraint, foreign bool) {
if constr.Name == "" && len(constr.Keys) > 0 {
colName := constr.Keys[0].Column.Name.L
var colName string
for _, keyPart := range constr.Keys {
if keyPart.Expr != nil {
colName = "expression_index"
}
}
if colName == "" {
colName = constr.Keys[0].Column.Name.L
}
constrName := colName
i := 2
if strings.EqualFold(constrName, mysql.PrimaryKeyName) {
Expand Down Expand Up @@ -1266,11 +1283,25 @@ func buildTableInfo(
Charset: charset,
Collate: collate,
}
tblColumns := make([]*table.Column, 0, len(cols))
for _, v := range cols {
v.ID = allocateColumnID(tbInfo)
tbInfo.Columns = append(tbInfo.Columns, v.ToInfo())
tblColumns = append(tblColumns, table.ToColumn(v.ToInfo()))
}
for _, constr := range constraints {
// Build hidden columns if necessary.
hiddenCols, err := buildHiddenColumnInfo(ctx, constr.Keys, model.NewCIStr(constr.Name), tbInfo, tblColumns)
if err != nil {
return nil, err
}
for _, hiddenCol := range hiddenCols {
hiddenCol.State = model.StatePublic
hiddenCol.ID = allocateColumnID(tbInfo)
hiddenCol.Offset = len(tbInfo.Columns)
tbInfo.Columns = append(tbInfo.Columns, hiddenCol)
tblColumns = append(tblColumns, table.ToColumn(hiddenCol))
}
if constr.Tp == ast.ConstraintForeignKey {
for _, fk := range tbInfo.ForeignKeys {
if fk.Name.L == strings.ToLower(constr.Name) {
Expand Down Expand Up @@ -1321,6 +1352,9 @@ func buildTableInfo(
if err != nil {
return nil, errors.Trace(err)
}
if len(hiddenCols) > 0 {
addIndexColumnFlag(tbInfo, idxInfo)
}
// check if the index is primary or unique.
switch constr.Tp {
case ast.ConstraintPrimaryKey:
Expand Down Expand Up @@ -4400,16 +4434,15 @@ func (d *ddl) CreatePrimaryKey(ctx sessionctx.Context, ti ast.Ident, indexName m
return errors.Trace(err)
}

func buildHiddenColumnInfo(ctx sessionctx.Context, t table.Table, indexPartSpecifications []*ast.IndexPartSpecification, indexName model.CIStr) ([]*model.ColumnInfo, error) {
tblInfo := t.Meta()
func buildHiddenColumnInfo(ctx sessionctx.Context, indexPartSpecifications []*ast.IndexPartSpecification, indexName model.CIStr, tblInfo *model.TableInfo, existCols []*table.Column) ([]*model.ColumnInfo, error) {
hiddenCols := make([]*model.ColumnInfo, 0, len(indexPartSpecifications))
for i, idxPart := range indexPartSpecifications {
if idxPart.Expr == nil {
continue
}
idxPart.Column = &ast.ColumnName{Name: model.NewCIStr(fmt.Sprintf("%s_%s_%d", expressionIndexPrefix, indexName, i))}
// Check whether the hidden columns have existed.
col := table.FindCol(t.Cols(), idxPart.Column.Name.L)
col := table.FindCol(existCols, idxPart.Column.Name.L)
if col != nil {
// TODO: Use expression index related error.
return nil, infoschema.ErrColumnExists.GenWithStackByArgs(col.Name.String())
Expand Down Expand Up @@ -4457,7 +4490,7 @@ func buildHiddenColumnInfo(ctx sessionctx.Context, t table.Table, indexPartSpeci
colInfo.Dependences[colName.Name.O] = struct{}{}
checkDependencies[colName.Name.O] = struct{}{}
}
if err = checkDependedColExist(checkDependencies, t.Cols()); err != nil {
if err = checkDependedColExist(checkDependencies, existCols); err != nil {
return nil, errors.Trace(err)
}
if err = checkAutoIncrementRef("", colInfo.Dependences, tblInfo); err != nil {
Expand Down Expand Up @@ -4513,7 +4546,7 @@ func (d *ddl) CreateIndex(ctx sessionctx.Context, ti ast.Ident, keyType ast.Inde
tblInfo := t.Meta()

// Build hidden columns if necessary.
hiddenCols, err := buildHiddenColumnInfo(ctx, t, indexPartSpecifications, indexName)
hiddenCols, err := buildHiddenColumnInfo(ctx, indexPartSpecifications, indexName, t.Meta(), t.Cols())
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions expression/function_traits.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ var IllegalFunctions4GeneratedColumns = map[string]struct{}{
ast.MasterPosWait: {},
ast.NameConst: {},
ast.ReleaseLock: {},
ast.RowFunc: {},
ast.RowCount: {},
ast.Schema: {},
ast.SessionUser: {},
Expand Down
9 changes: 3 additions & 6 deletions planner/core/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ func checkAutoIncrementOp(colDef *ast.ColumnDef, index int) (bool, error) {

func isConstraintKeyTp(constraints []*ast.Constraint, colDef *ast.ColumnDef) bool {
for _, c := range constraints {
if c.Keys[0].Expr != nil {
continue
}
// If the constraint as follows: primary key(c1, c2)
// we only support c1 column can be auto_increment.
if colDef.Name.Name.L != c.Keys[0].Column.Name.L {
Expand Down Expand Up @@ -463,12 +466,6 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) {
}
}
for _, constraint := range stmt.Constraints {
for _, spec := range constraint.Keys {
if spec.Expr != nil {
p.err = ErrNotSupportedYet.GenWithStackByArgs("create table with expression index")
return
}
}
switch tp := constraint.Tp; tp {
case ast.ConstraintKey, ast.ConstraintIndex, ast.ConstraintUniq, ast.ConstraintUniqKey, ast.ConstraintUniqIndex:
err := checkIndexInfo(constraint.Name, constraint.Keys)
Expand Down

0 comments on commit c7a836b

Please sign in to comment.