Change set_plan_references and join_references to take an rtable List
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 May 2002 02:25:50 +0000 (02:25 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 May 2002 02:25:50 +0000 (02:25 +0000)
rather than a Query node; this allows set_plan_references to recurse
into subplans correctly.  Fixes core dump on full outer joins in
subplans.  Also, invoke preprocess_expression on function RTEs'
function expressions.  This seems to fix the planner's problems with
outer-level Vars in function RTEs.

src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/util/var.c
src/include/optimizer/planmain.h
src/include/optimizer/var.h

index cd8b0e6612fda83f2f8a47d95d7e4fddc01440ec..f24fe23f15029d3bc28f7e445cb71dac3833e51f 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.114 2002/05/12 20:10:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.115 2002/05/18 02:25:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -671,19 +671,19 @@ create_nestloop_plan(Query *root,
 
                        /* only refs to outer vars get changed in the inner indexqual */
                        innerscan->indxqualorig = join_references(indxqualorig,
-                                                                                                         root,
+                                                                                                         root->rtable,
                                                                                                          outer_tlist,
                                                                                                          NIL,
                                                                                                          innerrel);
                        innerscan->indxqual = join_references(innerscan->indxqual,
-                                                                                                 root,
+                                                                                                 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,
+                                                                                                  root->rtable,
                                                                                                   outer_tlist,
                                                                                                   NIL,
                                                                                                   innerrel);
@@ -694,7 +694,7 @@ create_nestloop_plan(Query *root,
                TidScan    *innerscan = (TidScan *) inner_plan;
 
                innerscan->tideval = join_references(innerscan->tideval,
-                                                                                        root,
+                                                                                        root->rtable,
                                                                                         outer_tlist,
                                                                                         inner_tlist,
                                                                                         innerscan->scan.scanrelid);
@@ -716,12 +716,12 @@ create_nestloop_plan(Query *root,
         * Set quals to contain INNER/OUTER var references.
         */
        joinclauses = join_references(joinclauses,
-                                                                 root,
+                                                                 root->rtable,
                                                                  outer_tlist,
                                                                  inner_tlist,
                                                                  (Index) 0);
        otherclauses = join_references(otherclauses,
-                                                                  root,
+                                                                  root->rtable,
                                                                   outer_tlist,
                                                                   inner_tlist,
                                                                   (Index) 0);
@@ -760,7 +760,7 @@ create_mergejoin_plan(Query *root,
         * clauses to contain INNER/OUTER var references.
         */
        joinclauses = join_references(set_difference(joinclauses, mergeclauses),
-                                                                 root,
+                                                                 root->rtable,
                                                                  outer_tlist,
                                                                  inner_tlist,
                                                                  (Index) 0);
@@ -769,7 +769,7 @@ create_mergejoin_plan(Query *root,
         * Fix the additional qpquals too.
         */
        otherclauses = join_references(otherclauses,
-                                                                  root,
+                                                                  root->rtable,
                                                                   outer_tlist,
                                                                   inner_tlist,
                                                                   (Index) 0);
@@ -779,7 +779,7 @@ create_mergejoin_plan(Query *root,
         * that the outer variable is always on the left.
         */
        mergeclauses = switch_outer(join_references(mergeclauses,
-                                                                                               root,
+                                                                                               root->rtable,
                                                                                                outer_tlist,
                                                                                                inner_tlist,
                                                                                                (Index) 0));
@@ -886,7 +886,7 @@ create_hashjoin_plan(Query *root,
         * clauses to contain INNER/OUTER var references.
         */
        joinclauses = join_references(set_difference(joinclauses, hashclauses),
-                                                                 root,
+                                                                 root->rtable,
                                                                  outer_tlist,
                                                                  inner_tlist,
                                                                  (Index) 0);
@@ -895,7 +895,7 @@ create_hashjoin_plan(Query *root,
         * Fix the additional qpquals too.
         */
        otherclauses = join_references(otherclauses,
-                                                                  root,
+                                                                  root->rtable,
                                                                   outer_tlist,
                                                                   inner_tlist,
                                                                   (Index) 0);
@@ -905,7 +905,7 @@ create_hashjoin_plan(Query *root,
         * that the outer variable is always on the left.
         */
        hashclauses = switch_outer(join_references(hashclauses,
-                                                                                          root,
+                                                                                          root->rtable,
                                                                                           outer_tlist,
                                                                                           inner_tlist,
                                                                                           (Index) 0));
index fdd375acd83754e988746db58c81b59e6df97cd0..2d12a623f720c23bae5a89182ab70209bc85efe7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.71 2002/05/17 22:35:12 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.72 2002/05/18 02:25:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -177,7 +177,7 @@ add_vars_to_targetlist(Query *root, List *vars)
                        List   *varsused;
 
                        expansion = flatten_join_alias_vars((Node *) var,
-                                                                                               root, true);
+                                                                                               root->rtable, true);
                        varsused = pull_var_clause(expansion, false);
                        add_vars_to_targetlist(root, varsused);
                        freeList(varsused);
index 500297f2155fd87dc238b8078b93d499603e9265..a3eeced7bb13e3d062af8e8cbb027f306913e624 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.117 2002/05/12 23:43:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.118 2002/05/18 02:25:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,7 +101,7 @@ planner(Query *parse)
        result_plan->nParamExec = length(PlannerParamVar);
 
        /* final cleanup of the plan */
-       set_plan_references(parse, result_plan);
+       set_plan_references(result_plan, parse->rtable);
 
        /* restore state for outer planner, if any */
        PlannerQueryLevel = save_PlannerQueryLevel;
@@ -175,6 +175,17 @@ subquery_planner(Query *parse, double tuple_fraction)
        parse->havingQual = preprocess_expression(parse, parse->havingQual,
                                                                                          EXPRKIND_HAVING);
 
+       /* Also need to preprocess expressions for function RTEs */
+       foreach(lst, parse->rtable)
+       {
+               RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst);
+
+               if (rte->rtekind == RTE_FUNCTION)
+                       rte->funcexpr = preprocess_expression(parse, rte->funcexpr,
+                                                                                                 EXPRKIND_TARGET);
+               /* These are not targetlist items, but close enough... */
+       }
+
        /*
         * Check for ungrouped variables passed to subplans in targetlist and
         * HAVING clause (but not in WHERE or JOIN/ON clauses, since those are
@@ -737,7 +748,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
                }
        }
        if (has_join_rtes)
-               expr = flatten_join_alias_vars(expr, parse, false);
+               expr = flatten_join_alias_vars(expr, parse->rtable, false);
 
        return expr;
 }
index 1b05d49054ff5a8830d9bc185a2ad23c67a4b929..3f0187617ac0b0133a123ab37b54690b2bb1ca4b 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.77 2002/05/18 00:42:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.78 2002/05/18 02:25:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,7 @@
 
 typedef struct
 {
-       Query      *root;
+       List       *rtable;
        List       *outer_tlist;
        List       *inner_tlist;
        Index           acceptable_rel;
@@ -42,7 +42,7 @@ typedef struct
 } replace_vars_with_subplan_refs_context;
 
 static void fix_expr_references(Plan *plan, Node *node);
-static void set_join_references(Query *root, Join *join);
+static void set_join_references(Join *join, List *rtable);
 static void set_uppernode_references(Plan *plan, Index subvarno);
 static Node *join_references_mutator(Node *node,
                                                join_references_context *context);
@@ -75,7 +75,7 @@ static bool fix_opids_walker(Node *node, void *context);
  * Returns nothing of interest, but modifies internal fields of nodes.
  */
 void
-set_plan_references(Query *root, Plan *plan)
+set_plan_references(Plan *plan, List *rtable)
 {
        List       *pl;
 
@@ -110,16 +110,24 @@ set_plan_references(Query *root, Plan *plan)
                        fix_expr_references(plan, (Node *) plan->qual);
                        break;
                case T_SubqueryScan:
+                       {
+                               RangeTblEntry *rte;
 
-                       /*
-                        * We do not do set_uppernode_references() here, because a
-                        * SubqueryScan will always have been created with correct
-                        * references to its subplan's outputs to begin with.
-                        */
-                       fix_expr_references(plan, (Node *) plan->targetlist);
-                       fix_expr_references(plan, (Node *) plan->qual);
-                       /* Recurse into subplan too */
-                       set_plan_references(root, ((SubqueryScan *) plan)->subplan);
+                               /*
+                                * We do not do set_uppernode_references() here, because a
+                                * SubqueryScan will always have been created with correct
+                                * references to its subplan's outputs to begin with.
+                                */
+                               fix_expr_references(plan, (Node *) plan->targetlist);
+                               fix_expr_references(plan, (Node *) plan->qual);
+
+                               /* Recurse into subplan too */
+                               rte = rt_fetch(((SubqueryScan *) plan)->scan.scanrelid,
+                                                          rtable);
+                               Assert(rte->rtekind == RTE_SUBQUERY);
+                               set_plan_references(((SubqueryScan *) plan)->subplan,
+                                                                       rte->subquery->rtable);
+                       }
                        break;
                case T_FunctionScan:
                        {
@@ -128,19 +136,19 @@ set_plan_references(Query *root, Plan *plan)
                                fix_expr_references(plan, (Node *) plan->targetlist);
                                fix_expr_references(plan, (Node *) plan->qual);
                                rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
-                                                          root->rtable);
+                                                          rtable);
                                Assert(rte->rtekind == RTE_FUNCTION);
                                fix_expr_references(plan, rte->funcexpr);
                        }
                        break;
                case T_NestLoop:
-                       set_join_references(root, (Join *) plan);
+                       set_join_references((Join *) plan, rtable);
                        fix_expr_references(plan, (Node *) plan->targetlist);
                        fix_expr_references(plan, (Node *) plan->qual);
                        fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
                        break;
                case T_MergeJoin:
-                       set_join_references(root, (Join *) plan);
+                       set_join_references((Join *) plan, rtable);
                        fix_expr_references(plan, (Node *) plan->targetlist);
                        fix_expr_references(plan, (Node *) plan->qual);
                        fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
@@ -148,7 +156,7 @@ set_plan_references(Query *root, Plan *plan)
                                                        (Node *) ((MergeJoin *) plan)->mergeclauses);
                        break;
                case T_HashJoin:
-                       set_join_references(root, (Join *) plan);
+                       set_join_references((Join *) plan, rtable);
                        fix_expr_references(plan, (Node *) plan->targetlist);
                        fix_expr_references(plan, (Node *) plan->qual);
                        fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
@@ -202,7 +210,7 @@ set_plan_references(Query *root, Plan *plan)
                         * recurse into subplans.
                         */
                        foreach(pl, ((Append *) plan)->appendplans)
-                               set_plan_references(root, (Plan *) lfirst(pl));
+                               set_plan_references((Plan *) lfirst(pl), rtable);
                        break;
                default:
                        elog(ERROR, "set_plan_references: unknown plan type %d",
@@ -219,21 +227,21 @@ set_plan_references(Query *root, Plan *plan)
         * plan's var nodes against the already-modified nodes of the
         * subplans.
         */
-       set_plan_references(root, plan->lefttree);
-       set_plan_references(root, plan->righttree);
+       set_plan_references(plan->lefttree, rtable);
+       set_plan_references(plan->righttree, rtable);
        foreach(pl, plan->initPlan)
        {
                SubPlan    *sp = (SubPlan *) lfirst(pl);
 
                Assert(IsA(sp, SubPlan));
-               set_plan_references(root, sp->plan);
+               set_plan_references(sp->plan, sp->rtable);
        }
        foreach(pl, plan->subPlan)
        {
                SubPlan    *sp = (SubPlan *) lfirst(pl);
 
                Assert(IsA(sp, SubPlan));
-               set_plan_references(root, sp->plan);
+               set_plan_references(sp->plan, sp->rtable);
        }
 }
 
@@ -269,10 +277,11 @@ fix_expr_references(Plan *plan, Node *node)
  * 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.
  *
- * 'join' is a join plan node
+ *     'join' is a join plan node
+ *     'rtable' is the associated range table
  */
 static void
-set_join_references(Query *root, Join *join)
+set_join_references(Join *join, List *rtable)
 {
        Plan       *outer = join->plan.lefttree;
        Plan       *inner = join->plan.righttree;
@@ -280,7 +289,7 @@ set_join_references(Query *root, Join *join)
        List       *inner_tlist = ((inner == NULL) ? NIL : inner->targetlist);
 
        join->plan.targetlist = join_references(join->plan.targetlist,
-                                                                                       root,
+                                                                                       rtable,
                                                                                        outer_tlist,
                                                                                        inner_tlist,
                                                                                        (Index) 0);
@@ -374,6 +383,7 @@ set_uppernode_references(Plan *plan, Index subvarno)
  * pass inner_tlist = NIL and acceptable_rel = the ID of the inner relation.
  *
  * 'clauses' is the targetlist or list of join clauses
+ * 'rtable' is the current range table
  * 'outer_tlist' is the target list of the outer join relation
  * 'inner_tlist' is the target list of the inner join relation, or NIL
  * 'acceptable_rel' is either zero or the rangetable index of a relation
@@ -384,14 +394,14 @@ set_uppernode_references(Plan *plan, Index subvarno)
  */
 List *
 join_references(List *clauses,
-                               Query *root,
+                               List *rtable,
                                List *outer_tlist,
                                List *inner_tlist,
                                Index acceptable_rel)
 {
        join_references_context context;
 
-       context.root = root;
+       context.rtable = rtable;
        context.outer_tlist = outer_tlist;
        context.inner_tlist = inner_tlist;
        context.acceptable_rel = acceptable_rel;
@@ -432,7 +442,7 @@ join_references_mutator(Node *node,
 
                /* Perhaps it's a join alias that can be resolved to input vars? */
                newnode = flatten_join_alias_vars((Node *) var,
-                                                                                 context->root,
+                                                                                 context->rtable,
                                                                                  true);
                if (!equal(newnode, (Node *) var))
                {
index ee861c3557e2b460216e33ff307d086a190629c8..2bdb23897cf3fcf33413d8e479f6f79513ecb0e3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.36 2002/04/28 19:54:28 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.37 2002/05/18 02:25:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,7 +41,7 @@ typedef struct
 
 typedef struct
 {
-       Query      *root;
+       List       *rtable;
        bool            force;
 } flatten_join_alias_vars_context;
 
@@ -328,11 +328,11 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
  * of sublinks to subplans!
  */
 Node *
-flatten_join_alias_vars(Node *node, Query *root, bool force)
+flatten_join_alias_vars(Node *node, List *rtable, bool force)
 {
        flatten_join_alias_vars_context context;
 
-       context.root = root;
+       context.rtable = rtable;
        context.force = force;
 
        return flatten_join_alias_vars_mutator(node, &context);
@@ -352,7 +352,7 @@ flatten_join_alias_vars_mutator(Node *node,
 
                if (var->varlevelsup != 0)
                        return node;            /* no need to copy, really */
-               rte = rt_fetch(var->varno, context->root->rtable);
+               rte = rt_fetch(var->varno, context->rtable);
                if (rte->rtekind != RTE_JOIN)
                        return node;
                Assert(var->varattno > 0);
index 3956555a2e093998a7aa9c66ac9f5ae53718f8b1..29319a148561556331dd969dfc739d4e6808a435 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: planmain.h,v 1.56 2002/04/28 19:54:28 tgl Exp $
+ * $Id: planmain.h,v 1.57 2002/05/18 02:25:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,8 +56,8 @@ extern void process_implied_equality(Query *root, Node *item1, Node *item2,
 /*
  * prototypes for plan/setrefs.c
  */
-extern void set_plan_references(Query *root, Plan *plan);
-extern List *join_references(List *clauses, Query *root,
+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_opids(Node *node);
index c9a22b8f55a7685ca6d809e673fb8dc996ba630f..0ae554bc3e699a3efc5427f021003e12c296b71b 100644 (file)
@@ -7,14 +7,14 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: var.h,v 1.19 2002/04/28 19:54:28 tgl Exp $
+ * $Id: var.h,v 1.20 2002/05/18 02:25:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef VAR_H
 #define VAR_H
 
-#include "nodes/parsenodes.h"
+#include "nodes/primnodes.h"
 
 
 extern List *pull_varnos(Node *node);
@@ -23,6 +23,6 @@ extern bool contain_var_reference(Node *node, int varno, int varattno,
 extern bool contain_whole_tuple_var(Node *node, int varno, int levelsup);
 extern bool contain_var_clause(Node *node);
 extern List *pull_var_clause(Node *node, bool includeUpperVars);
-extern Node *flatten_join_alias_vars(Node *node, Query *root, bool force);
+extern Node *flatten_join_alias_vars(Node *node, List *rtable, bool force);
 
 #endif   /* VAR_H */