diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
commit | d31084e9d1118b25fd16580d9d8c2924b5740dff (patch) | |
tree | 3179e66307d54df9c7b966543550e601eb55e668 /src/backend/executor/execAmi.c | |
download | postgresql-PG95-1_01.tar.gz postgresql-PG95-1_01.zip |
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/executor/execAmi.c')
-rw-r--r-- | src/backend/executor/execAmi.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c new file mode 100644 index 00000000000..08d3e70d8b9 --- /dev/null +++ b/src/backend/executor/execAmi.c @@ -0,0 +1,439 @@ +/*------------------------------------------------------------------------- + * + * 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 <stdio.h> /* 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<numIndices; i++) { + /* ---------------- + * shut down each of the scans and + * close each of the index relations + * ---------------- + */ + if (indexScanDescs[i] != NULL) + index_endscan(indexScanDescs[i]); + + if (indexRelationDescs[i] != NULL) + index_close(indexRelationDescs[i]); + } + } +} + +/* ---------------------------------------------------------------- + * ExecReScan + * + * XXX this should be extended to cope with all the node types.. + * + * takes the new expression context as an argument, so that + * index scans needn't have their scan keys updated separately + * - marcel 09/20/94 + * ---------------------------------------------------------------- + */ +void +ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) +{ + switch(nodeTag(node)) { + case T_SeqScan: + ExecSeqReScan((SeqScan *) node, exprCtxt, parent); + return; + + case T_IndexScan: + ExecIndexReScan((IndexScan *) node, exprCtxt, parent); + return; + + case T_Material: + /* the first call to ExecReScan should have no effect because + * everything is initialized properly already. the following + * calls will be handled by ExecSeqReScan() because the nodes + * below the Material node have already been materialized into + * a temp relation. + */ + return; + + case T_Tee: + ExecTeeReScan((Tee*) node, exprCtxt, parent); + break; + + default: + elog(WARN, "ExecReScan: not a seqscan or indexscan node."); + return; + } +} + +/* ---------------------------------------------------------------- + * ExecReScanR + * + * XXX this does not do the right thing with indices yet. + * ---------------------------------------------------------------- + */ +HeapScanDesc +ExecReScanR(Relation relDesc, /* LLL relDesc unused */ + HeapScanDesc scanDesc, + ScanDirection direction, + int nkeys, /* LLL nkeys unused */ + ScanKey skeys) +{ + if (scanDesc != NULL) + heap_rescan(scanDesc, /* scan desc */ + ScanDirectionIsBackward(direction), /* backward flag */ + skeys); /* scan keys */ + + return scanDesc; +} + +/* ---------------------------------------------------------------- + * ExecMarkPos + * + * Marks the current scan position. + * + * XXX Needs to be extended to include all the node types. + * ---------------------------------------------------------------- + */ +void +ExecMarkPos(Plan *node) +{ + switch(nodeTag(node)) { + case T_SeqScan: + ExecSeqMarkPos((SeqScan *) node); + break; + + case T_IndexScan: + ExecIndexMarkPos((IndexScan *) node); + break; + + case T_Sort: + ExecSortMarkPos((Sort *) node); + break; + + default: + /* elog(DEBUG, "ExecMarkPos: unsupported node type"); */ + break; + } + return; +} + +/* ---------------------------------------------------------------- + * ExecRestrPos + * + * restores the scan position previously saved with ExecMarkPos() + * ---------------------------------------------------------------- + */ +void +ExecRestrPos(Plan *node) +{ + switch(nodeTag(node)) { + case T_SeqScan: + ExecSeqRestrPos((SeqScan *) node); + return; + + case T_IndexScan: + ExecIndexRestrPos((IndexScan *) node); + return; + + case T_Sort: + ExecSortRestrPos((Sort *) node); + return; + + default: + /* elog(DEBUG, "ExecRestrPos: node type not supported"); */ + 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 is this field is absent. + * ---------------------------------------------------------------- + */ + +Relation +ExecCreatR(TupleDesc tupType, + Oid relationOid) +{ + Relation relDesc; + + EU4_printf("ExecCreatR: %s numatts=%d type=%d oid=%d\n", + "entering: ", numberAttributes, tupType, relationOid); + CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext); + + relDesc = NULL; + + if (relationOid == _TEMP_RELATION_ID_ ) { + /* ---------------- + * create a temporary relation + * (currently the planner always puts a _TEMP_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) + * ---------------- + */ +/* + sprintf(tempname, "temp_%d.%d", getpid(), tmpcnt++); + EU1_printf("ExecCreatR: attempting to create %s\n", tempname); +*/ + /* heap_creatr creates a name if the argument to heap_creatr is '\0 ' */ + relDesc = heap_creatr("", + DEFAULT_SMGR, + tupType); + } 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; +} + |