Disallow finite partition bound following earlier UNBOUNDED column.
authorRobert Haas <rhaas@postgresql.org>
Wed, 10 May 2017 02:41:12 +0000 (22:41 -0400)
committerRobert Haas <rhaas@postgresql.org>
Wed, 10 May 2017 02:41:12 +0000 (22:41 -0400)
Amit Langote, per an observation by me.

Discussion: http://postgr.es/m/CA+TgmoYWnV2GMnYLG-Czsix-E1WGAbo4D+0tx7t9NdfYBDMFsA@mail.gmail.com

src/backend/parser/parse_utilcmd.c
src/test/regress/expected/create_table.out
src/test/regress/sql/create_table.sql

index e187409f6f24a42c7707d8e185c2e82f00a9f91d..882955bb1c98b0284387d8eb498724c9b1b8807e 100644 (file)
@@ -3358,6 +3358,7 @@ transformPartitionBound(ParseState *pstate, Relation parent, Node *bound)
        int         i,
                    j;
        char       *colname;
+       bool        seen_unbounded;
 
        if (spec->strategy != PARTITION_STRATEGY_RANGE)
            ereport(ERROR,
@@ -3376,6 +3377,39 @@ transformPartitionBound(ParseState *pstate, Relation parent, Node *bound)
                    (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                     errmsg("TO must specify exactly one value per partitioning column")));
 
+       /*
+        * Check that no finite value follows a UNBOUNDED literal in either of
+        * lower and upper bound lists.
+        */
+       seen_unbounded = false;
+       foreach(cell1, spec->lowerdatums)
+       {
+           PartitionRangeDatum *ldatum;
+
+           ldatum = (PartitionRangeDatum *) lfirst(cell1);
+           if (ldatum->infinite)
+               seen_unbounded = true;
+           else if (seen_unbounded)
+               ereport(ERROR,
+                       (errcode(ERRCODE_DATATYPE_MISMATCH),
+                        errmsg("cannot specify finite value after UNBOUNDED"),
+                        parser_errposition(pstate, exprLocation((Node *) ldatum))));
+       }
+       seen_unbounded = false;
+       foreach(cell1, spec->upperdatums)
+       {
+           PartitionRangeDatum *rdatum;
+
+           rdatum = (PartitionRangeDatum *) lfirst(cell1);
+           if (rdatum->infinite)
+               seen_unbounded = true;
+           else if (seen_unbounded)
+               ereport(ERROR,
+                       (errcode(ERRCODE_DATATYPE_MISMATCH),
+                        errmsg("cannot specify finite value after UNBOUNDED"),
+                        parser_errposition(pstate, exprLocation((Node *) rdatum))));
+       }
+
        i = j = 0;
        result_spec->lowerdatums = result_spec->upperdatums = NIL;
        forboth(cell1, spec->lowerdatums, cell2, spec->upperdatums)
index dda0d7ee5dfc28132506596c32cfff26f3a45c13..15d4ce591c7f567214580cd1471ddb7ced27b4d5 100644 (file)
@@ -505,6 +505,13 @@ ERROR:  TO must specify exactly one value per partitioning column
 -- cannot specify null values in range bounds
 CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (unbounded);
 ERROR:  cannot specify NULL in range bound
+-- cannot specify finite values after UNBOUNDED has been specified
+CREATE TABLE range_parted_multicol (a int, b int, c int) PARTITION BY RANGE (a, b, c);
+CREATE TABLE fail_part PARTITION OF range_parted_multicol FOR VALUES FROM (1, UNBOUNDED, 1) TO (UNBOUNDED, 1, 1);
+ERROR:  cannot specify finite value after UNBOUNDED
+LINE 1: ...ge_parted_multicol FOR VALUES FROM (1, UNBOUNDED, 1) TO (UNB...
+                                                             ^
+DROP TABLE range_parted_multicol;
 -- check if compatible with the specified parent
 -- cannot create as partition of a non-partitioned table
 CREATE TABLE unparted (
index caf5ddb58b3b2826adfe866df91061bb2d5a6b68..95035c5947c801a857b8c1ca127721640341a2e7 100644 (file)
@@ -473,6 +473,11 @@ CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a') TO ('z',
 -- cannot specify null values in range bounds
 CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (unbounded);
 
+-- cannot specify finite values after UNBOUNDED has been specified
+CREATE TABLE range_parted_multicol (a int, b int, c int) PARTITION BY RANGE (a, b, c);
+CREATE TABLE fail_part PARTITION OF range_parted_multicol FOR VALUES FROM (1, UNBOUNDED, 1) TO (UNBOUNDED, 1, 1);
+DROP TABLE range_parted_multicol;
+
 -- check if compatible with the specified parent
 
 -- cannot create as partition of a non-partitioned table