88 *
99 *
1010 * 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 $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
15- #include <sys/types.h>
16-
1715#include "postgres.h"
1816
1917#include "nodes/plannodes.h"
@@ -27,6 +25,12 @@ typedef struct
2725 int sublevels_up ;
2826} pull_varnos_context ;
2927
28+ typedef struct
29+ {
30+ int varno ;
31+ int sublevels_up ;
32+ } contain_whole_tuple_var_context ;
33+
3034typedef struct
3135{
3236 List * varlist ;
@@ -35,6 +39,8 @@ typedef struct
3539
3640static bool pull_varnos_walker (Node * node ,
3741 pull_varnos_context * context );
42+ static bool contain_whole_tuple_var_walker (Node * node ,
43+ contain_whole_tuple_var_context * context );
3844static bool contain_var_clause_walker (Node * node , void * context );
3945static bool pull_var_clause_walker (Node * node ,
4046 pull_var_clause_context * context );
@@ -46,11 +52,10 @@ static bool pull_var_clause_walker(Node *node,
4652 * Create a list of all the distinct varnos present in a parsetree.
4753 * Only varnos that reference level-zero rtable entries are considered.
4854 *
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.
5459 */
5560List *
5661pull_varnos (Node * node )
@@ -122,17 +127,105 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
122127 (void * ) context );
123128}
124129
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+
125215/*
126216 * contain_var_clause
127217 * Recursively scan a clause to discover whether it contains any Var nodes
128218 * (of the current query level).
129219 *
130220 * Returns true if any varnode found.
221+ *
222+ * Does not examine subqueries, therefore must only be used after reduction
223+ * of sublinks to subplans!
131224 */
132225bool
133- contain_var_clause (Node * clause )
226+ contain_var_clause (Node * node )
134227{
135- return contain_var_clause_walker (clause , NULL );
228+ return contain_var_clause_walker (node , NULL );
136229}
137230
138231static bool
@@ -150,6 +243,7 @@ contain_var_clause_walker(Node *node, void *context)
150243 return expression_tree_walker (node , contain_var_clause_walker , context );
151244}
152245
246+
153247/*
154248 * pull_var_clause
155249 * Recursively pulls all var nodes from an expression clause.
@@ -160,16 +254,19 @@ contain_var_clause_walker(Node *node, void *context)
160254 *
161255 * Returns list of varnodes found. Note the varnodes themselves are not
162256 * copied, only referenced.
257+ *
258+ * Does not examine subqueries, therefore must only be used after reduction
259+ * of sublinks to subplans!
163260 */
164261List *
165- pull_var_clause (Node * clause , bool includeUpperVars )
262+ pull_var_clause (Node * node , bool includeUpperVars )
166263{
167264 pull_var_clause_context context ;
168265
169266 context .varlist = NIL ;
170267 context .includeUpperVars = includeUpperVars ;
171268
172- pull_var_clause_walker (clause , & context );
269+ pull_var_clause_walker (node , & context );
173270 return context .varlist ;
174271}
175272
0 commit comments