diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index e187409f6f..882955bb1c 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -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) diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index dda0d7ee5d..15d4ce591c 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -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 ( diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index caf5ddb58b..95035c5947 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -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