]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Now that switch_outer processing no longer relies on being run after
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Jan 2003 23:10:32 +0000 (23:10 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Jan 2003 23:10:32 +0000 (23:10 +0000)
join_references(), it's practical to consolidate all join_references()
processing into the set_plan_references traversal in setrefs.c.  This
seems considerably cleaner than the old way where we did it for join
quals in createplan.c and for targetlists in setrefs.c.

src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/setrefs.c
src/include/optimizer/planmain.h

index 03ec35384797f41dfb0a5618f3dbfaf146b6ee93..f6e51d0d52f062c4f935bd558a08fc05e6d52080 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.130 2003/01/15 19:35:40 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.131 2003/01/15 23:10:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -651,20 +651,6 @@ create_functionscan_plan(Path *best_path, List *tlist, List *scan_clauses)
  *
  *     JOIN METHODS
  *
- * A general note about join_references() processing in these routines:
- * once we have changed a Var node to refer to a subplan output rather than
- * the original relation, it is no longer equal() to an unmodified Var node
- * for the same var.  So, we cannot easily compare reference-adjusted qual
- * clauses to clauses that have not been adjusted.     Fortunately, that
- * doesn't seem to be necessary; all the decisions are made before we do
- * the reference adjustments.
- *
- * A cleaner solution would be to not call join_references() here at all,
- * but leave it for setrefs.c to do at the end of plan tree construction.
- * But some care would be needed to get setrefs.c to do the right thing with
- * nestloop inner indexscan quals.  So, we do subplan reference adjustment
- * here for quals of join nodes (and *only* for quals of join nodes).
- *
  *****************************************************************************/
 
 static NestLoop *
@@ -676,8 +662,6 @@ create_nestloop_plan(Query *root,
                                         Plan *outer_plan,
                                         Plan *inner_plan)
 {
-       List       *outer_tlist = outer_plan->targetlist;
-       List       *inner_tlist = inner_plan->targetlist;
        NestLoop   *join_plan;
 
        if (IsA(inner_plan, IndexScan))
@@ -685,86 +669,27 @@ create_nestloop_plan(Query *root,
                /*
                 * An index is being used to reduce the number of tuples scanned
                 * in the inner relation.  If there are join clauses being used
-                * with the index, we must update their outer-rel var nodes to
-                * refer to the outer side of the join.
-                *
-                * We can also remove those join clauses from the list of clauses
-                * that have to be checked as qpquals at the join node, but only
-                * if there's just one indexscan in the inner path (otherwise,
-                * several different sets of clauses are being ORed together).
+                * with the index, we may remove those join clauses from the list of
+                * clauses that have to be checked as qpquals at the join node ---
+                * but only if there's just one indexscan in the inner path
+                * (otherwise, several different sets of clauses are being ORed
+                * together).
                 *
-                * Note: if the index is lossy, the same clauses may also be getting
-                * checked as qpquals in the indexscan.  We can still remove them
-                * from the nestloop's qpquals, but we gotta update the outer-rel
-                * vars in the indexscan's qpquals too.
-                *
-                * Note: we can safely do set_difference() against my clauses and
-                * join_references() because the innerscan is a primitive plan,
-                * and therefore has not itself done join_references renumbering
-                * of the vars in its quals.
+                * Note we must compare against indxqualorig not the "fixed" indxqual
+                * (which has index attnos instead of relation attnos, and may have
+                * been commuted as well).
                 */
                IndexScan  *innerscan = (IndexScan *) inner_plan;
                List       *indxqualorig = innerscan->indxqualorig;
 
-               /* No work needed if indxqual refers only to its own relation... */
-               if (NumRelids((Node *) indxqualorig) > 1)
+               if (length(indxqualorig) == 1) /* single indexscan? */
                {
-                       Index           innerrel = innerscan->scan.scanrelid;
-
-                       /*
-                        * Remove redundant tests from my clauses, if possible. Note
-                        * we must compare against indxqualorig not the "fixed"
-                        * indxqual (which has index attnos instead of relation
-                        * attnos, and may have been commuted as well).
-                        */
-                       if (length(indxqualorig) == 1)          /* single indexscan? */
+                       /* No work needed if indxqual refers only to its own relation... */
+                       if (NumRelids((Node *) indxqualorig) > 1)
                                joinclauses = set_difference(joinclauses,
                                                                                         lfirst(indxqualorig));
-
-                       /* only refs to outer vars get changed in the inner indexqual */
-                       innerscan->indxqualorig = join_references(indxqualorig,
-                                                                                                         root->rtable,
-                                                                                                         outer_tlist,
-                                                                                                         NIL,
-                                                                                                         innerrel);
-                       innerscan->indxqual = join_references(innerscan->indxqual,
-                                                                                                 root->rtable,
-                                                                                                 outer_tlist,
-                                                                                                 NIL,
-                                                                                                 innerrel);
-                       /* fix the inner qpqual too, if it has join clauses */
-                       if (NumRelids((Node *) inner_plan->qual) > 1)
-                               inner_plan->qual = join_references(inner_plan->qual,
-                                                                                                  root->rtable,
-                                                                                                  outer_tlist,
-                                                                                                  NIL,
-                                                                                                  innerrel);
                }
        }
-       else if (IsA(inner_plan, TidScan))
-       {
-               TidScan    *innerscan = (TidScan *) inner_plan;
-
-               innerscan->tideval = join_references(innerscan->tideval,
-                                                                                        root->rtable,
-                                                                                        outer_tlist,
-                                                                                        inner_tlist,
-                                                                                        innerscan->scan.scanrelid);
-       }
-
-       /*
-        * Set quals to contain INNER/OUTER var references.
-        */
-       joinclauses = join_references(joinclauses,
-                                                                 root->rtable,
-                                                                 outer_tlist,
-                                                                 inner_tlist,
-                                                                 (Index) 0);
-       otherclauses = join_references(otherclauses,
-                                                                  root->rtable,
-                                                                  outer_tlist,
-                                                                  inner_tlist,
-                                                                  (Index) 0);
 
        join_plan = make_nestloop(tlist,
                                                          joinclauses,
@@ -787,8 +712,6 @@ create_mergejoin_plan(Query *root,
                                          Plan *outer_plan,
                                          Plan *inner_plan)
 {
-       List       *outer_tlist = outer_plan->targetlist;
-       List       *inner_tlist = inner_plan->targetlist;
        List       *mergeclauses;
        MergeJoin  *join_plan;
 
@@ -806,25 +729,6 @@ create_mergejoin_plan(Query *root,
        mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
                                                                                best_path->jpath.outerjoinpath->parent->relids);
 
-       /*
-        * Fix all the join clauses to contain INNER/OUTER var references.
-        */
-       joinclauses = join_references(joinclauses,
-                                                                 root->rtable,
-                                                                 outer_tlist,
-                                                                 inner_tlist,
-                                                                 (Index) 0);
-       otherclauses = join_references(otherclauses,
-                                                                  root->rtable,
-                                                                  outer_tlist,
-                                                                  inner_tlist,
-                                                                  (Index) 0);
-       mergeclauses = join_references(mergeclauses,
-                                                                  root->rtable,
-                                                                  outer_tlist,
-                                                                  inner_tlist,
-                                                                  (Index) 0);
-
        /*
         * Create explicit sort nodes for the outer and inner join paths if
         * necessary.  The sort cost was already accounted for in the path.
@@ -868,8 +772,6 @@ create_hashjoin_plan(Query *root,
                                         Plan *outer_plan,
                                         Plan *inner_plan)
 {
-       List       *outer_tlist = outer_plan->targetlist;
-       List       *inner_tlist = inner_plan->targetlist;
        List       *hashclauses;
        HashJoin   *join_plan;
        Hash       *hash_plan;
@@ -890,25 +792,6 @@ create_hashjoin_plan(Query *root,
        hashclauses = get_switched_clauses(best_path->path_hashclauses,
                                                                           best_path->jpath.outerjoinpath->parent->relids);
 
-       /*
-        * Fix all the join clauses to contain INNER/OUTER var references.
-        */
-       joinclauses = join_references(joinclauses,
-                                                                 root->rtable,
-                                                                 outer_tlist,
-                                                                 inner_tlist,
-                                                                 (Index) 0);
-       otherclauses = join_references(otherclauses,
-                                                                  root->rtable,
-                                                                  outer_tlist,
-                                                                  inner_tlist,
-                                                                  (Index) 0);
-       hashclauses = join_references(hashclauses,
-                                                                 root->rtable,
-                                                                 outer_tlist,
-                                                                 inner_tlist,
-                                                                 (Index) 0);
-
        /*
         * Extract the inner hash keys (right-hand operands of the hashclauses)
         * to put in the Hash node.
@@ -922,7 +805,9 @@ create_hashjoin_plan(Query *root,
        /*
         * Build the hash node and hash join node.
         */
-       hash_plan = make_hash(inner_tlist, innerhashkeys, inner_plan);
+       hash_plan = make_hash(inner_plan->targetlist,
+                                                 innerhashkeys,
+                                                 inner_plan);
        join_plan = make_hashjoin(tlist,
                                                          joinclauses,
                                                          otherclauses,
index 1c9f8a27cff9044b7eac8887ecd81f967f5626e9..513480c4e20691d0964671c900f360e101bbd981 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.89 2003/01/15 19:35:43 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.90 2003/01/15 23:10:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,6 +44,11 @@ static void fix_expr_references(Plan *plan, Node *node);
 static bool fix_expr_references_walker(Node *node, void *context);
 static void set_join_references(Join *join, List *rtable);
 static void set_uppernode_references(Plan *plan, Index subvarno);
+static List *join_references(List *clauses,
+                                                        List *rtable,
+                                                        List *outer_tlist,
+                                                        List *inner_tlist,
+                                                        Index acceptable_rel);
 static Node *join_references_mutator(Node *node,
                                                join_references_context *context);
 static Node *replace_vars_with_subplan_refs(Node *node,
@@ -157,12 +162,26 @@ set_plan_references(Plan *plan, List *rtable)
                        fix_expr_references(plan,
                                                          (Node *) ((HashJoin *) plan)->hashclauses);
                        break;
+               case T_Hash:
+                       /*
+                        * Hash does not evaluate its targetlist or quals, so don't
+                        * touch those (see comments below).  But we do need to fix its
+                        * hashkeys.  The hashkeys are a little bizarre because they
+                        * need to match the hashclauses of the parent HashJoin node,
+                        * so we use join_references to fix them.
+                        */
+                       ((Hash *) plan)->hashkeys =
+                               join_references(((Hash *) plan)->hashkeys,
+                                                               rtable,
+                                                               NIL,
+                                                               plan->lefttree->targetlist,
+                                                               (Index) 0);
+                       break;
                case T_Material:
                case T_Sort:
                case T_Unique:
                case T_SetOp:
                case T_Limit:
-               case T_Hash:
 
                        /*
                         * These plan types don't actually bother to evaluate their
@@ -270,20 +289,14 @@ fix_expr_references_walker(Node *node, void *context)
 
 /*
  * set_join_references
- *       Modifies the target list of a join node to reference its subplans,
- *       by setting the varnos to OUTER or INNER and setting attno values to the
- *       result domain number of either the corresponding outer or inner join
- *       tuple item.
- *
- * Note: this same transformation has already been applied to the quals
- * of the join by createplan.c.  It's a little odd to do it here for the
- * targetlist and there for the quals, but it's easier that way.  (Look
- * at the handling of nestloop inner indexscans to see why.)
+ *       Modifies the target list and quals of a join node to reference its
+ *       subplans, by setting the varnos to OUTER or INNER and setting attno
+ *       values to the result domain number of either the corresponding outer
+ *       or inner join tuple item.
  *
- * Because the quals are reference-adjusted sooner, we cannot do equal()
- * comparisons between qual and tlist var nodes during the time between
- * creation of a plan node by createplan.c and its fixing by this module.
- * Fortunately, there doesn't seem to be any need to do that.
+ * In the case of a nestloop with inner indexscan, we will also need to
+ * apply the same transformation to any outer vars appearing in the
+ * quals of the child indexscan.
  *
  *     'join' is a join plan node
  *     'rtable' is the associated range table
@@ -291,16 +304,103 @@ fix_expr_references_walker(Node *node, void *context)
 static void
 set_join_references(Join *join, List *rtable)
 {
-       Plan       *outer = join->plan.lefttree;
-       Plan       *inner = join->plan.righttree;
-       List       *outer_tlist = ((outer == NULL) ? NIL : outer->targetlist);
-       List       *inner_tlist = ((inner == NULL) ? NIL : inner->targetlist);
+       Plan       *outer_plan = join->plan.lefttree;
+       Plan       *inner_plan = join->plan.righttree;
+       List       *outer_tlist = outer_plan->targetlist;
+       List       *inner_tlist = inner_plan->targetlist;
 
+       /* All join plans have tlist, qual, and joinqual */
        join->plan.targetlist = join_references(join->plan.targetlist,
                                                                                        rtable,
                                                                                        outer_tlist,
                                                                                        inner_tlist,
                                                                                        (Index) 0);
+       join->plan.qual = join_references(join->plan.qual,
+                                                                         rtable,
+                                                                         outer_tlist,
+                                                                         inner_tlist,
+                                                                         (Index) 0);
+       join->joinqual = join_references(join->joinqual,
+                                                                        rtable,
+                                                                        outer_tlist,
+                                                                        inner_tlist,
+                                                                        (Index) 0);
+
+       /* Now do join-type-specific stuff */
+       if (IsA(join, NestLoop))
+       {
+               if (IsA(inner_plan, IndexScan))
+               {
+                       /*
+                        * An index is being used to reduce the number of tuples scanned
+                        * in the inner relation.  If there are join clauses being used
+                        * with the index, we must update their outer-rel var nodes to
+                        * refer to the outer side of the join.
+                        */
+                       IndexScan  *innerscan = (IndexScan *) inner_plan;
+                       List       *indxqualorig = innerscan->indxqualorig;
+
+                       /* No work needed if indxqual refers only to its own rel... */
+                       if (NumRelids((Node *) indxqualorig) > 1)
+                       {
+                               Index           innerrel = innerscan->scan.scanrelid;
+
+                               /* only refs to outer vars get changed in the inner qual */
+                               innerscan->indxqualorig = join_references(indxqualorig,
+                                                                                                                 rtable,
+                                                                                                                 outer_tlist,
+                                                                                                                 NIL,
+                                                                                                                 innerrel);
+                               innerscan->indxqual = join_references(innerscan->indxqual,
+                                                                                                         rtable,
+                                                                                                         outer_tlist,
+                                                                                                         NIL,
+                                                                                                         innerrel);
+                               /*
+                                * We must fix the inner qpqual too, if it has join clauses
+                                * (this could happen if the index is lossy: some indxquals
+                                * may get rechecked as qpquals).
+                                */
+                               if (NumRelids((Node *) inner_plan->qual) > 1)
+                                       inner_plan->qual = join_references(inner_plan->qual,
+                                                                                                          rtable,
+                                                                                                          outer_tlist,
+                                                                                                          NIL,
+                                                                                                          innerrel);
+                       }
+               }
+               else if (IsA(inner_plan, TidScan))
+               {
+                       TidScan    *innerscan = (TidScan *) inner_plan;
+                       Index           innerrel = innerscan->scan.scanrelid;
+
+                       innerscan->tideval = join_references(innerscan->tideval,
+                                                                                                rtable,
+                                                                                                outer_tlist,
+                                                                                                NIL,
+                                                                                                innerrel);
+               }
+       }
+       else if (IsA(join, MergeJoin))
+       {
+               MergeJoin  *mj = (MergeJoin *) join;
+
+               mj->mergeclauses = join_references(mj->mergeclauses,
+                                                                                  rtable,
+                                                                                  outer_tlist,
+                                                                                  inner_tlist,
+                                                                                  (Index) 0);
+       }
+       else if (IsA(join, HashJoin))
+       {
+               HashJoin   *hj = (HashJoin *) join;
+
+               hj->hashclauses = join_references(hj->hashclauses,
+                                                                                 rtable,
+                                                                                 outer_tlist,
+                                                                                 inner_tlist,
+                                                                                 (Index) 0);
+       }
 }
 
 /*
@@ -400,7 +500,7 @@ set_uppernode_references(Plan *plan, Index subvarno)
  * Returns the new expression tree.  The original clause structure is
  * not modified.
  */
-List *
+static List *
 join_references(List *clauses,
                                List *rtable,
                                List *outer_tlist,
index f2604527001e039ffb1048e293b2fde2d3bfa876..66925931609054be37326186074989a126202aaf 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: planmain.h,v 1.65 2003/01/15 19:35:47 tgl Exp $
+ * $Id: planmain.h,v 1.66 2003/01/15 23:10:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,9 +63,6 @@ extern bool exprs_known_equal(Query *root, Node *item1, Node *item2);
  * prototypes for plan/setrefs.c
  */
 extern void set_plan_references(Plan *plan, List *rtable);
-extern List *join_references(List *clauses, List *rtable,
-                               List *outer_tlist, List *inner_tlist,
-                               Index acceptable_rel);
 extern void fix_opfuncids(Node *node);
 
 #endif   /* PLANMAIN_H */