fix_runtime_pruning_keyno_idx.patch
application/octet-stream
Filename: fix_runtime_pruning_keyno_idx.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/execPartition.c | 29 | 23 |
| src/test/regress/expected/partition_prune.out | 13 | 0 |
| src/test/regress/sql/partition_prune.sql | 6 | 0 |
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index eb8a87fd63..eec84115a7 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -2108,7 +2108,8 @@ InitPartitionPruneContext(PartitionPruneContext *context,
foreach(lc, pruning_steps)
{
PartitionPruneStepOp *step = (PartitionPruneStepOp *) lfirst(lc);
- ListCell *lc2;
+ ListCell *lc2 = list_head(step->exprs);
+
int keyno;
/* not needed for other step kinds */
@@ -2117,34 +2118,39 @@ InitPartitionPruneContext(PartitionPruneContext *context,
Assert(list_length(step->exprs) <= partnatts);
- keyno = 0;
- foreach(lc2, step->exprs)
+ for (keyno = 0; keyno < partnatts; keyno++)
{
- Expr *expr = (Expr *) lfirst(lc2);
+ if (bms_is_member(keyno, step->nullkeys))
+ continue;
/* not needed for Consts */
- if (!IsA(expr, Const))
+ if (lc2 != NULL)
{
- int stateidx = PruneCxtStateIdx(partnatts,
- step->step.step_id,
- keyno);
+ Expr *expr = lfirst(lc2);
- /*
- * When planstate is NULL, pruning_steps is known not to
- * contain any expressions that depend on the parent plan.
- * Information of any available EXTERN parameters must be
- * passed explicitly in that case, which the caller must have
- * made available via econtext.
- */
- if (planstate == NULL)
- context->exprstates[stateidx] =
- ExecInitExprWithParams(expr,
- econtext->ecxt_param_list_info);
- else
- context->exprstates[stateidx] =
- ExecInitExpr(expr, context->planstate);
+ if (!IsA(expr, Const))
+ {
+ int stateidx = PruneCxtStateIdx(partnatts,
+ step->step.step_id,
+ keyno);
+
+ /*
+ * When planstate is NULL, pruning_steps is known not to
+ * contain any expressions that depend on the parent plan.
+ * Information of any available EXTERN parameters must be
+ * passed explicitly in that case, which the caller must have
+ * made available via econtext.
+ */
+ if (planstate == NULL)
+ context->exprstates[stateidx] =
+ ExecInitExprWithParams(expr,
+ econtext->ecxt_param_list_info);
+ else
+ context->exprstates[stateidx] =
+ ExecInitExpr(expr, context->planstate);
+ }
+ lc2 = lnext(step->exprs, lc2);
}
- keyno++;
}
}
}
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index bb1223e2b1..36791293ee 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -1921,6 +1921,19 @@ explain (costs off) select * from hp where (a = 1 and b = 'abcde') or (a = 2 and
Filter: (((a = 1) AND (b = 'abcde'::text)) OR ((a = 2) AND (b = 'xxx'::text)) OR ((a IS NULL) AND (b IS NULL)))
(7 rows)
+-- test run-time pruning
+set plan_cache_mode = 'force_generic_plan';
+prepare stmt (text) AS select * from hp where a is null and b = $1;
+explain (costs off) execute stmt('xxx');
+ QUERY PLAN
+--------------------------------------------
+ Append
+ Subplans Removed: 3
+ -> Seq Scan on hp2 hp_1
+ Filter: ((a IS NULL) AND (b = $1))
+(4 rows)
+
+deallocate stmt;
-- test pruning when not all the partitions exist
drop table hp1;
drop table hp3;
diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql
index 83fed54b8c..d23133fe43 100644
--- a/src/test/regress/sql/partition_prune.sql
+++ b/src/test/regress/sql/partition_prune.sql
@@ -374,6 +374,12 @@ explain (costs off) select * from hp where a = 2 and b = 'xxx';
explain (costs off) select * from hp where a = 1 and b = 'abcde';
explain (costs off) select * from hp where (a = 1 and b = 'abcde') or (a = 2 and b = 'xxx') or (a is null and b is null);
+-- test run-time pruning
+set plan_cache_mode = 'force_generic_plan';
+prepare stmt (text) AS select * from hp where a is null and b = $1;
+explain (costs off) execute stmt('xxx');
+deallocate stmt;
+
-- test pruning when not all the partitions exist
drop table hp1;
drop table hp3;