aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeNestloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeNestloop.c')
-rw-r--r--src/backend/executor/nodeNestloop.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 1bcaef96e60..d59ed92f018 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeNestloop.c,v 1.55 2010/01/02 16:57:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeNestloop.c,v 1.56 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,6 +59,7 @@
TupleTableSlot *
ExecNestLoop(NestLoopState *node)
{
+ NestLoop *nl;
PlanState *innerPlan;
PlanState *outerPlan;
TupleTableSlot *outerTupleSlot;
@@ -66,12 +67,14 @@ ExecNestLoop(NestLoopState *node)
List *joinqual;
List *otherqual;
ExprContext *econtext;
+ ListCell *lc;
/*
* get information from the node
*/
ENL1_printf("getting info from node");
+ nl = (NestLoop *) node->js.ps.plan;
joinqual = node->js.joinqual;
otherqual = node->js.ps.qual;
outerPlan = outerPlanState(node);
@@ -134,16 +137,33 @@ ExecNestLoop(NestLoopState *node)
node->nl_MatchedOuter = false;
/*
- * now rescan the inner plan
+ * fetch the values of any outer Vars that must be passed to
+ * the inner scan, and store them in the appropriate PARAM_EXEC
+ * slots.
*/
- ENL1_printf("rescanning inner plan");
+ foreach(lc, nl->nestParams)
+ {
+ NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
+ int paramno = nlp->paramno;
+ ParamExecData *prm;
+
+ prm = &(econtext->ecxt_param_exec_vals[paramno]);
+ /* Param value should be an OUTER var */
+ Assert(nlp->paramval->varno == OUTER);
+ Assert(nlp->paramval->varattno > 0);
+ prm->value = slot_getattr(outerTupleSlot,
+ nlp->paramval->varattno,
+ &(prm->isnull));
+ /* Flag parameter value as changed */
+ innerPlan->chgParam = bms_add_member(innerPlan->chgParam,
+ paramno);
+ }
/*
- * The scan key of the inner plan might depend on the current
- * outer tuple (e.g. in index scans), that's why we pass our expr
- * context.
+ * now rescan the inner plan
*/
- ExecReScan(innerPlan, econtext);
+ ENL1_printf("rescanning inner plan");
+ ExecReScan(innerPlan);
}
/*
@@ -308,15 +328,18 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
/*
* initialize child nodes
*
- * Tell the inner child that cheap rescans would be good. (This is
- * unnecessary if we are doing nestloop with inner indexscan, because the
- * rescan will always be with a fresh parameter --- but since
- * nodeIndexscan doesn't actually care about REWIND, there's no point in
- * dealing with that refinement.)
+ * If we have no parameters to pass into the inner rel from the outer,
+ * tell the inner child that cheap rescans would be good. If we do have
+ * such parameters, then there is no point in REWIND support at all in
+ * the inner child, because it will always be rescanned with fresh
+ * parameter values.
*/
outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate, eflags);
- innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate,
- eflags | EXEC_FLAG_REWIND);
+ if (node->nestParams == NIL)
+ eflags |= EXEC_FLAG_REWIND;
+ else
+ eflags &= ~EXEC_FLAG_REWIND;
+ innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, eflags);
/*
* tuple table initialization
@@ -395,18 +418,22 @@ ExecEndNestLoop(NestLoopState *node)
* ----------------------------------------------------------------
*/
void
-ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt)
+ExecReScanNestLoop(NestLoopState *node)
{
PlanState *outerPlan = outerPlanState(node);
/*
* If outerPlan->chgParam is not null then plan will be automatically
- * re-scanned by first ExecProcNode. innerPlan is re-scanned for each new
- * outer tuple and MUST NOT be re-scanned from here or you'll get troubles
- * from inner index scans when outer Vars are used as run-time keys...
+ * re-scanned by first ExecProcNode.
*/
if (outerPlan->chgParam == NULL)
- ExecReScan(outerPlan, exprCtxt);
+ ExecReScan(outerPlan);
+
+ /*
+ * innerPlan is re-scanned for each new outer tuple and MUST NOT be
+ * re-scanned from here or you'll get troubles from inner index scans when
+ * outer Vars are used as run-time keys...
+ */
node->js.ps.ps_TupFromTlist = false;
node->nl_NeedNewOuter = true;