diff options
author | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
commit | 1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch) | |
tree | 8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/executor/nodeNestloop.c | |
parent | 8fecd4febf8357f3cc20383ed29ced484877d5ac (diff) | |
download | postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip |
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/executor/nodeNestloop.c')
-rw-r--r-- | src/backend/executor/nodeNestloop.c | 632 |
1 files changed, 323 insertions, 309 deletions
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index d83d306bba9..e7cba2e756e 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -1,21 +1,21 @@ /*------------------------------------------------------------------------- * * nodeNestloop.c-- - * routines to support nest-loop joins + * routines to support nest-loop joins * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.3 1996/11/08 05:56:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.4 1997/09/07 04:41:41 momjian Exp $ * *------------------------------------------------------------------------- */ /* - * INTERFACE ROUTINES - * ExecNestLoop - process a nestloop join of two plans - * ExecInitNestLoop - initialize the join - * ExecEndNestLoop - shut down the join + * INTERFACE ROUTINES + * ExecNestLoop - process a nestloop join of two plans + * ExecInitNestLoop - initialize the join + * ExecEndNestLoop - shut down the join */ #include "postgres.h" @@ -25,349 +25,363 @@ #include "executor/nodeIndexscan.h" /* ---------------------------------------------------------------- - * ExecNestLoop(node) + * ExecNestLoop(node) * * old comments - * Returns the tuple joined from inner and outer tuples which - * satisfies the qualification clause. + * Returns the tuple joined from inner and outer tuples which + * satisfies the qualification clause. * - * It scans the inner relation to join with current outer tuple. + * It scans the inner relation to join with current outer tuple. * - * If none is found, next tuple form the outer relation is retrieved - * and the inner relation is scanned from the beginning again to join - * with the outer tuple. + * If none is found, next tuple form the outer relation is retrieved + * and the inner relation is scanned from the beginning again to join + * with the outer tuple. * - * Nil is returned if all the remaining outer tuples are tried and - * all fail to join with the inner tuples. + * Nil is returned if all the remaining outer tuples are tried and + * all fail to join with the inner tuples. * - * Nil is also returned if there is no tuple from inner realtion. - * - * Conditions: - * -- outerTuple contains current tuple from outer relation and - * the right son(inner realtion) maintains "cursor" at the tuple - * returned previously. - * This is achieved by maintaining a scan position on the outer - * relation. - * - * Initial States: - * -- the outer child and the inner child - * are prepared to return the first tuple. + * Nil is also returned if there is no tuple from inner realtion. + * + * Conditions: + * -- outerTuple contains current tuple from outer relation and + * the right son(inner realtion) maintains "cursor" at the tuple + * returned previously. + * This is achieved by maintaining a scan position on the outer + * relation. + * + * Initial States: + * -- the outer child and the inner child + * are prepared to return the first tuple. * ---------------------------------------------------------------- */ TupleTableSlot * -ExecNestLoop(NestLoop *node, Plan* parent) +ExecNestLoop(NestLoop * node, Plan * parent) { - NestLoopState *nlstate; - Plan *innerPlan; - Plan *outerPlan; - bool needNewOuterTuple; - - TupleTableSlot *outerTupleSlot; - TupleTableSlot *innerTupleSlot; - - List *qual; - bool qualResult; - ExprContext *econtext; - - /* ---------------- - * get information from the node - * ---------------- - */ - ENL1_printf("getting info from node"); - - nlstate = node->nlstate; - qual = node->join.qual; - outerPlan = outerPlan(&node->join); - innerPlan = innerPlan(&node->join); - - /* ---------------- - * initialize expression context - * ---------------- - */ - econtext = nlstate->jstate.cs_ExprContext; - - /* ---------------- * get the current outer tuple - * ---------------- - */ - outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot; - econtext->ecxt_outertuple = outerTupleSlot; - - /* ---------------- - * Ok, everything is setup for the join so now loop until - * we return a qualifying join tuple.. - * ---------------- - */ - - if (nlstate->jstate.cs_TupFromTlist) { - TupleTableSlot *result; - bool isDone; - - result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); - if (!isDone) - return result; - } - - ENL1_printf("entering main loop"); - for(;;) { + NestLoopState *nlstate; + Plan *innerPlan; + Plan *outerPlan; + bool needNewOuterTuple; + + TupleTableSlot *outerTupleSlot; + TupleTableSlot *innerTupleSlot; + + List *qual; + bool qualResult; + ExprContext *econtext; + /* ---------------- - * The essential idea now is to get the next inner tuple - * and join it with the current outer tuple. + * get information from the node * ---------------- */ - needNewOuterTuple = false; - + ENL1_printf("getting info from node"); + + nlstate = node->nlstate; + qual = node->join.qual; + outerPlan = outerPlan(&node->join); + innerPlan = innerPlan(&node->join); + /* ---------------- - * If outer tuple is not null then that means - * we are in the middle of a scan and we should - * restore our previously saved scan position. + * initialize expression context * ---------------- */ - if (! TupIsNull(outerTupleSlot)) { - ENL1_printf("have outer tuple, restoring outer plan"); - ExecRestrPos(outerPlan); - } else { - ENL1_printf("outer tuple is nil, need new outer tuple"); - needNewOuterTuple = true; - } - - /* ---------------- - * if we have an outerTuple, try to get the next inner tuple. + econtext = nlstate->jstate.cs_ExprContext; + + /* ---------------- * get the current outer tuple * ---------------- */ - if (!needNewOuterTuple) { - ENL1_printf("getting new inner tuple"); - - innerTupleSlot = ExecProcNode(innerPlan, (Plan*)node); - econtext->ecxt_innertuple = innerTupleSlot; - - if (TupIsNull(innerTupleSlot)) { - ENL1_printf("no inner tuple, need new outer tuple"); - needNewOuterTuple = true; - } - } - + outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot; + econtext->ecxt_outertuple = outerTupleSlot; + /* ---------------- - * loop until we have a new outer tuple and a new - * inner tuple. + * Ok, everything is setup for the join so now loop until + * we return a qualifying join tuple.. * ---------------- */ - while (needNewOuterTuple) { - /* ---------------- - * now try to get the next outer tuple - * ---------------- - */ - ENL1_printf("getting new outer tuple"); - outerTupleSlot = ExecProcNode(outerPlan, (Plan*)node); - econtext->ecxt_outertuple = outerTupleSlot; - - /* ---------------- - * if there are no more outer tuples, then the join - * is complete.. - * ---------------- - */ - if (TupIsNull(outerTupleSlot)) { - ENL1_printf("no outer tuple, ending join"); - return NULL; - } - - /* ---------------- - * we have a new outer tuple so we mark our position - * in the outer scan and save the outer tuple in the - * NestLoop state - * ---------------- - */ - ENL1_printf("saving new outer tuple information"); - ExecMarkPos(outerPlan); - nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot; - - /* ---------------- - * now rescan the inner plan and get a new inner tuple - * ---------------- - */ - - ENL1_printf("rescanning inner plan"); - /* - * 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. - */ - ExecReScan(innerPlan, econtext, parent); - - ENL1_printf("getting new inner tuple"); - - innerTupleSlot = ExecProcNode(innerPlan, (Plan*)node); - econtext->ecxt_innertuple = innerTupleSlot; - - if (TupIsNull(innerTupleSlot)) { - ENL1_printf("couldn't get inner tuple - need new outer tuple"); - } else { - ENL1_printf("got inner and outer tuples"); + + if (nlstate->jstate.cs_TupFromTlist) + { + TupleTableSlot *result; + bool isDone; + + result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); + if (!isDone) + return result; + } + + ENL1_printf("entering main loop"); + for (;;) + { + /* ---------------- + * The essential idea now is to get the next inner tuple + * and join it with the current outer tuple. + * ---------------- + */ needNewOuterTuple = false; - } - } /* while (needNewOuterTuple) */ - + + /* ---------------- + * If outer tuple is not null then that means + * we are in the middle of a scan and we should + * restore our previously saved scan position. + * ---------------- + */ + if (!TupIsNull(outerTupleSlot)) + { + ENL1_printf("have outer tuple, restoring outer plan"); + ExecRestrPos(outerPlan); + } + else + { + ENL1_printf("outer tuple is nil, need new outer tuple"); + needNewOuterTuple = true; + } + + /* ---------------- + * if we have an outerTuple, try to get the next inner tuple. + * ---------------- + */ + if (!needNewOuterTuple) + { + ENL1_printf("getting new inner tuple"); + + innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); + econtext->ecxt_innertuple = innerTupleSlot; + + if (TupIsNull(innerTupleSlot)) + { + ENL1_printf("no inner tuple, need new outer tuple"); + needNewOuterTuple = true; + } + } + + /* ---------------- + * loop until we have a new outer tuple and a new + * inner tuple. + * ---------------- + */ + while (needNewOuterTuple) + { + /* ---------------- + * now try to get the next outer tuple + * ---------------- + */ + ENL1_printf("getting new outer tuple"); + outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); + econtext->ecxt_outertuple = outerTupleSlot; + + /* ---------------- + * if there are no more outer tuples, then the join + * is complete.. + * ---------------- + */ + if (TupIsNull(outerTupleSlot)) + { + ENL1_printf("no outer tuple, ending join"); + return NULL; + } + + /* ---------------- + * we have a new outer tuple so we mark our position + * in the outer scan and save the outer tuple in the + * NestLoop state + * ---------------- + */ + ENL1_printf("saving new outer tuple information"); + ExecMarkPos(outerPlan); + nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot; + + /* ---------------- + * now rescan the inner plan and get a new inner tuple + * ---------------- + */ + + ENL1_printf("rescanning inner plan"); + + /* + * 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. + */ + ExecReScan(innerPlan, econtext, parent); + + ENL1_printf("getting new inner tuple"); + + innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); + econtext->ecxt_innertuple = innerTupleSlot; + + if (TupIsNull(innerTupleSlot)) + { + ENL1_printf("couldn't get inner tuple - need new outer tuple"); + } + else + { + ENL1_printf("got inner and outer tuples"); + needNewOuterTuple = false; + } + } /* while (needNewOuterTuple) */ + + /* ---------------- + * at this point we have a new pair of inner and outer + * tuples so we test the inner and outer tuples to see + * if they satisify the node's qualification. + * ---------------- + */ + ENL1_printf("testing qualification"); + qualResult = ExecQual((List *) qual, econtext); + + if (qualResult) + { + /* ---------------- + * qualification was satisified so we project and + * return the slot containing the result tuple + * using ExecProject(). + * ---------------- + */ + ProjectionInfo *projInfo; + TupleTableSlot *result; + bool isDone; + + ENL1_printf("qualification succeeded, projecting tuple"); + + projInfo = nlstate->jstate.cs_ProjInfo; + result = ExecProject(projInfo, &isDone); + nlstate->jstate.cs_TupFromTlist = !isDone; + return result; + } + + /* ---------------- + * qualification failed so we have to try again.. + * ---------------- + */ + ENL1_printf("qualification failed, looping"); + } +} + +/* ---------------------------------------------------------------- + * ExecInitNestLoop + * + * Creates the run-time state information for the nestloop node + * produced by the planner and initailizes inner and outer relations + * (child nodes). + * ---------------------------------------------------------------- + */ +bool +ExecInitNestLoop(NestLoop * node, EState * estate, Plan * parent) +{ + NestLoopState *nlstate; + + NL1_printf("ExecInitNestLoop: %s\n", + "initializing node"); + /* ---------------- - * at this point we have a new pair of inner and outer - * tuples so we test the inner and outer tuples to see - * if they satisify the node's qualification. + * assign execution state to node * ---------------- */ - ENL1_printf("testing qualification"); - qualResult = ExecQual((List*)qual, econtext); - - if (qualResult) { - /* ---------------- - * qualification was satisified so we project and - * return the slot containing the result tuple - * using ExecProject(). - * ---------------- - */ - ProjectionInfo *projInfo; - TupleTableSlot *result; - bool isDone; - - ENL1_printf("qualification succeeded, projecting tuple"); - - projInfo = nlstate->jstate.cs_ProjInfo; - result = ExecProject(projInfo, &isDone); - nlstate->jstate.cs_TupFromTlist = !isDone; - return result; - } - + node->join.state = estate; + /* ---------------- - * qualification failed so we have to try again.. + * create new nest loop state * ---------------- */ - ENL1_printf("qualification failed, looping"); - } -} + nlstate = makeNode(NestLoopState); + nlstate->nl_PortalFlag = false; + node->nlstate = nlstate; -/* ---------------------------------------------------------------- - * ExecInitNestLoop - * - * Creates the run-time state information for the nestloop node - * produced by the planner and initailizes inner and outer relations - * (child nodes). - * ---------------------------------------------------------------- - */ -bool -ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) -{ - NestLoopState *nlstate; - - NL1_printf("ExecInitNestLoop: %s\n", - "initializing node"); - - /* ---------------- - * assign execution state to node - * ---------------- - */ - node->join.state = estate; - - /* ---------------- - * create new nest loop state - * ---------------- - */ - nlstate = makeNode(NestLoopState); - nlstate->nl_PortalFlag = false; - node->nlstate = nlstate; - - /* ---------------- - * Miscellanious initialization - * - * + assign node's base_id - * + assign debugging hooks and - * + create expression context for node - * ---------------- - */ - ExecAssignNodeBaseInfo(estate, &nlstate->jstate, parent); - ExecAssignExprContext(estate, &nlstate->jstate); + /* ---------------- + * Miscellanious initialization + * + * + assign node's base_id + * + assign debugging hooks and + * + create expression context for node + * ---------------- + */ + ExecAssignNodeBaseInfo(estate, &nlstate->jstate, parent); + ExecAssignExprContext(estate, &nlstate->jstate); #define NESTLOOP_NSLOTS 1 - /* ---------------- - * tuple table initialization - * ---------------- - */ - ExecInitResultTupleSlot(estate, &nlstate->jstate); - - /* ---------------- - * now initialize children - * ---------------- - */ - ExecInitNode(outerPlan((Plan*)node), estate, (Plan*)node); - ExecInitNode(innerPlan((Plan*)node), estate, (Plan*)node); - - /* ---------------- - * initialize tuple type and projection info - * ---------------- - */ - ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate); - ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate); - - /* ---------------- - * finally, wipe the current outer tuple clean. - * ---------------- - */ - nlstate->jstate.cs_OuterTupleSlot = NULL; - nlstate->jstate.cs_TupFromTlist = false; - - NL1_printf("ExecInitNestLoop: %s\n", - "node initialized"); - return TRUE; + /* ---------------- + * tuple table initialization + * ---------------- + */ + ExecInitResultTupleSlot(estate, &nlstate->jstate); + + /* ---------------- + * now initialize children + * ---------------- + */ + ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node); + ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node); + + /* ---------------- + * initialize tuple type and projection info + * ---------------- + */ + ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate); + ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate); + + /* ---------------- + * finally, wipe the current outer tuple clean. + * ---------------- + */ + nlstate->jstate.cs_OuterTupleSlot = NULL; + nlstate->jstate.cs_TupFromTlist = false; + + NL1_printf("ExecInitNestLoop: %s\n", + "node initialized"); + return TRUE; } int -ExecCountSlotsNestLoop(NestLoop *node) +ExecCountSlotsNestLoop(NestLoop * node) { - return ExecCountSlotsNode(outerPlan(node)) + - ExecCountSlotsNode(innerPlan(node)) + - NESTLOOP_NSLOTS; + return ExecCountSlotsNode(outerPlan(node)) + + ExecCountSlotsNode(innerPlan(node)) + + NESTLOOP_NSLOTS; } /* ---------------------------------------------------------------- - * ExecEndNestLoop - * - * closes down scans and frees allocated storage + * ExecEndNestLoop + * + * closes down scans and frees allocated storage * ---------------------------------------------------------------- */ void -ExecEndNestLoop(NestLoop *node) +ExecEndNestLoop(NestLoop * node) { - NestLoopState *nlstate; - - NL1_printf("ExecEndNestLoop: %s\n", - "ending node processing"); - - /* ---------------- - * get info from the node - * ---------------- - */ - nlstate = node->nlstate; - - /* ---------------- - * Free the projection info - * - * Note: we don't ExecFreeResultType(nlstate) - * because the rule manager depends on the tupType - * returned by ExecMain(). So for now, this - * is freed at end-transaction time. -cim 6/2/91 - * ---------------- - */ - ExecFreeProjectionInfo(&nlstate->jstate); - - /* ---------------- - * close down subplans - * ---------------- - */ - ExecEndNode(outerPlan((Plan *) node), (Plan*)node); - ExecEndNode(innerPlan((Plan *) node), (Plan*)node); - - /* ---------------- - * clean out the tuple table - * ---------------- - */ - ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot); - - NL1_printf("ExecEndNestLoop: %s\n", - "node processing ended"); + NestLoopState *nlstate; + + NL1_printf("ExecEndNestLoop: %s\n", + "ending node processing"); + + /* ---------------- + * get info from the node + * ---------------- + */ + nlstate = node->nlstate; + + /* ---------------- + * Free the projection info + * + * Note: we don't ExecFreeResultType(nlstate) + * because the rule manager depends on the tupType + * returned by ExecMain(). So for now, this + * is freed at end-transaction time. -cim 6/2/91 + * ---------------- + */ + ExecFreeProjectionInfo(&nlstate->jstate); + + /* ---------------- + * close down subplans + * ---------------- + */ + ExecEndNode(outerPlan((Plan *) node), (Plan *) node); + ExecEndNode(innerPlan((Plan *) node), (Plan *) node); + + /* ---------------- + * clean out the tuple table + * ---------------- + */ + ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot); + + NL1_printf("ExecEndNestLoop: %s\n", + "node processing ended"); } |