aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/partitioning/partprune.c56
-rw-r--r--src/test/regress/expected/partition_prune.out18
-rw-r--r--src/test/regress/sql/partition_prune.sql4
3 files changed, 52 insertions, 26 deletions
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 09c4ed83b68..2ed1e44c181 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -849,10 +849,11 @@ get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
* the context's steps list. Each step is assigned a step identifier, unique
* even across recursive calls.
*
- * If we find clauses that are mutually contradictory, or a pseudoconstant
- * clause that contains false, we set context->contradictory to true and
- * return NIL (that is, no pruning steps). Caller should consider all
- * partitions as pruned in that case.
+ * If we find clauses that are mutually contradictory, or contradictory with
+ * the partitioning constraint, or a pseudoconstant clause that contains
+ * false, we set context->contradictory to true and return NIL (that is, no
+ * pruning steps). Caller should consider all partitions as pruned in that
+ * case.
*/
static List *
gen_partprune_steps_internal(GeneratePruningStepsContext *context,
@@ -942,35 +943,15 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
}
else
{
+ PartitionPruneStep *orstep;
+
/*
* The arg didn't contain a clause matching this
* partition key. We cannot prune using such an arg.
* To indicate that to the pruning code, we must
* construct a dummy PartitionPruneStepCombine whose
* source_stepids is set to an empty List.
- *
- * However, if we can prove using constraint exclusion
- * that the clause refutes the table's partition
- * constraint (if it's sub-partitioned), we need not
- * bother with that. That is, we effectively ignore
- * this OR arm.
*/
- List *partconstr = context->rel->partition_qual;
- PartitionPruneStep *orstep;
-
- if (partconstr)
- {
- partconstr = (List *)
- expression_planner((Expr *) partconstr);
- if (context->rel->relid != 1)
- ChangeVarNodes((Node *) partconstr, 1,
- context->rel->relid, 0);
- if (predicate_refuted_by(partconstr,
- list_make1(arg),
- false))
- continue;
- }
-
orstep = gen_prune_step_combine(context, NIL,
PARTPRUNE_COMBINE_UNION);
arg_stepids = lappend_int(arg_stepids, orstep->step_id);
@@ -1039,6 +1020,29 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
}
/*
+ * If the clause contradicts the partition constraint, mark the clause
+ * as contradictory and we're done. This is particularly helpful to
+ * prune the default partition.
+ */
+ if (context->rel->partition_qual)
+ {
+ List *partconstr;
+
+ partconstr = (List *)
+ expression_planner((Expr *) context->rel->partition_qual);
+ if (context->rel->relid != 1)
+ ChangeVarNodes((Node *) partconstr, 1,
+ context->rel->relid, 0);
+ if (predicate_refuted_by(partconstr,
+ list_make1(clause),
+ false))
+ {
+ context->contradictory = true;
+ return NIL;
+ }
+ }
+
+ /*
* See if we can match this clause to any of the partition keys.
*/
for (i = 0; i < part_scheme->partnatts; i++)
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index 2d3229fd73f..6ccc91d390c 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -592,6 +592,24 @@ explain (costs off) select * from rlp where a < 1 or (a > 20 and a < 25);
Filter: ((a < 1) OR ((a > 20) AND (a < 25)))
(5 rows)
+-- where clause contradicts sub-partition's constraint
+explain (costs off) select * from rlp where a = 20 or a = 40;
+ QUERY PLAN
+----------------------------------------
+ Append
+ -> Seq Scan on rlp4_1
+ Filter: ((a = 20) OR (a = 40))
+ -> Seq Scan on rlp5_default
+ Filter: ((a = 20) OR (a = 40))
+(5 rows)
+
+explain (costs off) select * from rlp3 where a = 20; /* empty */
+ QUERY PLAN
+--------------------------
+ Result
+ One-Time Filter: false
+(2 rows)
+
-- redundant clauses are eliminated
explain (costs off) select * from rlp where a > 1 and a = 10; /* only default */
QUERY PLAN
diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql
index efdedaaeb8f..a26c2f0e72b 100644
--- a/src/test/regress/sql/partition_prune.sql
+++ b/src/test/regress/sql/partition_prune.sql
@@ -85,6 +85,10 @@ explain (costs off) select * from rlp where a = 29;
explain (costs off) select * from rlp where a >= 29;
explain (costs off) select * from rlp where a < 1 or (a > 20 and a < 25);
+-- where clause contradicts sub-partition's constraint
+explain (costs off) select * from rlp where a = 20 or a = 40;
+explain (costs off) select * from rlp3 where a = 20; /* empty */
+
-- redundant clauses are eliminated
explain (costs off) select * from rlp where a > 1 and a = 10; /* only default */
explain (costs off) select * from rlp where a > 1 and a >=15; /* rlp3 onwards, including default */