1 /*-------------------------------------------------------------------------
4 * miscellaneous executor access method routines
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * $Id: execAmi.c,v 1.53 2000/10/05 19:11:26 tgl Exp $
11 *-------------------------------------------------------------------------
16 * ExecOpenScanR \ / amopen
17 * ExecBeginScan \ / ambeginscan
18 * ExecCloseR \ / amclose
19 * ExecInsert \ executor interface / aminsert
20 * ExecReScanR / to access methods \ amrescan
21 * ExecMarkPos / \ ammarkpos
22 * ExecRestrPos / \ amrestpos
28 #include "access/genam.h"
29 #include "access/heapam.h"
30 #include "catalog/heap.h"
31 #include "executor/execdebug.h"
32 #include "executor/nodeAgg.h"
33 #include "executor/nodeAppend.h"
34 #include "executor/nodeGroup.h"
35 #include "executor/nodeGroup.h"
36 #include "executor/nodeHash.h"
37 #include "executor/nodeHashjoin.h"
38 #include "executor/nodeIndexscan.h"
39 #include "executor/nodeTidscan.h"
40 #include "executor/nodeMaterial.h"
41 #include "executor/nodeMergejoin.h"
42 #include "executor/nodeNestloop.h"
43 #include "executor/nodeResult.h"
44 #include "executor/nodeSeqscan.h"
45 #include "executor/nodeSetOp.h"
46 #include "executor/nodeSort.h"
47 #include "executor/nodeSubplan.h"
48 #include "executor/nodeSubqueryscan.h"
49 #include "executor/nodeUnique.h"
51 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
52 bool isindex, ScanDirection dir, Snapshot snapshot);
54 /* ----------------------------------------------------------------
59 * relation -- relation to be opened and scanned.
60 * nkeys -- number of keys
61 * skeys -- keys to restrict scanning
62 * isindex -- if this is true, the relation is the relid of
63 * an index relation, else it is an index into the
65 * Returns the relation as(relDesc scanDesc)
66 * If this structure is changed, need to modify the access macros
67 * defined in execInt.h.
68 * ----------------------------------------------------------------
71 ExecOpenScanR(Oid relOid,
77 Relation *returnRelation, /* return */
78 Pointer *returnScanDesc) /* return */
84 * note: scanDesc returned by ExecBeginScan can be either
85 * a HeapScanDesc or an IndexScanDesc so for now we
86 * make it a Pointer. There should be a better scan
87 * abstraction someday -cim 9/9/89
92 * open the relation with the correct call depending
93 * on whether this is a heap relation or an index relation.
95 * Do not lock the rel here; beginscan will acquire AccessShareLock.
99 relation = index_open(relOid);
101 relation = heap_open(relOid, NoLock);
103 scanDesc = ExecBeginScan(relation,
110 if (returnRelation != NULL)
111 *returnRelation = relation;
112 if (scanDesc != NULL)
113 *returnScanDesc = scanDesc;
116 /* ----------------------------------------------------------------
119 * beginscans a relation in current direction.
121 * XXX fix parameters to AMbeginscan (and btbeginscan)
122 * currently we need to pass a flag stating whether
123 * or not the scan should begin at an endpoint of
124 * the relation.. Right now we always pass false
126 * ----------------------------------------------------------------
129 ExecBeginScan(Relation relation,
141 * open the appropriate type of scan.
143 * Note: ambeginscan()'s second arg is a boolean indicating
144 * that the scan should be done in reverse.. That is,
145 * if you pass it true, then the scan is backward.
150 scanDesc = (Pointer) index_beginscan(relation,
151 false, /* see above comment */
157 scanDesc = (Pointer) heap_beginscan(relation,
158 ScanDirectionIsBackward(dir),
164 if (scanDesc == NULL)
165 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
170 /* ----------------------------------------------------------------
173 * closes the relation and scan descriptor for a scan node.
174 * Also closes index relations and scans for index scans.
175 * ----------------------------------------------------------------
178 ExecCloseR(Plan *node)
180 CommonScanState *state;
182 HeapScanDesc scanDesc;
185 * shut down the heap scan and close the heap relation
188 switch (nodeTag(node))
192 state = ((SeqScan *) node)->scanstate;
196 state = ((IndexScan *) node)->scan.scanstate;
200 state = ((TidScan *) node)->scan.scanstate;
204 elog(DEBUG, "ExecCloseR: not a scan node!");
208 relation = state->css_currentRelation;
209 scanDesc = state->css_currentScanDesc;
211 if (scanDesc != NULL)
212 heap_endscan(scanDesc);
215 * endscan released AccessShareLock acquired by beginscan. If we are
216 * holding any stronger locks on the rel, they should be held till end
217 * of xact. Therefore, we need only close the rel and not release
220 if (relation != NULL)
221 heap_close(relation, NoLock);
224 * if this is an index scan then we have to take care
225 * of the index relations as well..
228 if (IsA(node, IndexScan))
230 IndexScan *iscan = (IndexScan *) node;
231 IndexScanState *indexstate = iscan->indxstate;
233 RelationPtr indexRelationDescs;
234 IndexScanDescPtr indexScanDescs;
237 numIndices = indexstate->iss_NumIndices;
238 indexRelationDescs = indexstate->iss_RelationDescs;
239 indexScanDescs = indexstate->iss_ScanDescs;
241 for (i = 0; i < numIndices; i++)
244 * shut down each of the scans and
245 * close each of the index relations
248 if (indexScanDescs[i] != NULL)
249 index_endscan(indexScanDescs[i]);
251 if (indexRelationDescs[i] != NULL)
252 index_close(indexRelationDescs[i]);
257 /* ----------------------------------------------------------------
260 * XXX this should be extended to cope with all the node types..
262 * takes the new expression context as an argument, so that
263 * index scans needn't have their scan keys updated separately
265 * ----------------------------------------------------------------
268 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
271 if (node->chgParam != NULL) /* Wow! */
275 foreach(lst, node->initPlan)
277 Plan *splan = ((SubPlan *) lfirst(lst))->plan;
279 if (splan->extParam != NULL) /* don't care about child
281 SetChangedParamList(splan, node->chgParam);
282 if (splan->chgParam != NULL)
283 ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
285 foreach(lst, node->subPlan)
287 Plan *splan = ((SubPlan *) lfirst(lst))->plan;
289 if (splan->extParam != NULL)
290 SetChangedParamList(splan, node->chgParam);
292 /* Well. Now set chgParam for left/right trees. */
293 if (node->lefttree != NULL)
294 SetChangedParamList(node->lefttree, node->chgParam);
295 if (node->righttree != NULL)
296 SetChangedParamList(node->righttree, node->chgParam);
299 switch (nodeTag(node))
302 ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
306 ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
310 ExecTidReScan((TidScan *) node, exprCtxt, parent);
314 ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent);
318 ExecMaterialReScan((Material *) node, exprCtxt, parent);
322 ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
326 ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
330 ExecReScanHash((Hash *) node, exprCtxt, parent);
334 ExecReScanAgg((Agg *) node, exprCtxt, parent);
338 ExecReScanGroup((Group *) node, exprCtxt, parent);
342 ExecReScanResult((Result *) node, exprCtxt, parent);
346 ExecReScanUnique((Unique *) node, exprCtxt, parent);
350 ExecReScanSetOp((SetOp *) node, exprCtxt, parent);
354 ExecReScanSort((Sort *) node, exprCtxt, parent);
358 ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
362 ExecReScanAppend((Append *) node, exprCtxt, parent);
366 elog(ERROR, "ExecReScan: node type %d not supported",
371 if (node->chgParam != NULL)
373 freeList(node->chgParam);
374 node->chgParam = NULL;
378 /* ----------------------------------------------------------------
381 * XXX this does not do the right thing with indices yet.
382 * ----------------------------------------------------------------
385 ExecReScanR(Relation relDesc, /* LLL relDesc unused */
386 HeapScanDesc scanDesc,
387 ScanDirection direction,
388 int nkeys, /* LLL nkeys unused */
391 if (scanDesc != NULL)
392 heap_rescan(scanDesc, /* scan desc */
393 ScanDirectionIsBackward(direction), /* backward flag */
394 skeys); /* scan keys */
399 /* ----------------------------------------------------------------
402 * Marks the current scan position.
404 * XXX Needs to be extended to include all the node types,
405 * or at least all the ones that can be directly below a mergejoin.
406 * ----------------------------------------------------------------
409 ExecMarkPos(Plan *node)
411 switch (nodeTag(node))
414 ExecSeqMarkPos((SeqScan *) node);
418 ExecIndexMarkPos((IndexScan *) node);
422 ExecMaterialMarkPos((Material *) node);
426 ExecSortMarkPos((Sort *) node);
430 ExecTidMarkPos((TidScan *) node);
434 /* don't make hard error unless caller asks to restore... */
435 elog(DEBUG, "ExecMarkPos: node type %d not supported",
441 /* ----------------------------------------------------------------
444 * restores the scan position previously saved with ExecMarkPos()
446 * XXX Needs to be extended to include all the node types,
447 * or at least all the ones that can be directly below a mergejoin.
448 * ----------------------------------------------------------------
451 ExecRestrPos(Plan *node)
453 switch (nodeTag(node))
456 ExecSeqRestrPos((SeqScan *) node);
460 ExecIndexRestrPos((IndexScan *) node);
464 ExecMaterialRestrPos((Material *) node);
468 ExecSortRestrPos((Sort *) node);
472 elog(ERROR, "ExecRestrPos: node type %d not supported",