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.47 2000/06/15 04:09:50 momjian Exp $
11 *-------------------------------------------------------------------------
16 * ExecOpenScanR \ / amopen
17 * ExecBeginScan \ / ambeginscan
18 * ExecCloseR \ / amclose
19 * ExecInsert \ executor interface / aminsert
20 * ExecReScanNode / to access methods \ amrescan
21 * ExecReScanR / \ amrescan
22 * ExecMarkPos / \ ammarkpos
23 * ExecRestrPos / \ amrestpos
25 * ExecCreatR function to create temporary relations
32 #include "access/genam.h"
33 #include "access/heapam.h"
34 #include "catalog/heap.h"
35 #include "executor/execdebug.h"
36 #include "executor/nodeAgg.h"
37 #include "executor/nodeAppend.h"
38 #include "executor/nodeGroup.h"
39 #include "executor/nodeGroup.h"
40 #include "executor/nodeHash.h"
41 #include "executor/nodeHashjoin.h"
42 #include "executor/nodeIndexscan.h"
43 #include "executor/nodeTidscan.h"
44 #include "executor/nodeMaterial.h"
45 #include "executor/nodeMergejoin.h"
46 #include "executor/nodeNestloop.h"
47 #include "executor/nodeResult.h"
48 #include "executor/nodeSeqscan.h"
49 #include "executor/nodeSort.h"
50 #include "executor/nodeSubplan.h"
51 #include "executor/nodeUnique.h"
52 #include "optimizer/internal.h"
54 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
55 bool isindex, ScanDirection dir, Snapshot snapshot);
57 /* ----------------------------------------------------------------
62 * relation -- relation to be opened and scanned.
63 * nkeys -- number of keys
64 * skeys -- keys to restrict scanning
65 * isindex -- if this is true, the relation is the relid of
66 * an index relation, else it is an index into the
68 * Returns the relation as(relDesc scanDesc)
69 * If this structure is changed, need to modify the access macros
70 * defined in execInt.h.
71 * ----------------------------------------------------------------
74 ExecOpenScanR(Oid relOid,
80 Relation *returnRelation, /* return */
81 Pointer *returnScanDesc) /* return */
87 * note: scanDesc returned by ExecBeginScan can be either
88 * a HeapScanDesc or an IndexScanDesc so for now we
89 * make it a Pointer. There should be a better scan
90 * abstraction someday -cim 9/9/89
95 * open the relation with the correct call depending
96 * on whether this is a heap relation or an index relation.
98 * Do not lock the rel here; beginscan will acquire AccessShareLock.
102 relation = index_open(relOid);
104 relation = heap_open(relOid, NoLock);
106 if (relation == NULL)
107 elog(ERROR, "ExecOpenScanR: failed to open relation %u", relOid);
109 scanDesc = ExecBeginScan(relation,
116 if (returnRelation != NULL)
117 *returnRelation = relation;
118 if (scanDesc != NULL)
119 *returnScanDesc = scanDesc;
122 /* ----------------------------------------------------------------
125 * beginscans a relation in current direction.
127 * XXX fix parameters to AMbeginscan (and btbeginscan)
128 * currently we need to pass a flag stating whether
129 * or not the scan should begin at an endpoint of
130 * the relation.. Right now we always pass false
132 * ----------------------------------------------------------------
135 ExecBeginScan(Relation relation,
147 * open the appropriate type of scan.
149 * Note: ambeginscan()'s second arg is a boolean indicating
150 * that the scan should be done in reverse.. That is,
151 * if you pass it true, then the scan is backward.
156 scanDesc = (Pointer) index_beginscan(relation,
157 false, /* see above comment */
163 scanDesc = (Pointer) heap_beginscan(relation,
164 ScanDirectionIsBackward(dir),
170 if (scanDesc == NULL)
171 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
177 /* ----------------------------------------------------------------
180 * closes the relation and scan descriptor for a scan or sort
181 * node. Also closes index relations and scans for index scans.
184 * closes the relation indicated in 'relID'
185 * ----------------------------------------------------------------
188 ExecCloseR(Plan *node)
190 CommonScanState *state;
192 HeapScanDesc scanDesc;
195 * shut down the heap scan and close the heap relation
198 switch (nodeTag(node))
202 state = ((SeqScan *) node)->scanstate;
206 state = ((IndexScan *) node)->scan.scanstate;
210 state = &(((Material *) node)->matstate->csstate);
214 state = &(((Sort *) node)->sortstate->csstate);
218 state = &(((Agg *) node)->aggstate->csstate);
222 state = ((TidScan *) node)->scan.scanstate;
226 elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
230 relation = state->css_currentRelation;
231 scanDesc = state->css_currentScanDesc;
233 if (scanDesc != NULL)
234 heap_endscan(scanDesc);
237 * endscan released AccessShareLock acquired by beginscan. If we are
238 * holding any stronger locks on the rel, they should be held till end
239 * of xact. Therefore, we need only close the rel and not release
242 if (relation != NULL)
243 heap_close(relation, NoLock);
246 * if this is an index scan then we have to take care
247 * of the index relations as well..
250 if (IsA(node, IndexScan))
252 IndexScan *iscan = (IndexScan *) node;
253 IndexScanState *indexstate;
255 RelationPtr indexRelationDescs;
256 IndexScanDescPtr indexScanDescs;
259 indexstate = iscan->indxstate;
260 numIndices = indexstate->iss_NumIndices;
261 indexRelationDescs = indexstate->iss_RelationDescs;
262 indexScanDescs = indexstate->iss_ScanDescs;
264 for (i = 0; i < numIndices; i++)
267 * shut down each of the scans and
268 * close each of the index relations
271 if (indexScanDescs[i] != NULL)
272 index_endscan(indexScanDescs[i]);
274 if (indexRelationDescs[i] != NULL)
275 index_close(indexRelationDescs[i]);
280 /* ----------------------------------------------------------------
283 * XXX this should be extended to cope with all the node types..
285 * takes the new expression context as an argument, so that
286 * index scans needn't have their scan keys updated separately
288 * ----------------------------------------------------------------
291 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
294 if (node->chgParam != NULL) /* Wow! */
298 foreach(lst, node->initPlan)
300 Plan *splan = ((SubPlan *) lfirst(lst))->plan;
302 if (splan->extParam != NULL) /* don't care about child
304 SetChangedParamList(splan, node->chgParam);
305 if (splan->chgParam != NULL)
306 ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
308 foreach(lst, node->subPlan)
310 Plan *splan = ((SubPlan *) lfirst(lst))->plan;
312 if (splan->extParam != NULL)
313 SetChangedParamList(splan, node->chgParam);
315 /* Well. Now set chgParam for left/right trees. */
316 if (node->lefttree != NULL)
317 SetChangedParamList(node->lefttree, node->chgParam);
318 if (node->righttree != NULL)
319 SetChangedParamList(node->righttree, node->chgParam);
322 switch (nodeTag(node))
325 ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
329 ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
333 ExecMaterialReScan((Material *) node, exprCtxt, parent);
337 ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
341 ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
345 ExecReScanHash((Hash *) node, exprCtxt, parent);
349 ExecReScanAgg((Agg *) node, exprCtxt, parent);
353 ExecReScanGroup((Group *) node, exprCtxt, parent);
357 ExecReScanResult((Result *) node, exprCtxt, parent);
361 ExecReScanUnique((Unique *) node, exprCtxt, parent);
365 ExecReScanSort((Sort *) node, exprCtxt, parent);
369 ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
373 ExecReScanAppend((Append *) node, exprCtxt, parent);
377 ExecTidReScan((TidScan *) node, exprCtxt, parent);
381 elog(ERROR, "ExecReScan: node type %u not supported", nodeTag(node));
385 if (node->chgParam != NULL)
387 freeList(node->chgParam);
388 node->chgParam = NULL;
392 /* ----------------------------------------------------------------
395 * XXX this does not do the right thing with indices yet.
396 * ----------------------------------------------------------------
399 ExecReScanR(Relation relDesc, /* LLL relDesc unused */
400 HeapScanDesc scanDesc,
401 ScanDirection direction,
402 int nkeys, /* LLL nkeys unused */
405 if (scanDesc != NULL)
406 heap_rescan(scanDesc, /* scan desc */
407 ScanDirectionIsBackward(direction), /* backward flag */
408 skeys); /* scan keys */
413 /* ----------------------------------------------------------------
416 * Marks the current scan position.
418 * XXX Needs to be extended to include all the node types.
419 * ----------------------------------------------------------------
422 ExecMarkPos(Plan *node)
424 switch (nodeTag(node))
427 ExecSeqMarkPos((SeqScan *) node);
431 ExecIndexMarkPos((IndexScan *) node);
435 ExecSortMarkPos((Sort *) node);
439 ExecTidMarkPos((TidScan *) node);
443 elog(DEBUG, "ExecMarkPos: node type %u not supported", nodeTag(node));
449 /* ----------------------------------------------------------------
452 * restores the scan position previously saved with ExecMarkPos()
453 * ----------------------------------------------------------------
456 ExecRestrPos(Plan *node)
458 switch (nodeTag(node))
461 ExecSeqRestrPos((SeqScan *) node);
465 ExecIndexRestrPos((IndexScan *) node);
469 ExecSortRestrPos((Sort *) node);
473 elog(DEBUG, "ExecRestrPos: node type %u not supported", nodeTag(node));
478 /* ----------------------------------------------------------------
482 * Creates a relation.
485 * attrType -- type information on the attributes.
486 * accessMtd -- access methods used to access the created relation.
487 * relation -- optional. Either an index to the range table or
488 * negative number indicating a temporary relation.
489 * A temporary relation is assume if this field is absent.
490 * ----------------------------------------------------------------
494 ExecCreatR(TupleDesc tupType,
499 EU3_printf("ExecCreatR: %s type=%d oid=%u\n",
500 "entering: ", tupType, relationOid);
501 CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext);
505 if (relationOid == _NONAME_RELATION_ID_)
508 * create a temporary relation
509 * (currently the planner always puts a _NONAME_RELATION_ID
510 * in the relation argument so we expect this to be the case although
511 * it's possible that someday we'll get the name from
512 * from the range table.. -cim 10/12/89)
517 * heap_create creates a name if the argument to heap_create is
520 relDesc = heap_create(NULL, tupType, true, false, true);
525 * use a relation from the range table
528 elog(DEBUG, "ExecCreatR: %s",
529 "stuff using range table id's is not functional");
533 elog(DEBUG, "ExecCreatR: failed to create relation.");
535 EU1_printf("ExecCreatR: returning relDesc=%d\n", relDesc);