Commit 9361f6f5 authored by Robert Haas's avatar Robert Haas

After a MINVALUE/MAXVALUE bound, allow only more of the same.

In the old syntax, which used UNBOUNDED, we had a similar restriction,
but commit d363d42b, which changed the
syntax, eliminated it.  Put it back.

Patch by me, reviewed by Dean Rasheed.

Discussion: http://postgr.es/m/CA+Tgmobs+pLPC27tS3gOpEAxAffHrq5w509cvkwTf9pF6cWYbg@mail.gmail.com
parent c29145f0
...@@ -324,11 +324,10 @@ FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replace ...@@ -324,11 +324,10 @@ FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replace
</para> </para>
<para> <para>
Note that any values after <literal>MINVALUE</> or Note that if <literal>MINVALUE</> or <literal>MAXVALUE</> is used for
<literal>MAXVALUE</> in a partition bound are ignored; so the bound one column of a partitioning bound, the same value must be used for all
<literal>(10, MINVALUE, 0)</> is equivalent to subsequent columns. For example, <literal>(10, MINVALUE, 0)</> is not
<literal>(10, MINVALUE, 10)</> and <literal>(10, MINVALUE, MINVALUE)</> a valid bound; you should write <literal>(10, MINVALUE, MINVALUE)</>.
and <literal>(10, MINVALUE, MAXVALUE)</>.
</para> </para>
<para> <para>
...@@ -1665,7 +1664,7 @@ CREATE TABLE measurement_y2016m07 ...@@ -1665,7 +1664,7 @@ CREATE TABLE measurement_y2016m07
<programlisting> <programlisting>
CREATE TABLE measurement_ym_older CREATE TABLE measurement_ym_older
PARTITION OF measurement_year_month PARTITION OF measurement_year_month
FOR VALUES FROM (MINVALUE, 0) TO (2016, 11); FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);
CREATE TABLE measurement_ym_y2016m11 CREATE TABLE measurement_ym_y2016m11
PARTITION OF measurement_year_month PARTITION OF measurement_year_month
......
...@@ -135,6 +135,7 @@ static void transformConstraintAttrs(CreateStmtContext *cxt, ...@@ -135,6 +135,7 @@ static void transformConstraintAttrs(CreateStmtContext *cxt,
static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column); static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
static void setSchemaName(char *context_schema, char **stmt_schema_name); static void setSchemaName(char *context_schema, char **stmt_schema_name);
static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd); static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
static void validateInfiniteBounds(ParseState *pstate, List *blist);
static Const *transformPartitionBoundValue(ParseState *pstate, A_Const *con, static Const *transformPartitionBoundValue(ParseState *pstate, A_Const *con,
const char *colName, Oid colType, int32 colTypmod); const char *colName, Oid colType, int32 colTypmod);
...@@ -3397,6 +3398,13 @@ transformPartitionBound(ParseState *pstate, Relation parent, ...@@ -3397,6 +3398,13 @@ transformPartitionBound(ParseState *pstate, Relation parent,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION), (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("TO must specify exactly one value per partitioning column"))); errmsg("TO must specify exactly one value per partitioning column")));
/*
* Once we see MINVALUE or MAXVALUE for one column, the remaining
* columns must be the same.
*/
validateInfiniteBounds(pstate, spec->lowerdatums);
validateInfiniteBounds(pstate, spec->upperdatums);
/* Transform all the constants */ /* Transform all the constants */
i = j = 0; i = j = 0;
result_spec->lowerdatums = result_spec->upperdatums = NIL; result_spec->lowerdatums = result_spec->upperdatums = NIL;
...@@ -3468,6 +3476,46 @@ transformPartitionBound(ParseState *pstate, Relation parent, ...@@ -3468,6 +3476,46 @@ transformPartitionBound(ParseState *pstate, Relation parent,
return result_spec; return result_spec;
} }
/*
* validateInfiniteBounds
*
* Check that a MAXVALUE or MINVALUE specification in a partition bound is
* followed only by more of the same.
*/
static void
validateInfiniteBounds(ParseState *pstate, List *blist)
{
ListCell *lc;
PartitionRangeDatumKind kind = PARTITION_RANGE_DATUM_VALUE;
foreach(lc, blist)
{
PartitionRangeDatum *prd = castNode(PartitionRangeDatum, lfirst(lc));
if (kind == prd->kind)
continue;
switch (kind)
{
case PARTITION_RANGE_DATUM_VALUE:
kind = prd->kind;
break;
case PARTITION_RANGE_DATUM_MAXVALUE:
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("every bound following MAXVALUE must also be MAXVALUE"),
parser_errposition(pstate, exprLocation((Node *) prd))));
case PARTITION_RANGE_DATUM_MINVALUE:
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("every bound following MINVALUE must also be MINVALUE"),
parser_errposition(pstate, exprLocation((Node *) prd))));
}
}
}
/* /*
* Transform one constant in a partition bound spec * Transform one constant in a partition bound spec
*/ */
......
...@@ -723,7 +723,7 @@ Number of partitions: 3 (Use \d+ to list them.) ...@@ -723,7 +723,7 @@ Number of partitions: 3 (Use \d+ to list them.)
-- check that we get the expected partition constraints -- check that we get the expected partition constraints
CREATE TABLE range_parted4 (a int, b int, c int) PARTITION BY RANGE (abs(a), abs(b), c); CREATE TABLE range_parted4 (a int, b int, c int) PARTITION BY RANGE (abs(a), abs(b), c);
CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (MAXVALUE, 0, 0); CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (MAXVALUE, MAXVALUE, MAXVALUE);
\d+ unbounded_range_part \d+ unbounded_range_part
Table "public.unbounded_range_part" Table "public.unbounded_range_part"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
...@@ -731,11 +731,11 @@ CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MI ...@@ -731,11 +731,11 @@ CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MI
a | integer | | | | plain | | a | integer | | | | plain | |
b | integer | | | | plain | | b | integer | | | | plain | |
c | integer | | | | plain | | c | integer | | | | plain | |
Partition of: range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (MAXVALUE, 0, 0) Partition of: range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (MAXVALUE, MAXVALUE, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL)) Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL))
DROP TABLE unbounded_range_part; DROP TABLE unbounded_range_part;
CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (1, MAXVALUE, 0); CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (1, MAXVALUE, MAXVALUE);
\d+ range_parted4_1 \d+ range_parted4_1
Table "public.range_parted4_1" Table "public.range_parted4_1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
...@@ -743,7 +743,7 @@ CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALU ...@@ -743,7 +743,7 @@ CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALU
a | integer | | | | plain | | a | integer | | | | plain | |
b | integer | | | | plain | | b | integer | | | | plain | |
c | integer | | | | plain | | c | integer | | | | plain | |
Partition of: range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (1, MAXVALUE, 0) Partition of: range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (1, MAXVALUE, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND (abs(a) <= 1)) Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND (abs(a) <= 1))
CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE); CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE);
...@@ -757,7 +757,7 @@ CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5 ...@@ -757,7 +757,7 @@ CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5
Partition of: range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE) Partition of: range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 3) OR ((abs(a) = 3) AND (abs(b) > 4)) OR ((abs(a) = 3) AND (abs(b) = 4) AND (c >= 5))) AND ((abs(a) < 6) OR ((abs(a) = 6) AND (abs(b) <= 7)))) Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 3) OR ((abs(a) = 3) AND (abs(b) > 4)) OR ((abs(a) = 3) AND (abs(b) = 4) AND (c >= 5))) AND ((abs(a) < 6) OR ((abs(a) = 6) AND (abs(b) <= 7))))
CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, 0); CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MAXVALUE);
\d+ range_parted4_3 \d+ range_parted4_3
Table "public.range_parted4_3" Table "public.range_parted4_3"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
...@@ -765,7 +765,7 @@ CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, M ...@@ -765,7 +765,7 @@ CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, M
a | integer | | | | plain | | a | integer | | | | plain | |
b | integer | | | | plain | | b | integer | | | | plain | |
c | integer | | | | plain | | c | integer | | | | plain | |
Partition of: range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, 0) Partition of: range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MAXVALUE)
Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 6) OR ((abs(a) = 6) AND (abs(b) >= 8))) AND (abs(a) <= 9)) Partition constraint: ((abs(a) IS NOT NULL) AND (abs(b) IS NOT NULL) AND (c IS NOT NULL) AND ((abs(a) > 6) OR ((abs(a) = 6) AND (abs(b) >= 8))) AND (abs(a) <= 9))
DROP TABLE range_parted4; DROP TABLE range_parted4;
......
...@@ -1853,12 +1853,12 @@ drop table range_list_parted; ...@@ -1853,12 +1853,12 @@ drop table range_list_parted;
-- check that constraint exclusion is able to cope with the partition -- check that constraint exclusion is able to cope with the partition
-- constraint emitted for multi-column range partitioned tables -- constraint emitted for multi-column range partitioned tables
create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c); create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, 1, 1); create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, 1, 1);
create table mcrparted1 partition of mcrparted for values from (1, 1, 1) to (10, 5, 10); create table mcrparted1 partition of mcrparted for values from (1, 1, 1) to (10, 5, 10);
create table mcrparted2 partition of mcrparted for values from (10, 5, 10) to (10, 10, 10); create table mcrparted2 partition of mcrparted for values from (10, 5, 10) to (10, 10, 10);
create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10); create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
create table mcrparted4 partition of mcrparted for values from (20, 10, 10) to (20, 20, 20); create table mcrparted4 partition of mcrparted for values from (20, 10, 10) to (20, 20, 20);
create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, 0, 0); create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, maxvalue, maxvalue);
explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0 explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0
QUERY PLAN QUERY PLAN
------------------------------ ------------------------------
......
...@@ -574,15 +574,28 @@ revoke all on key_desc from someone_else; ...@@ -574,15 +574,28 @@ revoke all on key_desc from someone_else;
revoke all on key_desc_1 from someone_else; revoke all on key_desc_1 from someone_else;
drop role someone_else; drop role someone_else;
drop table key_desc, key_desc_1; drop table key_desc, key_desc_1;
-- test minvalue/maxvalue restrictions
create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, maxvalue, maxvalue);
ERROR: every bound following MINVALUE must also be MINVALUE
LINE 1: ...partition of mcrparted for values from (minvalue, 0, 0) to (...
^
create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, minvalue);
ERROR: every bound following MAXVALUE must also be MAXVALUE
LINE 1: ...r values from (10, 6, minvalue) to (10, maxvalue, minvalue);
^
create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, minvalue);
ERROR: every bound following MINVALUE must also be MINVALUE
LINE 1: ...ition of mcrparted for values from (21, minvalue, 0) to (30,...
^
-- check multi-column range partitioning expression enforces the same -- check multi-column range partitioning expression enforces the same
-- constraint as what tuple-routing would determine it to be -- constraint as what tuple-routing would determine it to be
create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c); create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, maxvalue, maxvalue);
create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, maxvalue, 0);
create table mcrparted1 partition of mcrparted for values from (2, 1, minvalue) to (10, 5, 10); create table mcrparted1 partition of mcrparted for values from (2, 1, minvalue) to (10, 5, 10);
create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, 0); create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, maxvalue);
create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10); create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, maxvalue); create table mcrparted4 partition of mcrparted for values from (21, minvalue, minvalue) to (30, 20, maxvalue);
create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, 0, 0); create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, maxvalue, maxvalue);
-- routed to mcrparted0 -- routed to mcrparted0
insert into mcrparted values (0, 1, 1); insert into mcrparted values (0, 1, 1);
insert into mcrparted0 values (0, 1, 1); insert into mcrparted0 values (0, 1, 1);
...@@ -666,14 +679,14 @@ drop table brtrigpartcon; ...@@ -666,14 +679,14 @@ drop table brtrigpartcon;
drop function brtrigpartcon1trigf(); drop function brtrigpartcon1trigf();
-- check multi-column range partitioning with minvalue/maxvalue constraints -- check multi-column range partitioning with minvalue/maxvalue constraints
create table mcrparted (a text, b int) partition by range(a, b); create table mcrparted (a text, b int) partition by range(a, b);
create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, 0) to ('b', minvalue); create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, minvalue) to ('b', minvalue);
create table mcrparted2_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue); create table mcrparted2_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue);
create table mcrparted3_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue); create table mcrparted3_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue);
create table mcrparted4_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0); create table mcrparted4_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0);
create table mcrparted5_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10); create table mcrparted5_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10);
create table mcrparted6_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue); create table mcrparted6_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue);
create table mcrparted7_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue); create table mcrparted7_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue);
create table mcrparted8_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, 0); create table mcrparted8_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, maxvalue);
\d+ mcrparted \d+ mcrparted
Table "public.mcrparted" Table "public.mcrparted"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
...@@ -681,14 +694,14 @@ create table mcrparted8_ge_d partition of mcrparted for values from ('d', minval ...@@ -681,14 +694,14 @@ create table mcrparted8_ge_d partition of mcrparted for values from ('d', minval
a | text | | | | extended | | a | text | | | | extended | |
b | integer | | | | plain | | b | integer | | | | plain | |
Partition key: RANGE (a, b) Partition key: RANGE (a, b)
Partitions: mcrparted1_lt_b FOR VALUES FROM (MINVALUE, 0) TO ('b', MINVALUE), Partitions: mcrparted1_lt_b FOR VALUES FROM (MINVALUE, MINVALUE) TO ('b', MINVALUE),
mcrparted2_b FOR VALUES FROM ('b', MINVALUE) TO ('c', MINVALUE), mcrparted2_b FOR VALUES FROM ('b', MINVALUE) TO ('c', MINVALUE),
mcrparted3_c_to_common FOR VALUES FROM ('c', MINVALUE) TO ('common', MINVALUE), mcrparted3_c_to_common FOR VALUES FROM ('c', MINVALUE) TO ('common', MINVALUE),
mcrparted4_common_lt_0 FOR VALUES FROM ('common', MINVALUE) TO ('common', 0), mcrparted4_common_lt_0 FOR VALUES FROM ('common', MINVALUE) TO ('common', 0),
mcrparted5_common_0_to_10 FOR VALUES FROM ('common', 0) TO ('common', 10), mcrparted5_common_0_to_10 FOR VALUES FROM ('common', 0) TO ('common', 10),
mcrparted6_common_ge_10 FOR VALUES FROM ('common', 10) TO ('common', MAXVALUE), mcrparted6_common_ge_10 FOR VALUES FROM ('common', 10) TO ('common', MAXVALUE),
mcrparted7_gt_common_lt_d FOR VALUES FROM ('common', MAXVALUE) TO ('d', MINVALUE), mcrparted7_gt_common_lt_d FOR VALUES FROM ('common', MAXVALUE) TO ('d', MINVALUE),
mcrparted8_ge_d FOR VALUES FROM ('d', MINVALUE) TO (MAXVALUE, 0) mcrparted8_ge_d FOR VALUES FROM ('d', MINVALUE) TO (MAXVALUE, MAXVALUE)
\d+ mcrparted1_lt_b \d+ mcrparted1_lt_b
Table "public.mcrparted1_lt_b" Table "public.mcrparted1_lt_b"
...@@ -696,7 +709,7 @@ Partitions: mcrparted1_lt_b FOR VALUES FROM (MINVALUE, 0) TO ('b', MINVALUE), ...@@ -696,7 +709,7 @@ Partitions: mcrparted1_lt_b FOR VALUES FROM (MINVALUE, 0) TO ('b', MINVALUE),
--------+---------+-----------+----------+---------+----------+--------------+------------- --------+---------+-----------+----------+---------+----------+--------------+-------------
a | text | | | | extended | | a | text | | | | extended | |
b | integer | | | | plain | | b | integer | | | | plain | |
Partition of: mcrparted FOR VALUES FROM (MINVALUE, 0) TO ('b', MINVALUE) Partition of: mcrparted FOR VALUES FROM (MINVALUE, MINVALUE) TO ('b', MINVALUE)
Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a < 'b'::text)) Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a < 'b'::text))
\d+ mcrparted2_b \d+ mcrparted2_b
...@@ -759,7 +772,7 @@ Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a > 'common'::te ...@@ -759,7 +772,7 @@ Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a > 'common'::te
--------+---------+-----------+----------+---------+----------+--------------+------------- --------+---------+-----------+----------+---------+----------+--------------+-------------
a | text | | | | extended | | a | text | | | | extended | |
b | integer | | | | plain | | b | integer | | | | plain | |
Partition of: mcrparted FOR VALUES FROM ('d', MINVALUE) TO (MAXVALUE, 0) Partition of: mcrparted FOR VALUES FROM ('d', MINVALUE) TO (MAXVALUE, MAXVALUE)
Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a >= 'd'::text)) Partition constraint: ((a IS NOT NULL) AND (b IS NOT NULL) AND (a >= 'd'::text))
insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 10), ('c', -10), insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 10), ('c', -10),
......
...@@ -641,14 +641,14 @@ CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10); ...@@ -641,14 +641,14 @@ CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10);
-- check that we get the expected partition constraints -- check that we get the expected partition constraints
CREATE TABLE range_parted4 (a int, b int, c int) PARTITION BY RANGE (abs(a), abs(b), c); CREATE TABLE range_parted4 (a int, b int, c int) PARTITION BY RANGE (abs(a), abs(b), c);
CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (MAXVALUE, 0, 0); CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (MAXVALUE, MAXVALUE, MAXVALUE);
\d+ unbounded_range_part \d+ unbounded_range_part
DROP TABLE unbounded_range_part; DROP TABLE unbounded_range_part;
CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (1, MAXVALUE, 0); CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, MINVALUE, MINVALUE) TO (1, MAXVALUE, MAXVALUE);
\d+ range_parted4_1 \d+ range_parted4_1
CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE); CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5) TO (6, 7, MAXVALUE);
\d+ range_parted4_2 \d+ range_parted4_2
CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, 0); CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, MAXVALUE);
\d+ range_parted4_3 \d+ range_parted4_3
DROP TABLE range_parted4; DROP TABLE range_parted4;
......
...@@ -664,12 +664,12 @@ drop table range_list_parted; ...@@ -664,12 +664,12 @@ drop table range_list_parted;
-- check that constraint exclusion is able to cope with the partition -- check that constraint exclusion is able to cope with the partition
-- constraint emitted for multi-column range partitioned tables -- constraint emitted for multi-column range partitioned tables
create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c); create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, 1, 1); create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, 1, 1);
create table mcrparted1 partition of mcrparted for values from (1, 1, 1) to (10, 5, 10); create table mcrparted1 partition of mcrparted for values from (1, 1, 1) to (10, 5, 10);
create table mcrparted2 partition of mcrparted for values from (10, 5, 10) to (10, 10, 10); create table mcrparted2 partition of mcrparted for values from (10, 5, 10) to (10, 10, 10);
create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10); create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
create table mcrparted4 partition of mcrparted for values from (20, 10, 10) to (20, 20, 20); create table mcrparted4 partition of mcrparted for values from (20, 10, 10) to (20, 20, 20);
create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, 0, 0); create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, maxvalue, maxvalue);
explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0 explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0
explain (costs off) select * from mcrparted where a = 10 and abs(b) < 5; -- scans mcrparted1 explain (costs off) select * from mcrparted where a = 10 and abs(b) < 5; -- scans mcrparted1
explain (costs off) select * from mcrparted where a = 10 and abs(b) = 5; -- scans mcrparted1, mcrparted2 explain (costs off) select * from mcrparted where a = 10 and abs(b) = 5; -- scans mcrparted1, mcrparted2
......
...@@ -369,15 +369,20 @@ revoke all on key_desc_1 from someone_else; ...@@ -369,15 +369,20 @@ revoke all on key_desc_1 from someone_else;
drop role someone_else; drop role someone_else;
drop table key_desc, key_desc_1; drop table key_desc, key_desc_1;
-- test minvalue/maxvalue restrictions
create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, maxvalue, maxvalue);
create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, minvalue);
create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, minvalue);
-- check multi-column range partitioning expression enforces the same -- check multi-column range partitioning expression enforces the same
-- constraint as what tuple-routing would determine it to be -- constraint as what tuple-routing would determine it to be
create table mcrparted (a int, b int, c int) partition by range (a, abs(b), c); create table mcrparted0 partition of mcrparted for values from (minvalue, minvalue, minvalue) to (1, maxvalue, maxvalue);
create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) to (1, maxvalue, 0);
create table mcrparted1 partition of mcrparted for values from (2, 1, minvalue) to (10, 5, 10); create table mcrparted1 partition of mcrparted for values from (2, 1, minvalue) to (10, 5, 10);
create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, 0); create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, maxvalue);
create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10); create table mcrparted3 partition of mcrparted for values from (11, 1, 1) to (20, 10, 10);
create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, maxvalue); create table mcrparted4 partition of mcrparted for values from (21, minvalue, minvalue) to (30, 20, maxvalue);
create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, 0, 0); create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, maxvalue, maxvalue);
-- routed to mcrparted0 -- routed to mcrparted0
insert into mcrparted values (0, 1, 1); insert into mcrparted values (0, 1, 1);
...@@ -442,14 +447,14 @@ drop function brtrigpartcon1trigf(); ...@@ -442,14 +447,14 @@ drop function brtrigpartcon1trigf();
-- check multi-column range partitioning with minvalue/maxvalue constraints -- check multi-column range partitioning with minvalue/maxvalue constraints
create table mcrparted (a text, b int) partition by range(a, b); create table mcrparted (a text, b int) partition by range(a, b);
create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, 0) to ('b', minvalue); create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, minvalue) to ('b', minvalue);
create table mcrparted2_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue); create table mcrparted2_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue);
create table mcrparted3_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue); create table mcrparted3_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue);
create table mcrparted4_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0); create table mcrparted4_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0);
create table mcrparted5_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10); create table mcrparted5_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10);
create table mcrparted6_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue); create table mcrparted6_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue);
create table mcrparted7_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue); create table mcrparted7_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue);
create table mcrparted8_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, 0); create table mcrparted8_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, maxvalue);
\d+ mcrparted \d+ mcrparted
\d+ mcrparted1_lt_b \d+ mcrparted1_lt_b
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment