8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.30 2001/03/22 03:59:40 momjian Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.31 2001/04/18 20:42:55 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
15
- #include <sys/types.h>
16
-
17
15
#include "postgres.h"
18
16
19
17
#include "nodes/plannodes.h"
@@ -27,6 +25,12 @@ typedef struct
27
25
int sublevels_up ;
28
26
} pull_varnos_context ;
29
27
28
+ typedef struct
29
+ {
30
+ int varno ;
31
+ int sublevels_up ;
32
+ } contain_whole_tuple_var_context ;
33
+
30
34
typedef struct
31
35
{
32
36
List * varlist ;
@@ -35,6 +39,8 @@ typedef struct
35
39
36
40
static bool pull_varnos_walker (Node * node ,
37
41
pull_varnos_context * context );
42
+ static bool contain_whole_tuple_var_walker (Node * node ,
43
+ contain_whole_tuple_var_context * context );
38
44
static bool contain_var_clause_walker (Node * node , void * context );
39
45
static bool pull_var_clause_walker (Node * node ,
40
46
pull_var_clause_context * context );
@@ -46,11 +52,10 @@ static bool pull_var_clause_walker(Node *node,
46
52
* Create a list of all the distinct varnos present in a parsetree.
47
53
* Only varnos that reference level-zero rtable entries are considered.
48
54
*
49
- * NOTE: unlike other routines in this file, pull_varnos() is used on
50
- * not-yet-planned expressions. It may therefore find bare SubLinks,
51
- * and if so it needs to recurse into them to look for uplevel references
52
- * to the desired rtable level! But when we find a completed SubPlan,
53
- * we only need to look at the parameters passed to the subplan.
55
+ * NOTE: this is used on not-yet-planned expressions. It may therefore find
56
+ * bare SubLinks, and if so it needs to recurse into them to look for uplevel
57
+ * references to the desired rtable level! But when we find a completed
58
+ * SubPlan, we only need to look at the parameters passed to the subplan.
54
59
*/
55
60
List *
56
61
pull_varnos (Node * node )
@@ -122,17 +127,105 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
122
127
(void * ) context );
123
128
}
124
129
130
+
131
+ /*
132
+ * contain_whole_tuple_var
133
+ *
134
+ * Detect whether a parsetree contains any references to the whole
135
+ * tuple of a given rtable entry (ie, a Var with varattno = 0).
136
+ *
137
+ * NOTE: this is used on not-yet-planned expressions. It may therefore find
138
+ * bare SubLinks, and if so it needs to recurse into them to look for uplevel
139
+ * references to the desired rtable entry! But when we find a completed
140
+ * SubPlan, we only need to look at the parameters passed to the subplan.
141
+ */
142
+ bool
143
+ contain_whole_tuple_var (Node * node , int varno , int levelsup )
144
+ {
145
+ contain_whole_tuple_var_context context ;
146
+
147
+ context .varno = varno ;
148
+ context .sublevels_up = levelsup ;
149
+
150
+ /*
151
+ * Must be prepared to start with a Query or a bare expression tree;
152
+ * if it's a Query, go straight to query_tree_walker to make sure that
153
+ * sublevels_up doesn't get incremented prematurely.
154
+ */
155
+ if (node && IsA (node , Query ))
156
+ return query_tree_walker ((Query * ) node ,
157
+ contain_whole_tuple_var_walker ,
158
+ (void * ) & context , true);
159
+ else
160
+ return contain_whole_tuple_var_walker (node , & context );
161
+ }
162
+
163
+ static bool
164
+ contain_whole_tuple_var_walker (Node * node ,
165
+ contain_whole_tuple_var_context * context )
166
+ {
167
+ if (node == NULL )
168
+ return false;
169
+ if (IsA (node , Var ))
170
+ {
171
+ Var * var = (Var * ) node ;
172
+
173
+ if (var -> varno == context -> varno &&
174
+ var -> varlevelsup == context -> sublevels_up &&
175
+ var -> varattno == InvalidAttrNumber )
176
+ return true;
177
+ return false;
178
+ }
179
+ if (is_subplan (node ))
180
+ {
181
+
182
+ /*
183
+ * Already-planned subquery. Examine the args list (parameters to
184
+ * be passed to subquery), as well as the "oper" list which is
185
+ * executed by the outer query. But short-circuit recursion into
186
+ * the subquery itself, which would be a waste of effort.
187
+ */
188
+ Expr * expr = (Expr * ) node ;
189
+
190
+ if (contain_whole_tuple_var_walker ((Node * ) ((SubPlan * ) expr -> oper )-> sublink -> oper ,
191
+ context ))
192
+ return true;
193
+ if (contain_whole_tuple_var_walker ((Node * ) expr -> args ,
194
+ context ))
195
+ return true;
196
+ return false;
197
+ }
198
+ if (IsA (node , Query ))
199
+ {
200
+ /* Recurse into RTE subquery or not-yet-planned sublink subquery */
201
+ bool result ;
202
+
203
+ context -> sublevels_up ++ ;
204
+ result = query_tree_walker ((Query * ) node ,
205
+ contain_whole_tuple_var_walker ,
206
+ (void * ) context , true);
207
+ context -> sublevels_up -- ;
208
+ return result ;
209
+ }
210
+ return expression_tree_walker (node , contain_whole_tuple_var_walker ,
211
+ (void * ) context );
212
+ }
213
+
214
+
125
215
/*
126
216
* contain_var_clause
127
217
* Recursively scan a clause to discover whether it contains any Var nodes
128
218
* (of the current query level).
129
219
*
130
220
* Returns true if any varnode found.
221
+ *
222
+ * Does not examine subqueries, therefore must only be used after reduction
223
+ * of sublinks to subplans!
131
224
*/
132
225
bool
133
- contain_var_clause (Node * clause )
226
+ contain_var_clause (Node * node )
134
227
{
135
- return contain_var_clause_walker (clause , NULL );
228
+ return contain_var_clause_walker (node , NULL );
136
229
}
137
230
138
231
static bool
@@ -150,6 +243,7 @@ contain_var_clause_walker(Node *node, void *context)
150
243
return expression_tree_walker (node , contain_var_clause_walker , context );
151
244
}
152
245
246
+
153
247
/*
154
248
* pull_var_clause
155
249
* Recursively pulls all var nodes from an expression clause.
@@ -160,16 +254,19 @@ contain_var_clause_walker(Node *node, void *context)
160
254
*
161
255
* Returns list of varnodes found. Note the varnodes themselves are not
162
256
* copied, only referenced.
257
+ *
258
+ * Does not examine subqueries, therefore must only be used after reduction
259
+ * of sublinks to subplans!
163
260
*/
164
261
List *
165
- pull_var_clause (Node * clause , bool includeUpperVars )
262
+ pull_var_clause (Node * node , bool includeUpperVars )
166
263
{
167
264
pull_var_clause_context context ;
168
265
169
266
context .varlist = NIL ;
170
267
context .includeUpperVars = includeUpperVars ;
171
268
172
- pull_var_clause_walker (clause , & context );
269
+ pull_var_clause_walker (node , & context );
173
270
return context .varlist ;
174
271
}
175
272
0 commit comments