]> granicus.if.org Git - postgresql/blob - src/backend/executor/execAmi.c
9d008494b30b15aa098a762c2ae36736c06288a0
[postgresql] / src / backend / executor / execAmi.c
1 /*-------------------------------------------------------------------------
2  *
3  * execAmi.c
4  *        miscellaneous executor access method routines
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *      $Id: execAmi.c,v 1.53 2000/10/05 19:11:26 tgl 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/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"
50
51 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
52                           bool isindex, ScanDirection dir, Snapshot snapshot);
53
54 /* ----------------------------------------------------------------
55  *              ExecOpenScanR
56  *
57  * old comments:
58  *              Parameters:
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
64  *                                               range table.
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  * ----------------------------------------------------------------
69  */
70 void
71 ExecOpenScanR(Oid relOid,
72                           int nkeys,
73                           ScanKey skeys,
74                           bool isindex,
75                           ScanDirection dir,
76                           Snapshot snapshot,
77                           Relation *returnRelation, /* return */
78                           Pointer *returnScanDesc)      /* return */
79 {
80         Relation        relation;
81         Pointer         scanDesc;
82
83         /* ----------------
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
88          * ----------------
89          */
90
91         /* ----------------
92          *      open the relation with the correct call depending
93          *      on whether this is a heap relation or an index relation.
94          *
95          *      Do not lock the rel here; beginscan will acquire AccessShareLock.
96          * ----------------
97          */
98         if (isindex)
99                 relation = index_open(relOid);
100         else
101                 relation = heap_open(relOid, NoLock);
102
103         scanDesc = ExecBeginScan(relation,
104                                                          nkeys,
105                                                          skeys,
106                                                          isindex,
107                                                          dir,
108                                                          snapshot);
109
110         if (returnRelation != NULL)
111                 *returnRelation = relation;
112         if (scanDesc != NULL)
113                 *returnScanDesc = scanDesc;
114 }
115
116 /* ----------------------------------------------------------------
117  *              ExecBeginScan
118  *
119  *              beginscans a relation in current direction.
120  *
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
125  *                              -cim 9/14/89
126  * ----------------------------------------------------------------
127  */
128 static Pointer
129 ExecBeginScan(Relation relation,
130                           int nkeys,
131                           ScanKey skeys,
132                           bool isindex,
133                           ScanDirection dir,
134                           Snapshot snapshot)
135 {
136         Pointer         scanDesc;
137
138         scanDesc = NULL;
139
140         /* ----------------
141          *      open the appropriate type of scan.
142          *
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.
146          * ----------------
147          */
148         if (isindex)
149         {
150                 scanDesc = (Pointer) index_beginscan(relation,
151                                                                                          false,         /* see above comment */
152                                                                                          nkeys,
153                                                                                          skeys);
154         }
155         else
156         {
157                 scanDesc = (Pointer) heap_beginscan(relation,
158                                                                                         ScanDirectionIsBackward(dir),
159                                                                                         snapshot,
160                                                                                         nkeys,
161                                                                                         skeys);
162         }
163
164         if (scanDesc == NULL)
165                 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
166
167         return scanDesc;
168 }
169
170 /* ----------------------------------------------------------------
171  *              ExecCloseR
172  *
173  *              closes the relation and scan descriptor for a scan node.
174  *              Also closes index relations and scans for index scans.
175  * ----------------------------------------------------------------
176  */
177 void
178 ExecCloseR(Plan *node)
179 {
180         CommonScanState *state;
181         Relation        relation;
182         HeapScanDesc scanDesc;
183
184         /* ----------------
185          *      shut down the heap scan and close the heap relation
186          * ----------------
187          */
188         switch (nodeTag(node))
189         {
190
191                 case T_SeqScan:
192                         state = ((SeqScan *) node)->scanstate;
193                         break;
194
195                 case T_IndexScan:
196                         state = ((IndexScan *) node)->scan.scanstate;
197                         break;
198
199                 case T_TidScan:
200                         state = ((TidScan *) node)->scan.scanstate;
201                         break;
202
203                 default:
204                         elog(DEBUG, "ExecCloseR: not a scan node!");
205                         return;
206         }
207
208         relation = state->css_currentRelation;
209         scanDesc = state->css_currentScanDesc;
210
211         if (scanDesc != NULL)
212                 heap_endscan(scanDesc);
213
214         /*
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
218          * locks.
219          */
220         if (relation != NULL)
221                 heap_close(relation, NoLock);
222
223         /* ----------------
224          *      if this is an index scan then we have to take care
225          *      of the index relations as well..
226          * ----------------
227          */
228         if (IsA(node, IndexScan))
229         {
230                 IndexScan  *iscan = (IndexScan *) node;
231                 IndexScanState *indexstate = iscan->indxstate;
232                 int                     numIndices;
233                 RelationPtr indexRelationDescs;
234                 IndexScanDescPtr indexScanDescs;
235                 int                     i;
236
237                 numIndices = indexstate->iss_NumIndices;
238                 indexRelationDescs = indexstate->iss_RelationDescs;
239                 indexScanDescs = indexstate->iss_ScanDescs;
240
241                 for (i = 0; i < numIndices; i++)
242                 {
243                         /* ----------------
244                          *      shut down each of the scans and
245                          *      close each of the index relations
246                          * ----------------
247                          */
248                         if (indexScanDescs[i] != NULL)
249                                 index_endscan(indexScanDescs[i]);
250
251                         if (indexRelationDescs[i] != NULL)
252                                 index_close(indexRelationDescs[i]);
253                 }
254         }
255 }
256
257 /* ----------------------------------------------------------------
258  *              ExecReScan
259  *
260  *              XXX this should be extended to cope with all the node types..
261  *
262  *              takes the new expression context as an argument, so that
263  *              index scans needn't have their scan keys updated separately
264  *              - marcel 09/20/94
265  * ----------------------------------------------------------------
266  */
267 void
268 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
269 {
270
271         if (node->chgParam != NULL) /* Wow! */
272         {
273                 List       *lst;
274
275                 foreach(lst, node->initPlan)
276                 {
277                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
278
279                         if (splan->extParam != NULL)            /* don't care about child
280                                                                                                  * locParam */
281                                 SetChangedParamList(splan, node->chgParam);
282                         if (splan->chgParam != NULL)
283                                 ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
284                 }
285                 foreach(lst, node->subPlan)
286                 {
287                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
288
289                         if (splan->extParam != NULL)
290                                 SetChangedParamList(splan, node->chgParam);
291                 }
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);
297         }
298
299         switch (nodeTag(node))
300         {
301                 case T_SeqScan:
302                         ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
303                         break;
304
305                 case T_IndexScan:
306                         ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
307                         break;
308
309                 case T_TidScan:
310                         ExecTidReScan((TidScan *) node, exprCtxt, parent);
311                         break;
312
313                 case T_SubqueryScan:
314                         ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent);
315                         break;
316
317                 case T_Material:
318                         ExecMaterialReScan((Material *) node, exprCtxt, parent);
319                         break;
320
321                 case T_NestLoop:
322                         ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
323                         break;
324
325                 case T_HashJoin:
326                         ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
327                         break;
328
329                 case T_Hash:
330                         ExecReScanHash((Hash *) node, exprCtxt, parent);
331                         break;
332
333                 case T_Agg:
334                         ExecReScanAgg((Agg *) node, exprCtxt, parent);
335                         break;
336
337                 case T_Group:
338                         ExecReScanGroup((Group *) node, exprCtxt, parent);
339                         break;
340
341                 case T_Result:
342                         ExecReScanResult((Result *) node, exprCtxt, parent);
343                         break;
344
345                 case T_Unique:
346                         ExecReScanUnique((Unique *) node, exprCtxt, parent);
347                         break;
348
349                 case T_SetOp:
350                         ExecReScanSetOp((SetOp *) node, exprCtxt, parent);
351                         break;
352
353                 case T_Sort:
354                         ExecReScanSort((Sort *) node, exprCtxt, parent);
355                         break;
356
357                 case T_MergeJoin:
358                         ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
359                         break;
360
361                 case T_Append:
362                         ExecReScanAppend((Append *) node, exprCtxt, parent);
363                         break;
364
365                 default:
366                         elog(ERROR, "ExecReScan: node type %d not supported",
367                                  nodeTag(node));
368                         return;
369         }
370
371         if (node->chgParam != NULL)
372         {
373                 freeList(node->chgParam);
374                 node->chgParam = NULL;
375         }
376 }
377
378 /* ----------------------------------------------------------------
379  *              ExecReScanR
380  *
381  *              XXX this does not do the right thing with indices yet.
382  * ----------------------------------------------------------------
383  */
384 HeapScanDesc
385 ExecReScanR(Relation relDesc,   /* LLL relDesc unused  */
386                         HeapScanDesc scanDesc,
387                         ScanDirection direction,
388                         int nkeys,                      /* LLL nkeys unused  */
389                         ScanKey skeys)
390 {
391         if (scanDesc != NULL)
392                 heap_rescan(scanDesc,   /* scan desc */
393                                         ScanDirectionIsBackward(direction), /* backward flag */
394                                         skeys);         /* scan keys */
395
396         return scanDesc;
397 }
398
399 /* ----------------------------------------------------------------
400  *              ExecMarkPos
401  *
402  *              Marks the current scan position.
403  *
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  * ----------------------------------------------------------------
407  */
408 void
409 ExecMarkPos(Plan *node)
410 {
411         switch (nodeTag(node))
412         {
413                 case T_SeqScan:
414                         ExecSeqMarkPos((SeqScan *) node);
415                         break;
416
417                 case T_IndexScan:
418                         ExecIndexMarkPos((IndexScan *) node);
419                         break;
420
421                 case T_Material:
422                         ExecMaterialMarkPos((Material *) node);
423                         break;
424
425                 case T_Sort:
426                         ExecSortMarkPos((Sort *) node);
427                         break;
428
429                 case T_TidScan:
430                         ExecTidMarkPos((TidScan *) node);
431                         break;
432
433                 default:
434                         /* don't make hard error unless caller asks to restore... */
435                         elog(DEBUG, "ExecMarkPos: node type %d not supported",
436                                  nodeTag(node));
437                         break;
438         }
439 }
440
441 /* ----------------------------------------------------------------
442  *              ExecRestrPos
443  *
444  *              restores the scan position previously saved with ExecMarkPos()
445  *
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  * ----------------------------------------------------------------
449  */
450 void
451 ExecRestrPos(Plan *node)
452 {
453         switch (nodeTag(node))
454         {
455                 case T_SeqScan:
456                         ExecSeqRestrPos((SeqScan *) node);
457                         break;
458
459                 case T_IndexScan:
460                         ExecIndexRestrPos((IndexScan *) node);
461                         break;
462
463                 case T_Material:
464                         ExecMaterialRestrPos((Material *) node);
465                         break;
466
467                 case T_Sort:
468                         ExecSortRestrPos((Sort *) node);
469                         break;
470
471                 default:
472                         elog(ERROR, "ExecRestrPos: node type %d not supported",
473                                  nodeTag(node));
474                         break;
475         }
476 }