From d26f33c3243669e95498039b2ffd92b296cfdcb2 Mon Sep 17 00:00:00 2001 From: David Rowley Date: Fri, 13 Oct 2023 01:13:59 +1300 Subject: Fix runtime partition pruning for HASH partitioned tables This could only affect HASH partitioned tables with at least 2 partition key columns. If partition pruning was delayed until execution and the query contained an IS NULL qual on one of the partitioned keys, and some subsequent partitioned key was being compared to a non-Const, then this could result in a crash due to the incorrect keyno being used to calculate the stateidx for the expression evaluation code. Here we fix this by properly skipping partitioned keys which have a nullkey set. Effectively, this must be the same as what's going on inside perform_pruning_base_step(). Sergei Glukhov also provided a patch, but that's not what's being used here. Reported-by: Sergei Glukhov Reviewed-by: tender wang, Sergei Glukhov Discussion: https://postgr.es/m/d05b26fa-af54-27e1-f693-6c31590802fa@postgrespro.ru Backpatch-through: 11, where runtime partition pruning was added. --- src/backend/executor/execPartition.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src/backend/executor') diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 606c920b068..8f1ad89bb7f 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -1774,7 +1774,7 @@ ExecInitPruningContext(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 */ @@ -1783,22 +1783,27 @@ ExecInitPruningContext(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); + + /* not needed for Consts */ + if (!IsA(expr, Const)) + { + int stateidx = PruneCxtStateIdx(partnatts, + step->step.step_id, + keyno); - context->exprstates[stateidx] = - ExecInitExpr(expr, context->planstate); + context->exprstates[stateidx] = + ExecInitExpr(expr, context->planstate); + } + lc2 = lnext(step->exprs, lc2); } - keyno++; } } } -- cgit v1.2.3