aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/setrefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r--src/backend/optimizer/plan/setrefs.c238
1 files changed, 26 insertions, 212 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 70be2e66f2d..450970e5c37 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.160 2010/02/26 02:00:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.161 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -89,8 +89,6 @@ static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset);
static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);
-static void set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
- indexed_tlist *outer_itlist);
static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset);
static void set_dummy_tlist_references(Plan *plan, int rtoffset);
static indexed_tlist *build_tlist_index(List *tlist);
@@ -878,12 +876,11 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Assert(var->varlevelsup == 0);
/*
- * We should not see any Vars marked INNER, but in a nestloop inner
- * scan there could be OUTER Vars. Leave them alone.
+ * We should not see any Vars marked INNER or OUTER.
*/
Assert(var->varno != INNER);
- if (var->varno > 0 && var->varno != OUTER)
- var->varno += context->rtoffset;
+ Assert(var->varno != OUTER);
+ var->varno += context->rtoffset;
if (var->varnoold > 0)
var->varnoold += context->rtoffset;
return (Node *) var;
@@ -927,10 +924,6 @@ fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
* values to the result domain number of either the corresponding outer
* or inner join tuple item. Also perform opcode lookup for these
* expressions. and add regclass OIDs to glob->relationOids.
- *
- * 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. set_inner_join_references does that.
*/
static void
set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
@@ -966,8 +959,18 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
/* Now do join-type-specific stuff */
if (IsA(join, NestLoop))
{
- /* This processing is split out to handle possible recursion */
- set_inner_join_references(glob, inner_plan, outer_itlist);
+ NestLoop *nl = (NestLoop *) join;
+ ListCell *lc;
+
+ foreach(lc, nl->nestParams)
+ {
+ NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
+
+ nlp->paramval = (Var *) fix_upper_expr(glob,
+ (Node *) nlp->paramval,
+ outer_itlist,
+ rtoffset);
+ }
}
else if (IsA(join, MergeJoin))
{
@@ -997,193 +1000,6 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
}
/*
- * set_inner_join_references
- * Handle join references appearing in an inner indexscan's quals
- *
- * To handle bitmap-scan plan trees, we have to be able to recurse down
- * to the bottom BitmapIndexScan nodes; likewise, appendrel indexscans
- * require recursing through Append nodes. This is split out as a separate
- * function so that it can recurse.
- *
- * Note we do *not* apply any rtoffset for non-join Vars; this is because
- * the quals will be processed again by fix_scan_expr when the set_plan_refs
- * recursion reaches the inner indexscan, and so we'd have done it twice.
- */
-static void
-set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
- indexed_tlist *outer_itlist)
-{
- 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 *indexqualorig = innerscan->indexqualorig;
-
- /* No work needed if indexqual refers only to its own rel... */
- if (NumRelids((Node *) indexqualorig) > 1)
- {
- Index innerrel = innerscan->scan.scanrelid;
-
- /* only refs to outer vars get changed in the inner qual */
- innerscan->indexqualorig = fix_join_expr(glob,
- indexqualorig,
- outer_itlist,
- NULL,
- innerrel,
- 0);
- innerscan->indexqual = fix_join_expr(glob,
- innerscan->indexqual,
- outer_itlist,
- NULL,
- innerrel,
- 0);
-
- /*
- * We must fix the inner qpqual too, if it has join clauses (this
- * could happen if special operators are involved: some indexquals
- * may get rechecked as qpquals).
- */
- if (NumRelids((Node *) inner_plan->qual) > 1)
- inner_plan->qual = fix_join_expr(glob,
- inner_plan->qual,
- outer_itlist,
- NULL,
- innerrel,
- 0);
- }
- }
- else if (IsA(inner_plan, BitmapIndexScan))
- {
- /*
- * Same, but index is being used within a bitmap plan.
- */
- BitmapIndexScan *innerscan = (BitmapIndexScan *) inner_plan;
- List *indexqualorig = innerscan->indexqualorig;
-
- /* No work needed if indexqual refers only to its own rel... */
- if (NumRelids((Node *) indexqualorig) > 1)
- {
- Index innerrel = innerscan->scan.scanrelid;
-
- /* only refs to outer vars get changed in the inner qual */
- innerscan->indexqualorig = fix_join_expr(glob,
- indexqualorig,
- outer_itlist,
- NULL,
- innerrel,
- 0);
- innerscan->indexqual = fix_join_expr(glob,
- innerscan->indexqual,
- outer_itlist,
- NULL,
- innerrel,
- 0);
- /* no need to fix inner qpqual */
- Assert(inner_plan->qual == NIL);
- }
- }
- else if (IsA(inner_plan, BitmapHeapScan))
- {
- /*
- * The inner side is a bitmap scan plan. Fix the top node, and
- * recurse to get the lower nodes.
- *
- * Note: create_bitmap_scan_plan removes clauses from bitmapqualorig
- * if they are duplicated in qpqual, so must test these independently.
- */
- BitmapHeapScan *innerscan = (BitmapHeapScan *) inner_plan;
- Index innerrel = innerscan->scan.scanrelid;
- List *bitmapqualorig = innerscan->bitmapqualorig;
-
- /* only refs to outer vars get changed in the inner qual */
- if (NumRelids((Node *) bitmapqualorig) > 1)
- innerscan->bitmapqualorig = fix_join_expr(glob,
- bitmapqualorig,
- outer_itlist,
- NULL,
- innerrel,
- 0);
-
- /*
- * We must fix the inner qpqual too, if it has join clauses (this
- * could happen if special operators are involved: some indexquals may
- * get rechecked as qpquals).
- */
- if (NumRelids((Node *) inner_plan->qual) > 1)
- inner_plan->qual = fix_join_expr(glob,
- inner_plan->qual,
- outer_itlist,
- NULL,
- innerrel,
- 0);
-
- /* Now recurse */
- set_inner_join_references(glob, inner_plan->lefttree, outer_itlist);
- }
- else if (IsA(inner_plan, BitmapAnd))
- {
- /* All we need do here is recurse */
- BitmapAnd *innerscan = (BitmapAnd *) inner_plan;
- ListCell *l;
-
- foreach(l, innerscan->bitmapplans)
- {
- set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist);
- }
- }
- else if (IsA(inner_plan, BitmapOr))
- {
- /* All we need do here is recurse */
- BitmapOr *innerscan = (BitmapOr *) inner_plan;
- ListCell *l;
-
- foreach(l, innerscan->bitmapplans)
- {
- set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist);
- }
- }
- else if (IsA(inner_plan, TidScan))
- {
- TidScan *innerscan = (TidScan *) inner_plan;
- Index innerrel = innerscan->scan.scanrelid;
-
- innerscan->tidquals = fix_join_expr(glob,
- innerscan->tidquals,
- outer_itlist,
- NULL,
- innerrel,
- 0);
- }
- else if (IsA(inner_plan, Append))
- {
- /*
- * The inner side is an append plan. Recurse to see if it contains
- * indexscans that need to be fixed.
- */
- Append *appendplan = (Append *) inner_plan;
- ListCell *l;
-
- foreach(l, appendplan->appendplans)
- {
- set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist);
- }
- }
- else if (IsA(inner_plan, Result))
- {
- /* Recurse through a gating Result node (similar to Append case) */
- Result *result = (Result *) inner_plan;
-
- if (result->plan.lefttree)
- set_inner_join_references(glob, result->plan.lefttree, outer_itlist);
- }
-}
-
-/*
* set_upper_references
* Update the targetlist and quals of an upper-level plan node
* to refer to the tuples returned by its lefttree subplan.
@@ -1532,23 +1348,21 @@ search_indexed_tlist_for_sortgroupref(Node *node,
*
* This is used in two different scenarios: a normal join clause, where
* all the Vars in the clause *must* be replaced by OUTER or INNER references;
- * and an indexscan being used on the inner side of a nestloop join.
- * In the latter case we want to replace the outer-relation Vars by OUTER
- * references, while Vars of the inner relation should be adjusted by rtoffset.
- * (We also implement RETURNING clause fixup using this second scenario.)
+ * and a RETURNING clause, which may contain both Vars of the target relation
+ * and Vars of other relations. In the latter case we want to replace the
+ * other-relation Vars by OUTER references, while leaving target Vars alone.
*
* For a normal join, acceptable_rel should be zero so that any failure to
- * match a Var will be reported as an error. For the indexscan case,
- * pass inner_itlist = NULL and acceptable_rel = the (not-offseted-yet) ID
- * of the inner relation.
+ * match a Var will be reported as an error. For the RETURNING case, pass
+ * inner_itlist = NULL and acceptable_rel = the ID of the target relation.
*
* 'clauses' is the targetlist or list of join clauses
* 'outer_itlist' is the indexed target list of the outer join relation
* 'inner_itlist' is the indexed target list of the inner join relation,
* or NULL
* 'acceptable_rel' is either zero or the rangetable index of a relation
- * whose Vars may appear in the clause without provoking an error.
- * 'rtoffset' is what to add to varno for Vars of acceptable_rel.
+ * whose Vars may appear in the clause without provoking an error
+ * 'rtoffset': how much to increment varnoold by
*
* Returns the new expression tree. The original clause structure is
* not modified.
@@ -1603,8 +1417,8 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
if (var->varno == context->acceptable_rel)
{
var = copyVar(var);
- var->varno += context->rtoffset;
- var->varnoold += context->rtoffset;
+ if (var->varnoold > 0)
+ var->varnoold += context->rtoffset;
return (Node *) var;
}
@@ -1783,7 +1597,7 @@ set_returning_clause_references(PlannerGlobal *glob,
/*
* We can perform the desired Var fixup by abusing the fix_join_expr
- * machinery that normally handles inner indexscan fixup. We search the
+ * machinery that formerly handled inner indexscan fixup. We search the
* top plan's targetlist for Vars of non-result relations, and use
* fix_join_expr to convert RETURNING Vars into references to those tlist
* entries, while leaving result-rel Vars as-is.