summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-12-23 12:53:13 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-12-23 12:53:13 -0500
commit281dd22ac0150603ab82c052a9b5995cc2c5fb8f (patch)
treed020e70c2a5632ca60dceb38e4dc84343f717652
parent31dfa40a834177b8e989a59252ee3ce1a3309075 (diff)
Disallow partition key expressions that return pseudo-types.
This wasn't checked originally, but it should have been, because in general pseudo-types can't be stored to and retrieved from disk. Notably, partition bound values of type "record" would not be interpretable by another session. In v12 and HEAD, add another flag to CheckAttributeType's repertoire so that it can produce a specific error message for this case. That's infeasible in older branches without an ABI break, so fall back to a slightly-less-nicely-worded error message in v10 and v11. Problem noted by Amit Langote, though this patch is not his initial solution. Back-patch to v10 where partitioning was introduced. Discussion: https://postgr.es/m/CA+HiwqFUzjfj9HEsJtYWcr1SgQ_=iCAvQ=O2Sx6aQxoDu4OiHw@mail.gmail.com
-rw-r--r--src/backend/commands/tablecmds.c10
-rw-r--r--src/test/regress/expected/create_table.out13
-rw-r--r--src/test/regress/sql/create_table.sql12
3 files changed, 33 insertions, 2 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 9a1ef78a1fb..d207bc299f9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -14403,6 +14403,16 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
attcollation = exprCollation(expr);
/*
+ * The expression must be of a storable type (e.g., not RECORD).
+ * The test is the same as for whether a table column is of a safe
+ * type (which is why we needn't check for the non-expression
+ * case).
+ */
+ CheckAttributeType("partition key",
+ atttype, attcollation,
+ NIL, false);
+
+ /*
* Strip any top-level COLLATE clause. This ensures that we treat
* "x COLLATE y" and "(x COLLATE y)" alike.
*/
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index d20ba3dbdf5..f44024aedcc 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -334,7 +334,7 @@ CREATE TABLE partitioned (
ERROR: cannot use subquery in partition key expression
CREATE TABLE partitioned (
a int
-) PARTITION BY RANGE (('a'));
+) PARTITION BY RANGE ((42));
ERROR: cannot use constant expression as partition key
CREATE FUNCTION const_func () RETURNS int AS $$ SELECT 1; $$ LANGUAGE SQL IMMUTABLE;
CREATE TABLE partitioned (
@@ -357,6 +357,17 @@ CREATE TABLE partitioned (
a int
) PARTITION BY RANGE (xmin);
ERROR: cannot use system column "xmin" in partition key
+-- cannot use pseudotypes
+CREATE TABLE partitioned (
+ a int,
+ b int
+) PARTITION BY RANGE (((a, b)));
+ERROR: column "partition key" has pseudo-type record
+CREATE TABLE partitioned (
+ a int,
+ b int
+) PARTITION BY RANGE (a, ('unknown'));
+ERROR: column "partition key" has pseudo-type unknown
-- functions in key must be immutable
CREATE FUNCTION immut_func (a int) RETURNS int AS $$ SELECT a + random()::int; $$ LANGUAGE SQL;
CREATE TABLE partitioned (
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 601a4b9dc3e..dc5b729ad8e 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -343,7 +343,7 @@ CREATE TABLE partitioned (
CREATE TABLE partitioned (
a int
-) PARTITION BY RANGE (('a'));
+) PARTITION BY RANGE ((42));
CREATE FUNCTION const_func () RETURNS int AS $$ SELECT 1; $$ LANGUAGE SQL IMMUTABLE;
CREATE TABLE partitioned (
@@ -366,6 +366,16 @@ CREATE TABLE partitioned (
a int
) PARTITION BY RANGE (xmin);
+-- cannot use pseudotypes
+CREATE TABLE partitioned (
+ a int,
+ b int
+) PARTITION BY RANGE (((a, b)));
+CREATE TABLE partitioned (
+ a int,
+ b int
+) PARTITION BY RANGE (a, ('unknown'));
+
-- functions in key must be immutable
CREATE FUNCTION immut_func (a int) RETURNS int AS $$ SELECT a + random()::int; $$ LANGUAGE SQL;
CREATE TABLE partitioned (