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