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

Commit05eb923

Browse files
committed
Avoid sharing PARAM_EXEC slots between different levels of NestLoop.
Up to now, createplan.c attempted to share PARAM_EXEC slots forNestLoopParams across different plan levels, if the same underlying Varwas being fed down to different righthand-side subplan trees by differentNestLoops. This was, I think, more of an artifact of using subselect.c'sPlannerParamItem infrastructure than an explicit design goal, but anywaythat was the end result.This works well enough as long as the plan tree is executing synchronously,but the feature whereby Gather can execute the parallelized subplan locallybreaks it. An upper NestLoop node might execute for a row retrieved froma parallel worker, and assign a value for a PARAM_EXEC slot from that row,while the leader's copy of the parallelized subplan is suspended with adifferent active value of the row the Var comes from. When controleventually returns to the leader's subplan, it gets the wrong answers ifthe same PARAM_EXEC slot is being used within the subplan, as reportedin bug #15577 from Bartosz Polnik.This is pretty reminiscent of the problem fixed in commit46c508f, andthe proper fix seems to be the same: don't try to share PARAM_EXEC slotsacross different levels of controlling NestLoop nodes.This requires decoupling NestLoopParam handling from PlannerParamItemhandling, although the logic remains somewhat similar. To avoid bizarredivision of labor between subselect.c and createplan.c, I decided to moveall the param-slot-assignment logic for both cases out of those filesand put it into a new file paramassign.c. Hopefully it's a bit betterdocumented now, too.A regression test case for this might be nice, but we don't know atest case that triggers the problem with a suitably small amountof data.Back-patch to 9.6 where we added Gather nodes. It's conceivable thatrelated problems exist in older branches; but without some evidencefor that, I'll leave the older branches alone.Discussion:https://postgr.es/m/15577-ca61ab18904af852@postgresql.org
1 parentc559d8d commit05eb923

File tree

7 files changed

+683
-537
lines changed

7 files changed

+683
-537
lines changed

‎src/backend/optimizer/plan/createplan.c

Lines changed: 10 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include<limits.h>
2020
#include<math.h>
2121

22-
#include"access/stratnum.h"
2322
#include"access/sysattr.h"
2423
#include"catalog/pg_class.h"
2524
#include"foreign/fdwapi.h"
@@ -29,11 +28,11 @@
2928
#include"nodes/nodeFuncs.h"
3029
#include"optimizer/clauses.h"
3130
#include"optimizer/cost.h"
31+
#include"optimizer/paramassign.h"
3232
#include"optimizer/paths.h"
3333
#include"optimizer/placeholder.h"
3434
#include"optimizer/plancat.h"
3535
#include"optimizer/planmain.h"
36-
#include"optimizer/planner.h"
3736
#include"optimizer/predtest.h"
3837
#include"optimizer/restrictinfo.h"
3938
#include"optimizer/subselect.h"
@@ -152,8 +151,6 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
152151
staticHashJoin*create_hashjoin_plan(PlannerInfo*root,HashPath*best_path);
153152
staticNode*replace_nestloop_params(PlannerInfo*root,Node*expr);
154153
staticNode*replace_nestloop_params_mutator(Node*node,PlannerInfo*root);
155-
staticvoidprocess_subquery_nestloop_params(PlannerInfo*root,
156-
List*subplan_params);
157154
staticList*fix_indexqual_references(PlannerInfo*root,IndexPath*index_path);
158155
staticList*fix_indexorderby_references(PlannerInfo*root,IndexPath*index_path);
159156
staticNode*fix_indexqual_operand(Node*node,IndexOptInfo*index,intindexcol);
@@ -312,7 +309,7 @@ create_plan(PlannerInfo *root, Path *best_path)
312309
/* plan_params should not be in use in current query level */
313310
Assert(root->plan_params==NIL);
314311

315-
/* Initialize this module'sprivateworkspace in PlannerInfo */
312+
/* Initialize this module's workspace in PlannerInfo */
316313
root->curOuterRels=NULL;
317314
root->curOuterParams=NIL;
318315

@@ -1531,7 +1528,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
15311528
gather_plan=make_gather(tlist,
15321529
NIL,
15331530
best_path->num_workers,
1534-
SS_assign_special_param(root),
1531+
assign_special_exec_param(root),
15351532
best_path->single_copy,
15361533
subplan);
15371534

@@ -1567,7 +1564,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
15671564
copy_generic_path_info(&gm_plan->plan,&best_path->path);
15681565

15691566
/* Assign the rescan Param. */
1570-
gm_plan->rescan_param=SS_assign_special_param(root);
1567+
gm_plan->rescan_param=assign_special_exec_param(root);
15711568

15721569
/* Gather Merge is pointless with no pathkeys; use Gather instead. */
15731570
Assert(pathkeys!=NIL);
@@ -3706,9 +3703,6 @@ create_nestloop_plan(PlannerInfo *root,
37063703
Relidsouterrelids;
37073704
List*nestParams;
37083705
RelidssaveOuterRels=root->curOuterRels;
3709-
ListCell*cell;
3710-
ListCell*prev;
3711-
ListCell*next;
37123706

37133707
/* NestLoop can project, so no need to be picky about child tlists */
37143708
outer_plan=create_plan_recurse(root,best_path->outerjoinpath,0);
@@ -3752,38 +3746,10 @@ create_nestloop_plan(PlannerInfo *root,
37523746

37533747
/*
37543748
* Identify any nestloop parameters that should be supplied by this join
3755-
* node, andmove them from root->curOuterParams to the nestParams list.
3749+
* node, andremove them from root->curOuterParams.
37563750
*/
37573751
outerrelids=best_path->outerjoinpath->parent->relids;
3758-
nestParams=NIL;
3759-
prev=NULL;
3760-
for (cell=list_head(root->curOuterParams);cell;cell=next)
3761-
{
3762-
NestLoopParam*nlp= (NestLoopParam*)lfirst(cell);
3763-
3764-
next=lnext(cell);
3765-
if (IsA(nlp->paramval,Var)&&
3766-
bms_is_member(nlp->paramval->varno,outerrelids))
3767-
{
3768-
root->curOuterParams=list_delete_cell(root->curOuterParams,
3769-
cell,prev);
3770-
nestParams=lappend(nestParams,nlp);
3771-
}
3772-
elseif (IsA(nlp->paramval,PlaceHolderVar)&&
3773-
bms_overlap(((PlaceHolderVar*)nlp->paramval)->phrels,
3774-
outerrelids)&&
3775-
bms_is_subset(find_placeholder_info(root,
3776-
(PlaceHolderVar*)nlp->paramval,
3777-
false)->ph_eval_at,
3778-
outerrelids))
3779-
{
3780-
root->curOuterParams=list_delete_cell(root->curOuterParams,
3781-
cell,prev);
3782-
nestParams=lappend(nestParams,nlp);
3783-
}
3784-
else
3785-
prev=cell;
3786-
}
3752+
nestParams=identify_current_nestloop_params(root,outerrelids);
37873753

37883754
join_plan=make_nestloop(tlist,
37893755
joinclauses,
@@ -4283,42 +4249,18 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
42834249
if (IsA(node,Var))
42844250
{
42854251
Var*var= (Var*)node;
4286-
Param*param;
4287-
NestLoopParam*nlp;
4288-
ListCell*lc;
42894252

42904253
/* Upper-level Vars should be long gone at this point */
42914254
Assert(var->varlevelsup==0);
42924255
/* If not to be replaced, we can just return the Var unmodified */
42934256
if (!bms_is_member(var->varno,root->curOuterRels))
42944257
returnnode;
4295-
/* Create a Param representing the Var */
4296-
param=assign_nestloop_param_var(root,var);
4297-
/* Is this param already listed in root->curOuterParams? */
4298-
foreach(lc,root->curOuterParams)
4299-
{
4300-
nlp= (NestLoopParam*)lfirst(lc);
4301-
if (nlp->paramno==param->paramid)
4302-
{
4303-
Assert(equal(var,nlp->paramval));
4304-
/* Present, so we can just return the Param */
4305-
return (Node*)param;
4306-
}
4307-
}
4308-
/* No, so add it */
4309-
nlp=makeNode(NestLoopParam);
4310-
nlp->paramno=param->paramid;
4311-
nlp->paramval=var;
4312-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4313-
/* And return the replacement Param */
4314-
return (Node*)param;
4258+
/* Replace the Var with a nestloop Param */
4259+
return (Node*)replace_nestloop_param_var(root,var);
43154260
}
43164261
if (IsA(node,PlaceHolderVar))
43174262
{
43184263
PlaceHolderVar*phv= (PlaceHolderVar*)node;
4319-
Param*param;
4320-
NestLoopParam*nlp;
4321-
ListCell*lc;
43224264

43234265
/* Upper-level PlaceHolderVars should be long gone at this point */
43244266
Assert(phv->phlevelsup==0);
@@ -4355,118 +4297,14 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
43554297
root);
43564298
return (Node*)newphv;
43574299
}
4358-
/* Create a Param representing the PlaceHolderVar */
4359-
param=assign_nestloop_param_placeholdervar(root,phv);
4360-
/* Is this param already listed in root->curOuterParams? */
4361-
foreach(lc,root->curOuterParams)
4362-
{
4363-
nlp= (NestLoopParam*)lfirst(lc);
4364-
if (nlp->paramno==param->paramid)
4365-
{
4366-
Assert(equal(phv,nlp->paramval));
4367-
/* Present, so we can just return the Param */
4368-
return (Node*)param;
4369-
}
4370-
}
4371-
/* No, so add it */
4372-
nlp=makeNode(NestLoopParam);
4373-
nlp->paramno=param->paramid;
4374-
nlp->paramval= (Var*)phv;
4375-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4376-
/* And return the replacement Param */
4377-
return (Node*)param;
4300+
/* Replace the PlaceHolderVar with a nestloop Param */
4301+
return (Node*)replace_nestloop_param_placeholdervar(root,phv);
43784302
}
43794303
returnexpression_tree_mutator(node,
43804304
replace_nestloop_params_mutator,
43814305
(void*)root);
43824306
}
43834307

4384-
/*
4385-
* process_subquery_nestloop_params
4386-
* Handle params of a parameterized subquery that need to be fed
4387-
* from an outer nestloop.
4388-
*
4389-
* Currently, that would be *all* params that a subquery in FROM has demanded
4390-
* from the current query level, since they must be LATERAL references.
4391-
*
4392-
* The subplan's references to the outer variables are already represented
4393-
* as PARAM_EXEC Params, so we need not modify the subplan here. What we
4394-
* do need to do is add entries to root->curOuterParams to signal the parent
4395-
* nestloop plan node that it must provide these values.
4396-
*/
4397-
staticvoid
4398-
process_subquery_nestloop_params(PlannerInfo*root,List*subplan_params)
4399-
{
4400-
ListCell*ppl;
4401-
4402-
foreach(ppl,subplan_params)
4403-
{
4404-
PlannerParamItem*pitem= (PlannerParamItem*)lfirst(ppl);
4405-
4406-
if (IsA(pitem->item,Var))
4407-
{
4408-
Var*var= (Var*)pitem->item;
4409-
NestLoopParam*nlp;
4410-
ListCell*lc;
4411-
4412-
/* If not from a nestloop outer rel, complain */
4413-
if (!bms_is_member(var->varno,root->curOuterRels))
4414-
elog(ERROR,"non-LATERAL parameter required by subquery");
4415-
/* Is this param already listed in root->curOuterParams? */
4416-
foreach(lc,root->curOuterParams)
4417-
{
4418-
nlp= (NestLoopParam*)lfirst(lc);
4419-
if (nlp->paramno==pitem->paramId)
4420-
{
4421-
Assert(equal(var,nlp->paramval));
4422-
/* Present, so nothing to do */
4423-
break;
4424-
}
4425-
}
4426-
if (lc==NULL)
4427-
{
4428-
/* No, so add it */
4429-
nlp=makeNode(NestLoopParam);
4430-
nlp->paramno=pitem->paramId;
4431-
nlp->paramval=copyObject(var);
4432-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4433-
}
4434-
}
4435-
elseif (IsA(pitem->item,PlaceHolderVar))
4436-
{
4437-
PlaceHolderVar*phv= (PlaceHolderVar*)pitem->item;
4438-
NestLoopParam*nlp;
4439-
ListCell*lc;
4440-
4441-
/* If not from a nestloop outer rel, complain */
4442-
if (!bms_is_subset(find_placeholder_info(root,phv, false)->ph_eval_at,
4443-
root->curOuterRels))
4444-
elog(ERROR,"non-LATERAL parameter required by subquery");
4445-
/* Is this param already listed in root->curOuterParams? */
4446-
foreach(lc,root->curOuterParams)
4447-
{
4448-
nlp= (NestLoopParam*)lfirst(lc);
4449-
if (nlp->paramno==pitem->paramId)
4450-
{
4451-
Assert(equal(phv,nlp->paramval));
4452-
/* Present, so nothing to do */
4453-
break;
4454-
}
4455-
}
4456-
if (lc==NULL)
4457-
{
4458-
/* No, so add it */
4459-
nlp=makeNode(NestLoopParam);
4460-
nlp->paramno=pitem->paramId;
4461-
nlp->paramval= (Var*)copyObject(phv);
4462-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4463-
}
4464-
}
4465-
else
4466-
elog(ERROR,"unexpected type of subquery parameter");
4467-
}
4468-
}
4469-
44704308
/*
44714309
* fix_indexqual_references
44724310
* Adjust indexqual clauses to the form the executor's indexqual

‎src/backend/optimizer/plan/planner.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#endif
4040
#include"optimizer/clauses.h"
4141
#include"optimizer/cost.h"
42+
#include"optimizer/paramassign.h"
4243
#include"optimizer/pathnode.h"
4344
#include"optimizer/paths.h"
4445
#include"optimizer/plancat.h"
@@ -625,7 +626,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
625626
root->inhTargetKind=INHKIND_NONE;
626627
root->hasRecursion=hasRecursion;
627628
if (hasRecursion)
628-
root->wt_param_id=SS_assign_special_param(root);
629+
root->wt_param_id=assign_special_exec_param(root);
629630
else
630631
root->wt_param_id=-1;
631632
root->non_recursive_path=NULL;
@@ -1640,7 +1641,7 @@ inheritance_planner(PlannerInfo *root)
16401641
returningLists,
16411642
rowMarks,
16421643
NULL,
1643-
SS_assign_special_param(root)));
1644+
assign_special_exec_param(root)));
16441645
}
16451646

16461647
/*--------------------
@@ -2155,7 +2156,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
21552156
{
21562157
path= (Path*)create_lockrows_path(root,final_rel,path,
21572158
root->rowMarks,
2158-
SS_assign_special_param(root));
2159+
assign_special_exec_param(root));
21592160
}
21602161

21612162
/*
@@ -2217,7 +2218,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
22172218
returningLists,
22182219
rowMarks,
22192220
parse->onConflict,
2220-
SS_assign_special_param(root));
2221+
assign_special_exec_param(root));
22212222
}
22222223

22232224
/* And shove it into final_rel */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp