Commit d363d42b authored by Dean Rasheed's avatar Dean Rasheed

Use MINVALUE/MAXVALUE instead of UNBOUNDED for range partition bounds.

Previously, UNBOUNDED meant no lower bound when used in the FROM list,
and no upper bound when used in the TO list, which was OK for
single-column range partitioning, but problematic with multiple
columns. For example, an upper bound of (10.0, UNBOUNDED) would not be
collocated with a lower bound of (10.0, UNBOUNDED), thus making it
difficult or impossible to define contiguous multi-column range
partitions in some cases.

Fix this by using MINVALUE and MAXVALUE instead of UNBOUNDED to
represent a partition column that is unbounded below or above
respectively. This syntax removes any ambiguity, and ensures that if
one partition's lower bound equals another partition's upper bound,
then the partitions are contiguous.

Also drop the constraint prohibiting finite values after an unbounded
column, and just document the fact that any values after MINVALUE or
MAXVALUE are ignored. Previously it was necessary to repeat UNBOUNDED
multiple times, which was needlessly verbose.

Note: Forces a post-PG 10 beta2 initdb.

Report by Amul Sul, original patch by Amit Langote with some
additional hacking by me.

Discussion: https://postgr.es/m/CAAJ_b947mowpLdxL3jo3YLKngRjrq9+Ej4ymduQTfYR+8=YAYQ@mail.gmail.com
parent 866f4a7c
...@@ -87,8 +87,8 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI ...@@ -87,8 +87,8 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
<phrase>and <replaceable class="PARAMETER">partition_bound_spec</replaceable> is:</phrase> <phrase>and <replaceable class="PARAMETER">partition_bound_spec</replaceable> is:</phrase>
IN ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replaceable class="PARAMETER">string_literal</replaceable> | NULL } [, ...] ) | IN ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replaceable class="PARAMETER">string_literal</replaceable> | NULL } [, ...] ) |
FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replaceable class="PARAMETER">string_literal</replaceable> | UNBOUNDED } [, ...] ) FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replaceable class="PARAMETER">string_literal</replaceable> | MINVALUE | MAXVALUE } [, ...] )
TO ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replaceable class="PARAMETER">string_literal</replaceable> | UNBOUNDED } [, ...] ) TO ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replaceable class="PARAMETER">string_literal</replaceable> | MINVALUE | MAXVALUE } [, ...] )
<phrase><replaceable class="PARAMETER">index_parameters</replaceable> in <literal>UNIQUE</literal>, <literal>PRIMARY KEY</literal>, and <literal>EXCLUDE</literal> constraints are:</phrase> <phrase><replaceable class="PARAMETER">index_parameters</replaceable> in <literal>UNIQUE</literal>, <literal>PRIMARY KEY</literal>, and <literal>EXCLUDE</literal> constraints are:</phrase>
...@@ -269,10 +269,10 @@ FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replace ...@@ -269,10 +269,10 @@ FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replace
<para> <para>
Each of the values specified in Each of the values specified in
the <replaceable class="PARAMETER">partition_bound_spec</> is the <replaceable class="PARAMETER">partition_bound_spec</> is
a literal, <literal>NULL</literal>, or <literal>UNBOUNDED</literal>. a literal, <literal>NULL</literal>, <literal>MINVALUE</literal>, or
Each literal value must be either a numeric constant that is coercible <literal>MAXVALUE</literal>. Each literal value must be either a
to the corresponding partition key column's type, or a string literal numeric constant that is coercible to the corresponding partition key
that is valid input for that type. column's type, or a string literal that is valid input for that type.
</para> </para>
<para> <para>
...@@ -300,13 +300,46 @@ FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replace ...@@ -300,13 +300,46 @@ FROM ( { <replaceable class="PARAMETER">numeric_literal</replaceable> | <replace
</para> </para>
<para> <para>
Writing <literal>UNBOUNDED</literal> in <literal>FROM</literal> The special values <literal>MINVALUE</> and <literal>MAXVALUE</>
signifies <literal>-infinity</literal> as the lower bound of the may be used when creating a range partition to indicate that there
corresponding column, whereas when written in <literal>TO</literal>, is no lower or upper bound on the column's value. For example, a
it signifies <literal>+infinity</literal> as the upper bound. partition defined using <literal>FROM (MINVALUE) TO (10)</> allows
All items following an <literal>UNBOUNDED</literal> item within any values less than 10, and a partition defined using
a <literal>FROM</literal> or <literal>TO</literal> list must also <literal>FROM (10) TO (MAXVALUE)</> allows any values greater than
be <literal>UNBOUNDED</literal>. or equal to 10.
</para>
<para>
When creating a range partition involving more than one column, it
can also make sense to use <literal>MAXVALUE</> as part of the lower
bound, and <literal>MINVALUE</> as part of the upper bound. For
example, a partition defined using
<literal>FROM (0, MAXVALUE) TO (10, MAXVALUE)</> allows any rows
where the first partition key column is greater than 0 and less than
or equal to 10. Similarly, a partition defined using
<literal>FROM ('a', MINVALUE) TO ('b', MINVALUE)</> allows any rows
where the first partition key column starts with "a".
</para>
<para>
Note that any values after <literal>MINVALUE</> or
<literal>MAXVALUE</> in a partition bound are ignored; so the bound
<literal>(10, MINVALUE, 0)</> is equivalent to
<literal>(10, MINVALUE, 10)</> and <literal>(10, MINVALUE, MINVALUE)</>
and <literal>(10, MINVALUE, MAXVALUE)</>.
</para>
<para>
Also note that some element types, such as <literal>timestamp</>,
have a notion of "infinity", which is just another value that can
be stored. This is different from <literal>MINVALUE</> and
<literal>MAXVALUE</>, which are not real values that can be stored,
but rather they are ways of saying that the value is unbounded.
<literal>MAXVALUE</> can be thought of as being greater than any
other value, including "infinity" and <literal>MINVALUE</> as being
less than any other value, including "minus infinity". Thus the range
<literal>FROM ('infinity') TO (MAXVALUE)</> is not an empty range; it
allows precisely one value to be stored &mdash; "infinity".
</para> </para>
<para> <para>
...@@ -1610,7 +1643,7 @@ CREATE TABLE measurement_y2016m07 ...@@ -1610,7 +1643,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 (unbounded, unbounded) TO (2016, 11); FOR VALUES FROM (MINVALUE, 0) TO (2016, 11);
CREATE TABLE measurement_ym_y2016m11 CREATE TABLE measurement_ym_y2016m11
PARTITION OF measurement_year_month PARTITION OF measurement_year_month
......
This diff is collapsed.
...@@ -4458,7 +4458,7 @@ _copyPartitionRangeDatum(const PartitionRangeDatum *from) ...@@ -4458,7 +4458,7 @@ _copyPartitionRangeDatum(const PartitionRangeDatum *from)
{ {
PartitionRangeDatum *newnode = makeNode(PartitionRangeDatum); PartitionRangeDatum *newnode = makeNode(PartitionRangeDatum);
COPY_SCALAR_FIELD(infinite); COPY_SCALAR_FIELD(kind);
COPY_NODE_FIELD(value); COPY_NODE_FIELD(value);
COPY_LOCATION_FIELD(location); COPY_LOCATION_FIELD(location);
......
...@@ -2849,7 +2849,7 @@ _equalPartitionBoundSpec(const PartitionBoundSpec *a, const PartitionBoundSpec * ...@@ -2849,7 +2849,7 @@ _equalPartitionBoundSpec(const PartitionBoundSpec *a, const PartitionBoundSpec *
static bool static bool
_equalPartitionRangeDatum(const PartitionRangeDatum *a, const PartitionRangeDatum *b) _equalPartitionRangeDatum(const PartitionRangeDatum *a, const PartitionRangeDatum *b)
{ {
COMPARE_SCALAR_FIELD(infinite); COMPARE_SCALAR_FIELD(kind);
COMPARE_NODE_FIELD(value); COMPARE_NODE_FIELD(value);
COMPARE_LOCATION_FIELD(location); COMPARE_LOCATION_FIELD(location);
......
...@@ -3582,7 +3582,7 @@ _outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node) ...@@ -3582,7 +3582,7 @@ _outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node)
{ {
WRITE_NODE_TYPE("PARTITIONRANGEDATUM"); WRITE_NODE_TYPE("PARTITIONRANGEDATUM");
WRITE_BOOL_FIELD(infinite); WRITE_ENUM_FIELD(kind, PartitionRangeDatumKind);
WRITE_NODE_FIELD(value); WRITE_NODE_FIELD(value);
WRITE_LOCATION_FIELD(location); WRITE_LOCATION_FIELD(location);
} }
......
...@@ -2404,7 +2404,7 @@ _readPartitionRangeDatum(void) ...@@ -2404,7 +2404,7 @@ _readPartitionRangeDatum(void)
{ {
READ_LOCALS(PartitionRangeDatum); READ_LOCALS(PartitionRangeDatum);
READ_BOOL_FIELD(infinite); READ_ENUM_FIELD(kind, PartitionRangeDatumKind);
READ_NODE_FIELD(value); READ_NODE_FIELD(value);
READ_LOCATION_FIELD(location); READ_LOCATION_FIELD(location);
......
...@@ -2696,11 +2696,21 @@ range_datum_list: ...@@ -2696,11 +2696,21 @@ range_datum_list:
; ;
PartitionRangeDatum: PartitionRangeDatum:
UNBOUNDED MINVALUE
{ {
PartitionRangeDatum *n = makeNode(PartitionRangeDatum); PartitionRangeDatum *n = makeNode(PartitionRangeDatum);
n->infinite = true; n->kind = PARTITION_RANGE_DATUM_MINVALUE;
n->value = NULL;
n->location = @1;
$$ = (Node *) n;
}
| MAXVALUE
{
PartitionRangeDatum *n = makeNode(PartitionRangeDatum);
n->kind = PARTITION_RANGE_DATUM_MAXVALUE;
n->value = NULL; n->value = NULL;
n->location = @1; n->location = @1;
...@@ -2710,7 +2720,7 @@ PartitionRangeDatum: ...@@ -2710,7 +2720,7 @@ PartitionRangeDatum:
{ {
PartitionRangeDatum *n = makeNode(PartitionRangeDatum); PartitionRangeDatum *n = makeNode(PartitionRangeDatum);
n->infinite = false; n->kind = PARTITION_RANGE_DATUM_VALUE;
n->value = $1; n->value = $1;
n->location = @1; n->location = @1;
......
...@@ -3365,7 +3365,6 @@ transformPartitionBound(ParseState *pstate, Relation parent, ...@@ -3365,7 +3365,6 @@ transformPartitionBound(ParseState *pstate, Relation parent,
*cell2; *cell2;
int i, int i,
j; j;
bool seen_unbounded;
if (spec->strategy != PARTITION_STRATEGY_RANGE) if (spec->strategy != PARTITION_STRATEGY_RANGE)
ereport(ERROR, ereport(ERROR,
...@@ -3382,39 +3381,6 @@ transformPartitionBound(ParseState *pstate, Relation parent, ...@@ -3382,39 +3381,6 @@ 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")));
/*
* Check that no finite value follows an UNBOUNDED item in either of
* lower and upper bound lists.
*/
seen_unbounded = false;
foreach(cell1, spec->lowerdatums)
{
PartitionRangeDatum *ldatum = castNode(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 = castNode(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))));
}
/* 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;
......
...@@ -8715,8 +8715,10 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -8715,8 +8715,10 @@ get_rule_expr(Node *node, deparse_context *context,
castNode(PartitionRangeDatum, lfirst(cell)); castNode(PartitionRangeDatum, lfirst(cell));
appendStringInfoString(buf, sep); appendStringInfoString(buf, sep);
if (datum->infinite) if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
appendStringInfoString(buf, "UNBOUNDED"); appendStringInfoString(buf, "MINVALUE");
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
appendStringInfoString(buf, "MAXVALUE");
else else
{ {
Const *val = castNode(Const, datum->value); Const *val = castNode(Const, datum->value);
...@@ -8733,8 +8735,10 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -8733,8 +8735,10 @@ get_rule_expr(Node *node, deparse_context *context,
castNode(PartitionRangeDatum, lfirst(cell)); castNode(PartitionRangeDatum, lfirst(cell));
appendStringInfoString(buf, sep); appendStringInfoString(buf, sep);
if (datum->infinite) if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
appendStringInfoString(buf, "UNBOUNDED"); appendStringInfoString(buf, "MINVALUE");
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
appendStringInfoString(buf, "MAXVALUE");
else else
{ {
Const *val = castNode(Const, datum->value); Const *val = castNode(Const, datum->value);
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201706241 #define CATALOG_VERSION_NO 201707211
#endif #endif
...@@ -809,16 +809,24 @@ typedef struct PartitionBoundSpec ...@@ -809,16 +809,24 @@ typedef struct PartitionBoundSpec
} PartitionBoundSpec; } PartitionBoundSpec;
/* /*
* PartitionRangeDatum - can be either a value or UNBOUNDED * PartitionRangeDatum - one of the values in a range partition bound
* *
* "value" is an A_Const in raw grammar output, a Const after analysis * This can be MINVALUE, MAXVALUE or a specific bounded value.
*/ */
typedef enum PartitionRangeDatumKind
{
PARTITION_RANGE_DATUM_MINVALUE = -1, /* less than any other value */
PARTITION_RANGE_DATUM_VALUE = 0, /* a specific (bounded) value */
PARTITION_RANGE_DATUM_MAXVALUE = 1 /* greater than any other value */
} PartitionRangeDatumKind;
typedef struct PartitionRangeDatum typedef struct PartitionRangeDatum
{ {
NodeTag type; NodeTag type;
bool infinite; /* true if UNBOUNDED */ PartitionRangeDatumKind kind;
Node *value; /* null if UNBOUNDED */ Node *value; /* Const (or A_Const in raw tree), if kind is
* PARTITION_RANGE_DATUM_VALUE, else NULL */
int location; /* token location, or -1 if unknown */ int location; /* token location, or -1 if unknown */
} PartitionRangeDatum; } PartitionRangeDatum;
......
...@@ -512,15 +512,8 @@ ERROR: FROM must specify exactly one value per partitioning column ...@@ -512,15 +512,8 @@ ERROR: FROM must specify exactly one value per partitioning column
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a') TO ('z', 1); CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a') TO ('z', 1);
ERROR: TO must specify exactly one value per partitioning column ERROR: TO must specify exactly one value per partitioning column
-- cannot specify null values in range bounds -- cannot specify null values in range bounds
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (unbounded); CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (maxvalue);
ERROR: cannot specify NULL in range bound 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 -- check if compatible with the specified parent
-- cannot create as partition of a non-partitioned table -- cannot create as partition of a non-partitioned table
CREATE TABLE unparted ( CREATE TABLE unparted (
...@@ -578,11 +571,11 @@ ERROR: cannot create range partition with empty range ...@@ -578,11 +571,11 @@ ERROR: cannot create range partition with empty range
-- note that the range '[1, 1)' has no elements -- note that the range '[1, 1)' has no elements
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1);
ERROR: cannot create range partition with empty range ERROR: cannot create range partition with empty range
CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (unbounded) TO (1); CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (1);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (unbounded) TO (2); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (2);
ERROR: partition "fail_part" would overlap partition "part0" ERROR: partition "fail_part" would overlap partition "part0"
CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10); CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (unbounded); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (maxvalue);
ERROR: partition "fail_part" would overlap partition "part1" ERROR: partition "fail_part" would overlap partition "part1"
CREATE TABLE part2 PARTITION OF range_parted2 FOR VALUES FROM (20) TO (30); CREATE TABLE part2 PARTITION OF range_parted2 FOR VALUES FROM (20) TO (30);
CREATE TABLE part3 PARTITION OF range_parted2 FOR VALUES FROM (30) TO (40); CREATE TABLE part3 PARTITION OF range_parted2 FOR VALUES FROM (30) TO (40);
...@@ -595,18 +588,18 @@ CREATE TABLE range_parted3 ( ...@@ -595,18 +588,18 @@ CREATE TABLE range_parted3 (
a int, a int,
b int b int
) PARTITION BY RANGE (a, (b+1)); ) PARTITION BY RANGE (a, (b+1));
CREATE TABLE part00 PARTITION OF range_parted3 FOR VALUES FROM (0, unbounded) TO (0, unbounded); CREATE TABLE part00 PARTITION OF range_parted3 FOR VALUES FROM (0, minvalue) TO (0, maxvalue);
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (0, unbounded) TO (0, 1); CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (0, minvalue) TO (0, 1);
ERROR: partition "fail_part" would overlap partition "part00" ERROR: partition "fail_part" would overlap partition "part00"
CREATE TABLE part10 PARTITION OF range_parted3 FOR VALUES FROM (1, unbounded) TO (1, 1); CREATE TABLE part10 PARTITION OF range_parted3 FOR VALUES FROM (1, minvalue) TO (1, 1);
CREATE TABLE part11 PARTITION OF range_parted3 FOR VALUES FROM (1, 1) TO (1, 10); CREATE TABLE part11 PARTITION OF range_parted3 FOR VALUES FROM (1, 1) TO (1, 10);
CREATE TABLE part12 PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, unbounded); CREATE TABLE part12 PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, maxvalue);
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, 20); CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, 20);
ERROR: partition "fail_part" would overlap partition "part12" ERROR: partition "fail_part" would overlap partition "part12"
-- cannot create a partition that says column b is allowed to range -- cannot create a partition that says column b is allowed to range
-- from -infinity to +infinity, while there exist partitions that have -- from -infinity to +infinity, while there exist partitions that have
-- more specific ranges -- more specific ranges
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, unbounded) TO (1, unbounded); CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, minvalue) TO (1, maxvalue);
ERROR: partition "fail_part" would overlap partition "part10" ERROR: partition "fail_part" would overlap partition "part10"
-- check schema propagation from parent -- check schema propagation from parent
CREATE TABLE parted ( CREATE TABLE parted (
...@@ -708,7 +701,7 @@ Number of partitions: 3 (Use \d+ to list them.) ...@@ -708,7 +701,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 (UNBOUNDED, UNBOUNDED, UNBOUNDED) TO (UNBOUNDED, UNBOUNDED, UNBOUNDED); CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (MAXVALUE, 0, 0);
\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
...@@ -716,11 +709,11 @@ CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (UN ...@@ -716,11 +709,11 @@ CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (UN
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 (UNBOUNDED, UNBOUNDED, UNBOUNDED) TO (UNBOUNDED, UNBOUNDED, UNBOUNDED) Partition of: range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (MAXVALUE, 0, 0)
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 (UNBOUNDED, UNBOUNDED, UNBOUNDED) TO (1, UNBOUNDED, UNBOUNDED); CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (1, MAXVALUE, 0);
\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
...@@ -728,10 +721,10 @@ CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (UNBOUND ...@@ -728,10 +721,10 @@ CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (UNBOUND
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 (UNBOUNDED, UNBOUNDED, UNBOUNDED) TO (1, UNBOUNDED, UNBOUNDED) Partition of: range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (1, MAXVALUE, 0)
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, UNBOUNDED); 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
Table "public.range_parted4_2" Table "public.range_parted4_2"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
...@@ -739,10 +732,10 @@ CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5 ...@@ -739,10 +732,10 @@ CREATE TABLE range_parted4_2 PARTITION OF range_parted4 FOR VALUES FROM (3, 4, 5
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 (3, 4, 5) TO (6, 7, UNBOUNDED) 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, UNBOUNDED) TO (9, UNBOUNDED, UNBOUNDED); CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, 0);
\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
...@@ -750,7 +743,7 @@ CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, U ...@@ -750,7 +743,7 @@ CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, U
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, UNBOUNDED) TO (9, UNBOUNDED, UNBOUNDED) Partition of: range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, 0)
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;
......
...@@ -1718,7 +1718,7 @@ create table part_10_20_cd partition of part_10_20 for values in ('cd'); ...@@ -1718,7 +1718,7 @@ create table part_10_20_cd partition of part_10_20 for values in ('cd');
create table part_21_30 partition of range_list_parted for values from (21) to (30) partition by list (b); create table part_21_30 partition of range_list_parted for values from (21) to (30) partition by list (b);
create table part_21_30_ab partition of part_21_30 for values in ('ab'); create table part_21_30_ab partition of part_21_30 for values in ('ab');
create table part_21_30_cd partition of part_21_30 for values in ('cd'); create table part_21_30_cd partition of part_21_30 for values in ('cd');
create table part_40_inf partition of range_list_parted for values from (40) to (unbounded) partition by list (b); create table part_40_inf partition of range_list_parted for values from (40) to (maxvalue) partition by list (b);
create table part_40_inf_ab partition of part_40_inf for values in ('ab'); create table part_40_inf_ab partition of part_40_inf for values in ('ab');
create table part_40_inf_cd partition of part_40_inf for values in ('cd'); create table part_40_inf_cd partition of part_40_inf for values in ('cd');
create table part_40_inf_null partition of part_40_inf for values in (null); create table part_40_inf_null partition of part_40_inf for values in (null);
...@@ -1831,12 +1831,12 @@ drop table range_list_parted; ...@@ -1831,12 +1831,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 (unbounded, unbounded, unbounded) to (1, 1, 1); create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) 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 (unbounded, unbounded, unbounded); create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, 0, 0);
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
------------------------------ ------------------------------
......
This diff is collapsed.
...@@ -483,12 +483,7 @@ CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a', 1) TO ('z ...@@ -483,12 +483,7 @@ CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a', 1) TO ('z
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a') TO ('z', 1); CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM ('a') TO ('z', 1);
-- cannot specify null values in range bounds -- cannot specify null values in range bounds
CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (unbounded); CREATE TABLE fail_part PARTITION OF range_parted FOR VALUES FROM (null) TO (maxvalue);
-- 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 -- check if compatible with the specified parent
...@@ -542,10 +537,10 @@ CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (0); ...@@ -542,10 +537,10 @@ CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (0);
-- note that the range '[1, 1)' has no elements -- note that the range '[1, 1)' has no elements
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1);
CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (unbounded) TO (1); CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (1);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (unbounded) TO (2); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (2);
CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10); CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (unbounded); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (maxvalue);
CREATE TABLE part2 PARTITION OF range_parted2 FOR VALUES FROM (20) TO (30); CREATE TABLE part2 PARTITION OF range_parted2 FOR VALUES FROM (20) TO (30);
CREATE TABLE part3 PARTITION OF range_parted2 FOR VALUES FROM (30) TO (40); CREATE TABLE part3 PARTITION OF range_parted2 FOR VALUES FROM (30) TO (40);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (10) TO (30); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (10) TO (30);
...@@ -557,18 +552,18 @@ CREATE TABLE range_parted3 ( ...@@ -557,18 +552,18 @@ CREATE TABLE range_parted3 (
b int b int
) PARTITION BY RANGE (a, (b+1)); ) PARTITION BY RANGE (a, (b+1));
CREATE TABLE part00 PARTITION OF range_parted3 FOR VALUES FROM (0, unbounded) TO (0, unbounded); CREATE TABLE part00 PARTITION OF range_parted3 FOR VALUES FROM (0, minvalue) TO (0, maxvalue);
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (0, unbounded) TO (0, 1); CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (0, minvalue) TO (0, 1);
CREATE TABLE part10 PARTITION OF range_parted3 FOR VALUES FROM (1, unbounded) TO (1, 1); CREATE TABLE part10 PARTITION OF range_parted3 FOR VALUES FROM (1, minvalue) TO (1, 1);
CREATE TABLE part11 PARTITION OF range_parted3 FOR VALUES FROM (1, 1) TO (1, 10); CREATE TABLE part11 PARTITION OF range_parted3 FOR VALUES FROM (1, 1) TO (1, 10);
CREATE TABLE part12 PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, unbounded); CREATE TABLE part12 PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, maxvalue);
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, 20); CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, 10) TO (1, 20);
-- cannot create a partition that says column b is allowed to range -- cannot create a partition that says column b is allowed to range
-- from -infinity to +infinity, while there exist partitions that have -- from -infinity to +infinity, while there exist partitions that have
-- more specific ranges -- more specific ranges
CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, unbounded) TO (1, unbounded); CREATE TABLE fail_part PARTITION OF range_parted3 FOR VALUES FROM (1, minvalue) TO (1, maxvalue);
-- check schema propagation from parent -- check schema propagation from parent
...@@ -626,14 +621,14 @@ CREATE TABLE part_c_1_10 PARTITION OF part_c FOR VALUES FROM (1) TO (10); ...@@ -626,14 +621,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 (UNBOUNDED, UNBOUNDED, UNBOUNDED) TO (UNBOUNDED, UNBOUNDED, UNBOUNDED); CREATE TABLE unbounded_range_part PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (MAXVALUE, 0, 0);
\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 (UNBOUNDED, UNBOUNDED, UNBOUNDED) TO (1, UNBOUNDED, UNBOUNDED); CREATE TABLE range_parted4_1 PARTITION OF range_parted4 FOR VALUES FROM (MINVALUE, 0, 0) TO (1, MAXVALUE, 0);
\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, UNBOUNDED); 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, UNBOUNDED) TO (9, UNBOUNDED, UNBOUNDED); CREATE TABLE range_parted4_3 PARTITION OF range_parted4 FOR VALUES FROM (6, 8, MINVALUE) TO (9, MAXVALUE, 0);
\d+ range_parted4_3 \d+ range_parted4_3
DROP TABLE range_parted4; DROP TABLE range_parted4;
......
...@@ -623,7 +623,7 @@ create table part_10_20_cd partition of part_10_20 for values in ('cd'); ...@@ -623,7 +623,7 @@ create table part_10_20_cd partition of part_10_20 for values in ('cd');
create table part_21_30 partition of range_list_parted for values from (21) to (30) partition by list (b); create table part_21_30 partition of range_list_parted for values from (21) to (30) partition by list (b);
create table part_21_30_ab partition of part_21_30 for values in ('ab'); create table part_21_30_ab partition of part_21_30 for values in ('ab');
create table part_21_30_cd partition of part_21_30 for values in ('cd'); create table part_21_30_cd partition of part_21_30 for values in ('cd');
create table part_40_inf partition of range_list_parted for values from (40) to (unbounded) partition by list (b); create table part_40_inf partition of range_list_parted for values from (40) to (maxvalue) partition by list (b);
create table part_40_inf_ab partition of part_40_inf for values in ('ab'); create table part_40_inf_ab partition of part_40_inf for values in ('ab');
create table part_40_inf_cd partition of part_40_inf for values in ('cd'); create table part_40_inf_cd partition of part_40_inf for values in ('cd');
create table part_40_inf_null partition of part_40_inf for values in (null); create table part_40_inf_null partition of part_40_inf for values in (null);
...@@ -647,12 +647,12 @@ drop table range_list_parted; ...@@ -647,12 +647,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 (unbounded, unbounded, unbounded) to (1, 1, 1); create table mcrparted0 partition of mcrparted for values from (minvalue, 0, 0) 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 (unbounded, unbounded, unbounded); create table mcrparted5 partition of mcrparted for values from (20, 20, 20) to (maxvalue, 0, 0);
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
......
...@@ -169,7 +169,7 @@ select tableoid::regclass, * from list_parted; ...@@ -169,7 +169,7 @@ select tableoid::regclass, * from list_parted;
-- some more tests to exercise tuple-routing with multi-level partitioning -- some more tests to exercise tuple-routing with multi-level partitioning
create table part_gg partition of list_parted for values in ('gg') partition by range (b); create table part_gg partition of list_parted for values in ('gg') partition by range (b);
create table part_gg1 partition of part_gg for values from (unbounded) to (1); create table part_gg1 partition of part_gg for values from (minvalue) to (1);
create table part_gg2 partition of part_gg for values from (1) to (10) partition by range (b); create table part_gg2 partition of part_gg for values from (1) to (10) partition by range (b);
create table part_gg2_1 partition of part_gg2 for values from (1) to (5); create table part_gg2_1 partition of part_gg2 for values from (1) to (5);
create table part_gg2_2 partition of part_gg2 for values from (5) to (10); create table part_gg2_2 partition of part_gg2 for values from (5) to (10);
...@@ -293,12 +293,12 @@ drop table key_desc, key_desc_1; ...@@ -293,12 +293,12 @@ drop table key_desc, key_desc_1;
-- 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 mcrparted (a int, b int, c int) partition by range (a, abs(b), c);
create table mcrparted0 partition of mcrparted for values from (unbounded, unbounded, unbounded) to (1, unbounded, unbounded); 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, unbounded) 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, unbounded) to (10, unbounded, unbounded); create table mcrparted2 partition of mcrparted for values from (10, 6, minvalue) to (10, maxvalue, 0);
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, unbounded, unbounded) to (30, 20, unbounded); create table mcrparted4 partition of mcrparted for values from (21, minvalue, 0) to (30, 20, maxvalue);
create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (unbounded, unbounded, unbounded); create table mcrparted5 partition of mcrparted for values from (30, 21, 20) to (maxvalue, 0, 0);
-- routed to mcrparted0 -- routed to mcrparted0
insert into mcrparted values (0, 1, 1); insert into mcrparted values (0, 1, 1);
...@@ -360,3 +360,30 @@ drop role regress_coldesc_role; ...@@ -360,3 +360,30 @@ drop role regress_coldesc_role;
drop table inserttest3; drop table inserttest3;
drop table brtrigpartcon; drop table brtrigpartcon;
drop function brtrigpartcon1trigf(); drop function brtrigpartcon1trigf();
-- check multi-column range partitioning with minvalue/maxvalue constraints
create table mcrparted (a text, b int) partition by range(a, b);
create table mcrparted_lt_b partition of mcrparted for values from (minvalue, 0) to ('b', minvalue);
create table mcrparted_b partition of mcrparted for values from ('b', minvalue) to ('c', minvalue);
create table mcrparted_c_to_common partition of mcrparted for values from ('c', minvalue) to ('common', minvalue);
create table mcrparted_common_lt_0 partition of mcrparted for values from ('common', minvalue) to ('common', 0);
create table mcrparted_common_0_to_10 partition of mcrparted for values from ('common', 0) to ('common', 10);
create table mcrparted_common_ge_10 partition of mcrparted for values from ('common', 10) to ('common', maxvalue);
create table mcrparted_gt_common_lt_d partition of mcrparted for values from ('common', maxvalue) to ('d', minvalue);
create table mcrparted_ge_d partition of mcrparted for values from ('d', minvalue) to (maxvalue, 0);
\d+ mcrparted
\d+ mcrparted_lt_b
\d+ mcrparted_b
\d+ mcrparted_c_to_common
\d+ mcrparted_common_lt_0
\d+ mcrparted_common_0_to_10
\d+ mcrparted_common_ge_10
\d+ mcrparted_gt_common_lt_d
\d+ mcrparted_ge_d
insert into mcrparted values ('aaa', 0), ('b', 0), ('bz', 10), ('c', -10),
('comm', -10), ('common', -10), ('common', 0), ('common', 10),
('commons', 0), ('d', -10), ('e', 0);
select tableoid::regclass, * from mcrparted order by a, b;
drop table mcrparted;
...@@ -1562,6 +1562,7 @@ PartitionKey ...@@ -1562,6 +1562,7 @@ PartitionKey
PartitionListValue PartitionListValue
PartitionRangeBound PartitionRangeBound
PartitionRangeDatum PartitionRangeDatum
PartitionRangeDatumKind
PartitionSpec PartitionSpec
PartitionedChildRelInfo PartitionedChildRelInfo
PasswordType PasswordType
......
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