11/*-------------------------------------------------------------------------
22 *
33 * subselect.c
4+ * Planning routines for subselects and parameters.
5+ *
6+ * Copyright (c) 1994, Regents of the University of California
7+ *
8+ * IDENTIFICATION
9+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.18 1999/06/21 01:20:57 tgl Exp $
410 *
511 *-------------------------------------------------------------------------
612 */
713#include "postgres.h"
814
915#include "catalog/pg_type.h"
10-
1116#include "nodes/pg_list.h"
1217#include "nodes/plannodes.h"
1318#include "nodes/parsenodes.h"
1419#include "nodes/relation.h"
1520#include "nodes/makefuncs.h"
1621#include "nodes/nodeFuncs.h"
17-
1822#include "optimizer/subselect.h"
1923#include "optimizer/planner.h"
2024#include "optimizer/planmain.h"
2731#include "optimizer/cost.h"
2832
2933int PlannerQueryLevel ;/* level of current query */
30- List * PlannerVarParam ;/* correlation Vars to Param mapper */
31- List * PlannerParamVar ;/* to get Var from Param->paramid */
3234List * PlannerInitPlan ;/* init subplans for current query */
33- int PlannerPlanId ;
35+ List * PlannerParamVar ;/* to get Var from Param->paramid */
36+ int PlannerPlanId ;/* to assign unique ID to subquery plans */
37+
38+ /*--------------------
39+ * PlannerParamVar is a list of Var nodes, wherein the n'th entry
40+ * (n counts from 0) corresponds to Param->paramid = n. The Var nodes
41+ * are ordinary except for one thing: their varlevelsup field does NOT
42+ * have the usual interpretation of "subplan levels out from current".
43+ * Instead, it contains the absolute plan level, with the outermost
44+ * plan being level 1 and nested plans having higher level numbers.
45+ * This nonstandardness is useful because we don't have to run around
46+ * and update the list elements when we enter or exit a subplan
47+ * recursion level. But we must pay attention not to confuse this
48+ * meaning with the normal meaning of varlevelsup.
49+ *--------------------
50+ */
3451
3552
53+ /*
54+ * Create a new entry in the PlannerParamVar list, and return its index.
55+ *
56+ * var contains the data to be copied, except for varlevelsup which
57+ * is set from the absolute level value given by varlevel.
58+ */
3659static int
3760_new_param (Var * var ,int varlevel )
3861{
@@ -61,38 +84,49 @@ _new_param(Var *var, int varlevel)
6184return i ;
6285}
6386
87+ /*
88+ * Generate a Param node to replace the given Var,
89+ * which is expected to have varlevelsup > 0 (ie, it is not local).
90+ */
6491static Param *
6592_replace_var (Var * var )
6693{
67- List * * rt = (List * * )nth (var -> varlevelsup ,PlannerVarParam );
68- List * vpe = rt [var -> varno - 1 ];
94+ List * ppv ;
6995Param * retval ;
96+ int varlevel ;
7097int i ;
7198
72- if (vpe == NULL )
73- {
74- vpe = rt [var -> varno - 1 ]= makeNode (List );
75- lfirsti (vpe )= -1 ;
76- lnext (vpe )= NULL ;
77- }
99+ Assert (var -> varlevelsup > 0 && var -> varlevelsup < PlannerQueryLevel );
100+ varlevel = PlannerQueryLevel - var -> varlevelsup ;
78101
79- for (i = ObjectIdAttributeNumber ;;i ++ )
102+ /*
103+ * If there's already a PlannerParamVar entry for this same Var,
104+ * just use it. NOTE: in situations involving UNION or inheritance,
105+ * it is possible for the same varno/varlevel to refer to different RTEs
106+ * in different parts of the parsetree, so that different fields might
107+ * end up sharing the same Param number. As long as we check the vartype
108+ * as well, I believe that this sort of aliasing will cause no trouble.
109+ * The correct field should get stored into the Param slot at execution
110+ * in each part of the tree.
111+ */
112+ i = 0 ;
113+ foreach (ppv ,PlannerParamVar )
80114{
81- if (i == var -> varattno )
115+ Var * pvar = lfirst (ppv );
116+
117+ if (pvar -> varno == var -> varno &&
118+ pvar -> varattno == var -> varattno &&
119+ pvar -> varlevelsup == varlevel &&
120+ pvar -> vartype == var -> vartype )
82121break ;
83- if (lnext (vpe )== NULL )
84- {
85- lnext (vpe )= makeNode (List );
86- vpe = lnext (vpe );
87- lfirsti (vpe )= -1 ;
88- lnext (vpe )= NULL ;
89- }
90- else
91- vpe = lnext (vpe );
122+ i ++ ;
92123}
93124
94- if ((i = lfirsti (vpe ))< 0 )/* parameter is not assigned */
95- i = _new_param (var ,PlannerQueryLevel - var -> varlevelsup );
125+ if (!ppv )
126+ {
127+ /* Nope, so make a new one */
128+ i = _new_param (var ,varlevel );
129+ }
96130
97131retval = makeNode (Param );
98132retval -> paramkind = PARAM_EXEC ;
@@ -125,7 +159,7 @@ _make_subplan(SubLink *slink)
125159(void )SS_finalize_plan (plan );
126160plan -> initPlan = PlannerInitPlan ;
127161
128- /*Get extParamfrom InitPlan-s */
162+ /*Create extParamlist as union of InitPlan-s' lists */
129163foreach (lst ,PlannerInitPlan )
130164{
131165List * lp ;
@@ -146,11 +180,12 @@ _make_subplan(SubLink *slink)
146180node -> sublink = slink ;
147181slink -> subselect = NULL ;/* cool ?! */
148182
149- /* make parParam list */
183+ /* make parParam listof params coming from current query level */
150184foreach (lst ,plan -> extParam )
151185{
152186Var * var = nth (lfirsti (lst ),PlannerParamVar );
153187
188+ /* note varlevelsup is absolute level number */
154189if (var -> varlevelsup == PlannerQueryLevel )
155190node -> parParam = lappendi (node -> parParam ,lfirsti (lst ));
156191}
@@ -170,7 +205,7 @@ _make_subplan(SubLink *slink)
170205TargetEntry * te = nth (i ,plan -> targetlist );
171206Var * var = makeVar (0 ,0 ,te -> resdom -> restype ,
172207te -> resdom -> restypmod ,
173- PlannerQueryLevel ,0 ,0 );
208+ 0 ,0 ,0 );
174209Param * prm = makeNode (Param );
175210
176211prm -> paramkind = PARAM_EXEC ;
@@ -190,7 +225,7 @@ _make_subplan(SubLink *slink)
190225}
191226else if (node -> parParam == NULL && slink -> subLinkType == EXISTS_SUBLINK )
192227{
193- Var * var = makeVar (0 ,0 ,BOOLOID ,-1 ,PlannerQueryLevel ,0 ,0 );
228+ Var * var = makeVar (0 ,0 ,BOOLOID ,-1 ,0 ,0 ,0 );
194229Param * prm = makeNode (Param );
195230
196231prm -> paramkind = PARAM_EXEC ;
@@ -202,10 +237,10 @@ _make_subplan(SubLink *slink)
202237result = (Node * )prm ;
203238}
204239else
205- /* make expression of SUBPLAN type */
206240{
241+ /* make expression of SUBPLAN type */
207242Expr * expr = makeNode (Expr );
208- List * args = NULL ;
243+ List * args = NIL ;
209244int i = 0 ;
210245
211246expr -> typeOid = BOOLOID ;
@@ -222,6 +257,10 @@ _make_subplan(SubLink *slink)
222257Var * var = nth (lfirsti (lst ),PlannerParamVar );
223258
224259var = (Var * )copyObject (var );
260+ /* Must fix absolute-level varlevelsup from the
261+ * PlannerParamVar entry. But since var is at current
262+ * subplan level, this is easy:
263+ */
225264var -> varlevelsup = 0 ;
226265args = lappend (args ,var );
227266}
@@ -240,7 +279,6 @@ _make_subplan(SubLink *slink)
240279}
241280
242281return result ;
243-
244282}
245283
246284static List *
@@ -305,6 +343,7 @@ _finalize_primnode(void *expr, List **subplan)
305343{
306344Var * var = nth (lfirsti (lst ),PlannerParamVar );
307345
346+ /* note varlevelsup is absolute level number */
308347if (var -> varlevelsup < PlannerQueryLevel &&
309348!intMember (lfirsti (lst ),result ))
310349result = lappendi (result ,lfirsti (lst ));
@@ -332,10 +371,7 @@ SS_replace_correlation_vars(Node *expr)
332371else if (IsA (expr ,Var ))
333372{
334373if (((Var * )expr )-> varlevelsup > 0 )
335- {
336- Assert (((Var * )expr )-> varlevelsup < PlannerQueryLevel );
337374expr = (Node * )_replace_var ((Var * )expr );
338- }
339375}
340376else if (IsA (expr ,Iter ))
341377((Iter * )expr )-> iterexpr = SS_replace_correlation_vars (((Iter * )expr )-> iterexpr );
@@ -480,6 +516,7 @@ SS_finalize_plan(Plan *plan)
480516{
481517Var * var = nth (lfirsti (lst ),PlannerParamVar );
482518
519+ /* note varlevelsup is absolute level number */
483520if (var -> varlevelsup < PlannerQueryLevel )
484521extParam = lappendi (extParam ,lfirsti (lst ));
485522else if (var -> varlevelsup > PlannerQueryLevel )