if (or_expr_args != NIL)
{
- /* OR all the non-default partition constraints; then negate it */
- result = lappend(result,
- list_length(or_expr_args) > 1
- ? makeBoolExpr(OR_EXPR, or_expr_args, -1)
- : linitial(or_expr_args));
- result = list_make1(makeBoolExpr(NOT_EXPR, result, -1));
+ Expr *other_parts_constr;
+
+ /*
+ * Combine the constraints obtained for non-default partitions
+ * using OR. As requested, each of the OR's args doesn't include
+ * the NOT NULL test for partition keys (which is to avoid its
+ * useless repetition). Add the same now.
+ */
+ other_parts_constr =
+ makeBoolExpr(AND_EXPR,
+ lappend(get_range_nulltest(key),
+ list_length(or_expr_args) > 1
+ ? makeBoolExpr(OR_EXPR, or_expr_args,
+ -1)
+ : linitial(or_expr_args)),
+ -1);
+
+ /*
+ * Finally, the default partition contains everything *NOT*
+ * contained in the non-default partitions.
+ */
+ result = list_make1(makeBoolExpr(NOT_EXPR,
+ list_make1(other_parts_constr), -1));
}
return result;
-- check that constraint exclusion is able to cope with the partition
-- 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_def partition of mcrparted default;
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 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 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, maxvalue, maxvalue);
-explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0
- QUERY PLAN
-------------------------------
+explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0, mcrparted_def
+ QUERY PLAN
+---------------------------------
Append
-> Seq Scan on mcrparted0
Filter: (a = 0)
-(3 rows)
+ -> Seq Scan on mcrparted_def
+ Filter: (a = 0)
+(5 rows)
-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, mcrparted_def
QUERY PLAN
---------------------------------------------
Append
-> Seq Scan on mcrparted1
Filter: ((a = 10) AND (abs(b) < 5))
-(3 rows)
+ -> Seq Scan on mcrparted_def
+ Filter: ((a = 10) AND (abs(b) < 5))
+(5 rows)
-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, mcrparted_def
QUERY PLAN
---------------------------------------------
Append
Filter: ((a = 10) AND (abs(b) = 5))
-> Seq Scan on mcrparted2
Filter: ((a = 10) AND (abs(b) = 5))
-(5 rows)
+ -> Seq Scan on mcrparted_def
+ Filter: ((a = 10) AND (abs(b) = 5))
+(7 rows)
explain (costs off) select * from mcrparted where abs(b) = 5; -- scans all partitions
- QUERY PLAN
-------------------------------
+ QUERY PLAN
+---------------------------------
Append
-> Seq Scan on mcrparted0
Filter: (abs(b) = 5)
Filter: (abs(b) = 5)
-> Seq Scan on mcrparted5
Filter: (abs(b) = 5)
-(11 rows)
+ -> Seq Scan on mcrparted_def
+ Filter: (abs(b) = 5)
+(13 rows)
explain (costs off) select * from mcrparted where a > -1; -- scans all partitions
QUERY PLAN
Filter: (a > '-1'::integer)
-> Seq Scan on mcrparted5
Filter: (a > '-1'::integer)
-(13 rows)
+ -> Seq Scan on mcrparted_def
+ Filter: (a > '-1'::integer)
+(15 rows)
explain (costs off) select * from mcrparted where a = 20 and abs(b) = 10 and c > 10; -- scans mcrparted4
QUERY PLAN
Filter: ((c > 10) AND (a = 20) AND (abs(b) = 10))
(3 rows)
-explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5
+explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5, mcrparted_def
QUERY PLAN
-----------------------------------------
Append
Filter: ((c > 20) AND (a = 20))
-> Seq Scan on mcrparted5
Filter: ((c > 20) AND (a = 20))
-(7 rows)
+ -> Seq Scan on mcrparted_def
+ Filter: ((c > 20) AND (a = 20))
+(9 rows)
drop table mcrparted;
-- check that partitioned table Appends cope with being referenced in
-- check that constraint exclusion is able to cope with the partition
-- 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_def partition of mcrparted default;
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 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 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, maxvalue, maxvalue);
-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, mcrparted2
+explain (costs off) select * from mcrparted where a = 0; -- scans mcrparted0, mcrparted_def
+explain (costs off) select * from mcrparted where a = 10 and abs(b) < 5; -- scans mcrparted1, mcrparted_def
+explain (costs off) select * from mcrparted where a = 10 and abs(b) = 5; -- scans mcrparted1, mcrparted2, mcrparted_def
explain (costs off) select * from mcrparted where abs(b) = 5; -- scans all partitions
explain (costs off) select * from mcrparted where a > -1; -- scans all partitions
explain (costs off) select * from mcrparted where a = 20 and abs(b) = 10 and c > 10; -- scans mcrparted4
-explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5
+explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5, mcrparted_def
drop table mcrparted;
-- check that partitioned table Appends cope with being referenced in