diff options
Diffstat (limited to 'src/backend/executor/nodeMaterial.c')
-rw-r--r-- | src/backend/executor/nodeMaterial.c | 277 |
1 files changed, 97 insertions, 180 deletions
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 4348f89ccc9..1d5c9042489 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -8,42 +8,37 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30 2000/03/02 04:06:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.31 2000/06/18 22:44:03 tgl Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * ExecMaterial - generate a temporary relation - * ExecInitMaterial - initialize node and subnodes.. + * ExecMaterial - materialize the result of a subplan + * ExecInitMaterial - initialize node and subnodes * ExecEndMaterial - shutdown node and subnodes * */ #include "postgres.h" - -#include "access/heapam.h" -#include "catalog/heap.h" #include "executor/executor.h" #include "executor/nodeMaterial.h" -#include "optimizer/internal.h" +#include "miscadmin.h" +#include "utils/tuplestore.h" /* ---------------------------------------------------------------- * ExecMaterial * * The first time this is called, ExecMaterial retrieves tuples - * from this node's outer subplan and inserts them into a temporary - * relation. After this is done, a flag is set indicating that - * the subplan has been materialized. Once the relation is - * materialized, the first tuple is then returned. Successive - * calls to ExecMaterial return successive tuples from the temp - * relation. + * from this node's outer subplan and inserts them into a tuplestore + * (a temporary tuple storage structure). The first tuple is then + * returned. Successive calls to ExecMaterial return successive + * tuples from the tuplestore. * * Initial State: * - * ExecMaterial assumes the temporary relation has been - * created and opened by ExecInitMaterial during the prior - * InitPlan() phase. + * matstate->tuplestorestate is initially NULL, indicating we + * haven't yet collected the results of the subplan. * * ---------------------------------------------------------------- */ @@ -52,13 +47,11 @@ ExecMaterial(Material *node) { EState *estate; MaterialState *matstate; - Plan *outerNode; ScanDirection dir; - Relation tempRelation; - Relation currentRelation; - HeapScanDesc currentScanDesc; + Tuplestorestate *tuplestorestate; HeapTuple heapTuple; TupleTableSlot *slot; + bool should_free; /* ---------------- * get state info from node @@ -67,42 +60,42 @@ ExecMaterial(Material *node) matstate = node->matstate; estate = node->plan.state; dir = estate->es_direction; + tuplestorestate = (Tuplestorestate *) matstate->tuplestorestate; /* ---------------- - * the first time we call this, we retrieve all tuples - * from the subplan into a temporary relation and then - * we sort the relation. Subsequent calls return tuples - * from the temporary relation. + * If first time through, read all tuples from outer plan and + * pass them to tuplestore.c. + * Subsequent calls just fetch tuples from tuplestore. * ---------------- */ - if (matstate->mat_Flag == false) + if (tuplestorestate == NULL) { + Plan *outerNode; + /* ---------------- - * set all relations to be scanned in the forward direction - * while creating the temporary relation. + * Want to scan subplan in the forward direction while creating + * the stored data. (Does setting my direction actually affect + * the subplan? I bet this is useless code...) * ---------------- */ estate->es_direction = ForwardScanDirection; /* ---------------- - * if we couldn't create the temp relation then - * we print a warning and return NULL. + * Initialize tuplestore module. * ---------------- */ - tempRelation = matstate->mat_TempRelation; - if (tempRelation == NULL) - { - elog(DEBUG, "ExecMaterial: temp relation is NULL! aborting..."); - return NULL; - } + tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */ + SortMem); + + matstate->tuplestorestate = (void *) tuplestorestate; /* ---------------- - * retrieve tuples from the subplan and - * insert them in the temporary relation + * Scan the subplan and feed all the tuples to tuplestore. * ---------------- */ outerNode = outerPlan((Plan *) node); + for (;;) { slot = ExecProcNode(outerNode, (Plan *) node); @@ -110,63 +103,34 @@ ExecMaterial(Material *node) if (TupIsNull(slot)) break; - heap_insert(tempRelation, slot->val); - + tuplestore_puttuple(tuplestorestate, (void *) slot->val); ExecClearTuple(slot); } /* ---------------- - * restore to user specified direction + * Complete the store. * ---------------- */ - estate->es_direction = dir; + tuplestore_donestoring(tuplestorestate); /* ---------------- - * now initialize the scan descriptor to scan the - * sorted relation and update the sortstate information - * ---------------- - */ - currentRelation = tempRelation; - currentScanDesc = heap_beginscan(currentRelation, /* relation */ - ScanDirectionIsBackward(dir), - SnapshotSelf, /* seeself */ - 0, /* num scan keys */ - NULL); /* scan keys */ - matstate->csstate.css_currentRelation = currentRelation; - matstate->csstate.css_currentScanDesc = currentScanDesc; - - ExecAssignScanType(&matstate->csstate, - RelationGetDescr(currentRelation)); - - /* ---------------- - * finally set the sorted flag to true + * restore to user specified direction * ---------------- */ - matstate->mat_Flag = true; + estate->es_direction = dir; } /* ---------------- - * at this point we know we have a sorted relation so - * we perform a simple scan on it with amgetnext().. - * ---------------- - */ - currentScanDesc = matstate->csstate.css_currentScanDesc; - - heapTuple = heap_getnext(currentScanDesc, ScanDirectionIsBackward(dir)); - - /* ---------------- - * put the tuple into the scan tuple slot and return the slot. - * Note: since the tuple is really a pointer to a page, we don't want - * to call pfree() on it.. + * Get the first or next tuple from tuplestore. + * Returns NULL if no more tuples. * ---------------- */ - slot = (TupleTableSlot *) matstate->csstate.css_ScanTupleSlot; - - return ExecStoreTuple(heapTuple, /* tuple to store */ - slot, /* slot to store in */ - currentScanDesc->rs_cbuf, /* buffer for this tuple */ - false); /* don't pfree this pointer */ + slot = (TupleTableSlot *) matstate->csstate.cstate.cs_ResultTupleSlot; + heapTuple = tuplestore_getheaptuple(tuplestorestate, + ScanDirectionIsForward(dir), + &should_free); + return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free); } /* ---------------------------------------------------------------- @@ -178,10 +142,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent) { MaterialState *matstate; Plan *outerPlan; - TupleDesc tupType; - Relation tempDesc; - - /* int len; */ /* ---------------- * assign the node's execution state @@ -194,8 +154,7 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent) * ---------------- */ matstate = makeNode(MaterialState); - matstate->mat_Flag = false; - matstate->mat_TempRelation = NULL; + matstate->tuplestorestate = NULL; node->matstate = matstate; /* ---------------- @@ -214,8 +173,12 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent) #define MATERIAL_NSLOTS 1 /* ---------------- * tuple table initialization + * + * material nodes only return tuples from their materialized + * relation. * ---------------- */ + ExecInitResultTupleSlot(estate, &matstate->csstate.cstate); ExecInitScanTupleSlot(estate, &matstate->csstate); /* ---------------- @@ -226,52 +189,14 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent) ExecInitNode(outerPlan, estate, (Plan *) node); /* ---------------- - * initialize matstate information - * ---------------- - */ - matstate->mat_Flag = false; - - /* ---------------- * initialize tuple type. no need to initialize projection * info because this node doesn't do projections. * ---------------- */ + ExecAssignResultTypeFromOuterPlan((Plan *) node, &matstate->csstate.cstate); ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate); matstate->csstate.cstate.cs_ProjInfo = NULL; - /* ---------------- - * get type information needed for ExecCreatR - * ---------------- - */ - tupType = ExecGetScanType(&matstate->csstate); - - /* ---------------- - * ExecCreatR wants its second argument to be an object id of - * a relation in the range table or a _NONAME_RELATION_ID - * indicating that the relation is not in the range table. - * - * In the second case ExecCreatR creates a temp relation. - * (currently this is the only case we support -cim 10/16/89) - * ---------------- - */ - /* ---------------- - * create the temporary relation - * ---------------- - */ - tempDesc = ExecCreatR(tupType, _NONAME_RELATION_ID_); - - /* ---------------- - * save the relation descriptor in the sortstate - * ---------------- - */ - matstate->mat_TempRelation = tempDesc; - matstate->csstate.css_currentRelation = NULL; - - /* ---------------- - * return relation oid of temporary relation in a list - * (someday -- for now we return LispTrue... cim 10/12/89) - * ---------------- - */ return TRUE; } @@ -285,16 +210,12 @@ ExecCountSlotsMaterial(Material *node) /* ---------------------------------------------------------------- * ExecEndMaterial - * - * old comments - * destroys the temporary relation. * ---------------------------------------------------------------- */ void ExecEndMaterial(Material *node) { MaterialState *matstate; - Relation tempRelation; Plan *outerPlan; /* ---------------- @@ -302,14 +223,6 @@ ExecEndMaterial(Material *node) * ---------------- */ matstate = node->matstate; - tempRelation = matstate->mat_TempRelation; - - /* ---------------- - * shut down the scan, but don't close the temp relation - * ---------------- - */ - matstate->csstate.css_currentRelation = NULL; - ExecCloseR((Plan *) node); /* ---------------- * shut down the subplan @@ -325,88 +238,92 @@ ExecEndMaterial(Material *node) ExecClearTuple(matstate->csstate.css_ScanTupleSlot); /* ---------------- - * delete the temp relation + * Release tuplestore resources * ---------------- */ - if (tempRelation != NULL) - heap_drop(tempRelation); + if (matstate->tuplestorestate != NULL) + tuplestore_end((Tuplestorestate *) matstate->tuplestorestate); + matstate->tuplestorestate = NULL; } /* ---------------------------------------------------------------- - * ExecMaterialReScan + * ExecMaterialMarkPos * - * Rescans the temporary relation. + * Calls tuplestore to save the current position in the stored file. * ---------------------------------------------------------------- */ void -ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent) +ExecMaterialMarkPos(Material *node) { - MaterialState *matstate = node->matstate; + MaterialState *matstate = node->matstate; - if (matstate->mat_Flag == false) + /* ---------------- + * if we haven't materialized yet, just return. + * ---------------- + */ + if (!matstate->tuplestorestate) return; - matstate->csstate.css_currentScanDesc = ExecReScanR(matstate->csstate.css_currentRelation, - matstate->csstate.css_currentScanDesc, - node->plan.state->es_direction, 0, NULL); - + tuplestore_markpos((Tuplestorestate *) matstate->tuplestorestate); } -#ifdef NOT_USED /* not used */ /* ---------------------------------------------------------------- - * ExecMaterialMarkPos + * ExecMaterialRestrPos + * + * Calls tuplestore to restore the last saved file position. * ---------------------------------------------------------------- */ -List /* nothing of interest */ -ExecMaterialMarkPos(Material node) +void +ExecMaterialRestrPos(Material *node) { - MaterialState matstate; - HeapScanDesc scan; + MaterialState *matstate = node->matstate; /* ---------------- - * if we haven't materialized yet, just return NIL. + * if we haven't materialized yet, just return. * ---------------- */ - matstate = get_matstate(node); - if (get_mat_Flag(matstate) == false) - return NIL; + if (!matstate->tuplestorestate) + return; /* ---------------- - * XXX access methods don't return positions yet so - * for now we return NIL. It's possible that - * they will never return positions for all I know -cim 10/16/89 + * restore the scan to the previously marked position * ---------------- */ - scan = get_css_currentScanDesc((CommonScanState) matstate); - heap_markpos(scan); - - return NIL; + tuplestore_restorepos((Tuplestorestate *) matstate->tuplestorestate); } /* ---------------------------------------------------------------- - * ExecMaterialRestrPos + * ExecMaterialReScan + * + * Rescans the materialized relation. * ---------------------------------------------------------------- */ void -ExecMaterialRestrPos(Material node) +ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent) { - MaterialState matstate; - HeapScanDesc scan; + MaterialState *matstate = node->matstate; - /* ---------------- - * if we haven't materialized yet, just return. - * ---------------- + /* + * 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. */ - matstate = get_matstate(node); - if (get_mat_Flag(matstate) == false) + if (!matstate->tuplestorestate) return; - /* ---------------- - * restore the scan to the previously marked position - * ---------------- + ExecClearTuple(matstate->csstate.cstate.cs_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. */ - scan = get_css_currentScanDesc((CommonScanState) matstate); - heap_restrpos(scan); + if (((Plan *) node)->lefttree->chgParam != NULL) + { + tuplestore_end((Tuplestorestate *) matstate->tuplestorestate); + matstate->tuplestorestate = NULL; + } + else + tuplestore_rescan((Tuplestorestate *) matstate->tuplestorestate); } - -#endif |