8000 Fix PARAM_EXEC assignment mechanism to be safe in the presence of WITH. · haying/postgres@6e54298 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6e54298

Browse files
committed
Fix PARAM_EXEC assignment mechanism to be safe in the presence of WITH.
The planner previously assumed that parameter Vars having the same absolute query level, varno, and varattno could safely be assigned the same runtime PARAM_EXEC slot, even though they might be different Vars appearing in different subqueries. This was (probably) safe before the introduction of CTEs, but the lazy-evalution mechanism used for CTEs means that a CTE can be executed during execution of some other subquery, causing the lifespan of Params at the same syntactic nesting level as the CTE to overlap with use of the same slots inside the CTE. In 9.1 we created additional hazards by using the same parameter-assignment technology for nestloop inner scan parameters, but it was broken before that, as illustrated by the added regression test. To fix, restructure the planner's management of PlannerParamItems so that items having different semantic lifespans are kept rigorously separated. This will probably result in complex queries using more runtime PARAM_EXEC slots than before, but the slots are cheap enough that this hardly matters. Also, stop generating PlannerParamItems containing Params for subquery outputs: all we really need to do is reserve the PARAM_EXEC slot number, and that now only takes incrementing a counter. The planning code is simpler and probably faster than before, as well as being more correct. Per report from Vik Reykja. Back-patch of commit 46c508f into all branches that support WITH.
1 parent 7e21ff3 commit 6e54298

File tree

9 files changed

+218
-149
lines changed

9 files changed

+218
-149
lines changed

src/backend/nodes/outfuncs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,13 +1459,13 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node)
14591459
WRITE_NODE_TYPE("PLANNERGLOBAL");
14601460

14611461
/* NB: this isn't a complete set of fields */
1462-
WRITE_NODE_FIELD(paramlist);
14631462
WRITE_NODE_FIELD(subplans);
14641463
WRITE_NODE_FIELD(subrtables);
14651464
WRITE_BITMAPSET_FIELD(rewindPlanIDs);
14661465
WRITE_NODE_FIELD(finalrtable);
14671466
WRITE_NODE_FIELD(relationOids);
14681467
WRITE_NODE_FIELD(invalItems);
1468+
WRITE_INT_FIELD(nParamExec);
14691469
WRITE_UINT_FIELD(lastPHId);
14701470
WRITE_BOOL_FIELD(transientPlan);
14711471
}
@@ -1479,6 +1479,7 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node)
14791479
WRITE_NODE_FIELD(parse);
14801480
WRITE_NODE_FIELD(glob);
14811481
WRITE_UINT_FIELD(query_level);
1482+
WRITE_NODE_FIELD(plan_params);
14821483
WRITE_NODE_FIELD(join_rel_list);
14831484
WRITE_NODE_FIELD(resultRelations);
14841485
WRITE_NODE_FIELD(returningLists);
@@ -1699,7 +1700,7 @@ _outPlannerParamItem(StringInfo str, PlannerParamItem *node)
16991700
WRITE_NODE_TYPE("PLANNERPARAMITEM");
17001701

17011702
WRITE_NODE_FIELD(item);
1702-
WRITE_UINT_FIELD(abslevel);
1703+
WRITE_INT_FIELD(paramId);
17031704
}
17041705

17051706
/*****************************************************************************

src/backend/optimizer/path/allpaths.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,13 +626,23 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
626626
else
627627
tuple_fraction = root->tuple_fraction;
628628

629+
/* plan_params should not be in use in current query level */
630+
Assert(root->plan_params == NIL);
631+
629632
/* Generate the plan for the subquery */
630633
rel->subplan = subquery_planner(root->glob, subquery,
631634
root,
632635
false, tuple_fraction,
633636
&subroot);
634637
rel->subrtable = subroot->parse->rtable;
635638

639+
/*
640+
* Since we don't yet support LATERAL, it should not be possible for the
641+
* sub-query to have requested parameters of this level.
642+
*/
643+
if (root->plan_params)
644+
elog(ERROR, "unexpected outer reference in subquery in FROM");
645+
636646
/* Copy number of output rows from subplan */
637647
rel->tuples = rel->subplan->plan_rows;
638648

src/backend/optimizer/plan/planner.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,13 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
148148
glob = makeNode(PlannerGlobal);
149149

150150
glob->boundParams = boundParams;
151-
glob->paramlist = NIL;
152151
glob->subplans = NIL;
153152
glob->subrtables = NIL;
154153
glob->rewindPlanIDs = NULL;
155154
glob->finalrtable = NIL;
156155
glob->relationOids = NIL;
157156
glob->invalItems = NIL;
157+
glob->nParamExec = 0;
158158
glob->lastPHId = 0;
159159
glob->transientPlan = false;
160160

@@ -230,7 +230,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
230230
result->rowMarks = parse->rowMarks;
231231
result->relationOids = glob->relationOids;
232232
result->invalItems = glob->invalItems;
233-
result->nParamExec = list_length(glob->paramlist);
233+
result->nParamExec = glob->nParamExec;
234234

235235
return result;
236236
}
@@ -282,6 +282,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
282282
root->glob = glob;
283283
root->query_level = parent_root ? parent_root->query_level + 1 : 1;
284284
root->parent_root = parent_root;
285+
root->plan_params = NIL;
285286
root->planner_cxt = CurrentMemoryContext;
286287
root->init_plans = NIL;
287288
root->cte_plan_ids = NIL;

0 commit comments

Comments
 (0)
0