1
1
/*-------------------------------------------------------------------------
2
2
*
3
3
* 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 $
4
10
*
5
11
*-------------------------------------------------------------------------
6
12
*/
7
13
#include "postgres.h"
8
14
9
15
#include "catalog/pg_type.h"
10
-
11
16
#include "nodes/pg_list.h"
12
17
#include "nodes/plannodes.h"
13
18
#include "nodes/parsenodes.h"
14
19
#include "nodes/relation.h"
15
20
#include "nodes/makefuncs.h"
16
21
#include "nodes/nodeFuncs.h"
17
-
18
22
#include "optimizer/subselect.h"
19
23
#include "optimizer/planner.h"
20
24
#include "optimizer/planmain.h"
27
31
#include "optimizer/cost.h"
28
32
29
33
int PlannerQueryLevel ; /* level of current query */
30
- List * PlannerVarParam ; /* correlation Vars to Param mapper */
31
- List * PlannerParamVar ; /* to get Var from Param->paramid */
32
34
List * 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
+ */
34
51
35
52
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
+ */
36
59
static int
37
60
_new_param (Var * var , int varlevel )
38
61
{
@@ -61,38 +84,49 @@ _new_param(Var *var, int varlevel)
61
84
return i ;
62
85
}
63
86
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
+ */
64
91
static Param *
65
92
_replace_var (Var * var )
66
93
{
67
- List * * rt = (List * * ) nth (var -> varlevelsup , PlannerVarParam );
68
- List * vpe = rt [var -> varno - 1 ];
94
+ List * ppv ;
69
95
Param * retval ;
96
+ int varlevel ;
70
97
int i ;
71
98
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 ;
78
101
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 )
80
114
{
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 )
82
121
break ;
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 ++ ;
92
123
}
93
124
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
+ }
96
130
97
131
retval = makeNode (Param );
98
132
retval -> paramkind = PARAM_EXEC ;
@@ -125,7 +159,7 @@ _make_subplan(SubLink *slink)
125
159
(void ) SS_finalize_plan (plan );
126
160
plan -> initPlan = PlannerInitPlan ;
127
161
128
- /* Get extParam from InitPlan-s */
162
+ /* Create extParam list as union of InitPlan-s' lists */
129
163
foreach (lst , PlannerInitPlan )
130
164
{
131
165
List * lp ;
@@ -146,11 +180,12 @@ _make_subplan(SubLink *slink)
146
180
node -> sublink = slink ;
147
181
slink -> subselect = NULL ; /* cool ?! */
148
182
149
- /* make parParam list */
183
+ /* make parParam list of params coming from current query level */
150
184
foreach (lst , plan -> extParam )
151
185
{
152
186
Var * var = nth (lfirsti (lst ), PlannerParamVar );
153
187
188
+ /* note varlevelsup is absolute level number */
154
189
if (var -> varlevelsup == PlannerQueryLevel )
155
190
node -> parParam = lappendi (node -> parParam , lfirsti (lst ));
156
191
}
@@ -170,7 +205,7 @@ _make_subplan(SubLink *slink)
170
205
TargetEntry * te = nth (i , plan -> targetlist );
171
206
Var * var = makeVar (0 , 0 , te -> resdom -> restype ,
172
207
te -> resdom -> restypmod ,
173
- PlannerQueryLevel , 0 , 0 );
208
+ 0 , 0 , 0 );
174
209
Param * prm = makeNode (Param );
175
210
176
211
prm -> paramkind = PARAM_EXEC ;
@@ -190,7 +225,7 @@ _make_subplan(SubLink *slink)
190
225
}
191
226
else if (node -> parParam == NULL && slink -> subLinkType == EXISTS_SUBLINK )
192
227
{
193
- Var * var = makeVar (0 , 0 , BOOLOID , -1 , PlannerQueryLevel , 0 , 0 );
228
+ Var * var = makeVar (0 , 0 , BOOLOID , -1 , 0 , 0 , 0 );
194
229
Param * prm = makeNode (Param );
195
230
196
231
prm -> paramkind = PARAM_EXEC ;
@@ -202,10 +237,10 @@ _make_subplan(SubLink *slink)
202
237
result = (Node * ) prm ;
203
238
}
204
239
else
205
- /* make expression of SUBPLAN type */
206
240
{
241
+ /* make expression of SUBPLAN type */
207
242
Expr * expr = makeNode (Expr );
208
- List * args = NULL ;
243
+ List * args = NIL ;
209
244
int i = 0 ;
210
245
211
246
expr -> typeOid = BOOLOID ;
@@ -222,6 +257,10 @@ _make_subplan(SubLink *slink)
222
257
Var * var = nth (lfirsti (lst ), PlannerParamVar );
223
258
224
259
var = (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
+ */
225
264
var -> varlevelsup = 0 ;
226
265
args = lappend (args , var );
227
266
}
@@ -240,7 +279,6 @@ _make_subplan(SubLink *slink)
240
279
}
241
280
242
281
return result ;
243
-
244
282
}
245
283
246
284
static List *
@@ -305,6 +343,7 @@ _finalize_primnode(void *expr, List **subplan)
305
343
{
306
344
Var * var = nth (lfirsti (lst ), PlannerParamVar );
307
345
346
+ /* note varlevelsup is absolute level number */
308
347
if (var -> varlevelsup < PlannerQueryLevel &&
309
348
!intMember (lfirsti (lst ), result ))
310
349
result = lappendi (result , lfirsti (lst ));
@@ -332,10 +371,7 @@ SS_replace_correlation_vars(Node *expr)
332
371
else if (IsA (expr , Var ))
333
372
{
334
373
if (((Var * ) expr )-> varlevelsup > 0 )
335
- {
336
- Assert (((Var * ) expr )-> varlevelsup < PlannerQueryLevel );
337
374
expr = (Node * ) _replace_var ((Var * ) expr );
338
- }
339
375
}
340
376
else if (IsA (expr , Iter ))
341
377
((Iter * ) expr )-> iterexpr = SS_replace_correlation_vars (((Iter * ) expr )-> iterexpr );
@@ -480,6 +516,7 @@ SS_finalize_plan(Plan *plan)
480
516
{
481
517
Var * var = nth (lfirsti (lst ), PlannerParamVar );
482
518
519
+ /* note varlevelsup is absolute level number */
483
520
if (var -> varlevelsup < PlannerQueryLevel )
484
521
extParam = lappendi (extParam , lfirsti (lst ));
485
522
else if (var -> varlevelsup > PlannerQueryLevel )
0 commit comments