diff --git a/enginetest/queries/index_queries.go b/enginetest/queries/index_queries.go index 99d9b56633..6327585153 100644 --- a/enginetest/queries/index_queries.go +++ b/enginetest/queries/index_queries.go @@ -4533,4 +4533,24 @@ var IndexQueries = []ScriptTest{ }, }, }, + { + Name: "functional indices warning", + SetUpScript: []string{ + "CREATE TABLE test (i int, b int)", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "CREATE INDEX idx ON test ((i + b))", + Expected: []sql.Row{ + {types.NewOkResult(0)}, + }, + }, + { + Query: "SHOW WARNINGS", + Expected: []sql.Row{ + {"Error", 0, "Index not created, functional indexes not implemented"}, + }, + }, + }, + }, } diff --git a/sql/plan/alter_index.go b/sql/plan/alter_index.go index f164c71a92..c2d8ac6158 100644 --- a/sql/plan/alter_index.go +++ b/sql/plan/alter_index.go @@ -58,6 +58,9 @@ type AlterIndex struct { targetSchema sql.Schema // Columns contains the column names (and possibly lengths) when creating an index Columns []sql.IndexColumn + // Expression holds the expression when creating an index + // TODO: Not currently implemented. Returns a no-op & warning if used + Expression sql.Expression // TODO: This should just use sql.IndexDef // Using states whether you're using BTREE, HASH, or non Using sql.IndexUsing @@ -79,7 +82,7 @@ var _ sql.Expressioner = (*AlterIndex)(nil) var _ sql.Node = (*AlterIndex)(nil) var _ sql.CollationCoercible = (*AlterIndex)(nil) -func NewAlterCreateIndex(db sql.Database, table sql.TableNode, ifNotExists bool, indexName string, using sql.IndexUsing, constraint sql.IndexConstraint, columns []sql.IndexColumn, comment string) *AlterIndex { +func NewAlterCreateIndex(db sql.Database, table sql.TableNode, ifNotExists bool, indexName string, using sql.IndexUsing, constraint sql.IndexConstraint, columns []sql.IndexColumn, expression sql.Expression, comment string) *AlterIndex { return &AlterIndex{ Action: IndexAction_Create, Db: db, @@ -89,6 +92,7 @@ func NewAlterCreateIndex(db sql.Database, table sql.TableNode, ifNotExists bool, Using: using, Constraint: constraint, Columns: columns, + Expression: expression, Comment: comment, } } diff --git a/sql/planbuilder/ddl.go b/sql/planbuilder/ddl.go index 268763caf2..a9cb2165b4 100644 --- a/sql/planbuilder/ddl.go +++ b/sql/planbuilder/ddl.go @@ -617,6 +617,7 @@ func (b *Builder) buildAlterTableClause(inScope *scope, ddl *ast.DDL) []*scope { sql.IndexUsing_BTree, sql.IndexConstraint_Unique, []sql.IndexColumn{{Name: column.Name.String()}}, + nil, "", ) @@ -981,6 +982,11 @@ func (b *Builder) buildAlterIndex(inScope *scope, ddl *ast.DDL, table *plan.Reso columns := b.gatherIndexColumns(ddl.IndexSpec.Columns) + var indexExpr sql.Expression + if ddl.IndexSpec.Expression != nil { + indexExpr = b.buildScalar(inScope, ddl.IndexSpec.Expression) + } + var comment string for _, option := range ddl.IndexSpec.Options { if strings.ToLower(option.Name) == strings.ToLower(ast.KeywordString(ast.COMMENT_KEYWORD)) { @@ -1007,6 +1013,7 @@ func (b *Builder) buildAlterIndex(inScope *scope, ddl *ast.DDL, table *plan.Reso using, constraint, columns, + indexExpr, comment, ) outScope.node = b.modifySchemaTarget(inScope, createIndex, table.Schema()) diff --git a/sql/rowexec/ddl_iters.go b/sql/rowexec/ddl_iters.go index aaac4a0c40..fe6f80e1b5 100644 --- a/sql/rowexec/ddl_iters.go +++ b/sql/rowexec/ddl_iters.go @@ -2109,6 +2109,13 @@ func (b *BaseBuilder) executeAlterIndex(ctx *sql.Context, n *plan.AlterIndex) er switch n.Action { case plan.IndexAction_Create: + if n.Expression != nil { + // Dolt doesn't currently support creating indices with expression arguments. + // If we parse a query attempting to do so, we offer a warning and no-op + ctx.Session.Warn(&sql.Warning{Level: "Error", Message: "Index not created, functional indexes not implemented"}) + return nil + } + if len(n.Columns) == 0 { return plan.ErrCreateIndexMissingColumns.New() }