partbound-error.patch
text/x-diff
Filename: partbound-error.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/parser/parse_relation.c | 9 | 1 |
| src/backend/parser/parse_utilcmd.c | 10 | 2 |
| src/test/regress/expected/create_table.out | 31 | 0 |
| src/test/regress/sql/create_table.sql | 16 | 0 |
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index f3b6d193aa..6b248f116f 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -3259,6 +3259,9 @@ errorMissingRTE(ParseState *pstate, RangeVar *relation)
* If we found a match that doesn't meet those criteria, assume the
* problem is illegal use of a relation outside its scope, as in the
* MySQL-ism "SELECT ... FROM a, b LEFT JOIN c ON (a.x = c.y)".
+ *
+ * Also, in the context of parsing a partition bound, produce a more
+ * helpful error message.
*/
if (rte && rte->alias &&
strcmp(rte->eref->aliasname, relation->relname) != 0 &&
@@ -3267,7 +3270,12 @@ errorMissingRTE(ParseState *pstate, RangeVar *relation)
&sublevels_up) == rte)
badAlias = rte->eref->aliasname;
- if (rte)
+ if (pstate->p_expr_kind == EXPR_KIND_PARTITION_BOUND)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("invalid reference in partition bound expression for table \"%s\"",
+ relation->relname)));
+ else if (rte)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("invalid reference to FROM-clause entry for table \"%s\"",
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index a37d1f18be..ee129ba18f 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -3750,8 +3750,16 @@ transformPartitionRangeBounds(ParseState *pstate, List *blist,
IsA(linitial(cref->fields), String))
cname = strVal(linitial(cref->fields));
- Assert(cname != NULL);
- if (strcmp("minvalue", cname) == 0)
+ if (cname == NULL)
+ {
+ /*
+ * No field names have been found, meaning that there
+ * is not much to do with special value handling. Instead
+ * let the expression transformation handle any errors and
+ * limitations.
+ */
+ }
+ else if (strcmp("minvalue", cname) == 0)
{
prd = makeNode(PartitionRangeDatum);
prd->kind = PARTITION_RANGE_DATUM_MINVALUE;
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index d51e547278..0b3c9fb1ff 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -494,6 +494,10 @@ CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somena
ERROR: column "somename" does not exist
LINE 1: ...expr_fail PARTITION OF list_parted FOR VALUES IN (somename);
^
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename.somename);
+ERROR: invalid reference in partition bound expression for table "somename"
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename.somename.somename);
+ERROR: invalid reference in partition bound expression for table "somename"
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a);
ERROR: cannot use column references in partition bound expression
LINE 1: ..._bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a);
@@ -558,6 +562,33 @@ DROP TABLE bigintp;
CREATE TABLE range_parted (
a date
) PARTITION BY RANGE (a);
+-- forbidden expressions for partition bounds
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (a) TO (1);
+ERROR: cannot use column references in partition bound expression
+LINE 2: FOR VALUES FROM (a) TO (1);
+ ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (somename) TO (1);
+ERROR: column "somename" does not exist
+LINE 2: FOR VALUES FROM (somename) TO (1);
+ ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (somename.somename) TO (1);
+ERROR: invalid reference in partition bound expression for table "somename"
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (somename.somename.somename) TO (1);
+ERROR: invalid reference in partition bound expression for table "somename"
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM ((select 1)) TO (10);
+ERROR: cannot use subquery in partition bound
+LINE 2: FOR VALUES FROM ((select 1)) TO (10);
+ ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (generate_series(4, 6)) TO (10);
+ERROR: set-returning functions are not allowed in partition bound
+LINE 2: FOR VALUES FROM (generate_series(4, 6)) TO (10);
+ ^
-- trying to specify list for range partitioned table
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES IN ('a');
ERROR: invalid bound specification for a range partition
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 4091c19cf0..7ffa187eb4 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -452,6 +452,8 @@ CREATE TABLE part_null PARTITION OF list_parted FOR VALUES IN (null);
-- forbidden expressions for partition bound
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename);
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename.somename);
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename.somename.somename);
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a);
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(a));
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((select 1));
@@ -497,6 +499,20 @@ CREATE TABLE range_parted (
a date
) PARTITION BY RANGE (a);
+-- forbidden expressions for partition bounds
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (a) TO (1);
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (somename) TO (1);
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (somename.somename) TO (1);
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (somename.somename.somename) TO (1);
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM ((select 1)) TO (10);
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+ FOR VALUES FROM (generate_series(4, 6)) TO (10);
+
-- trying to specify list for range partitioned table
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES IN ('a');
-- trying to specify modulus and remainder for range partitioned table