Skip to content

Commit 51fd22a

Browse files
committed
Change set_plan_references and join_references to take an rtable List
rather than a Query node; this allows set_plan_references to recurse into subplans correctly. Fixes core dump on full outer joins in subplans. Also, invoke preprocess_expression on function RTEs' function expressions. This seems to fix the planner's problems with outer-level Vars in function RTEs.
1 parent 0a75715 commit 51fd22a

File tree

7 files changed

+78
-57
lines changed

7 files changed

+78
-57
lines changed

src/backend/optimizer/plan/createplan.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.114 2002/05/12 20:10:03 tgl Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.115 2002/05/18 02:25:49 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -671,19 +671,19 @@ create_nestloop_plan(Query *root,
671671

672672
/* only refs to outer vars get changed in the inner indexqual */
673673
innerscan->indxqualorig = join_references(indxqualorig,
674-
root,
674+
root->rtable,
675675
outer_tlist,
676676
NIL,
677677
innerrel);
678678
innerscan->indxqual = join_references(innerscan->indxqual,
679-
root,
679+
root->rtable,
680680
outer_tlist,
681681
NIL,
682682
innerrel);
683683
/* fix the inner qpqual too, if it has join clauses */
684684
if (NumRelids((Node *) inner_plan->qual) > 1)
685685
inner_plan->qual = join_references(inner_plan->qual,
686-
root,
686+
root->rtable,
687687
outer_tlist,
688688
NIL,
689689
innerrel);
@@ -694,7 +694,7 @@ create_nestloop_plan(Query *root,
694694
TidScan *innerscan = (TidScan *) inner_plan;
695695

696696
innerscan->tideval = join_references(innerscan->tideval,
697-
root,
697+
root->rtable,
698698
outer_tlist,
699699
inner_tlist,
700700
innerscan->scan.scanrelid);
@@ -716,12 +716,12 @@ create_nestloop_plan(Query *root,
716716
* Set quals to contain INNER/OUTER var references.
717717
*/
718718
joinclauses = join_references(joinclauses,
719-
root,
719+
root->rtable,
720720
outer_tlist,
721721
inner_tlist,
722722
(Index) 0);
723723
otherclauses = join_references(otherclauses,
724-
root,
724+
root->rtable,
725725
outer_tlist,
726726
inner_tlist,
727727
(Index) 0);
@@ -760,7 +760,7 @@ create_mergejoin_plan(Query *root,
760760
* clauses to contain INNER/OUTER var references.
761761
*/
762762
joinclauses = join_references(set_difference(joinclauses, mergeclauses),
763-
root,
763+
root->rtable,
764764
outer_tlist,
765765
inner_tlist,
766766
(Index) 0);
@@ -769,7 +769,7 @@ create_mergejoin_plan(Query *root,
769769
* Fix the additional qpquals too.
770770
*/
771771
otherclauses = join_references(otherclauses,
772-
root,
772+
root->rtable,
773773
outer_tlist,
774774
inner_tlist,
775775
(Index) 0);
@@ -779,7 +779,7 @@ create_mergejoin_plan(Query *root,
779779
* that the outer variable is always on the left.
780780
*/
781781
mergeclauses = switch_outer(join_references(mergeclauses,
782-
root,
782+
root->rtable,
783783
outer_tlist,
784784
inner_tlist,
785785
(Index) 0));
@@ -886,7 +886,7 @@ create_hashjoin_plan(Query *root,
886886
* clauses to contain INNER/OUTER var references.
887887
*/
888888
joinclauses = join_references(set_difference(joinclauses, hashclauses),
889-
root,
889+
root->rtable,
890890
outer_tlist,
891891
inner_tlist,
892892
(Index) 0);
@@ -895,7 +895,7 @@ create_hashjoin_plan(Query *root,
895895
* Fix the additional qpquals too.
896896
*/
897897
otherclauses = join_references(otherclauses,
898-
root,
898+
root->rtable,
899899
outer_tlist,
900900
inner_tlist,
901901
(Index) 0);
@@ -905,7 +905,7 @@ create_hashjoin_plan(Query *root,
905905
* that the outer variable is always on the left.
906906
*/
907907
hashclauses = switch_outer(join_references(hashclauses,
908-
root,
908+
root->rtable,
909909
outer_tlist,
910910
inner_tlist,
911911
(Index) 0));

src/backend/optimizer/plan/initsplan.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.71 2002/05/17 22:35:12 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.72 2002/05/18 02:25:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -177,7 +177,7 @@ add_vars_to_targetlist(Query *root, List *vars)
177177
List *varsused;
178178

179179
expansion = flatten_join_alias_vars((Node *) var,
180-
root, true);
180+
root->rtable, true);
181181
varsused = pull_var_clause(expansion, false);
182182
add_vars_to_targetlist(root, varsused);
183183
freeList(varsused);

src/backend/optimizer/plan/planner.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.117 2002/05/12 23:43:03 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.118 2002/05/18 02:25:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -101,7 +101,7 @@ planner(Query *parse)
101101
result_plan->nParamExec = length(PlannerParamVar);
102102

103103
/* final cleanup of the plan */
104-
set_plan_references(parse, result_plan);
104+
set_plan_references(result_plan, parse->rtable);
105105

106106
/* restore state for outer planner, if any */
107107
PlannerQueryLevel = save_PlannerQueryLevel;
@@ -175,6 +175,17 @@ subquery_planner(Query *parse, double tuple_fraction)
175175
parse->havingQual = preprocess_expression(parse, parse->havingQual,
176176
EXPRKIND_HAVING);
177177

178+
/* Also need to preprocess expressions for function RTEs */
179+
foreach(lst, parse->rtable)
180+
{
181+
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst);
182+
183+
if (rte->rtekind == RTE_FUNCTION)
184+
rte->funcexpr = preprocess_expression(parse, rte->funcexpr,
185+
EXPRKIND_TARGET);
186+
/* These are not targetlist items, but close enough... */
187+
}
188+
178189
/*
179190
* Check for ungrouped variables passed to subplans in targetlist and
180191
* HAVING clause (but not in WHERE or JOIN/ON clauses, since those are
@@ -737,7 +748,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
737748
}
738749
}
739750
if (has_join_rtes)
740-
expr = flatten_join_alias_vars(expr, parse, false);
751+
expr = flatten_join_alias_vars(expr, parse->rtable, false);
741752

742753
return expr;
743754
}

src/backend/optimizer/plan/setrefs.c

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.77 2002/05/18 00:42:55 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.78 2002/05/18 02:25:50 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -28,7 +28,7 @@
2828

2929
typedef struct
3030
{
31-
Query *root;
31+
List *rtable;
3232
List *outer_tlist;
3333
List *inner_tlist;
3434
Index acceptable_rel;
@@ -42,7 +42,7 @@ typedef struct
4242
} replace_vars_with_subplan_refs_context;
4343

4444
static void fix_expr_references(Plan *plan, Node *node);
45-
static void set_join_references(Query *root, Join *join);
45+
static void set_join_references(Join *join, List *rtable);
4646
static void set_uppernode_references(Plan *plan, Index subvarno);
4747
static Node *join_references_mutator(Node *node,
4848
join_references_context *context);
@@ -75,7 +75,7 @@ static bool fix_opids_walker(Node *node, void *context);
7575
* Returns nothing of interest, but modifies internal fields of nodes.
7676
*/
7777
void
78-
set_plan_references(Query *root, Plan *plan)
78+
set_plan_references(Plan *plan, List *rtable)
7979
{
8080
List *pl;
8181

@@ -110,16 +110,24 @@ set_plan_references(Query *root, Plan *plan)
110110
fix_expr_references(plan, (Node *) plan->qual);
111111
break;
112112
case T_SubqueryScan:
113+
{
114+
RangeTblEntry *rte;
113115

114-
/*
115-
* We do not do set_uppernode_references() here, because a
116-
* SubqueryScan will always have been created with correct
117-
* references to its subplan's outputs to begin with.
118-
*/
119-
fix_expr_references(plan, (Node *) plan->targetlist);
120-
fix_expr_references(plan, (Node *) plan->qual);
121-
/* Recurse into subplan too */
122-
set_plan_references(root, ((SubqueryScan *) plan)->subplan);
116+
/*
117+
* We do not do set_uppernode_references() here, because a
118+
* SubqueryScan will always have been created with correct
119+
* references to its subplan's outputs to begin with.
120+
*/
121+
fix_expr_references(plan, (Node *) plan->targetlist);
122+
fix_expr_references(plan, (Node *) plan->qual);
123+
124+
/* Recurse into subplan too */
125+
rte = rt_fetch(((SubqueryScan *) plan)->scan.scanrelid,
126+
rtable);
127+
Assert(rte->rtekind == RTE_SUBQUERY);
128+
set_plan_references(((SubqueryScan *) plan)->subplan,
129+
rte->subquery->rtable);
130+
}
123131
break;
124132
case T_FunctionScan:
125133
{
@@ -128,27 +136,27 @@ set_plan_references(Query *root, Plan *plan)
128136
fix_expr_references(plan, (Node *) plan->targetlist);
129137
fix_expr_references(plan, (Node *) plan->qual);
130138
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
131-
root->rtable);
139+
rtable);
132140
Assert(rte->rtekind == RTE_FUNCTION);
133141
fix_expr_references(plan, rte->funcexpr);
134142
}
135143
break;
136144
case T_NestLoop:
137-
set_join_references(root, (Join *) plan);
145+
set_join_references((Join *) plan, rtable);
138146
fix_expr_references(plan, (Node *) plan->targetlist);
139147
fix_expr_references(plan, (Node *) plan->qual);
140148
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
141149
break;
142150
case T_MergeJoin:
143-
set_join_references(root, (Join *) plan);
151+
set_join_references((Join *) plan, rtable);
144152
fix_expr_references(plan, (Node *) plan->targetlist);
145153
fix_expr_references(plan, (Node *) plan->qual);
146154
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
147155
fix_expr_references(plan,
148156
(Node *) ((MergeJoin *) plan)->mergeclauses);
149157
break;
150158
case T_HashJoin:
151-
set_join_references(root, (Join *) plan);
159+
set_join_references((Join *) plan, rtable);
152160
fix_expr_references(plan, (Node *) plan->targetlist);
153161
fix_expr_references(plan, (Node *) plan->qual);
154162
fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
@@ -202,7 +210,7 @@ set_plan_references(Query *root, Plan *plan)
202210
* recurse into subplans.
203211
*/
204212
foreach(pl, ((Append *) plan)->appendplans)
205-
set_plan_references(root, (Plan *) lfirst(pl));
213+
set_plan_references((Plan *) lfirst(pl), rtable);
206214
break;
207215
default:
208216
elog(ERROR, "set_plan_references: unknown plan type %d",
@@ -219,21 +227,21 @@ set_plan_references(Query *root, Plan *plan)
219227
* plan's var nodes against the already-modified nodes of the
220228
* subplans.
221229
*/
222-
set_plan_references(root, plan->lefttree);
223-
set_plan_references(root, plan->righttree);
230+
set_plan_references(plan->lefttree, rtable);
231+
set_plan_references(plan->righttree, rtable);
224232
foreach(pl, plan->initPlan)
225233
{
226234
SubPlan *sp = (SubPlan *) lfirst(pl);
227235

228236
Assert(IsA(sp, SubPlan));
229-
set_plan_references(root, sp->plan);
237+
set_plan_references(sp->plan, sp->rtable);
230238
}
231239
foreach(pl, plan->subPlan)
232240
{
233241
SubPlan *sp = (SubPlan *) lfirst(pl);
234242

235243
Assert(IsA(sp, SubPlan));
236-
set_plan_references(root, sp->plan);
244+
set_plan_references(sp->plan, sp->rtable);
237245
}
238246
}
239247

@@ -269,18 +277,19 @@ fix_expr_references(Plan *plan, Node *node)
269277
* creation of a plan node by createplan.c and its fixing by this module.
270278
* Fortunately, there doesn't seem to be any need to do that.
271279
*
272-
* 'join' is a join plan node
280+
* 'join' is a join plan node
281+
* 'rtable' is the associated range table
273282
*/
274283
static void
275-
set_join_references(Query *root, Join *join)
284+
set_join_references(Join *join, List *rtable)
276285
{
277286
Plan *outer = join->plan.lefttree;
278287
Plan *inner = join->plan.righttree;
279288
List *outer_tlist = ((outer == NULL) ? NIL : outer->targetlist);
280289
List *inner_tlist = ((inner == NULL) ? NIL : inner->targetlist);
281290

282291
join->plan.targetlist = join_references(join->plan.targetlist,
283-
root,
292+
rtable,
284293
outer_tlist,
285294
inner_tlist,
286295
(Index) 0);
@@ -374,6 +383,7 @@ set_uppernode_references(Plan *plan, Index subvarno)
374383
* pass inner_tlist = NIL and acceptable_rel = the ID of the inner relation.
375384
*
376385
* 'clauses' is the targetlist or list of join clauses
386+
* 'rtable' is the current range table
377387
* 'outer_tlist' is the target list of the outer join relation
378388
* 'inner_tlist' is the target list of the inner join relation, or NIL
379389
* 'acceptable_rel' is either zero or the rangetable index of a relation
@@ -384,14 +394,14 @@ set_uppernode_references(Plan *plan, Index subvarno)
384394
*/
385395
List *
386396
join_references(List *clauses,
387-
Query *root,
397+
List *rtable,
388398
List *outer_tlist,
389399
List *inner_tlist,
390400
Index acceptable_rel)
391401
{
392402
join_references_context context;
393403

394-
context.root = root;
404+
context.rtable = rtable;
395405
context.outer_tlist = outer_tlist;
396406
context.inner_tlist = inner_tlist;
397407
context.acceptable_rel = acceptable_rel;
@@ -432,7 +442,7 @@ join_references_mutator(Node *node,
432442

433443
/* Perhaps it's a join alias that can be resolved to input vars? */
434444
newnode = flatten_join_alias_vars((Node *) var,
435-
context->root,
445+
context->rtable,
436446
true);
437447
if (!equal(newnode, (Node *) var))
438448
{

0 commit comments

Comments
 (0)