]> granicus.if.org Git - postgresql/blob - src/backend/executor/execAmi.c
pgindent run on all C files. Java run to follow. initdb/regression
[postgresql] / src / backend / executor / execAmi.c
1 /*-------------------------------------------------------------------------
2  *
3  * execAmi.c
4  *        miscellaneous executor access method routines
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *      $Id: execAmi.c,v 1.60 2001/10/25 05:49:27 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13 /*
14  *       INTERFACE ROUTINES
15  *
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
23  */
24
25 #include "postgres.h"
26
27
28 #include "access/genam.h"
29 #include "access/heapam.h"
30 #include "catalog/heap.h"
31 #include "executor/execdebug.h"
32 #include "executor/instrument.h"
33 #include "executor/nodeAgg.h"
34 #include "executor/nodeAppend.h"
35 #include "executor/nodeGroup.h"
36 #include "executor/nodeGroup.h"
37 #include "executor/nodeHash.h"
38 #include "executor/nodeHashjoin.h"
39 #include "executor/nodeIndexscan.h"
40 #include "executor/nodeTidscan.h"
41 #include "executor/nodeLimit.h"
42 #include "executor/nodeMaterial.h"
43 #include "executor/nodeMergejoin.h"
44 #include "executor/nodeNestloop.h"
45 #include "executor/nodeResult.h"
46 #include "executor/nodeSeqscan.h"
47 #include "executor/nodeSetOp.h"
48 #include "executor/nodeSort.h"
49 #include "executor/nodeSubplan.h"
50 #include "executor/nodeSubqueryscan.h"
51 #include "executor/nodeUnique.h"
52
53 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
54                           bool isindex, ScanDirection dir, Snapshot snapshot);
55
56 /* ----------------------------------------------------------------
57  *              ExecOpenScanR
58  *
59  * old comments:
60  *              Parameters:
61  *                relation -- relation to be opened and scanned.
62  *                nkeys    -- number of keys
63  *                skeys    -- keys to restrict scanning
64  *                       isindex  -- if this is true, the relation is the relid of
65  *                                               an index relation, else it is a heap relation.
66  *              Returns the relation as(relDesc scanDesc)
67  * ----------------------------------------------------------------
68  */
69 void
70 ExecOpenScanR(Oid relOid,
71                           int nkeys,
72                           ScanKey skeys,
73                           bool isindex,
74                           ScanDirection dir,
75                           Snapshot snapshot,
76                           Relation *returnRelation, /* return */
77                           Pointer *returnScanDesc)      /* return */
78 {
79         Relation        relation;
80         Pointer         scanDesc;
81
82         /*
83          * note: scanDesc returned by ExecBeginScan can be either a
84          * HeapScanDesc or an IndexScanDesc so for now we make it a Pointer.
85          * There should be a better scan abstraction someday -cim 9/9/89
86          */
87
88         /*
89          * Open the relation with the correct call depending on whether this
90          * is a heap relation or an index relation.
91          *
92          * For a table, acquire AccessShareLock for the duration of the query
93          * execution.  For indexes, acquire no lock here; the index machinery
94          * does its own locks and unlocks.      (We rely on having some kind of
95          * lock on the parent table to ensure the index won't go away!)
96          */
97         if (isindex)
98                 relation = index_open(relOid);
99         else
100                 relation = heap_open(relOid, AccessShareLock);
101
102         scanDesc = ExecBeginScan(relation,
103                                                          nkeys,
104                                                          skeys,
105                                                          isindex,
106                                                          dir,
107                                                          snapshot);
108
109         if (returnRelation != NULL)
110                 *returnRelation = relation;
111         if (scanDesc != NULL)
112                 *returnScanDesc = scanDesc;
113 }
114
115 /* ----------------------------------------------------------------
116  *              ExecBeginScan
117  *
118  *              beginscans a relation in current direction.
119  *
120  *              XXX fix parameters to AMbeginscan (and btbeginscan)
121  *                              currently we need to pass a flag stating whether
122  *                              or not the scan should begin at an endpoint of
123  *                              the relation.. Right now we always pass false
124  *                              -cim 9/14/89
125  * ----------------------------------------------------------------
126  */
127 static Pointer
128 ExecBeginScan(Relation relation,
129                           int nkeys,
130                           ScanKey skeys,
131                           bool isindex,
132                           ScanDirection dir,
133                           Snapshot snapshot)
134 {
135         Pointer         scanDesc;
136
137         /*
138          * open the appropriate type of scan.
139          *
140          * Note: ambeginscan()'s second arg is a boolean indicating that the scan
141          * should be done in reverse..  That is, if you pass it true, then the
142          * scan is backward.
143          */
144         if (isindex)
145         {
146                 scanDesc = (Pointer) index_beginscan(relation,
147                                                                                          false,         /* see above comment */
148                                                                                          nkeys,
149                                                                                          skeys);
150         }
151         else
152         {
153                 scanDesc = (Pointer) heap_beginscan(relation,
154                                                                                         ScanDirectionIsBackward(dir),
155                                                                                         snapshot,
156                                                                                         nkeys,
157                                                                                         skeys);
158         }
159
160         if (scanDesc == NULL)
161                 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
162
163         return scanDesc;
164 }
165
166 /* ----------------------------------------------------------------
167  *              ExecCloseR
168  *
169  *              closes the relation and scan descriptor for a scan node.
170  *              Also closes index relations and scans for index scans.
171  * ----------------------------------------------------------------
172  */
173 void
174 ExecCloseR(Plan *node)
175 {
176         CommonScanState *state;
177         Relation        relation;
178         HeapScanDesc scanDesc;
179
180         /*
181          * get state for node and shut down the heap scan, if any
182          */
183         switch (nodeTag(node))
184         {
185                 case T_SeqScan:
186                         state = ((SeqScan *) node)->scanstate;
187                         break;
188
189                 case T_IndexScan:
190                         state = ((IndexScan *) node)->scan.scanstate;
191                         break;
192
193                 case T_TidScan:
194                         state = ((TidScan *) node)->scan.scanstate;
195                         break;
196
197                 default:
198                         elog(DEBUG, "ExecCloseR: not a scan node!");
199                         return;
200         }
201
202         relation = state->css_currentRelation;
203         scanDesc = state->css_currentScanDesc;
204
205         if (scanDesc != NULL)
206                 heap_endscan(scanDesc);
207
208         /*
209          * if this is an index scan then we have to take care of the index
210          * relations as well.
211          */
212         if (IsA(node, IndexScan))
213         {
214                 IndexScan  *iscan = (IndexScan *) node;
215                 IndexScanState *indexstate = iscan->indxstate;
216                 int                     numIndices;
217                 RelationPtr indexRelationDescs;
218                 IndexScanDescPtr indexScanDescs;
219                 int                     i;
220
221                 numIndices = indexstate->iss_NumIndices;
222                 indexRelationDescs = indexstate->iss_RelationDescs;
223                 indexScanDescs = indexstate->iss_ScanDescs;
224
225                 for (i = 0; i < numIndices; i++)
226                 {
227                         /*
228                          * shut down each of the index scans and close each of the
229                          * index relations
230                          */
231                         if (indexScanDescs[i] != NULL)
232                                 index_endscan(indexScanDescs[i]);
233
234                         if (indexRelationDescs[i] != NULL)
235                                 index_close(indexRelationDescs[i]);
236                 }
237         }
238
239         /*
240          * Finally, close the heap relation.
241          *
242          * Currently, we do not release the AccessShareLock acquired by
243          * ExecOpenScanR.  This lock should be held till end of transaction.
244          * (There is a faction that considers this too much locking, however.)
245          */
246         if (relation != NULL)
247                 heap_close(relation, NoLock);
248 }
249
250 /* ----------------------------------------------------------------
251  *              ExecReScan
252  *
253  *              XXX this should be extended to cope with all the node types..
254  *
255  *              takes the new expression context as an argument, so that
256  *              index scans needn't have their scan keys updated separately
257  *              - marcel 09/20/94
258  * ----------------------------------------------------------------
259  */
260 void
261 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
262 {
263         if (node->instrument)
264                 InstrEndLoop(node->instrument);
265
266         if (node->chgParam != NULL) /* Wow! */
267         {
268                 List       *lst;
269
270                 foreach(lst, node->initPlan)
271                 {
272                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
273
274                         if (splan->extParam != NULL)            /* don't care about child
275                                                                                                  * locParam */
276                                 SetChangedParamList(splan, node->chgParam);
277                         if (splan->chgParam != NULL)
278                                 ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
279                 }
280                 foreach(lst, node->subPlan)
281                 {
282                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
283
284                         if (splan->extParam != NULL)
285                                 SetChangedParamList(splan, node->chgParam);
286                 }
287                 /* Well. Now set chgParam for left/right trees. */
288                 if (node->lefttree != NULL)
289                         SetChangedParamList(node->lefttree, node->chgParam);
290                 if (node->righttree != NULL)
291                         SetChangedParamList(node->righttree, node->chgParam);
292         }
293
294         switch (nodeTag(node))
295         {
296                 case T_SeqScan:
297                         ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
298                         break;
299
300                 case T_IndexScan:
301                         ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
302                         break;
303
304                 case T_TidScan:
305                         ExecTidReScan((TidScan *) node, exprCtxt, parent);
306                         break;
307
308                 case T_SubqueryScan:
309                         ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent);
310                         break;
311
312                 case T_Material:
313                         ExecMaterialReScan((Material *) node, exprCtxt, parent);
314                         break;
315
316                 case T_NestLoop:
317                         ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
318                         break;
319
320                 case T_HashJoin:
321                         ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
322                         break;
323
324                 case T_Hash:
325                         ExecReScanHash((Hash *) node, exprCtxt, parent);
326                         break;
327
328                 case T_Agg:
329                         ExecReScanAgg((Agg *) node, exprCtxt, parent);
330                         break;
331
332                 case T_Group:
333                         ExecReScanGroup((Group *) node, exprCtxt, parent);
334                         break;
335
336                 case T_Result:
337                         ExecReScanResult((Result *) node, exprCtxt, parent);
338                         break;
339
340                 case T_Unique:
341                         ExecReScanUnique((Unique *) node, exprCtxt, parent);
342                         break;
343
344                 case T_SetOp:
345                         ExecReScanSetOp((SetOp *) node, exprCtxt, parent);
346                         break;
347
348                 case T_Limit:
349                         ExecReScanLimit((Limit *) node, exprCtxt, parent);
350                         break;
351
352                 case T_Sort:
353                         ExecReScanSort((Sort *) node, exprCtxt, parent);
354                         break;
355
356                 case T_MergeJoin:
357                         ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
358                         break;
359
360                 case T_Append:
361                         ExecReScanAppend((Append *) node, exprCtxt, parent);
362                         break;
363
364                 default:
365                         elog(ERROR, "ExecReScan: node type %d not supported",
366                                  nodeTag(node));
367                         return;
368         }
369
370         if (node->chgParam != NULL)
371         {
372                 freeList(node->chgParam);
373                 node->chgParam = NULL;
374         }
375 }
376
377 /* ----------------------------------------------------------------
378  *              ExecReScanR
379  *
380  *              XXX this does not do the right thing with indices yet.
381  * ----------------------------------------------------------------
382  */
383 HeapScanDesc
384 ExecReScanR(Relation relDesc,   /* LLL relDesc unused  */
385                         HeapScanDesc scanDesc,
386                         ScanDirection direction,
387                         int nkeys,                      /* LLL nkeys unused  */
388                         ScanKey skeys)
389 {
390         if (scanDesc != NULL)
391                 heap_rescan(scanDesc,   /* scan desc */
392                                         ScanDirectionIsBackward(direction), /* backward flag */
393                                         skeys);         /* scan keys */
394
395         return scanDesc;
396 }
397
398 /* ----------------------------------------------------------------
399  *              ExecMarkPos
400  *
401  *              Marks the current scan position.
402  *
403  *              XXX Needs to be extended to include all the node types,
404  *              or at least all the ones that can be directly below a mergejoin.
405  * ----------------------------------------------------------------
406  */
407 void
408 ExecMarkPos(Plan *node)
409 {
410         switch (nodeTag(node))
411         {
412                 case T_SeqScan:
413                         ExecSeqMarkPos((SeqScan *) node);
414                         break;
415
416                 case T_IndexScan:
417                         ExecIndexMarkPos((IndexScan *) node);
418                         break;
419
420                 case T_Material:
421                         ExecMaterialMarkPos((Material *) node);
422                         break;
423
424                 case T_Sort:
425                         ExecSortMarkPos((Sort *) node);
426                         break;
427
428                 case T_TidScan:
429                         ExecTidMarkPos((TidScan *) node);
430                         break;
431
432                 default:
433                         /* don't make hard error unless caller asks to restore... */
434                         elog(DEBUG, "ExecMarkPos: node type %d not supported",
435                                  nodeTag(node));
436                         break;
437         }
438 }
439
440 /* ----------------------------------------------------------------
441  *              ExecRestrPos
442  *
443  *              restores the scan position previously saved with ExecMarkPos()
444  *
445  *              XXX Needs to be extended to include all the node types,
446  *              or at least all the ones that can be directly below a mergejoin.
447  * ----------------------------------------------------------------
448  */
449 void
450 ExecRestrPos(Plan *node)
451 {
452         switch (nodeTag(node))
453         {
454                 case T_SeqScan:
455                         ExecSeqRestrPos((SeqScan *) node);
456                         break;
457
458                 case T_IndexScan:
459                         ExecIndexRestrPos((IndexScan *) node);
460                         break;
461
462                 case T_Material:
463                         ExecMaterialRestrPos((Material *) node);
464                         break;
465
466                 case T_Sort:
467                         ExecSortRestrPos((Sort *) node);
468                         break;
469
470                 default:
471                         elog(ERROR, "ExecRestrPos: node type %d not supported",
472                                  nodeTag(node));
473                         break;
474         }
475 }