diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-10-01 19:51:50 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-10-01 19:51:50 +0000 |
commit | dad4cb6258382e99409c3e0673f1a5ec5b8bf03f (patch) | |
tree | fc13e11ae4ec12a824befec58c61fe8e5b398197 /src/backend/executor | |
parent | 233f135144ffc02512490eaffdb2575284a3af9d (diff) | |
download | postgresql-dad4cb6258382e99409c3e0673f1a5ec5b8bf03f.tar.gz postgresql-dad4cb6258382e99409c3e0673f1a5ec5b8bf03f.zip |
Improve tuplestore.c to support multiple concurrent read positions.
This facility replaces the former mark/restore support but is otherwise
upward-compatible with previous uses. It's expected to be needed for
single evaluation of CTEs and also for window functions, so I'm committing
it separately instead of waiting for either one of those patches to be
finished. Per discussion with Greg Stark and Hitoshi Harada.
Note: I removed nodeFunctionscan's mark/restore support, instead of bothering
to update it for this change, because it was dead code anyway.
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execAmi.c | 13 | ||||
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 41 | ||||
-rw-r--r-- | src/backend/executor/nodeMaterial.c | 33 |
3 files changed, 30 insertions, 57 deletions
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 1381a4a4f09..afddf4d3920 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.97 2008/08/05 21:28:29 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.98 2008/10/01 19:51:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -239,10 +239,6 @@ ExecMarkPos(PlanState *node) ExecTidMarkPos((TidScanState *) node); break; - case T_FunctionScanState: - ExecFunctionMarkPos((FunctionScanState *) node); - break; - case T_ValuesScanState: ExecValuesMarkPos((ValuesScanState *) node); break; @@ -296,10 +292,6 @@ ExecRestrPos(PlanState *node) ExecTidRestrPos((TidScanState *) node); break; - case T_FunctionScanState: - ExecFunctionRestrPos((FunctionScanState *) node); - break; - case T_ValuesScanState: ExecValuesRestrPos((ValuesScanState *) node); break; @@ -332,7 +324,7 @@ ExecRestrPos(PlanState *node) * (However, since the only present use of mark/restore is in mergejoin, * there is no need to support mark/restore in any plan type that is not * capable of generating ordered output. So the seqscan, tidscan, - * functionscan, and valuesscan support is actually useless code at present.) + * and valuesscan support is actually useless code at present.) */ bool ExecSupportsMarkRestore(NodeTag plantype) @@ -342,7 +334,6 @@ ExecSupportsMarkRestore(NodeTag plantype) case T_SeqScan: case T_IndexScan: case T_TidScan: - case T_FunctionScan: case T_ValuesScan: case T_Material: case T_Sort: diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 6bbb5b139b6..6113a2c9067 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.46 2008/02/29 02:49:39 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.47 2008/10/01 19:51:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -131,6 +131,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) TypeFuncClass functypclass; TupleDesc tupdesc = NULL; + /* check for unsupported flags */ + Assert(!(eflags & EXEC_FLAG_MARK)); + /* * FunctionScan should not have any children. */ @@ -274,42 +277,6 @@ ExecEndFunctionScan(FunctionScanState *node) } /* ---------------------------------------------------------------- - * ExecFunctionMarkPos - * - * Calls tuplestore to save the current position in the stored file. - * ---------------------------------------------------------------- - */ -void -ExecFunctionMarkPos(FunctionScanState *node) -{ - /* - * if we haven't materialized yet, just return. - */ - if (!node->tuplestorestate) - return; - - tuplestore_markpos(node->tuplestorestate); -} - -/* ---------------------------------------------------------------- - * ExecFunctionRestrPos - * - * Calls tuplestore to restore the last saved file position. - * ---------------------------------------------------------------- - */ -void -ExecFunctionRestrPos(FunctionScanState *node) -{ - /* - * if we haven't materialized yet, just return. - */ - if (!node->tuplestorestate) - return; - - tuplestore_restorepos(node->tuplestorestate); -} - -/* ---------------------------------------------------------------- * ExecFunctionReScan * * Rescans the relation. diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 3c096356a37..494560d0f46 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.62 2008/03/23 00:54:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.63 2008/10/01 19:51:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,7 +51,7 @@ ExecMaterial(MaterialState *node) estate = node->ss.ps.state; dir = estate->es_direction; forward = ScanDirectionIsForward(dir); - tuplestorestate = (Tuplestorestate *) node->tuplestorestate; + tuplestorestate = node->tuplestorestate; /* * If first time through, and we need a tuplestore, initialize it. @@ -60,7 +60,19 @@ ExecMaterial(MaterialState *node) { tuplestorestate = tuplestore_begin_heap(true, false, work_mem); tuplestore_set_eflags(tuplestorestate, node->eflags); - node->tuplestorestate = (void *) tuplestorestate; + if (node->eflags & EXEC_FLAG_MARK) + { + /* + * Allocate a second read pointer to serve as the mark. + * We know it must have index 1, so needn't store that. + */ + int ptrn; + + ptrn = tuplestore_alloc_read_pointer(tuplestorestate, + node->eflags); + Assert(ptrn == 1); + } + node->tuplestorestate = tuplestorestate; } /* @@ -236,7 +248,7 @@ ExecEndMaterial(MaterialState *node) * Release tuplestore resources */ if (node->tuplestorestate != NULL) - tuplestore_end((Tuplestorestate *) node->tuplestorestate); + tuplestore_end(node->tuplestorestate); node->tuplestorestate = NULL; /* @@ -262,7 +274,10 @@ ExecMaterialMarkPos(MaterialState *node) if (!node->tuplestorestate) return; - tuplestore_markpos((Tuplestorestate *) node->tuplestorestate); + /* + * copy the active read pointer to the mark. + */ + tuplestore_copy_read_pointer(node->tuplestorestate, 0, 1); } /* ---------------------------------------------------------------- @@ -283,9 +298,9 @@ ExecMaterialRestrPos(MaterialState *node) return; /* - * restore the scan to the previously marked position + * copy the mark to the active read pointer. */ - tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate); + tuplestore_copy_read_pointer(node->tuplestorestate, 1, 0); } /* ---------------------------------------------------------------- @@ -322,14 +337,14 @@ ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt) if (((PlanState *) node)->lefttree->chgParam != NULL || (node->eflags & EXEC_FLAG_REWIND) == 0) { - tuplestore_end((Tuplestorestate *) node->tuplestorestate); + tuplestore_end(node->tuplestorestate); node->tuplestorestate = NULL; if (((PlanState *) node)->lefttree->chgParam == NULL) ExecReScan(((PlanState *) node)->lefttree, exprCtxt); node->eof_underlying = false; } else - tuplestore_rescan((Tuplestorestate *) node->tuplestorestate); + tuplestore_rescan(node->tuplestorestate); } else { |