Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe3d900

Browse files
committed
Fix run-time partition pruning code to handle NULL values properly.
The previous coding just ignored pruning constraints that compare apartition key to a null-valued expression. This is silly, since reallywhat we can do there is conclude that all partitions are rejected: thepruning operator is known strict so the comparison must always fail.This also fixes the logic to not ignore constisnull for a Const comparisonvalue. That's probably an unreachable case, since the planner wouldnormally have simplified away a strict operator with a constant-null input.But this code has no business assuming that.David Rowley, per a gripe from meDiscussion:https://postgr.es/m/26279.1528670981@sss.pgh.pa.us
1 parent387543f commitbe3d900

File tree

3 files changed

+53
-13
lines changed

3 files changed

+53
-13
lines changed

‎src/backend/partitioning/partprune.c

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *cont
170170
staticboolmatch_boolean_partition_clause(Oidpartopfamily,Expr*clause,
171171
Expr*partkey,Expr**outconst);
172172
staticboolpartkey_datum_from_expr(PartitionPruneContext*context,
173-
Expr*expr,intstateidx,Datum*value);
173+
Expr*expr,intstateidx,
174+
Datum*value,bool*isnull);
174175

175176

176177
/*
@@ -184,8 +185,9 @@ static bool partkey_datum_from_expr(PartitionPruneContext *context,
184185
* indexes.
185186
*
186187
* If no non-Const expressions are being compared to the partition key in any
187-
* of the 'partitioned_rels', then we return NIL. In such a case run-time
188-
* partition pruning would be useless, since the planner did it already.
188+
* of the 'partitioned_rels', then we return NIL to indicate no run-time
189+
* pruning should be performed. Run-time pruning would be useless, since the
190+
* pruning done during planning will have pruned everything that can be.
189191
*/
190192
List*
191193
make_partition_pruneinfo(PlannerInfo*root,List*partition_rels,
@@ -2835,14 +2837,33 @@ perform_pruning_base_step(PartitionPruneContext *context,
28352837
Expr*expr;
28362838
intstateidx;
28372839
Datumdatum;
2840+
boolisnull;
28382841

28392842
expr=lfirst(lc1);
28402843
stateidx=PruneCxtStateIdx(context->partnatts,
28412844
opstep->step.step_id,keyno);
2842-
if (partkey_datum_from_expr(context,expr,stateidx,&datum))
2845+
if (partkey_datum_from_expr(context,expr,stateidx,
2846+
&datum,&isnull))
28432847
{
28442848
Oidcmpfn;
28452849

2850+
/*
2851+
* Since we only allow strict operators in pruning steps, any
2852+
* null-valued comparison value must cause the comparison to
2853+
* fail, so that no partitions could match.
2854+
*/
2855+
if (isnull)
2856+
{
2857+
PruneStepResult*result;
2858+
2859+
result= (PruneStepResult*)palloc(sizeof(PruneStepResult));
2860+
result->bound_offsets=NULL;
2861+
result->scan_default= false;
2862+
result->scan_null= false;
2863+
2864+
returnresult;
2865+
}
2866+
28462867
/*
28472868
* If we're going to need a different comparison function than
28482869
* the one cached in the PartitionKey, we'll need to look up
@@ -3072,8 +3093,8 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
30723093
*Evaluate expression for potential partition pruning
30733094
*
30743095
* Evaluate 'expr', whose ExprState is stateidx of the context exprstate
3075-
* array; set *value to the resulting Datum. Return true if evaluation was
3076-
* possible, otherwise false.
3096+
* array; set *valueand *isnullto the resulting Datum and nullflag.
3097+
*Return true if evaluation waspossible, otherwise false.
30773098
*
30783099
* Note that the evaluated result may be in the per-tuple memory context of
30793100
* context->planstate->ps_ExprContext, and we may have leaked other memory
@@ -3082,11 +3103,16 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
30823103
*/
30833104
staticbool
30843105
partkey_datum_from_expr(PartitionPruneContext*context,
3085-
Expr*expr,intstateidx,Datum*value)
3106+
Expr*expr,intstateidx,
3107+
Datum*value,bool*isnull)
30863108
{
30873109
if (IsA(expr,Const))
30883110
{
3089-
*value= ((Const*)expr)->constvalue;
3111+
/* We can always determine the value of a constant */
3112+
Const*con= (Const*)expr;
3113+
3114+
*value=con->constvalue;
3115+
*isnull=con->constisnull;
30903116
return true;
30913117
}
30923118
else
@@ -3105,14 +3131,10 @@ partkey_datum_from_expr(PartitionPruneContext *context,
31053131
{
31063132
ExprState*exprstate;
31073133
ExprContext*ectx;
3108-
boolisNull;
31093134

31103135
exprstate=context->exprstates[stateidx];
31113136
ectx=context->planstate->ps_ExprContext;
3112-
*value=ExecEvalExprSwitchContext(exprstate,ectx,&isNull);
3113-
if (isNull)
3114-
return false;
3115-
3137+
*value=ExecEvalExprSwitchContext(exprstate,ectx,isnull);
31163138
return true;
31173139
}
31183140
}

‎src/test/regress/expected/partition_prune.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,6 +2731,20 @@ explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,1);
27312731
Filter: ((b = ANY (ARRAY[$1, $2])) AND ($3 <> b) AND ($4 <> b))
27322732
(4 rows)
27332733

2734+
-- Ensure Params that evaluate to NULL properly prune away all partitions
2735+
explain (analyze, costs off, summary off, timing off)
2736+
select * from listp where a = (select null::int);
2737+
QUERY PLAN
2738+
----------------------------------------------
2739+
Append (actual rows=0 loops=1)
2740+
InitPlan 1 (returns $0)
2741+
-> Result (actual rows=1 loops=1)
2742+
-> Seq Scan on listp_1_1 (never executed)
2743+
Filter: (a = $0)
2744+
-> Seq Scan on listp_2_1 (never executed)
2745+
Filter: (a = $0)
2746+
(7 rows)
2747+
27342748
drop table listp;
27352749
-- Ensure runtime pruning works with initplans params with boolean types
27362750
create table boolvalues (value bool not null);

‎src/test/regress/sql/partition_prune.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,10 @@ explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,0);
685685
-- One subplan will remain in this case, but it should not be executed.
686686
explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,1);
687687

688+
-- Ensure Params that evaluate to NULL properly prune away all partitions
689+
explain (analyze, costs off, summary off, timing off)
690+
select*from listpwhere a= (selectnull::int);
691+
688692
droptable listp;
689693

690694
-- Ensure runtime pruning works with initplans params with boolean types

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp