From 941e357fbac6defd014843dc72f54a1f49b53dcd Mon Sep 17 00:00:00 2001 From: Daniel Harrison Date: Mon, 18 Dec 2017 17:33:30 -0500 Subject: [PATCH] sql: add parsing for interleaved & partitioning with CREATE TABLE AS CREATE TABLE a (b) INTERLEAVE IN PARENT ... AS ... CREATE TABLE a (b) PARTITION BY ... AS ... The interleave/partition clauses could also plausably go after the AS, but I felt like this was more parallel to CREATE TABLE where they go right after the column defs. (Plus there's all sorts of grammar conflicts with putting it after the AS). Implementation is blocked on #20940, but in the meantime, this will return a friendly error message. Also cleans up some unnecessary function parameters that I noticed were being passed around. For #20178 Release note: None --- pkg/ccl/sqlccl/csv.go | 2 +- pkg/sql/alter_table.go | 4 +-- pkg/sql/create_index.go | 2 +- pkg/sql/create_table.go | 31 ++++++++++++------- .../logictest/testdata/logic_test/interleaved | 6 ++++ .../testdata/logic_test/partitioning | 5 ++- pkg/sql/parser/parse_test.go | 4 +++ pkg/sql/parser/sql.y | 24 +++++++++++--- pkg/sql/sem/tree/create.go | 6 ++++ 9 files changed, 64 insertions(+), 20 deletions(-) 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 {