/*------------------------------------------------------------------------- * * execAmi.c-- * miscellanious executor access method routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.1.1.1 1996/07/09 06:21:24 scrappy Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES * * ExecOpenScanR \ / amopen * 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 * */ #include /* for sprintf() */ #include "executor/executor.h" #include "storage/smgr.h" #include "executor/nodeSeqscan.h" #include "executor/nodeIndexscan.h" #include "executor/nodeSort.h" #include "executor/nodeTee.h" #include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */ /* ---------------------------------------------------------------- * ExecOpenScanR * * old comments: * Parameters: * relation -- relation to be opened and scanned. * nkeys -- number of keys * skeys -- keys to restrict scanning * isindex -- if this is true, the relation is the relid of * an index relation, else it is an index into the * range table. * Returns the relation as(relDesc scanDesc) * If this structure is changed, need to modify the access macros * defined in execInt.h. * ---------------------------------------------------------------- */ void ExecOpenScanR(Oid relOid, int nkeys, ScanKey skeys, bool isindex, ScanDirection dir, TimeQual timeRange, Relation *returnRelation, /* return */ Pointer *returnScanDesc) /* return */ { Relation relation; Pointer scanDesc; /* ---------------- * note: scanDesc returned by ExecBeginScan can be either * a HeapScanDesc or an IndexScanDesc so for now we * make it a Pointer. There should be a better scan * abstraction someday -cim 9/9/89 * ---------------- */ relation = ExecOpenR(relOid, isindex); scanDesc = ExecBeginScan(relation, nkeys, skeys, isindex, dir, timeRange); if (returnRelation != NULL) *returnRelation = relation; if (scanDesc != NULL) *returnScanDesc = scanDesc; } /* ---------------------------------------------------------------- * ExecOpenR * * returns a relation descriptor given an object id. * ---------------------------------------------------------------- */ Relation ExecOpenR(Oid relationOid, bool isindex) { Relation relation; relation = (Relation) NULL; /* ---------------- * open the relation with the correct call depending * on whether this is a heap relation or an index relation. * ---------------- */ if (isindex) { relation = index_open(relationOid); } else relation = heap_open(relationOid); if (relation == NULL) elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed."); return relation; } /* ---------------------------------------------------------------- * ExecBeginScan * * beginscans a relation in current direction. * * XXX fix parameters to AMbeginscan (and btbeginscan) * currently we need to pass a flag stating whether * or not the scan should begin at an endpoint of * the relation.. Right now we always pass false * -cim 9/14/89 * ---------------------------------------------------------------- */ Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys, bool isindex, ScanDirection dir, TimeQual time_range) { Pointer scanDesc; scanDesc = NULL; /* ---------------- * open the appropriate type of scan. * * Note: ambeginscan()'s second arg is a boolean indicating * that the scan should be done in reverse.. That is, * if you pass it true, then the scan is backward. * ---------------- */ if (isindex) { scanDesc = (Pointer) index_beginscan(relation, false, /* see above comment */ nkeys, skeys); } else { scanDesc = (Pointer) heap_beginscan(relation, ScanDirectionIsBackward(dir), time_range, nkeys, skeys); } if (scanDesc == NULL) elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed."); return scanDesc; } /* ---------------------------------------------------------------- * ExecCloseR * * 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 ExecCloseR(Plan *node) { CommonScanState *state; Relation relation; HeapScanDesc scanDesc; /* ---------------- * shut down the heap scan and close the heap relation * ---------------- */ switch (nodeTag(node)) { case T_SeqScan: state = ((SeqScan *)node)->scanstate; break; case T_IndexScan: state = ((IndexScan *)node)->scan.scanstate; break; case T_Material: state = &(((Material *)node)->matstate->csstate); break; case T_Sort: state = &(((Sort *)node)->sortstate->csstate); break; case T_Agg: state = &(((Agg *)node)->aggstate->csstate); break; default: elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!"); return; } relation = state->css_currentRelation; scanDesc = state->css_currentScanDesc; if (scanDesc != NULL) heap_endscan(scanDesc); if (relation != NULL) heap_close(relation); /* ---------------- * if this is an index scan then we have to take care * of the index relations as well.. * ---------------- */ if (nodeTag(node) == T_IndexScan) { IndexScan *iscan= (IndexScan *)node; IndexScanState *indexstate; int numIndices; RelationPtr indexRelationDescs; IndexScanDescPtr indexScanDescs; int i; indexstate = iscan->indxstate; numIndices = indexstate->iss_NumIndices; indexRelationDescs = indexstate->iss_RelationDescs; indexScanDescs = indexstate->iss_ScanDescs; for (i = 0; i