1 /*-------------------------------------------------------------------------
4 * miscellanious executor access method routines
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.16 1998/01/16 23:19:47 momjian Exp $
12 *-------------------------------------------------------------------------
17 * ExecOpenScanR \ / amopen
18 * ExecBeginScan \ / ambeginscan
19 * ExecCloseR \ / amclose
20 * ExecInsert \ executor interface / aminsert
21 * ExecReScanNode / to access methods \ amrescan
22 * ExecReScanR / \ amrescan
23 * ExecMarkPos / \ ammarkpos
24 * ExecRestrPos / \ amrestpos
26 * ExecCreatR function to create temporary relations
29 #include <stdio.h> /* for sprintf() */
33 #include "executor/executor.h"
34 #include "storage/smgr.h"
35 #include "utils/mcxt.h"
36 #include "executor/nodeSeqscan.h"
37 #include "executor/nodeIndexscan.h"
38 #include "executor/nodeSort.h"
39 #include "executor/nodeTee.h"
40 #include "executor/execdebug.h"
41 #include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */
42 #include "access/genam.h"
43 #include "access/heapam.h"
44 #include "catalog/heap.h"
47 ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
48 bool isindex, ScanDirection dir);
49 static Relation ExecOpenR(Oid relationOid, bool isindex);
51 /* ----------------------------------------------------------------
56 * relation -- relation to be opened and scanned.
57 * nkeys -- number of keys
58 * skeys -- keys to restrict scanning
59 * isindex -- if this is true, the relation is the relid of
60 * an index relation, else it is an index into the
62 * Returns the relation as(relDesc scanDesc)
63 * If this structure is changed, need to modify the access macros
64 * defined in execInt.h.
65 * ----------------------------------------------------------------
68 ExecOpenScanR(Oid relOid,
73 Relation *returnRelation, /* return */
74 Pointer *returnScanDesc) /* return */
80 * note: scanDesc returned by ExecBeginScan can be either
81 * a HeapScanDesc or an IndexScanDesc so for now we
82 * make it a Pointer. There should be a better scan
83 * abstraction someday -cim 9/9/89
86 relation = ExecOpenR(relOid, isindex);
87 scanDesc = ExecBeginScan(relation,
93 if (returnRelation != NULL)
94 *returnRelation = relation;
96 *returnScanDesc = scanDesc;
99 /* ----------------------------------------------------------------
102 * returns a relation descriptor given an object id.
103 * ----------------------------------------------------------------
106 ExecOpenR(Oid relationOid, bool isindex)
110 relation = (Relation) NULL;
113 * open the relation with the correct call depending
114 * on whether this is a heap relation or an index relation.
119 relation = index_open(relationOid);
122 relation = heap_open(relationOid);
124 if (relation == NULL)
125 elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");
130 /* ----------------------------------------------------------------
133 * beginscans a relation in current direction.
135 * XXX fix parameters to AMbeginscan (and btbeginscan)
136 * currently we need to pass a flag stating whether
137 * or not the scan should begin at an endpoint of
138 * the relation.. Right now we always pass false
140 * ----------------------------------------------------------------
143 ExecBeginScan(Relation relation,
154 * open the appropriate type of scan.
156 * Note: ambeginscan()'s second arg is a boolean indicating
157 * that the scan should be done in reverse.. That is,
158 * if you pass it true, then the scan is backward.
163 scanDesc = (Pointer) index_beginscan(relation,
164 false, /* see above comment */
170 scanDesc = (Pointer) heap_beginscan(relation,
171 ScanDirectionIsBackward(dir),
177 if (scanDesc == NULL)
178 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
184 /* ----------------------------------------------------------------
187 * closes the relation and scan descriptor for a scan or sort
188 * node. Also closes index relations and scans for index scans.
191 * closes the relation indicated in 'relID'
192 * ----------------------------------------------------------------
195 ExecCloseR(Plan *node)
197 CommonScanState *state;
199 HeapScanDesc scanDesc;
202 * shut down the heap scan and close the heap relation
205 switch (nodeTag(node))
209 state = ((SeqScan *) node)->scanstate;
213 state = ((IndexScan *) node)->scan.scanstate;
217 state = &(((Material *) node)->matstate->csstate);
221 state = &(((Sort *) node)->sortstate->csstate);
225 state = &(((Agg *) node)->aggstate->csstate);
229 elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
233 relation = state->css_currentRelation;
234 scanDesc = state->css_currentScanDesc;
236 if (scanDesc != NULL)
237 heap_endscan(scanDesc);
239 if (relation != NULL)
240 heap_close(relation);
243 * if this is an index scan then we have to take care
244 * of the index relations as well..
247 if (nodeTag(node) == T_IndexScan)
249 IndexScan *iscan = (IndexScan *) node;
250 IndexScanState *indexstate;
252 RelationPtr indexRelationDescs;
253 IndexScanDescPtr indexScanDescs;
256 indexstate = iscan->indxstate;
257 numIndices = indexstate->iss_NumIndices;
258 indexRelationDescs = indexstate->iss_RelationDescs;
259 indexScanDescs = indexstate->iss_ScanDescs;
261 for (i = 0; i < numIndices; i++)
264 * shut down each of the scans and
265 * close each of the index relations
268 if (indexScanDescs[i] != NULL)
269 index_endscan(indexScanDescs[i]);
271 if (indexRelationDescs[i] != NULL)
272 index_close(indexRelationDescs[i]);
277 /* ----------------------------------------------------------------
280 * XXX this should be extended to cope with all the node types..
282 * takes the new expression context as an argument, so that
283 * index scans needn't have their scan keys updated separately
285 * ----------------------------------------------------------------
288 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
290 switch (nodeTag(node))
293 ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
297 ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
303 * the first call to ExecReScan should have no effect because
304 * everything is initialized properly already. the following
305 * calls will be handled by ExecSeqReScan() because the nodes
306 * below the Material node have already been materialized into
312 ExecTeeReScan((Tee *) node, exprCtxt, parent);
316 elog(ERROR, "ExecReScan: not a seqscan or indexscan node.");
321 /* ----------------------------------------------------------------
324 * XXX this does not do the right thing with indices yet.
325 * ----------------------------------------------------------------
328 ExecReScanR(Relation relDesc, /* LLL relDesc unused */
329 HeapScanDesc scanDesc,
330 ScanDirection direction,
331 int nkeys, /* LLL nkeys unused */
334 if (scanDesc != NULL)
335 heap_rescan(scanDesc, /* scan desc */
336 ScanDirectionIsBackward(direction), /* backward flag */
337 skeys); /* scan keys */
342 /* ----------------------------------------------------------------
345 * Marks the current scan position.
347 * XXX Needs to be extended to include all the node types.
348 * ----------------------------------------------------------------
351 ExecMarkPos(Plan *node)
353 switch (nodeTag(node))
356 ExecSeqMarkPos((SeqScan *) node);
360 ExecIndexMarkPos((IndexScan *) node);
364 ExecSortMarkPos((Sort *) node);
368 /* elog(DEBUG, "ExecMarkPos: unsupported node type"); */
374 /* ----------------------------------------------------------------
377 * restores the scan position previously saved with ExecMarkPos()
378 * ----------------------------------------------------------------
381 ExecRestrPos(Plan *node)
383 switch (nodeTag(node))
386 ExecSeqRestrPos((SeqScan *) node);
390 ExecIndexRestrPos((IndexScan *) node);
394 ExecSortRestrPos((Sort *) node);
398 /* elog(DEBUG, "ExecRestrPos: node type not supported"); */
403 /* ----------------------------------------------------------------
407 * Creates a relation.
410 * attrType -- type information on the attributes.
411 * accessMtd -- access methods used to access the created relation.
412 * relation -- optional. Either an index to the range table or
413 * negative number indicating a temporary relation.
414 * A temporary relation is assume if this field is absent.
415 * ----------------------------------------------------------------
419 ExecCreatR(TupleDesc tupType,
424 EU3_printf("ExecCreatR: %s type=%d oid=%d\n",
425 "entering: ", tupType, relationOid);
426 CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext);
430 if (relationOid == _TEMP_RELATION_ID_)
433 * create a temporary relation
434 * (currently the planner always puts a _TEMP_RELATION_ID
435 * in the relation argument so we expect this to be the case although
436 * it's possible that someday we'll get the name from
437 * from the range table.. -cim 10/12/89)
441 sprintf(tempname, "temp_%d.%d", getpid(), tmpcnt++);
442 EU1_printf("ExecCreatR: attempting to create %s\n", tempname);
446 * heap_create creates a name if the argument to heap_create is
449 relDesc = heap_create("", tupType);
454 * use a relation from the range table
457 elog(DEBUG, "ExecCreatR: %s",
458 "stuff using range table id's is not functional");
462 elog(DEBUG, "ExecCreatR: failed to create relation.");
464 EU1_printf("ExecCreatR: returning relDesc=%d\n", relDesc);