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

Attachment: signature.asc
Description: PGP signature

Reply via email to