diff options
Diffstat (limited to 'src/backend/executor/nodeNestloop.c')
-rw-r--r-- | src/backend/executor/nodeNestloop.c | 65 |
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; |