diff options
Diffstat (limited to 'src/backend/executor/nodeResult.c')
-rw-r--r-- | src/backend/executor/nodeResult.c | 454 |
1 files changed, 230 insertions, 224 deletions
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index f4553dcc7b7..743bd73f2b3 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -1,33 +1,33 @@ /*------------------------------------------------------------------------- * * nodeResult.c-- - * support for constant nodes needing special code. + * support for constant nodes needing special code. * * Copyright (c) 1994, Regents of the University of California * * - * DESCRIPTION + * DESCRIPTION * - * Example: in constant queries where no relations are scanned, - * the planner generates result nodes. Examples of such queries are: + * Example: in constant queries where no relations are scanned, + * the planner generates result nodes. Examples of such queries are: * - * retrieve (x = 1) - * and - * append emp (name = "mike", salary = 15000) + * retrieve (x = 1) + * and + * append emp (name = "mike", salary = 15000) * - * Result nodes are also used to optimise queries - * with tautological qualifications like: + * Result nodes are also used to optimise queries + * with tautological qualifications like: * - * retrieve (emp.all) where 2 > 1 + * retrieve (emp.all) where 2 > 1 * - * In this case, the plan generated is + * In this case, the plan generated is * - * Result (with 2 > 1 qual) - * / - * SeqScan (emp.all) + * Result (with 2 > 1 qual) + * / + * SeqScan (emp.all) * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.2 1996/10/31 10:12:18 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.3 1997/09/07 04:41:42 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -38,253 +38,259 @@ #include "executor/nodeResult.h" /* ---------------------------------------------------------------- - * ExecResult(node) + * ExecResult(node) * - * returns the tuples from the outer plan which satisify the - * qualification clause. Since result nodes with right - * subtrees are never planned, we ignore the right subtree - * entirely (for now).. -cim 10/7/89 + * returns the tuples from the outer plan which satisify the + * qualification clause. Since result nodes with right + * subtrees are never planned, we ignore the right subtree + * entirely (for now).. -cim 10/7/89 * - * The qualification containing only constant clauses are - * checked first before any processing is done. It always returns - * 'nil' if the constant qualification is not satisfied. + * The qualification containing only constant clauses are + * checked first before any processing is done. It always returns + * 'nil' if the constant qualification is not satisfied. * ---------------------------------------------------------------- */ TupleTableSlot * -ExecResult(Result *node) +ExecResult(Result * node) { - ResultState *resstate; - TupleTableSlot *outerTupleSlot; - TupleTableSlot *resultSlot; - Plan *outerPlan; - ExprContext *econtext; - Node *qual; - bool qualResult; - bool isDone; - ProjectionInfo *projInfo; - - /* ---------------- - * initialize the result node's state - * ---------------- - */ - resstate = node->resstate; - - /* ---------------- - * get the expression context - * ---------------- - */ - econtext = resstate->cstate.cs_ExprContext; - - /* ---------------- - * check tautological qualifications like (2 > 1) - * ---------------- - */ - qual = node->resconstantqual; - if (qual != NULL) { - qualResult = ExecQual((List*)qual, econtext); - /* ---------------- - * if we failed the constant qual, then there - * is no need to continue processing because regardless of - * what happens, the constant qual will be false.. - * ---------------- - */ - if (qualResult == false) - return NULL; - - /* ---------------- - * our constant qualification succeeded so now we - * throw away the qual because we know it will always - * succeed. - * ---------------- - */ - node->resconstantqual = NULL; - } - - if (resstate->cstate.cs_TupFromTlist) { + ResultState *resstate; + TupleTableSlot *outerTupleSlot; + TupleTableSlot *resultSlot; + Plan *outerPlan; + ExprContext *econtext; + Node *qual; + bool qualResult; + bool isDone; ProjectionInfo *projInfo; - - projInfo = resstate->cstate.cs_ProjInfo; - resultSlot = ExecProject(projInfo, &isDone); - if (!isDone) - return resultSlot; - } - - /* ---------------- - * retrieve a tuple that satisfy the qual from the outer plan until - * there are no more. - * - * if rs_done is 1 then it means that we were asked to return - * a constant tuple and we alread did the last time ExecResult() - * was called, so now we are through. - * ---------------- - */ - outerPlan = outerPlan(node); - - while (!resstate->rs_done) { /* ---------------- - * get next outer tuple if necessary. + * initialize the result node's state * ---------------- */ - if (outerPlan != NULL) { - outerTupleSlot = ExecProcNode(outerPlan, (Plan*)node); - - if (TupIsNull(outerTupleSlot)) - return NULL; - - resstate->cstate.cs_OuterTupleSlot = outerTupleSlot; - } else { - - /* ---------------- - * if we don't have an outer plan, then it's probably - * the case that we are doing a retrieve or an append - * with a constant target list, so we should only return - * the constant tuple once or never if we fail the qual. - * ---------------- - */ - resstate->rs_done = 1; - } - + resstate = node->resstate; + /* ---------------- - * get the information to place into the expr context + * get the expression context * ---------------- */ - resstate = node->resstate; - - outerTupleSlot = resstate->cstate.cs_OuterTupleSlot; - + econtext = resstate->cstate.cs_ExprContext; + /* ---------------- - * fill in the information in the expression context - * XXX gross hack. use outer tuple as scan tuple + * check tautological qualifications like (2 > 1) * ---------------- */ - econtext->ecxt_outertuple = outerTupleSlot; - econtext->ecxt_scantuple = outerTupleSlot; - + qual = node->resconstantqual; + if (qual != NULL) + { + qualResult = ExecQual((List *) qual, econtext); + /* ---------------- + * if we failed the constant qual, then there + * is no need to continue processing because regardless of + * what happens, the constant qual will be false.. + * ---------------- + */ + if (qualResult == false) + return NULL; + + /* ---------------- + * our constant qualification succeeded so now we + * throw away the qual because we know it will always + * succeed. + * ---------------- + */ + node->resconstantqual = NULL; + } + + if (resstate->cstate.cs_TupFromTlist) + { + ProjectionInfo *projInfo; + + projInfo = resstate->cstate.cs_ProjInfo; + resultSlot = ExecProject(projInfo, &isDone); + if (!isDone) + return resultSlot; + } + /* ---------------- - * form the result tuple and pass it back using ExecProject() + * retrieve a tuple that satisfy the qual from the outer plan until + * there are no more. + * + * if rs_done is 1 then it means that we were asked to return + * a constant tuple and we alread did the last time ExecResult() + * was called, so now we are through. * ---------------- */ - projInfo = resstate->cstate.cs_ProjInfo; - resultSlot = ExecProject(projInfo, &isDone); - resstate->cstate.cs_TupFromTlist = !isDone; - return resultSlot; - } + outerPlan = outerPlan(node); + + while (!resstate->rs_done) + { + + /* ---------------- + * get next outer tuple if necessary. + * ---------------- + */ + if (outerPlan != NULL) + { + outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); + + if (TupIsNull(outerTupleSlot)) + return NULL; - return NULL; + resstate->cstate.cs_OuterTupleSlot = outerTupleSlot; + } + else + { + + /* ---------------- + * if we don't have an outer plan, then it's probably + * the case that we are doing a retrieve or an append + * with a constant target list, so we should only return + * the constant tuple once or never if we fail the qual. + * ---------------- + */ + resstate->rs_done = 1; + } + + /* ---------------- + * get the information to place into the expr context + * ---------------- + */ + resstate = node->resstate; + + outerTupleSlot = resstate->cstate.cs_OuterTupleSlot; + + /* ---------------- + * fill in the information in the expression context + * XXX gross hack. use outer tuple as scan tuple + * ---------------- + */ + econtext->ecxt_outertuple = outerTupleSlot; + econtext->ecxt_scantuple = outerTupleSlot; + + /* ---------------- + * form the result tuple and pass it back using ExecProject() + * ---------------- + */ + projInfo = resstate->cstate.cs_ProjInfo; + resultSlot = ExecProject(projInfo, &isDone); + resstate->cstate.cs_TupFromTlist = !isDone; + return resultSlot; + } + + return NULL; } /* ---------------------------------------------------------------- - * ExecInitResult - * - * Creates the run-time state information for the result node - * produced by the planner and initailizes outer relations - * (child nodes). + * ExecInitResult + * + * Creates the run-time state information for the result node + * produced by the planner and initailizes outer relations + * (child nodes). * ---------------------------------------------------------------- */ bool -ExecInitResult(Result *node, EState *estate, Plan *parent) +ExecInitResult(Result * node, EState * estate, Plan * parent) { - ResultState *resstate; - - /* ---------------- - * assign execution state to node - * ---------------- - */ - node->plan.state = estate; - - /* ---------------- - * create new ResultState for node - * ---------------- - */ - resstate = makeNode(ResultState); - resstate->rs_done = 0; - node->resstate = resstate; - - /* ---------------- - * Miscellanious initialization - * - * + assign node's base_id - * + assign debugging hooks and - * + create expression context for node - * ---------------- - */ - ExecAssignNodeBaseInfo(estate, &resstate->cstate, parent); - ExecAssignExprContext(estate, &resstate->cstate); - + ResultState *resstate; + + /* ---------------- + * assign execution state to node + * ---------------- + */ + node->plan.state = estate; + + /* ---------------- + * create new ResultState for node + * ---------------- + */ + resstate = makeNode(ResultState); + resstate->rs_done = 0; + node->resstate = resstate; + + /* ---------------- + * Miscellanious initialization + * + * + assign node's base_id + * + assign debugging hooks and + * + create expression context for node + * ---------------- + */ + ExecAssignNodeBaseInfo(estate, &resstate->cstate, parent); + ExecAssignExprContext(estate, &resstate->cstate); + #define RESULT_NSLOTS 1 - /* ---------------- - * tuple table initialization - * ---------------- - */ - ExecInitResultTupleSlot(estate, &resstate->cstate); - - /* ---------------- - * then initialize children - * ---------------- - */ - ExecInitNode(outerPlan(node), estate, (Plan*)node); - - /* - * we don't use inner plan - */ - Assert(innerPlan(node)==NULL); - - /* ---------------- - * initialize tuple type and projection info - * ---------------- - */ - ExecAssignResultTypeFromTL((Plan*)node, &resstate->cstate); - ExecAssignProjectionInfo((Plan*)node, &resstate->cstate); - - /* ---------------- - * set "are we done yet" to false - * ---------------- - */ - resstate->rs_done = 0; - - return TRUE; + /* ---------------- + * tuple table initialization + * ---------------- + */ + ExecInitResultTupleSlot(estate, &resstate->cstate); + + /* ---------------- + * then initialize children + * ---------------- + */ + ExecInitNode(outerPlan(node), estate, (Plan *) node); + + /* + * we don't use inner plan + */ + Assert(innerPlan(node) == NULL); + + /* ---------------- + * initialize tuple type and projection info + * ---------------- + */ + ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate); + ExecAssignProjectionInfo((Plan *) node, &resstate->cstate); + + /* ---------------- + * set "are we done yet" to false + * ---------------- + */ + resstate->rs_done = 0; + + return TRUE; } int -ExecCountSlotsResult(Result *node) +ExecCountSlotsResult(Result * node) { - return ExecCountSlotsNode(outerPlan(node)) + RESULT_NSLOTS; + return ExecCountSlotsNode(outerPlan(node)) + RESULT_NSLOTS; } /* ---------------------------------------------------------------- - * ExecEndResult - * - * fees up storage allocated through C routines + * ExecEndResult + * + * fees up storage allocated through C routines * ---------------------------------------------------------------- */ void -ExecEndResult(Result *node) +ExecEndResult(Result * node) { - ResultState *resstate; - - resstate = node->resstate; - - /* ---------------- - * Free the projection info - * - * Note: we don't ExecFreeResultType(resstate) - * 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(&resstate->cstate); - - /* ---------------- - * shut down subplans - * ---------------- - */ - ExecEndNode(outerPlan(node), (Plan*)node); - - /* ---------------- - * clean out the tuple table - * ---------------- - */ - ExecClearTuple(resstate->cstate.cs_ResultTupleSlot); + ResultState *resstate; + + resstate = node->resstate; + + /* ---------------- + * Free the projection info + * + * Note: we don't ExecFreeResultType(resstate) + * 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(&resstate->cstate); + + /* ---------------- + * shut down subplans + * ---------------- + */ + ExecEndNode(outerPlan(node), (Plan *) node); + + /* ---------------- + * clean out the tuple table + * ---------------- + */ + ExecClearTuple(resstate->cstate.cs_ResultTupleSlot); } |