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

Commit1db5667

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 parent8b89a88 commit1db5667

File tree

7 files changed

+678
-553
lines changed

7 files changed

+678
-553
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"
@@ -151,8 +150,6 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
151150
staticHashJoin*create_hashjoin_plan(PlannerInfo*root,HashPath*best_path);
152151
staticNode*replace_nestloop_params(PlannerInfo*root,Node*expr);
153152
staticNode*replace_nestloop_params_mutator(Node*node,PlannerInfo*root);
154-
staticvoidprocess_subquery_nestloop_params(PlannerInfo*root,
155-
List*subplan_params);
156153
staticList*fix_indexqual_references(PlannerInfo*root,IndexPath*index_path);
157154
staticList*fix_indexorderby_references(PlannerInfo*root,IndexPath*index_path);
158155
staticNode*fix_indexqual_operand(Node*node,IndexOptInfo*index,intindexcol);
@@ -310,7 +307,7 @@ create_plan(PlannerInfo *root, Path *best_path)
310307
/* plan_params should not be in use in current query level */
311308
Assert(root->plan_params==NIL);
312309

313-
/* Initialize this module'sprivateworkspace in PlannerInfo */
310+
/* Initialize this module's workspace in PlannerInfo */
314311
root->curOuterRels=NULL;
315312
root->curOuterParams=NIL;
316313

@@ -1554,7 +1551,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
15541551
gather_plan=make_gather(tlist,
15551552
NIL,
15561553
best_path->num_workers,
1557-
SS_assign_special_param(root),
1554+
assign_special_exec_param(root),
15581555
best_path->single_copy,
15591556
subplan);
15601557

@@ -1590,7 +1587,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
15901587
copy_generic_path_info(&gm_plan->plan,&best_path->path);
15911588

15921589
/* Assign the rescan Param. */
1593-
gm_plan->rescan_param=SS_assign_special_param(root);
1590+
gm_plan->rescan_param=assign_special_exec_param(root);
15941591

15951592
/* Gather Merge is pointless with no pathkeys; use Gather instead. */
15961593
Assert(pathkeys!=NIL);
@@ -3774,9 +3771,6 @@ create_nestloop_plan(PlannerInfo *root,
37743771
Relidsouterrelids;
37753772
List*nestParams;
37763773
RelidssaveOuterRels=root->curOuterRels;
3777-
ListCell*cell;
3778-
ListCell*prev;
3779-
ListCell*next;
37803774

37813775
/* NestLoop can project, so no need to be picky about child tlists */
37823776
outer_plan=create_plan_recurse(root,best_path->outerjoinpath,0);
@@ -3820,38 +3814,10 @@ create_nestloop_plan(PlannerInfo *root,
38203814

38213815
/*
38223816
* Identify any nestloop parameters that should be supplied by this join
3823-
* node, andmove them from root->curOuterParams to the nestParams list.
3817+
* node, andremove them from root->curOuterParams.
38243818
*/
38253819
outerrelids=best_path->outerjoinpath->parent->relids;
3826-
nestParams=NIL;
3827-
prev=NULL;
3828-
for (cell=list_head(root->curOuterParams);cell;cell=next)
3829-
{
3830-
NestLoopParam*nlp= (NestLoopParam*)lfirst(cell);
3831-
3832-
next=lnext(cell);
3833-
if (IsA(nlp->paramval,Var)&&
3834-
bms_is_member(nlp->paramval->varno,outerrelids))
3835-
{
3836-
root->curOuterParams=list_delete_cell(root->curOuterParams,
3837-
cell,prev);
3838-
nestParams=lappend(nestParams,nlp);
3839-
}
3840-
elseif (IsA(nlp->paramval,PlaceHolderVar)&&
3841-
bms_overlap(((PlaceHolderVar*)nlp->paramval)->phrels,
3842-
outerrelids)&&
3843-
bms_is_subset(find_placeholder_info(root,
3844-
(PlaceHolderVar*)nlp->paramval,
3845-
false)->ph_eval_at,
3846-
outerrelids))
3847-
{
3848-
root->curOuterParams=list_delete_cell(root->curOuterParams,
3849-
cell,prev);
3850-
nestParams=lappend(nestParams,nlp);
3851-
}
3852-
else
3853-
prev=cell;
3854-
}
3820+
nestParams=identify_current_nestloop_params(root,outerrelids);
38553821

38563822
join_plan=make_nestloop(tlist,
38573823
joinclauses,
@@ -4351,42 +4317,18 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
43514317
if (IsA(node,Var))
43524318
{
43534319
Var*var= (Var*)node;
4354-
Param*param;
4355-
NestLoopParam*nlp;
4356-
ListCell*lc;
43574320

43584321
/* Upper-level Vars should be long gone at this point */
43594322
Assert(var->varlevelsup==0);
43604323
/* If not to be replaced, we can just return the Var unmodified */
43614324
if (!bms_is_member(var->varno,root->curOuterRels))
43624325
returnnode;
4363-
/* Create a Param representing the Var */
4364-
param=assign_nestloop_param_var(root,var);
4365-
/* Is this param already listed in root->curOuterParams? */
4366-
foreach(lc,root->curOuterParams)
4367-
{
4368-
nlp= (NestLoopParam*)lfirst(lc);
4369-
if (nlp->paramno==param->paramid)
4370-
{
4371-
Assert(equal(var,nlp->paramval));
4372-
/* Present, so we can just return the Param */
4373-
return (Node*)param;
4374-
}
4375-
}
4376-
/* No, so add it */
4377-
nlp=makeNode(NestLoopParam);
4378-
nlp->paramno=param->paramid;
4379-
nlp->paramval=var;
4380-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4381-
/* And return the replacement Param */
4382-
return (Node*)param;
4326+
/* Replace the Var with a nestloop Param */
4327+
return (Node*)replace_nestloop_param_var(root,var);
43834328
}
43844329
if (IsA(node,PlaceHolderVar))
43854330
{
43864331
PlaceHolderVar*phv= (PlaceHolderVar*)node;
4387-
Param*param;
4388-
NestLoopParam*nlp;
4389-
ListCell*lc;
43904332

43914333
/* Upper-level PlaceHolderVars should be long gone at this point */
43924334
Assert(phv->phlevelsup==0);
@@ -4423,118 +4365,14 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
44234365
root);
44244366
return (Node*)newphv;
44254367
}
4426-
/* Create a Param representing the PlaceHolderVar */
4427-
param=assign_nestloop_param_placeholdervar(root,phv);
4428-
/* Is this param already listed in root->curOuterParams? */
4429-
foreach(lc,root->curOuterParams)
4430-
{
4431-
nlp= (NestLoopParam*)lfirst(lc);
4432-
if (nlp->paramno==param->paramid)
4433-
{
4434-
Assert(equal(phv,nlp->paramval));
4435-
/* Present, so we can just return the Param */
4436-
return (Node*)param;
4437-
}
4438-
}
4439-
/* No, so add it */
4440-
nlp=makeNode(NestLoopParam);
4441-
nlp->paramno=param->paramid;
4442-
nlp->paramval= (Var*)phv;
4443-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4444-
/* And return the replacement Param */
4445-
return (Node*)param;
4368+
/* Replace the PlaceHolderVar with a nestloop Param */
4369+
return (Node*)replace_nestloop_param_placeholdervar(root,phv);
44464370
}
44474371
returnexpression_tree_mutator(node,
44484372
replace_nestloop_params_mutator,
44494373
(void*)root);
44504374
}
44514375

4452-
/*
4453-
* process_subquery_nestloop_params
4454-
* Handle params of a parameterized subquery that need to be fed
4455-
* from an outer nestloop.
4456-
*
4457-
* Currently, that would be *all* params that a subquery in FROM has demanded
4458-
* from the current query level, since they must be LATERAL references.
4459-
*
4460-
* The subplan's references to the outer variables are already represented
4461-
* as PARAM_EXEC Params, so we need not modify the subplan here. What we
4462-
* do need to do is add entries to root->curOuterParams to signal the parent
4463-
* nestloop plan node that it must provide these values.
4464-
*/
4465-
staticvoid
4466-
process_subquery_nestloop_params(PlannerInfo*root,List*subplan_params)
4467-
{
4468-
ListCell*ppl;
4469-
4470-
foreach(ppl,subplan_params)
4471-
{
4472-
PlannerParamItem*pitem= (PlannerParamItem*)lfirst(ppl);
4473-
4474-
if (IsA(pitem->item,Var))
4475-
{
4476-
Var*var= (Var*)pitem->item;
4477-
NestLoopParam*nlp;
4478-
ListCell*lc;
4479-
4480-
/* If not from a nestloop outer rel, complain */
4481-
if (!bms_is_member(var->varno,root->curOuterRels))
4482-
elog(ERROR,"non-LATERAL parameter required by subquery");
4483-
/* Is this param already listed in root->curOuterParams? */
4484-
foreach(lc,root->curOuterParams)
4485-
{
4486-
nlp= (NestLoopParam*)lfirst(lc);
4487-
if (nlp->paramno==pitem->paramId)
4488-
{
4489-
Assert(equal(var,nlp->paramval));
4490-
/* Present, so nothing to do */
4491-
break;
4492-
}
4493-
}
4494-
if (lc==NULL)
4495-
{
4496-
/* No, so add it */
4497-
nlp=makeNode(NestLoopParam);
4498-
nlp->paramno=pitem->paramId;
4499-
nlp->paramval=copyObject(var);
4500-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4501-
}
4502-
}
4503-
elseif (IsA(pitem->item,PlaceHolderVar))
4504-
{
4505-
PlaceHolderVar*phv= (PlaceHolderVar*)pitem->item;
4506-
NestLoopParam*nlp;
4507-
ListCell*lc;
4508-
4509-
/* If not from a nestloop outer rel, complain */
4510-
if (!bms_is_subset(find_placeholder_info(root,phv, false)->ph_eval_at,
4511-
root->curOuterRels))
4512-
elog(ERROR,"non-LATERAL parameter required by subquery");
4513-
/* Is this param already listed in root->curOuterParams? */
4514-
foreach(lc,root->curOuterParams)
4515-
{
4516-
nlp= (NestLoopParam*)lfirst(lc);
4517-
if (nlp->paramno==pitem->paramId)
4518-
{
4519-
Assert(equal(phv,nlp->paramval));
4520-
/* Present, so nothing to do */
4521-
break;
4522-
}
4523-
}
4524-
if (lc==NULL)
4525-
{
4526-
/* No, so add it */
4527-
nlp=makeNode(NestLoopParam);
4528-
nlp->paramno=pitem->paramId;
4529-
nlp->paramval= (Var*)copyObject(phv);
4530-
root->curOuterParams=lappend(root->curOuterParams,nlp);
4531-
}
4532-
}
4533-
else
4534-
elog(ERROR,"unexpected type of subquery parameter");
4535-
}
4536-
}
4537-
45384376
/*
45394377
* fix_indexqual_references
45404378
* 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
@@ -41,6 +41,7 @@
4141
#include"optimizer/clauses.h"
4242
#include"optimizer/cost.h"
4343
#include"optimizer/inherit.h"
44+
#include"optimizer/paramassign.h"
4445
#include"optimizer/pathnode.h"
4546
#include"optimizer/paths.h"
4647
#include"optimizer/plancat.h"
@@ -635,7 +636,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
635636
root->inhTargetKind=INHKIND_NONE;
636637
root->hasRecursion=hasRecursion;
637638
if (hasRecursion)
638-
root->wt_param_id=SS_assign_special_param(root);
639+
root->wt_param_id=assign_special_exec_param(root);
639640
else
640641
root->wt_param_id=-1;
641642
root->non_recursive_path=NULL;
@@ -1616,7 +1617,7 @@ inheritance_planner(PlannerInfo *root)
16161617
returningLists,
16171618
rowMarks,
16181619
NULL,
1619-
SS_assign_special_param(root)));
1620+
assign_special_exec_param(root)));
16201621
}
16211622

16221623
/*--------------------
@@ -2131,7 +2132,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
21312132
{
21322133
path= (Path*)create_lockrows_path(root,final_rel,path,
21332134
root->rowMarks,
2134-
SS_assign_special_param(root));
2135+
assign_special_exec_param(root));
21352136
}
21362137

21372138
/*
@@ -2204,7 +2205,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
22042205
returningLists,
22052206
rowMarks,
22062207
parse->onConflict,
2207-
SS_assign_special_param(root));
2208+
assign_special_exec_param(root));
22082209
}
22092210

22102211
/* And shove it into final_rel */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp