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

Commit2977a31

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 parentcbb3e08 commit2977a31

File tree

7 files changed

+666
-520
lines changed

7 files changed

+666
-520
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"
@@ -153,8 +152,6 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
153152
staticHashJoin*create_hashjoin_plan(PlannerInfo*root,HashPath*best_path);
154153
staticNode*replace_nestloop_params(PlannerInfo*root,Node*expr);
155154
staticNode*replace_nestloop_params_mutator(Node*node,PlannerInfo*root);
156-
staticvoidprocess_subquery_nestloop_params(PlannerInfo*root,
157-
List*subplan_params);
158155
staticList*fix_indexqual_references(PlannerInfo*root,IndexPath*index_path);
159156
staticList*fix_indexorderby_references(PlannerInfo*root,IndexPath*index_path);
160157
staticNode*fix_indexqual_operand(Node*node,IndexOptInfo*index,intindexcol);
@@ -307,7 +304,7 @@ create_plan(PlannerInfo *root, Path *best_path)
307304
/* plan_params should not be in use in current query level */
308305
Assert(root->plan_params==NIL);
309306

310-
/* Initialize this module'sprivateworkspace in PlannerInfo */
307+
/* Initialize this module's workspace in PlannerInfo */
311308
root->curOuterRels=NULL;
312309
root->curOuterParams=NIL;
313310

@@ -1464,7 +1461,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
14641461
gather_plan=make_gather(tlist,
14651462
NIL,
14661463
best_path->num_workers,
1467-
SS_assign_special_param(root),
1464+
assign_special_exec_param(root),
14681465
best_path->single_copy,
14691466
subplan);
14701467

@@ -1500,7 +1497,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
15001497
copy_generic_path_info(&gm_plan->plan,&best_path->path);
15011498

15021499
/* Assign the rescan Param. */
1503-
gm_plan->rescan_param=SS_assign_special_param(root);
1500+
gm_plan->rescan_param=assign_special_exec_param(root);
15041501

15051502
/* Gather Merge is pointless with no pathkeys; use Gather instead. */
15061503
Assert(pathkeys!=NIL);
@@ -3684,9 +3681,6 @@ create_nestloop_plan(PlannerInfo *root,
36843681
Relidsouterrelids;
36853682
List*nestParams;
36863683
RelidssaveOuterRels=root->curOuterRels;
3687-
ListCell*cell;
3688-
ListCell*prev;
3689-
ListCell*next;
36903684

36913685
/* NestLoop can project, so no need to be picky about child tlists */
36923686
outer_plan=create_plan_recurse(root,best_path->outerjoinpath,0);
@@ -3730,38 +3724,10 @@ create_nestloop_plan(PlannerInfo *root,
37303724

37313725
/*
37323726
* Identify any nestloop parameters that should be supplied by this join
3733-
* node, andmove them from root->curOuterParams to the nestParams list.
3727+
* node, andremove them from root->curOuterParams.
37343728
*/
37353729
outerrelids=best_path->outerjoinpath->parent->relids;
3736-
nestParams=NIL;
3737-
prev=NULL;
3738-
for (cell=list_head(root->curOuterParams);cell;cell=next)
3739-
{
3740-
NestLoopParam*nlp= (NestLoopParam*)lfirst(cell);
3741-
3742-
next=lnext(cell);
3743-
if (IsA(nlp->paramval,Var)&&
3744-
bms_is_member(nlp->paramval->varno,outerrelids))
3745-
{
3746-
root->curOuterParams=list_delete_cell(root->curOuterParams,
3747-
cell,prev);
3748-
nestParams=lappend(nestParams,nlp);
3749-
}
3750-
elseif (IsA(nlp->paramval,PlaceHolderVar)&&
3751-
bms_overlap(((PlaceHolderVar*)nlp->paramval)->phrels,
3752-
outerrelids)&&
3753-
bms_is_subset(find_placeholder_info(root,
3754-
(PlaceHolderVar*)nlp->paramval,
3755-
false)->ph_eval_at,
3756-
outerrelids))
3757-
{
3758-
root->curOuterParams=list_delete_cell(root->curOuterParams,
3759-
cell,prev);
3760-
nestParams=lappend(nestParams,nlp);
3761-
}
3762-
else
3763-
prev=cell;
3764-
}
3730+
nestParams=identify_current_nestloop_params(root,outerrelids);
37653731

37663732
join_plan=make_nestloop(tlist,
37673733
joinclauses,
@@ -4244,42 +4210,18 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
42444210
if (IsA(node,Var))
42454211
{
42464212
Var*var= (Var*)node;
4247-
Param*param;
4248-
NestLoopParam*nlp;
4249-
ListCell*lc;
42504213

42514214
/* Upper-level Vars should be long gone at this point */
42524215
Assert(var->varlevelsup==0);
42534216
/* If not to be replaced, we can just return the Var unmodified */
42544217
if (!bms_is_member(var->varno,root->curOuterRels))
42554218
returnnode;
4256-
/* Create a Param representing the Var */
4257-
param=assign_nestloop_param_var(root,var);
4258-
/* Is this param already listed in root->curOuterParams? */
4259-
foreach(lc,root->curOuterParams)
4260-
{
4261-
nlp= (NestLoopParam*)lfirst(lc);
4262-
if (nlp->paramno==param->paramid)
4263-
{
4264-
Assert(equal(var,nlp->paramval));
4265-
/* Present, so we can just return the Param */
4266-
return (Node*)param;
4267-
}
4268-
}
4269-
/* No, so add it */
4270-
nlp=makeNode(NestLoopParam);
4271-
nlp->paramno=param->paramid;
4272-
nlp->paramval=var;
4273-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4274-
/* And return the replacement Param */
4275-
return (Node*)param;
4219+
/* Replace the Var with a nestloop Param */
4220+
return (Node*)replace_nestloop_param_var(root,var);
42764221
}
42774222
if (IsA(node,PlaceHolderVar))
42784223
{
42794224
PlaceHolderVar*phv= (PlaceHolderVar*)node;
4280-
Param*param;
4281-
NestLoopParam*nlp;
4282-
ListCell*lc;
42834225

42844226
/* Upper-level PlaceHolderVars should be long gone at this point */
42854227
Assert(phv->phlevelsup==0);
@@ -4316,118 +4258,14 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
43164258
root);
43174259
return (Node*)newphv;
43184260
}
4319-
/* Create a Param representing the PlaceHolderVar */
4320-
param=assign_nestloop_param_placeholdervar(root,phv);
4321-
/* Is this param already listed in root->curOuterParams? */
4322-
foreach(lc,root->curOuterParams)
4323-
{
4324-
nlp= (NestLoopParam*)lfirst(lc);
4325-
if (nlp->paramno==param->paramid)
4326-
{
4327-
Assert(equal(phv,nlp->paramval));
4328-
/* Present, so we can just return the Param */
4329-
return (Node*)param;
4330-
}
4331-
}
4332-
/* No, so add it */
4333-
nlp=makeNode(NestLoopParam);
4334-
nlp->paramno=param->paramid;
4335-
nlp->paramval= (Var*)phv;
4336-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4337-
/* And return the replacement Param */
4338-
return (Node*)param;
4261+
/* Replace the PlaceHolderVar with a nestloop Param */
4262+
return (Node*)replace_nestloop_param_placeholdervar(root,phv);
43394263
}
43404264
returnexpression_tree_mutator(node,
43414265
replace_nestloop_params_mutator,
43424266
(void*)root);
43434267
}
43444268

4345-
/*
4346-
* process_subquery_nestloop_params
4347-
* Handle params of a parameterized subquery that need to be fed
4348-
* from an outer nestloop.
4349-
*
4350-
* Currently, that would be *all* params that a subquery in FROM has demanded
4351-
* from the current query level, since they must be LATERAL references.
4352-
*
4353-
* The subplan's references to the outer variables are already represented
4354-
* as PARAM_EXEC Params, so we need not modify the subplan here. What we
4355-
* do need to do is add entries to root->curOuterParams to signal the parent
4356-
* nestloop plan node that it must provide these values.
4357-
*/
4358-
staticvoid
4359-
process_subquery_nestloop_params(PlannerInfo*root,List*subplan_params)
4360-
{
4361-
ListCell*ppl;
4362-
4363-
foreach(ppl,subplan_params)
4364-
{
4365-
PlannerParamItem*pitem= (PlannerParamItem*)lfirst(ppl);
4366-
4367-
if (IsA(pitem->item,Var))
4368-
{
4369-
Var*var= (Var*)pitem->item;
4370-
NestLoopParam*nlp;
4371-
ListCell*lc;
4372-
4373-
/* If not from a nestloop outer rel, complain */
4374-
if (!bms_is_member(var->varno,root->curOuterRels))
4375-
elog(ERROR,"non-LATERAL parameter required by subquery");
4376-
/* Is this param already listed in root->curOuterParams? */
4377-
foreach(lc,root->curOuterParams)
4378-
{
4379-
nlp= (NestLoopParam*)lfirst(lc);
4380-
if (nlp->paramno==pitem->paramId)
4381-
{
4382-
Assert(equal(var,nlp->paramval));
4383-
/* Present, so nothing to do */
4384-
break;
4385-
}
4386-
}
4387-
if (lc==NULL)
4388-
{
4389-
/* No, so add it */
4390-
nlp=makeNode(NestLoopParam);
4391-
nlp->paramno=pitem->paramId;
4392-
nlp->paramval=copyObject(var);
4393-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4394-
}
4395-
}
4396-
elseif (IsA(pitem->item,PlaceHolderVar))
4397-
{
4398-
PlaceHolderVar*phv= (PlaceHolderVar*)pitem->item;
4399-
NestLoopParam*nlp;
4400-
ListCell*lc;
4401-
4402-
/* If not from a nestloop outer rel, complain */
4403-
if (!bms_is_subset(find_placeholder_info(root,phv, false)->ph_eval_at,
4404-
root->curOuterRels))
4405-
elog(ERROR,"non-LATERAL parameter required by subquery");
4406-
/* Is this param already listed in root->curOuterParams? */
4407-
foreach(lc,root->curOuterParams)
4408-
{
4409-
nlp= (NestLoopParam*)lfirst(lc);
4410-
if (nlp->paramno==pitem->paramId)
4411-
{
4412-
Assert(equal(phv,nlp->paramval));
4413-
/* Present, so nothing to do */
4414-
break;
4415-
}
4416-
}
4417-
if (lc==NULL)
4418-
{
4419-
/* No, so add it */
4420-
nlp=makeNode(NestLoopParam);
4421-
nlp->paramno=pitem->paramId;
4422-
nlp->paramval= (Var*)copyObject(phv);
4423-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4424-
}
4425-
}
4426-
else
4427-
elog(ERROR,"unexpected type of subquery parameter");
4428-
}
4429-
}
4430-
44314269
/*
44324270
* fix_indexqual_references
44334271
* 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
@@ -38,6 +38,7 @@
3838
#endif
3939
#include"optimizer/clauses.h"
4040
#include"optimizer/cost.h"
41+
#include"optimizer/paramassign.h"
4142
#include"optimizer/pathnode.h"
4243
#include"optimizer/paths.h"
4344
#include"optimizer/plancat.h"
@@ -522,7 +523,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
522523
root->hasInheritedTarget= false;
523524
root->hasRecursion=hasRecursion;
524525
if (hasRecursion)
525-
root->wt_param_id=SS_assign_special_param(root);
526+
root->wt_param_id=assign_special_exec_param(root);
526527
else
527528
root->wt_param_id=-1;
528529
root->non_recursive_path=NULL;
@@ -1449,7 +1450,7 @@ inheritance_planner(PlannerInfo *root)
14491450
returningLists,
14501451
rowMarks,
14511452
NULL,
1452-
SS_assign_special_param(root)));
1453+
assign_special_exec_param(root)));
14531454
}
14541455

14551456
/*--------------------
@@ -1999,7 +2000,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
19992000
{
20002001
path= (Path*)create_lockrows_path(root,final_rel,path,
20012002
root->rowMarks,
2002-
SS_assign_special_param(root));
2003+
assign_special_exec_param(root));
20032004
}
20042005

20052006
/*
@@ -2060,7 +2061,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
20602061
returningLists,
20612062
rowMarks,
20622063
parse->onConflict,
2063-
SS_assign_special_param(root));
2064+
assign_special_exec_param(root));
20642065
}
20652066

20662067
/* And shove it into final_rel */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp