diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execAmi.c | 97 | ||||
-rw-r--r-- | src/backend/executor/nodeMaterial.c | 277 |
2 files changed, 112 insertions, 262 deletions
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index ed20aec5a8..ff3fa0b6ed 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execAmi.c,v 1.47 2000/06/15 04:09:50 momjian Exp $ + * $Id: execAmi.c,v 1.48 2000/06/18 22:44:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,13 +17,9 @@ * ExecBeginScan \ / ambeginscan * ExecCloseR \ / amclose * ExecInsert \ executor interface / aminsert - * ExecReScanNode / to access methods \ amrescan - * ExecReScanR / \ amrescan - * ExecMarkPos / \ ammarkpos - * ExecRestrPos / \ amrestpos - * - * ExecCreatR function to create temporary relations - * + * ExecReScanR / to access methods \ amrescan + * ExecMarkPos / \ ammarkpos + * ExecRestrPos / \ amrestpos */ #include "postgres.h" @@ -49,7 +45,6 @@ #include "executor/nodeSort.h" #include "executor/nodeSubplan.h" #include "executor/nodeUnique.h" -#include "optimizer/internal.h" static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys, bool isindex, ScanDirection dir, Snapshot snapshot); @@ -170,7 +165,6 @@ ExecBeginScan(Relation relation, if (scanDesc == NULL) elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed."); - return scanDesc; } @@ -179,9 +173,6 @@ ExecBeginScan(Relation relation, * * closes the relation and scan descriptor for a scan or sort * node. Also closes index relations and scans for index scans. - * - * old comments - * closes the relation indicated in 'relID' * ---------------------------------------------------------------- */ void @@ -206,10 +197,6 @@ ExecCloseR(Plan *node) state = ((IndexScan *) node)->scan.scanstate; break; - case T_Material: - state = &(((Material *) node)->matstate->csstate); - break; - case T_Sort: state = &(((Sort *) node)->sortstate->csstate); break; @@ -223,7 +210,7 @@ ExecCloseR(Plan *node) break; default: - elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!"); + elog(DEBUG, "ExecCloseR: not a scan or sort node!"); return; } @@ -423,7 +410,7 @@ ExecMarkPos(Plan *node) { switch (nodeTag(node)) { - case T_SeqScan: + case T_SeqScan: ExecSeqMarkPos((SeqScan *) node); break; @@ -431,6 +418,10 @@ ExecMarkPos(Plan *node) ExecIndexMarkPos((IndexScan *) node); break; + case T_Material: + ExecMaterialMarkPos((Material *) node); + break; + case T_Sort: ExecSortMarkPos((Sort *) node); break; @@ -457,7 +448,7 @@ ExecRestrPos(Plan *node) { switch (nodeTag(node)) { - case T_SeqScan: + case T_SeqScan: ExecSeqRestrPos((SeqScan *) node); return; @@ -465,6 +456,10 @@ ExecRestrPos(Plan *node) ExecIndexRestrPos((IndexScan *) node); return; + case T_Material: + ExecMaterialRestrPos((Material *) node); + return; + case T_Sort: ExecSortRestrPos((Sort *) node); return; @@ -474,65 +469,3 @@ ExecRestrPos(Plan *node) return; } } - -/* ---------------------------------------------------------------- - * ExecCreatR - * - * old comments - * Creates a relation. - * - * Parameters: - * attrType -- type information on the attributes. - * accessMtd -- access methods used to access the created relation. - * relation -- optional. Either an index to the range table or - * negative number indicating a temporary relation. - * A temporary relation is assume if this field is absent. - * ---------------------------------------------------------------- - */ - -Relation -ExecCreatR(TupleDesc tupType, - Oid relationOid) -{ - Relation relDesc; - - EU3_printf("ExecCreatR: %s type=%d oid=%u\n", - "entering: ", tupType, relationOid); - CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext); - - relDesc = NULL; - - if (relationOid == _NONAME_RELATION_ID_) - { - /* ---------------- - * create a temporary relation - * (currently the planner always puts a _NONAME_RELATION_ID - * in the relation argument so we expect this to be the case although - * it's possible that someday we'll get the name from - * from the range table.. -cim 10/12/89) - * ---------------- - */ - - /* - * heap_create creates a name if the argument to heap_create is - * '\0 ' - */ - relDesc = heap_create(NULL, tupType, true, false, true); - } - else - { - /* ---------------- - * use a relation from the range table - * ---------------- - */ - elog(DEBUG, "ExecCreatR: %s", - "stuff using range table id's is not functional"); - } - - if (relDesc == NULL) - elog(DEBUG, "ExecCreatR: failed to create relation."); - - EU1_printf("ExecCreatR: returning relDesc=%d\n", relDesc); - - return relDesc; -} diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 4348f89ccc..1d5c904248 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 |