aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeMaterial.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-02-28 05:48:44 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-02-28 05:48:44 +0000
commitd2c555ee538f34be7aff744b994df4d2369a9140 (patch)
tree3a1bd752d04ff238cc5ff71dc081097f1710919c /src/backend/executor/nodeMaterial.c
parent2c0ef9777cce8f97dd01073d962e6aa31722b5ad (diff)
downloadpostgresql-d2c555ee538f34be7aff744b994df4d2369a9140.tar.gz
postgresql-d2c555ee538f34be7aff744b994df4d2369a9140.zip
Teach nodeSort and nodeMaterial to optimize out unnecessary overhead
when the passed-down eflags indicate they can. Simon Riggs and Tom Lane
Diffstat (limited to 'src/backend/executor/nodeMaterial.c')
-rw-r--r--src/backend/executor/nodeMaterial.c83
1 files changed, 57 insertions, 26 deletions
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 641fe3afc2d..34e1b2538fa 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.52 2006/02/28 04:10:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.53 2006/02/28 05:48:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,9 +58,9 @@ ExecMaterial(MaterialState *node)
tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
/*
- * If first time through, initialize the tuplestore.
+ * If first time through, and we need a tuplestore, initialize it.
*/
- if (tuplestorestate == NULL)
+ if (tuplestorestate == NULL && node->randomAccess)
{
tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
@@ -71,7 +71,8 @@ ExecMaterial(MaterialState *node)
* If we are not at the end of the tuplestore, or are going backwards, try
* to fetch a tuple from tuplestore.
*/
- eof_tuplestore = tuplestore_ateof(tuplestorestate);
+ eof_tuplestore = (tuplestorestate == NULL) ||
+ tuplestore_ateof(tuplestorestate);
if (!forward && eof_tuplestore)
{
@@ -135,7 +136,8 @@ ExecMaterial(MaterialState *node)
* tuplestore is certainly in EOF state, its read position will move
* forward over the added tuple. This is what we want.
*/
- tuplestore_puttuple(tuplestorestate, (void *) heapTuple);
+ if (tuplestorestate)
+ tuplestore_puttuple(tuplestorestate, (void *) heapTuple);
}
/*
@@ -165,8 +167,18 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
matstate->ss.ps.plan = (Plan *) node;
matstate->ss.ps.state = estate;
- matstate->tuplestorestate = NULL;
+ /*
+ * We must have random access to the subplan output to do backward scan
+ * or mark/restore. We also prefer to materialize the subplan output
+ * if we might be called on to rewind and replay it many times.
+ * However, if none of these cases apply, we can skip storing the data.
+ */
+ matstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
+ EXEC_FLAG_BACKWARD |
+ EXEC_FLAG_MARK)) != 0;
+
matstate->eof_underlying = false;
+ matstate->tuplestorestate = NULL;
/*
* Miscellaneous initialization
@@ -249,6 +261,8 @@ ExecEndMaterial(MaterialState *node)
void
ExecMaterialMarkPos(MaterialState *node)
{
+ Assert(node->randomAccess);
+
/*
* if we haven't materialized yet, just return.
*/
@@ -267,6 +281,8 @@ ExecMaterialMarkPos(MaterialState *node)
void
ExecMaterialRestrPos(MaterialState *node)
{
+ Assert(node->randomAccess);
+
/*
* if we haven't materialized yet, just return.
*/
@@ -288,29 +304,44 @@ ExecMaterialRestrPos(MaterialState *node)
void
ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
{
- /*
- * If we haven't materialized yet, just return. If outerplan' chgParam is
- * not NULL then it will be re-scanned by ExecProcNode, else - no reason
- * to re-scan it at all.
- */
- if (!node->tuplestorestate)
- return;
-
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
- /*
- * If subnode is to be rescanned then we forget previous stored results;
- * we have to re-read the subplan and re-store.
- *
- * Otherwise we can just rewind and rescan the stored output. The state of
- * the subnode does not change.
- */
- if (((PlanState *) node)->lefttree->chgParam != NULL)
+ if (node->randomAccess)
{
- tuplestore_end((Tuplestorestate *) node->tuplestorestate);
- node->tuplestorestate = NULL;
- node->eof_underlying = false;
+ /*
+ * If we haven't materialized yet, just return. If outerplan' chgParam
+ * is not NULL then it will be re-scanned by ExecProcNode, else - no
+ * reason to re-scan it at all.
+ */
+ if (!node->tuplestorestate)
+ return;
+
+ /*
+ * If subnode is to be rescanned then we forget previous stored
+ * results; we have to re-read the subplan and re-store.
+ *
+ * Otherwise we can just rewind and rescan the stored output. The
+ * state of the subnode does not change.
+ */
+ if (((PlanState *) node)->lefttree->chgParam != NULL)
+ {
+ tuplestore_end((Tuplestorestate *) node->tuplestorestate);
+ node->tuplestorestate = NULL;
+ node->eof_underlying = false;
+ }
+ else
+ tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
}
else
- tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
+ {
+ /* In this case we are just passing on the subquery's output */
+
+ /*
+ * if chgParam of subnode is not null then plan will be re-scanned by
+ * first ExecProcNode.
+ */
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+ node->eof_underlying = false;
+ }
}