diff --git a/pkg/ccl/sqlccl/csv.go b/pkg/ccl/sqlccl/csv.go index 1a91ffe7c0e6..00db711834be 100644 --- a/pkg/ccl/sqlccl/csv.go +++ b/pkg/ccl/sqlccl/csv.go @@ -342,7 +342,7 @@ func makeSimpleTableDescriptor( } } semaCtx := tree.SemaContext{} - evalCtx := tree.EvalContext{} + evalCtx := tree.EvalContext{Settings: st} tableDesc, err := sql.MakeTableDesc( ctx, nil, /* txn */ diff --git a/pkg/sql/alter_table.go b/pkg/sql/alter_table.go index 3f883bb2fbfc..1875783c26ff 100644 --- a/pkg/sql/alter_table.go +++ b/pkg/sql/alter_table.go @@ -143,7 +143,7 @@ func (n *alterTableNode) startExec(params runParams) error { return err } if d.PartitionBy != nil { - partitioning, _, err := createPartitionedBy(params.ctx, params.p.ExecCfg().Settings, + partitioning, _, err := createPartitionedBy( params.evalCtx, n.tableDesc, &idx, d.PartitionBy) if err != nil { return err @@ -445,7 +445,7 @@ func (n *alterTableNode) startExec(params runParams) error { case *tree.AlterTablePartitionBy: previousTableDesc := *n.tableDesc - partitioning, _, err := createPartitionedBy(params.ctx, params.p.ExecCfg().Settings, + partitioning, _, err := createPartitionedBy( ¶ms.p.evalCtx, n.tableDesc, &n.tableDesc.PrimaryIndex, t.PartitionBy) if err != nil { return err diff --git a/pkg/sql/create_index.go b/pkg/sql/create_index.go index ef8623c981fe..66d8ed472f2c 100644 --- a/pkg/sql/create_index.go +++ b/pkg/sql/create_index.go @@ -72,7 +72,7 @@ func (n *createIndexNode) startExec(params runParams) error { return err } if n.n.PartitionBy != nil { - partitioning, _, err := createPartitionedBy(params.ctx, params.p.ExecCfg().Settings, + partitioning, _, err := createPartitionedBy( params.evalCtx, n.tableDesc, &indexDesc, n.n.PartitionBy) if err != nil { return err diff --git a/pkg/sql/create_table.go b/pkg/sql/create_table.go index e02b1184924d..68219cbef109 100644 --- a/pkg/sql/create_table.go +++ b/pkg/sql/create_table.go @@ -131,10 +131,13 @@ func (n *createTableNode) startExec(params runParams) error { var affected map[sqlbase.ID]*sqlbase.TableDescriptor creationTime := params.p.txn.OrigTimestamp() if n.n.As() { - desc, err = makeTableDescIfAs(n.n, n.dbDesc.ID, id, creationTime, planColumns(n.sourcePlan), privs, ¶ms.p.semaCtx, params.evalCtx) + desc, err = makeTableDescIfAs( + n.n, n.dbDesc.ID, id, creationTime, planColumns(n.sourcePlan), privs, ¶ms.p.semaCtx, + params.evalCtx) } else { affected = make(map[sqlbase.ID]*sqlbase.TableDescriptor) - desc, err = params.p.makeTableDesc(params.ctx, n.n, n.dbDesc.ID, id, creationTime, privs, affected) + desc, err = params.p.makeTableDesc( + params.ctx, n.n, n.dbDesc.ID, id, creationTime, privs, affected) } if err != nil { return err @@ -817,7 +820,6 @@ func valueEncodePartitionTuple( } func createPartitionedByImpl( - ctx context.Context, evalCtx *tree.EvalContext, tableDesc *sqlbase.TableDescriptor, indexDesc *sqlbase.IndexDescriptor, @@ -897,7 +899,7 @@ func createPartitionedByImpl( if l.Subpartition != nil { newColOffset := colOffset + int(partDesc.NumColumns) subpartitioning, subCheckExpr, err := createPartitionedByImpl( - ctx, evalCtx, tableDesc, indexDesc, l.Subpartition, newColOffset) + evalCtx, tableDesc, indexDesc, l.Subpartition, newColOffset) if err != nil { return partDesc, nil, err } @@ -932,20 +934,18 @@ func createPartitionedByImpl( // returns a CHECK constraint that can be used to prevent rows that do not // belong to any partition from being inserted into the index's table. func createPartitionedBy( - ctx context.Context, - st *cluster.Settings, evalCtx *tree.EvalContext, tableDesc *sqlbase.TableDescriptor, indexDesc *sqlbase.IndexDescriptor, partBy *tree.PartitionBy, ) (sqlbase.PartitioningDescriptor, *sqlbase.TableDescriptor_CheckConstraint, error) { - if !st.Version.IsMinSupported(cluster.VersionPartitioning) { + if !evalCtx.Settings.Version.IsMinSupported(cluster.VersionPartitioning) { return sqlbase.PartitioningDescriptor{}, nil, errors.New("cluster version does not support partitioning") } partitioning, checkExpr, err := createPartitionedByImpl( - ctx, evalCtx, tableDesc, indexDesc, partBy, 0 /* colOffset */) + evalCtx, tableDesc, indexDesc, partBy, 0 /* colOffset */) if err != nil { return partitioning, nil, err } @@ -1049,6 +1049,15 @@ func makeTableDescIfAs( desc.AddColumn(*col) } + if p.Interleave != nil { + return desc, pgerror.UnimplementedWithIssueError(20940, + "INTERLEAVE IN PARENT is currently unsupported with CREATE TABLE AS") + } + if p.PartitionBy != nil { + return desc, pgerror.UnimplementedWithIssueError(20940, + "PARTITION BY is currently unsupported with CREATE TABLE AS") + } + return desc, desc.AllocateIDs() } @@ -1121,7 +1130,7 @@ func MakeTableDesc( return desc, err } if d.PartitionBy != nil { - partitioning, _, err := createPartitionedBy(ctx, st, evalCtx, &desc, &idx, d.PartitionBy) + partitioning, _, err := createPartitionedBy(evalCtx, &desc, &idx, d.PartitionBy) if err != nil { return desc, err } @@ -1145,7 +1154,7 @@ func MakeTableDesc( return desc, err } if d.PartitionBy != nil { - partitioning, _, err := createPartitionedBy(ctx, st, evalCtx, &desc, &idx, d.PartitionBy) + partitioning, _, err := createPartitionedBy(evalCtx, &desc, &idx, d.PartitionBy) if err != nil { return desc, err } @@ -1208,7 +1217,7 @@ func MakeTableDesc( if n.PartitionBy != nil { partitioning, check, err := createPartitionedBy( - ctx, st, evalCtx, &desc, &desc.PrimaryIndex, n.PartitionBy) + evalCtx, &desc, &desc.PrimaryIndex, n.PartitionBy) if err != nil { return desc, err } diff --git a/pkg/sql/logictest/testdata/logic_test/interleaved b/pkg/sql/logictest/testdata/logic_test/interleaved index 705457cda9b3..c4cc447ad811 100644 --- a/pkg/sql/logictest/testdata/logic_test/interleaved +++ b/pkg/sql/logictest/testdata/logic_test/interleaved @@ -377,3 +377,9 @@ END statement error duplicate key value \(p_id,c_id\)=\(1,1\) violates unique constraint "primary" INSERT INTO c20067 VALUES (1, 1, 'John Doe') + +# Placeholder error so CREATE TABLE AS parses with INTERLEAVE IN PARENT but +# fails with a friendly error + +statement error unimplemented: INTERLEAVE IN PARENT is currently unsupported with CREATE TABLE AS +CREATE TABLE err (a) INTERLEAVE IN PARENT p1_1 (i) AS VALUES (1) diff --git a/pkg/sql/logictest/testdata/logic_test/partitioning b/pkg/sql/logictest/testdata/logic_test/partitioning index 51680a039eda..9a6ebaa6ba4b 100644 --- a/pkg/sql/logictest/testdata/logic_test/partitioning +++ b/pkg/sql/logictest/testdata/logic_test/partitioning @@ -250,6 +250,10 @@ CREATE TABLE t (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a) ( PARTITION p1 VALUES IN ($1) ) +statement error unimplemented: PARTITION BY is currently unsupported with CREATE TABLE AS +CREATE TABLE t (a) PARTITION BY LIST (a) (PARTITION p1 VALUES IN (1)) AS VALUES (1) + + statement ok CREATE TABLE ok1 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTITION BY LIST (a) ( PARTITION p1 VALUES IN (1), @@ -518,7 +522,6 @@ CREATE TABLE IF NOT EXISTS ok12 (a INT, b INT, c INT, PRIMARY KEY (a, b)) PARTIT PARTITION p2 VALUES IN (2) ) - query TT SHOW CREATE TABLE ok12 ---- diff --git a/pkg/sql/parser/parse_test.go b/pkg/sql/parser/parse_test.go index c6286b36a928..06652a5cb204 100644 --- a/pkg/sql/parser/parse_test.go +++ b/pkg/sql/parser/parse_test.go @@ -178,6 +178,8 @@ func TestParse(t *testing.T) { {`CREATE TABLE a (b INT, c STRING, FAMILY foo (b), FAMILY (c))`}, {`CREATE TABLE a (b INT) INTERLEAVE IN PARENT foo (c, d)`}, {`CREATE TABLE a (b INT) INTERLEAVE IN PARENT foo (c) CASCADE`}, + {`CREATE TABLE a (b) INTERLEAVE IN PARENT foo (b) AS VALUES (1)`}, + {`CREATE TABLE IF NOT EXISTS a (b) INTERLEAVE IN PARENT foo (b) AS VALUES (1)`}, {`CREATE TABLE a.b (b INT)`}, {`CREATE TABLE IF NOT EXISTS a (b INT)`}, @@ -199,6 +201,8 @@ func TestParse(t *testing.T) { }, {`CREATE TABLE a () INTERLEAVE IN PARENT b (c) PARTITION BY LIST (d) (PARTITION e VALUES IN (1))`}, {`CREATE TABLE IF NOT EXISTS a () PARTITION BY LIST (b) (PARTITION c VALUES IN (1))`}, + {`CREATE TABLE a (b) PARTITION BY LIST (c) (PARTITION d VALUES IN (1)) AS VALUES (1)`}, + {`CREATE TABLE IF NOT EXISTS a (b) PARTITION BY LIST (c) (PARTITION d VALUES IN (1)) AS VALUES (1)`}, {`CREATE TABLE a (INDEX (b) PARTITION BY LIST (c) (PARTITION d VALUES IN (1)))`}, {`CREATE TABLE a (UNIQUE (b) PARTITION BY LIST (c) (PARTITION d VALUES IN (1)))`}, {`CREATE INDEX ON a (b) PARTITION BY LIST (c) (PARTITION d VALUES IN (1))`}, diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 7742e31c0179..9c52a6c4626e 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -2963,13 +2963,29 @@ create_table_stmt: } create_table_as_stmt: - CREATE TABLE any_name opt_column_list AS select_stmt + CREATE TABLE any_name opt_column_list opt_interleave opt_partition_by AS select_stmt { - $$.val = &tree.CreateTable{Table: $3.normalizableTableName(), IfNotExists: false, Interleave: nil, Defs: nil, AsSource: $6.slct(), AsColumnNames: $4.nameList()} + $$.val = &tree.CreateTable{ + Table: $3.normalizableTableName(), + IfNotExists: false, + Interleave: $5.interleave(), + Defs: nil, + AsSource: $8.slct(), + AsColumnNames: $4.nameList(), + PartitionBy: $6.partitionBy(), + } } -| CREATE TABLE IF NOT EXISTS any_name opt_column_list AS select_stmt +| CREATE TABLE IF NOT EXISTS any_name opt_column_list opt_interleave opt_partition_by AS select_stmt { - $$.val = &tree.CreateTable{Table: $6.normalizableTableName(), IfNotExists: true, Interleave: nil, Defs: nil, AsSource: $9.slct(), AsColumnNames: $7.nameList()} + $$.val = &tree.CreateTable{ + Table: $6.normalizableTableName(), + IfNotExists: true, + Interleave: $8.interleave(), + Defs: nil, + AsSource: $11.slct(), + AsColumnNames: $7.nameList(), + PartitionBy: $9.partitionBy(), + } } opt_table_elem_list: diff --git a/pkg/sql/sem/tree/create.go b/pkg/sql/sem/tree/create.go index 0b295b3dea3a..221852353c89 100644 --- a/pkg/sql/sem/tree/create.go +++ b/pkg/sql/sem/tree/create.go @@ -833,6 +833,12 @@ func (node *CreateTable) Format(buf *bytes.Buffer, f FmtFlags) { FormatNode(buf, f, node.AsColumnNames) buf.WriteByte(')') } + if node.Interleave != nil { + FormatNode(buf, f, node.Interleave) + } + if node.PartitionBy != nil { + FormatNode(buf, f, node.PartitionBy) + } buf.WriteString(" AS ") FormatNode(buf, f, node.AsSource) } else {