]> granicus.if.org Git - postgresql/commitdiff
Clean up some mistakes in handling of uplevel Vars in planner.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Aug 1999 05:09:06 +0000 (05:09 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Aug 1999 05:09:06 +0000 (05:09 +0000)
Most parts of the planner should ignore, or indeed never even see, uplevel
Vars because they will be or have been replaced by Params.  There were a
couple of places that got it wrong though, probably my fault from recent
changes...

src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/tlist.c
src/backend/optimizer/util/var.c
src/include/optimizer/var.h

index a89c40b943598bde2181c7637a0f98782cb51806..20a01902efc143b28afd5f47c6435177a24b1731 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.38 1999/08/22 20:14:47 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.39 1999/08/26 05:07:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,7 +50,7 @@ static void check_hashjoinable(RestrictInfo *restrictinfo);
 void
 make_var_only_tlist(Query *root, List *tlist)
 {
-       List       *tlist_vars = pull_var_clause((Node *) tlist);
+       List       *tlist_vars = pull_var_clause((Node *) tlist, false);
 
        add_vars_to_targetlist(root, tlist_vars);
        freeList(tlist_vars);
index 3c7a665563c85212c2a27bcb0cf4156d3142ae49..b5c8d7d3de8161917c786468166328bdf33095b0 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.65 1999/08/22 23:56:45 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.66 1999/08/26 05:07:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -296,26 +296,27 @@ union_planner(Query *parse)
 
        /*
         * If we have a HAVING clause, do the necessary things with it.
+        * This code should parallel query_planner()'s initial processing
+        * of the WHERE clause.
         */
        if (parse->havingQual)
        {
                List       *ql;
 
-               /* convert the havingQual to conjunctive normal form (cnf) */
-               parse->havingQual = (Node *) cnfify((Expr *) parse->havingQual, true);
+               /* Replace uplevel Vars with Params */
+               if (PlannerQueryLevel > 1)
+                       parse->havingQual = SS_replace_correlation_vars(parse->havingQual);
 
                if (parse->hasSubLinks)
                {
-                       /*
-                        * There may be a subselect in the havingQual, so we have to
-                        * process it using the same function as for a subselect in
-                        * 'where'
-                        */
+                       /* Expand SubLinks to SubPlans */
                        parse->havingQual = SS_process_sublinks(parse->havingQual);
 
                        /*
                         * Check for ungrouped variables passed to subplans. (Probably
-                        * this should be done for the targetlist as well???)
+                        * this should be done for the targetlist as well???  But we
+                        * should NOT do it for the WHERE qual, since WHERE is
+                        * evaluated pre-GROUP.)
                         */
                        if (check_subplans_for_ungrouped_vars(parse->havingQual,
                                                                                                  parse->groupClause,
@@ -323,6 +324,9 @@ union_planner(Query *parse)
                                elog(ERROR, "Sub-SELECT in HAVING clause must use only GROUPed attributes from outer SELECT");
                }
 
+               /* convert the havingQual to conjunctive normal form (cnf) */
+               parse->havingQual = (Node *) cnfify((Expr *) parse->havingQual, true);
+
                /*
                 * Require an aggregate function to appear in each clause of the
                 * havingQual (else it could have been done as a WHERE constraint).
@@ -428,10 +432,11 @@ make_subplanTargetList(Query *parse,
 
        /*
         * Otherwise, start with a "flattened" tlist (having just the vars
-        * mentioned in the targetlist and HAVING qual).
+        * mentioned in the targetlist and HAVING qual --- but not upper-
+        * level Vars; they will be replaced by Params later on).
         */
        sub_tlist = flatten_tlist(tlist);
-       extravars = pull_var_clause(parse->havingQual);
+       extravars = pull_var_clause(parse->havingQual, false);
        sub_tlist = add_to_flat_tlist(sub_tlist, extravars);
        freeList(extravars);
 
index 2d960b5cf03ac21cb9b284b062101f262ae0120d..1ab09217c5928e32a8c56cd1a582d3399df58169 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.49 1999/08/25 23:21:41 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.50 1999/08/26 05:09:05 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -339,7 +339,7 @@ make_ands_implicit(Expr *clause)
 /*
  * pull_constant_clauses
  *       Scans through a list of qualifications and find those that
- *       contain no variables.
+ *       contain no variables (of the current query level).
  *
  * Returns a list of the constant clauses in constantQual and the remaining
  * quals as the return value.
@@ -480,11 +480,14 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
  *             Var nodes are considered distinct if they have different varno
  *             or varattno values.  If there are several occurrences of the same
  *             varno/varattno, you get a randomly chosen one...
+ *
+ * Note that upper-level vars are ignored, since they normally will
+ * become Params with respect to this query level.
  */
 void
 clause_get_relids_vars(Node *clause, Relids *relids, List **vars)
 {
-       List       *clvars = pull_var_clause(clause);
+       List       *clvars = pull_var_clause(clause, false);
        List       *varno_list = NIL;
        List       *var_list = NIL;
        List       *i;
@@ -494,7 +497,6 @@ clause_get_relids_vars(Node *clause, Relids *relids, List **vars)
                Var                *var = (Var *) lfirst(i);
                List       *vi;
 
-               Assert(var->varlevelsup == 0);
                if (!intMember(var->varno, varno_list))
                        varno_list = lconsi(var->varno, varno_list);
                foreach(vi, var_list)
index dfe2963581feec6d9b934956226bfd64ea3272b1..43007f33fff8685b490928d7f060efd1730e1bec 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.40 1999/08/22 20:14:54 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.41 1999/08/26 05:09:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -147,6 +147,10 @@ new_unsorted_tlist(List *targetlist)
  * flatten_tlist
  *       Create a target list that only contains unique variables.
  *
+ * Note that Vars with varlevelsup > 0 are not included in the output
+ * tlist.  We expect that those will eventually be replaced with Params,
+ * but that probably has not happened at the time this routine is called.
+ *
  * 'tlist' is the current target list
  *
  * Returns the "flattened" new target list.
@@ -157,7 +161,7 @@ new_unsorted_tlist(List *targetlist)
 List *
 flatten_tlist(List *tlist)
 {
-       List       *vlist = pull_var_clause((Node *) tlist);
+       List       *vlist = pull_var_clause((Node *) tlist, false);
        List       *new_tlist;
 
        new_tlist = add_to_flat_tlist(NIL, vlist);
index a544041122b2f4aff43b692330665c4ce9a33b76..af58b2556d6011eac6dc463ed5075dab18e56ee8 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.23 1999/08/22 20:14:54 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.24 1999/08/26 05:09:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "optimizer/var.h"
 
 
+typedef struct {
+       List       *varlist;
+       bool            includeUpperVars;
+} pull_var_clause_context;
+
 static bool pull_varnos_walker(Node *node, List **listptr);
 static bool contain_var_clause_walker(Node *node, void *context);
-static bool pull_var_clause_walker(Node *node, List **listptr);
+static bool pull_var_clause_walker(Node *node,
+                                                                  pull_var_clause_context *context);
 
 
 /*
  *             pull_varnos
  *
  *             Create a list of all the distinct varnos present in a parsetree
- *             (tlist or qual).
+ *             (tlist or qual).  Note that only varnos attached to level-zero
+ *             Vars are considered --- upper Vars refer to some other rtable!
  */
 List *
 pull_varnos(Node *node)
@@ -47,7 +54,7 @@ pull_varnos_walker(Node *node, List **listptr)
        if (IsA(node, Var))
        {
                Var        *var = (Var *) node;
-               if (!intMember(var->varno, *listptr))
+               if (var->varlevelsup == 0 && !intMember(var->varno, *listptr))
                        *listptr = lconsi(var->varno, *listptr);
                return false;
        }
@@ -56,7 +63,8 @@ pull_varnos_walker(Node *node, List **listptr)
 
 /*
  * contain_var_clause
- *       Recursively scan a clause to discover whether it contains any Var nodes.
+ *       Recursively scan a clause to discover whether it contains any Var nodes
+ *       (of the current query level).
  *
  *       Returns true if any varnode found.
  */
@@ -72,7 +80,11 @@ contain_var_clause_walker(Node *node, void *context)
        if (node == NULL)
                return false;
        if (IsA(node, Var))
-               return true;                    /* abort the tree traversal and return true */
+       {
+               if (((Var *) node)->varlevelsup == 0)
+                       return true;            /* abort the tree traversal and return true */
+               return false;
+       }
        return expression_tree_walker(node, contain_var_clause_walker, context);
 }
 
@@ -80,28 +92,36 @@ contain_var_clause_walker(Node *node, void *context)
  * pull_var_clause
  *       Recursively pulls all var nodes from an expression clause.
  *
+ *       Upper-level vars (with varlevelsup > 0) are included only
+ *       if includeUpperVars is true.  Most callers probably want
+ *       to ignore upper-level vars.
+ *
  *       Returns list of varnodes found.  Note the varnodes themselves are not
  *       copied, only referenced.
  */
 List *
-pull_var_clause(Node *clause)
+pull_var_clause(Node *clause, bool includeUpperVars)
 {
-       List       *result = NIL;
+       pull_var_clause_context         context;
 
-       pull_var_clause_walker(clause, &result);
-       return result;
+       context.varlist = NIL;
+       context.includeUpperVars = includeUpperVars;
+
+       pull_var_clause_walker(clause, &context);
+       return context.varlist;
 }
 
 static bool
-pull_var_clause_walker(Node *node, List **listptr)
+pull_var_clause_walker(Node *node, pull_var_clause_context *context)
 {
        if (node == NULL)
                return false;
        if (IsA(node, Var))
        {
-               *listptr = lappend(*listptr, node);
+               if (((Var *) node)->varlevelsup == 0 || context->includeUpperVars)
+                       context->varlist = lappend(context->varlist, node);
                return false;
        }
        return expression_tree_walker(node, pull_var_clause_walker,
-                                                                 (void *) listptr);
+                                                                 (void *) context);
 }
index 440b62f49adc75d5b6bf5c693c9bfb48f8958288..e2d5390876bff9036a66a4c2b3955fad4db3f53d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: var.h,v 1.9 1999/08/22 20:14:57 tgl Exp $
+ * $Id: var.h,v 1.10 1999/08/26 05:06:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,6 @@
 
 extern List *pull_varnos(Node *me);
 extern bool contain_var_clause(Node *clause);
-extern List *pull_var_clause(Node *clause);
+extern List *pull_var_clause(Node *clause, bool includeUpperVars);
 
 #endif  /* VAR_H */