]> granicus.if.org Git - postgresql/commitdiff
Clean up tlist.c tree-walking routines with
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 Aug 1999 05:34:13 +0000 (05:34 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 Aug 1999 05:34:13 +0000 (05:34 +0000)
expression_tree_mutator.

src/backend/optimizer/util/tlist.c

index e348fa1b0f0531a918a3a805729903b1f8eec60c..386f23dba85c9fd778e534d672c3286334f245c2 100644 (file)
@@ -7,21 +7,19 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.36 1999/07/16 04:59:27 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.37 1999/08/09 05:34:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
-
-
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
 #include "optimizer/clauses.h"
 #include "optimizer/tlist.h"
 #include "optimizer/var.h"
 
-static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
+static Node *flatten_tlist_vars_mutator(Node *node, List *flat_tlist);
 
 /*****************************************************************************
  *     ---------- RELATION node target list routines ----------
@@ -29,25 +27,19 @@ static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
 
 /*
  * tlistentry_member
- *
- * RETURNS:  the leftmost member of sequence "targetlist" that satisfies
- *                      the predicate "var_equal"
- * MODIFIES: nothing
- * REQUIRES: test = function which can operate on a lispval union
- *                      var = valid var_node
- *                      targetlist = valid sequence
+ *       Finds the (first) member of the given tlist whose expression is
+ *       var_equal() to the given var.  Result is NULL if no such member.
  */
 TargetEntry *
 tlistentry_member(Var *var, List *targetlist)
 {
-       if (var)
+       if (var && IsA(var, Var))
        {
                List       *temp;
 
                foreach(temp, targetlist)
                {
-                       if (var_equal(var,
-                                                 get_expr(lfirst(temp))))
+                       if (var_equal(var, get_expr(lfirst(temp))))
                                return (TargetEntry *) lfirst(temp);
                }
        }
@@ -56,11 +48,8 @@ tlistentry_member(Var *var, List *targetlist)
 
 /*
  * matching_tlist_var
- *
- * RETURNS:  var node in a target list which is var_equal to 'var',
- *                      if one exists.
- * REQUIRES: "test" operates on lispval unions,
- *
+ *       Same as tlistentry_member(), except returns the tlist expression
+ *       rather than its parent TargetEntry node.
  */
 Expr *
 matching_tlist_var(Var *var, List *targetlist)
@@ -74,54 +63,45 @@ matching_tlist_var(Var *var, List *targetlist)
        return (Expr *) NULL;
 }
 
+/*
+ * tlist_member
+ *       Same as tlistentry_member(), except returns the Resdom node
+ *       rather than its parent TargetEntry node.
+ */
+Resdom *
+tlist_member(Var *var, List *tlist)
+{
+       TargetEntry *tlentry;
+
+       tlentry = tlistentry_member(var, tlist);
+       if (tlentry)
+               return tlentry->resdom;
+
+       return (Resdom *) NULL;
+}
+
 /*
  * add_var_to_tlist
  *       Creates a targetlist entry corresponding to the supplied var node
- *
- * 'var' and adds the new targetlist entry to the targetlist field of
- * 'rel'
- *
- * RETURNS: nothing
- * MODIFIES: vartype and varid fields of leftmost varnode that matches
- *                      argument "var" (sometimes).
- * CREATES:  new var_node iff no matching var_node exists in targetlist
+ *       'var' and adds the new targetlist entry to the targetlist field of
+ *       'rel'.  No entry is created if 'var' is already in the tlist.
  */
 void
 add_var_to_tlist(RelOptInfo *rel, Var *var)
 {
-       Expr       *oldvar;
-
-       oldvar = matching_tlist_var(var, rel->targetlist);
-
-       /*
-        * If 'var' is not already in 'rel's target list, add a new node.
-        */
-       if (oldvar == NULL)
+       if (tlistentry_member(var, rel->targetlist) == NULL)
        {
-               List       *tlist = rel->targetlist;
-               Var                *newvar = makeVar(var->varno,
-                                                                        var->varattno,
-                                                                        var->vartype,
-                                                                        var->vartypmod,
-                                                                        var->varlevelsup,
-                                                                        var->varno,
-                                                                        var->varoattno);
-
-               rel->targetlist = lappend(tlist,
-                                                                 create_tl_element(newvar,
-                                                                                                       length(tlist) + 1));
-
+               /* XXX is copyObject necessary here? */
+               rel->targetlist = lappend(rel->targetlist,
+                                                       create_tl_element((Var *) copyObject(var),
+                                                                                         length(rel->targetlist) + 1));
        }
 }
 
 /*
  * create_tl_element
  *       Creates a target list entry node and its associated (resdom var) pair
- *       with its resdom number equal to 'resdomno' and the joinlist field set
- *       to 'joinlist'.
- *
- * RETURNS:  newly created tlist_entry
- * CREATES:  new targetlist entry (always).
+ *       with its resdom number equal to 'resdomno'.
  */
 TargetEntry *
 create_tl_element(Var *var, int resdomno)
@@ -176,35 +156,6 @@ get_actual_tlist(List *tlist)
  *             ---------- GENERAL target list routines ----------
  *****************************************************************************/
 
-/*
- * tlist_member
- *       Determines whether a var node is already contained within a
- *       target list.
- *
- * 'var' is the var node
- * 'tlist' is the target list
- *
- * Returns the resdom entry of the matching var node, or NULL if no match.
- *
- */
-Resdom *
-tlist_member(Var *var, List *tlist)
-{
-       if (var)
-       {
-               List       *i;
-
-               foreach(i, tlist)
-               {
-                       TargetEntry *tle = (TargetEntry *) lfirst(i);
-
-                       if (var_equal(var, get_expr(tle)))
-                               return tle->resdom;
-               }
-       }
-       return (Resdom *) NULL;
-}
-
 /*
  *      Routine to get the resdom out of a targetlist.
  */
@@ -228,51 +179,36 @@ tlist_resdom(List *tlist, Resdom *resnode)
 
 /*
  * match_varid
- *       Searches a target list for an entry with some desired varid.
- *
- * 'varid' is the desired id
- * 'tlist' is the target list that is searched
- *
- * Returns the target list entry (resdom var) of the matching var.
+ *       Searches a target list for an entry matching a given var.
  *
- * Now checks to make sure array references (in addition to range
- * table indices) are identical - retrieve (a.b[1],a.b[2]) should
- * not be turned into retrieve (a.b[1],a.b[1]).
- *
- * [what used to be varid is now broken up into two fields varnoold and
- *     varoattno. Also, nested attnos are long gone. - ay 2/95]
+ * Returns the target list entry (resdom var) of the matching var,
+ * or NULL if no match.
  */
 TargetEntry *
 match_varid(Var *test_var, List *tlist)
 {
        List       *tl;
-       Oid                     type_var;
 
-       type_var = (Oid) test_var->vartype;
+       Assert(test_var->varlevelsup == 0);     /* XXX why? */
 
-       Assert(test_var->varlevelsup == 0);
        foreach(tl, tlist)
        {
-               TargetEntry *entry;
-               Var                *tlvar;
-
-               entry = lfirst(tl);
-               tlvar = get_expr(entry);
+               TargetEntry *entry = lfirst(tl);
+               Var                *tlvar = get_expr(entry);
 
                if (!IsA(tlvar, Var))
                        continue;
 
                /*
-                * we test the original varno (instead of varno which might be
-                * changed to INNER/OUTER.
+                * we test the original varnoinstead of varno which might be
+                * changed to INNER/OUTER.  XXX is test on vartype necessary?
                 */
                Assert(tlvar->varlevelsup == 0);
+
                if (tlvar->varnoold == test_var->varnoold &&
-                       tlvar->varoattno == test_var->varoattno)
-               {
-                       if (tlvar->vartype == type_var)
-                               return entry;
-               }
+                       tlvar->varoattno == test_var->varoattno &&
+                       tlvar->vartype == test_var->vartype)
+                       return entry;
        }
 
        return NULL;
@@ -321,11 +257,12 @@ List *
 copy_vars(List *target, List *source)
 {
        List       *result = NIL;
-       List       *src = NIL;
-       List       *dest = NIL;
+       List       *src;
+       List       *dest;
 
-       for (src = source, dest = target; src != NIL &&
-                dest != NIL; src = lnext(src), dest = lnext(dest))
+       for (src = source, dest = target;
+                src != NIL && dest != NIL;
+                src = lnext(src), dest = lnext(dest))
        {
                TargetEntry *temp = makeTargetEntry(((TargetEntry *) lfirst(dest))->resdom,
                                                                                 (Node *) get_expr(lfirst(src)));
@@ -350,35 +287,34 @@ flatten_tlist(List *tlist)
 {
        int                     last_resdomno = 1;
        List       *new_tlist = NIL;
-       List       *tlist_vars = NIL;
-       List       *temp;
-
-       foreach(temp, tlist)
-       {
-               TargetEntry *temp_entry = (TargetEntry *) lfirst(temp);
-
-               tlist_vars = nconc(tlist_vars,
-                                                pull_var_clause((Node *) get_expr(temp_entry)));
-       }
+       List       *tl;
 
-       foreach(temp, tlist_vars)
+       foreach(tl, tlist)
        {
-               Var                *var = lfirst(temp);
+               TargetEntry *tl_entry = (TargetEntry *) lfirst(tl);
+               List       *vlist = pull_var_clause((Node *) get_expr(tl_entry));
+               List       *v;
 
-               if (!(tlist_member(var, new_tlist)))
+               foreach(v, vlist)
                {
-                       Resdom     *r;
-
-                       r = makeResdom(last_resdomno,
-                                                  var->vartype,
-                                                  var->vartypmod,
-                                                  NULL,
-                                                  (Index) 0,
-                                                  (Oid) 0,
-                                                  false);
-                       last_resdomno++;
-                       new_tlist = lappend(new_tlist, makeTargetEntry(r, (Node *) var));
+                       Var                *var = lfirst(v);
+
+                       if (! tlistentry_member(var, new_tlist))
+                       {
+                               Resdom     *r;
+
+                               r = makeResdom(last_resdomno++,
+                                                          var->vartype,
+                                                          var->vartypmod,
+                                                          NULL,
+                                                          (Index) 0,
+                                                          (Oid) 0,
+                                                          false);
+                               new_tlist = lappend(new_tlist,
+                                                                       makeTargetEntry(r, (Node *) var));
+                       }
                }
+               freeList(vlist);
        }
 
        return new_tlist;
@@ -386,14 +322,13 @@ flatten_tlist(List *tlist)
 
 /*
  * flatten_tlist_vars
- *       Redoes the target list of a query with no nested attributes by
- *       replacing vars within computational expressions with vars from
- *       the 'flattened' target list of the query.
+ *       Redoes the target list of a query by replacing vars within
+ *       target expressions with vars from the 'flattened' target list.
  *
- * 'full_tlist' is the actual target list
+ * 'full_tlist' is the original target list
  * 'flat_tlist' is the flattened (var-only) target list
  *
- * Returns the modified actual target list.
+ * Returns the rebuilt target list.  The original is not modified.
  *
  */
 List *
@@ -406,105 +341,25 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist)
        {
                TargetEntry *tle = lfirst(x);
 
-               result = lappend(result, makeTargetEntry(tle->resdom,
-                                                          flatten_tlistentry((Node *) get_expr(tle),
-                                                                                                 flat_tlist)));
+               result = lappend(result,
+                                                makeTargetEntry(tle->resdom,
+                                                       flatten_tlist_vars_mutator((Node *) get_expr(tle),
+                                                                                                          flat_tlist)));
        }
 
        return result;
 }
 
-/*
- * flatten_tlistentry
- *       Replaces vars within a target list entry with vars from a flattened
- *       target list.
- *
- * 'tlistentry' is the target list entry to be modified
- * 'flat_tlist' is the flattened target list
- *
- * Returns the (modified) target_list entry from the target list.
- *
- */
 static Node *
-flatten_tlistentry(Node *tlistentry, List *flat_tlist)
+flatten_tlist_vars_mutator(Node *node, List *flat_tlist)
 {
-       List       *temp;
-
-       if (tlistentry == NULL)
+       if (node == NULL)
                return NULL;
-       else if (IsA(tlistentry, Var))
-               return (Node *) get_expr(match_varid((Var *) tlistentry,
+       if (IsA(node, Var))
+               return (Node *) get_expr(match_varid((Var *) node,
                                                                                         flat_tlist));
-       else if (single_node(tlistentry))
-               return tlistentry;
-       else if (IsA(tlistentry, Iter))
-       {
-               ((Iter *) tlistentry)->iterexpr =
-                       flatten_tlistentry((Node *) ((Iter *) tlistentry)->iterexpr,
-                                                          flat_tlist);
-               return tlistentry;
-       }
-       else if (is_subplan(tlistentry))
-       {
-               /* do we need to support this case? */
-               elog(ERROR, "flatten_tlistentry: subplan case not implemented");
-               return tlistentry;
-       }
-       else if (IsA(tlistentry, Expr))
-       {
-
-               /*
-                * Recursively scan the arguments of an expression. NOTE: this
-                * must come after is_subplan() case since subplan is a kind of
-                * Expr node.
-                */
-               foreach(temp, ((Expr *) tlistentry)->args)
-                       lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
-               return tlistentry;
-       }
-       else if (IsA(tlistentry, Aggref))
-       {
-
-               /*
-                * XXX shouldn't this be recursing into the agg's target? Seems to
-                * work though, so will leave it alone ... tgl 5/99
-                */
-               return tlistentry;
-       }
-       else if (IsA(tlistentry, ArrayRef))
-       {
-               ArrayRef   *aref = (ArrayRef *) tlistentry;
-
-               foreach(temp, aref->refupperindexpr)
-                       lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
-               foreach(temp, aref->reflowerindexpr)
-                       lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
-               aref->refexpr = flatten_tlistentry(aref->refexpr, flat_tlist);
-               aref->refassgnexpr = flatten_tlistentry(aref->refassgnexpr, flat_tlist);
-
-               return tlistentry;
-       }
-       else if (case_clause(tlistentry))
-       {
-               CaseExpr   *cexpr = (CaseExpr *) tlistentry;
-
-               foreach(temp, cexpr->args)
-               {
-                       CaseWhen   *cwhen = (CaseWhen *) lfirst(temp);
-
-                       cwhen->expr = flatten_tlistentry(cwhen->expr, flat_tlist);
-                       cwhen->result = flatten_tlistentry(cwhen->result, flat_tlist);
-               }
-               cexpr->defresult = flatten_tlistentry(cexpr->defresult, flat_tlist);
-
-               return tlistentry;
-       }
-       else
-       {
-               elog(ERROR, "flatten_tlistentry: Cannot handle node type %d",
-                        nodeTag(tlistentry));
-               return tlistentry;
-       }
+       return expression_tree_mutator(node, flatten_tlist_vars_mutator,
+                                                                  (void *) flat_tlist);
 }
 
 
@@ -522,11 +377,10 @@ Var *
 get_groupclause_expr(GroupClause *groupClause, List *targetList)
 {
        List       *l;
-       TargetEntry *tle;
 
        foreach(l, targetList)
        {
-               tle = (TargetEntry *) lfirst(l);
+               TargetEntry *tle = (TargetEntry *) lfirst(l);
                if (tle->resdom->resgroupref == groupClause->tleGroupref)
                        return get_expr(tle);
        }
@@ -535,49 +389,3 @@ get_groupclause_expr(GroupClause *groupClause, List *targetList)
        "get_groupclause_expr: GROUP BY expression not found in targetlist");
        return NULL;
 }
-
-
-/*****************************************************************************
- *
- *****************************************************************************/
-
-/*
- * AddGroupAttrToTlist -
- *       append the group attribute to the target list if it's not already
- *       in there.
- */
-#ifdef NOT_USED
-/*
- * WARNING!!! If this ever get's used again, the new reference
- * mechanism from group clause to targetlist entry must be implemented
- * here too. Jan
- */
-void
-AddGroupAttrToTlist(List *tlist, List *grpCl)
-{
-       List       *gl;
-       int                     last_resdomno = length(tlist) + 1;
-
-       foreach(gl, grpCl)
-       {
-               GroupClause *gc = (GroupClause *) lfirst(gl);
-               Var                *var = gc->grpAttr;
-
-               if (!(tlist_member(var, tlist)))
-               {
-                       Resdom     *r;
-
-                       r = makeResdom(last_resdomno,
-                                                  var->vartype,
-                                                  var->vartypmod,
-                                                  NULL,
-                                                  (Index) 0,
-                                                  (Oid) 0,
-                                                  false);
-                       last_resdomno++;
-                       tlist = lappend(tlist, makeTargetEntry(r, (Node *) var));
-               }
-       }
-}
-
-#endif