diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-07-12 02:37:39 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-07-12 02:37:39 +0000 |
commit | badce86a2c327b40c6146242526d1523455d64a6 (patch) | |
tree | 6e0cb658889a2688e76d9ac19a56555c5eb0e738 /src/backend/executor/nodeResult.c | |
parent | 46fb9c29e2990ba470bb741ff6dd60f2ae218e64 (diff) | |
download | postgresql-badce86a2c327b40c6146242526d1523455d64a6.tar.gz postgresql-badce86a2c327b40c6146242526d1523455d64a6.zip |
First stage of reclaiming memory in executor by resetting short-term
memory contexts. Currently, only leaks in expressions executed as
quals or projections are handled. Clean up some old dead cruft in
executor while at it --- unused fields in state nodes, that sort of thing.
Diffstat (limited to 'src/backend/executor/nodeResult.c')
-rw-r--r-- | src/backend/executor/nodeResult.c | 117 |
1 files changed, 55 insertions, 62 deletions
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index 5bf132520cb..a1daaf52c4b 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -3,21 +3,18 @@ * nodeResult.c * support for constant nodes needing special code. * - * Portions Copyright (c) 1996-2000, PostgreSQL, Inc - * Portions Copyright (c) 1994, Regents of the University of California - * - * * DESCRIPTION * - * Example: in constant queries where no relations are scanned, - * the planner generates result nodes. Examples of such queries are: + * Result nodes are used in queries where no relations are scanned. + * Examples of such queries are: * * 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 constant + * qualifications (ie, quals that do not depend on the scanned data), + * such as: * * retrieve (emp.all) where 2 > 1 * @@ -27,13 +24,22 @@ * / * SeqScan (emp.all) * + * At runtime, the Result node evaluates the constant qual once. + * If it's false, we can return an empty result set without running + * the controlled plan at all. If it's true, we run the controlled + * plan normally and pass back the results. + * + * + * Portions Copyright (c) 1996-2000, PostgreSQL, Inc + * Portions Copyright (c) 1994, Regents of the University of California + * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.13 2000/01/26 05:56:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.14 2000/07/12 02:37:04 tgl Exp $ * *------------------------------------------------------------------------- */ -#include "postgres.h" +#include "postgres.h" #include "executor/executor.h" #include "executor/nodeResult.h" @@ -41,7 +47,7 @@ /* ---------------------------------------------------------------- * ExecResult(node) * - * returns the tuples from the outer plan which satisify the + * returns the tuples from the outer plan which satisfy the * qualification clause. Since result nodes with right * subtrees are never planned, we ignore the right subtree * entirely (for now).. -cim 10/7/89 @@ -67,15 +73,17 @@ ExecResult(Result *node) * ---------------- */ resstate = node->resstate; + econtext = resstate->cstate.cs_ExprContext; /* ---------------- - * get the expression context + * Reset per-tuple memory context to free any expression evaluation + * storage allocated in the previous tuple cycle. * ---------------- */ - econtext = resstate->cstate.cs_ExprContext; + ResetExprContext(econtext); /* ---------------- - * check tautological qualifications like (2 > 1) + * check constant qualifications like (2 > 1), if not already done * ---------------- */ if (resstate->rs_checkqual) @@ -92,74 +100,64 @@ ExecResult(Result *node) } } + /* ---------------- + * Check to see if we're still projecting out tuples from a previous + * scan tuple (because there is a function-returning-set in the + * projection expressions). If so, try to project another one. + * ---------------- + */ if (resstate->cstate.cs_TupFromTlist) { - ProjectionInfo *projInfo; - - projInfo = resstate->cstate.cs_ProjInfo; - resultSlot = ExecProject(projInfo, &isDone); + resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone); if (!isDone) return resultSlot; + /* Done with that source tuple... */ + resstate->cstate.cs_TupFromTlist = false; } /* ---------------- - * 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. + * if rs_done is true then it means that we were asked to return + * a constant tuple and we already did the last time ExecResult() + * was called, OR that we failed the constant qual check. + * Either way, now we are through. * ---------------- */ - outerPlan = outerPlan(node); - - while (!resstate->rs_done) + if (!resstate->rs_done) { + outerPlan = outerPlan(node); - /* ---------------- - * get next outer tuple if necessary. - * ---------------- - */ if (outerPlan != NULL) { + /* ---------------- + * retrieve tuples from the outer plan until there are no more. + * ---------------- + */ outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); if (TupIsNull(outerTupleSlot)) return NULL; resstate->cstate.cs_OuterTupleSlot = outerTupleSlot; + + /* ---------------- + * XXX gross hack. use outer tuple as scan tuple for projection + * ---------------- + */ + econtext->ecxt_outertuple = outerTupleSlot; + econtext->ecxt_scantuple = 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. + * if we don't have an outer plan, then we are just generating + * the results from a constant target list. Do it only once. * ---------------- */ - resstate->rs_done = 1; + resstate->rs_done = true; } /* ---------------- - * 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() + * form the result tuple using ExecProject(), and return it. * ---------------- */ projInfo = resstate->cstate.cs_ProjInfo; @@ -200,14 +198,11 @@ ExecInitResult(Result *node, EState *estate, Plan *parent) node->resstate = resstate; /* ---------------- - * Miscellanious initialization + * Miscellaneous 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 @@ -247,7 +242,7 @@ ExecCountSlotsResult(Result *node) /* ---------------------------------------------------------------- * ExecEndResult * - * fees up storage allocated through C routines + * frees up storage allocated through C routines * ---------------------------------------------------------------- */ void @@ -266,9 +261,8 @@ ExecEndResult(Result *node) * is freed at end-transaction time. -cim 6/2/91 * ---------------- */ - ExecFreeExprContext(&resstate->cstate); /* XXX - new for us - er1p */ - ExecFreeTypeInfo(&resstate->cstate); /* XXX - new for us - er1p */ ExecFreeProjectionInfo(&resstate->cstate); + ExecFreeExprContext(&resstate->cstate); /* ---------------- * shut down subplans @@ -301,5 +295,4 @@ ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent) if (((Plan *) node)->lefttree && ((Plan *) node)->lefttree->chgParam == NULL) ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); - } |