From 61e77542fe720edcb7b80689ca0191ea195071ec Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Fri, 22 Mar 2019 13:49:41 +0900
Subject: [PATCH 1/2] Fix crash in partition bounds

---
 src/backend/parser/parse_utilcmd.c         | 12 +++-
 src/test/regress/expected/create_table.out | 65 +++++++++++++++++++++-
 src/test/regress/sql/create_table.sql      | 26 ++++++++-
 3 files changed, 99 insertions(+), 4 deletions(-)

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..130dccb241 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -489,19 +489,35 @@ Partitions: part_null FOR VALUES IN (NULL),
             part_p2 FOR VALUES IN (2),
             part_p3 FOR VALUES IN (3)
 
--- forbidden expressions for partition bound
+-- forbidden expressions for partition bound with list partitioned table
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (somename);
 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:  missing FROM-clause entry for table "somename"
+LINE 1: ...expr_fail PARTITION OF list_parted FOR VALUES IN (somename.s...
+                                                             ^
 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);
                                                                     ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a.a);
+ERROR:  missing FROM-clause entry for table "a"
+LINE 1: ...ogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a.a);
+                                                                  ^
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(a));
 ERROR:  aggregate functions are not allowed in partition bound
 LINE 1: ...s_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(a));
                                                                ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(somename));
+ERROR:  column "somename" does not exist
+LINE 1: ..._fail PARTITION OF list_parted FOR VALUES IN (sum(somename))...
+                                                             ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(1));
+ERROR:  aggregate functions are not allowed in partition bound
+LINE 1: ...s_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(1));
+                                                               ^
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((select 1));
 ERROR:  cannot use subquery in partition bound
 LINE 1: ...expr_fail PARTITION OF list_parted FOR VALUES IN ((select 1)...
@@ -558,6 +574,53 @@ DROP TABLE bigintp;
 CREATE TABLE range_parted (
 	a date
 ) PARTITION BY RANGE (a);
+-- forbidden expressions for partition bounds with range partitioned table
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (somename) TO ('2019-01-01');
+ERROR:  column "somename" does not exist
+LINE 2:   FOR VALUES FROM (somename) TO ('2019-01-01');
+                           ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (somename.somename) TO ('2019-01-01');
+ERROR:  missing FROM-clause entry for table "somename"
+LINE 2:   FOR VALUES FROM (somename.somename) TO ('2019-01-01');
+                           ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (a) TO ('2019-01-01');
+ERROR:  cannot use column references in partition bound expression
+LINE 2:   FOR VALUES FROM (a) TO ('2019-01-01');
+                           ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (a.a) TO ('2019-01-01');
+ERROR:  missing FROM-clause entry for table "a"
+LINE 2:   FOR VALUES FROM (a.a) TO ('2019-01-01');
+                           ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (sum(a)) TO ('2019-01-01');
+ERROR:  function sum(date) does not exist
+LINE 2:   FOR VALUES FROM (sum(a)) TO ('2019-01-01');
+                           ^
+HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (sum(somename)) TO ('2019-01-01');
+ERROR:  column "somename" does not exist
+LINE 2:   FOR VALUES FROM (sum(somename)) TO ('2019-01-01');
+                               ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (sum(1)) TO ('2019-01-01');
+ERROR:  aggregate functions are not allowed in partition bound
+LINE 2:   FOR VALUES FROM (sum(1)) TO ('2019-01-01');
+                           ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM ((select 1)) TO ('2019-01-01');
+ERROR:  cannot use subquery in partition bound
+LINE 2:   FOR VALUES FROM ((select 1)) TO ('2019-01-01');
+                           ^
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (generate_series(1, 3)) TO ('2019-01-01');
+ERROR:  set-returning functions are not allowed in partition bound
+LINE 2:   FOR VALUES FROM (generate_series(1, 3)) TO ('2019-01-01');
+                           ^
 -- 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..fac6ffe947 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -450,10 +450,14 @@ CREATE TABLE part_p3 PARTITION OF list_parted FOR VALUES IN ((2+1));
 CREATE TABLE part_null PARTITION OF list_parted FOR VALUES IN (null);
 \d+ list_parted
 
--- forbidden expressions for partition bound
+-- forbidden expressions for partition bound with list partitioned table
 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 (a);
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (a.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 (sum(somename));
+CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(1));
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((select 1));
 CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (generate_series(4, 6));
 
@@ -497,6 +501,26 @@ CREATE TABLE range_parted (
 	a date
 ) PARTITION BY RANGE (a);
 
+-- forbidden expressions for partition bounds with range partitioned table
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (somename) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (somename.somename) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (a) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (a.a) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (sum(a)) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (sum(somename)) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (sum(1)) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM ((select 1)) TO ('2019-01-01');
+CREATE TABLE part_bogus_expr_fail PARTITION OF range_parted
+  FOR VALUES FROM (generate_series(1, 3)) TO ('2019-01-01');
+
 -- 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
-- 
2.20.1

