On Mon, Mar 11, 2019 at 03:44:39PM +0900, Amit Langote wrote: > We could make the error message more meaningful depending on the context, > but maybe it'd better be pursue it as a separate project.
Yeah, I noticed that stuff when working on it this afternoon. The error message does not completely feel right even in your produced tests. Out of curiosity I have been working on this thing myself, and it is possible to have a context-related message. Please see attached, that's in my opinion less confusing, and of course debatable. Still this approach does not feel completely right either as that means hijacking the code path which generates a generic message for missing RTEs. :( -- Michael
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
signature.asc
Description: PGP signature