OSDN Git Service

Final #include cleanup.
[pg-rex/syncrep.git] / 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.47 2000/06/15 04:09:50 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  *              ExecReScanNode     /  to access methods    \    amrescan
21  *              ExecReScanR               /                                                     \       amrescan
22  *              ExecMarkPos              /                                                       \      ammarkpos
23  *              ExecRestrPos    /                                                         \ amrestpos
24  *
25  *              ExecCreatR              function to create temporary relations
26  *
27  */
28
29 #include "postgres.h"
30
31
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"
53
54 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
55                           bool isindex, ScanDirection dir, Snapshot snapshot);
56
57 /* ----------------------------------------------------------------
58  *              ExecOpenScanR
59  *
60  * old comments:
61  *              Parameters:
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
67  *                                               range table.
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  * ----------------------------------------------------------------
72  */
73 void
74 ExecOpenScanR(Oid relOid,
75                           int nkeys,
76                           ScanKey skeys,
77                           bool isindex,
78                           ScanDirection dir,
79                           Snapshot snapshot,
80                           Relation *returnRelation, /* return */
81                           Pointer *returnScanDesc)      /* return */
82 {
83         Relation        relation;
84         Pointer         scanDesc;
85
86         /* ----------------
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
91          * ----------------
92          */
93
94         /* ----------------
95          *      open the relation with the correct call depending
96          *      on whether this is a heap relation or an index relation.
97          *
98          *      Do not lock the rel here; beginscan will acquire AccessShareLock.
99          * ----------------
100          */
101         if (isindex)
102                 relation = index_open(relOid);
103         else
104                 relation = heap_open(relOid, NoLock);
105
106         if (relation == NULL)
107                 elog(ERROR, "ExecOpenScanR: failed to open relation %u", relOid);
108
109         scanDesc = ExecBeginScan(relation,
110                                                          nkeys,
111                                                          skeys,
112                                                          isindex,
113                                                          dir,
114                                                          snapshot);
115
116         if (returnRelation != NULL)
117                 *returnRelation = relation;
118         if (scanDesc != NULL)
119                 *returnScanDesc = scanDesc;
120 }
121
122 /* ----------------------------------------------------------------
123  *              ExecBeginScan
124  *
125  *              beginscans a relation in current direction.
126  *
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
131  *                              -cim 9/14/89
132  * ----------------------------------------------------------------
133  */
134 static Pointer
135 ExecBeginScan(Relation relation,
136                           int nkeys,
137                           ScanKey skeys,
138                           bool isindex,
139                           ScanDirection dir,
140                           Snapshot snapshot)
141 {
142         Pointer         scanDesc;
143
144         scanDesc = NULL;
145
146         /* ----------------
147          *      open the appropriate type of scan.
148          *
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.
152          * ----------------
153          */
154         if (isindex)
155         {
156                 scanDesc = (Pointer) index_beginscan(relation,
157                                                                                          false,         /* see above comment */
158                                                                                          nkeys,
159                                                                                          skeys);
160         }
161         else
162         {
163                 scanDesc = (Pointer) heap_beginscan(relation,
164                                                                                         ScanDirectionIsBackward(dir),
165                                                                                         snapshot,
166                                                                                         nkeys,
167                                                                                         skeys);
168         }
169
170         if (scanDesc == NULL)
171                 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
172
173
174         return scanDesc;
175 }
176
177 /* ----------------------------------------------------------------
178  *              ExecCloseR
179  *
180  *              closes the relation and scan descriptor for a scan or sort
181  *              node.  Also closes index relations and scans for index scans.
182  *
183  * old comments
184  *              closes the relation indicated in 'relID'
185  * ----------------------------------------------------------------
186  */
187 void
188 ExecCloseR(Plan *node)
189 {
190         CommonScanState *state;
191         Relation        relation;
192         HeapScanDesc scanDesc;
193
194         /* ----------------
195          *      shut down the heap scan and close the heap relation
196          * ----------------
197          */
198         switch (nodeTag(node))
199         {
200
201                 case T_SeqScan:
202                         state = ((SeqScan *) node)->scanstate;
203                         break;
204
205                 case T_IndexScan:
206                         state = ((IndexScan *) node)->scan.scanstate;
207                         break;
208
209                 case T_Material:
210                         state = &(((Material *) node)->matstate->csstate);
211                         break;
212
213                 case T_Sort:
214                         state = &(((Sort *) node)->sortstate->csstate);
215                         break;
216
217                 case T_Agg:
218                         state = &(((Agg *) node)->aggstate->csstate);
219                         break;
220
221                 case T_TidScan:
222                         state = ((TidScan *) node)->scan.scanstate;
223                         break;
224
225                 default:
226                         elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
227                         return;
228         }
229
230         relation = state->css_currentRelation;
231         scanDesc = state->css_currentScanDesc;
232
233         if (scanDesc != NULL)
234                 heap_endscan(scanDesc);
235
236         /*
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
240          * locks.
241          */
242         if (relation != NULL)
243                 heap_close(relation, NoLock);
244
245         /* ----------------
246          *      if this is an index scan then we have to take care
247          *      of the index relations as well..
248          * ----------------
249          */
250         if (IsA(node, IndexScan))
251         {
252                 IndexScan  *iscan = (IndexScan *) node;
253                 IndexScanState *indexstate;
254                 int                     numIndices;
255                 RelationPtr indexRelationDescs;
256                 IndexScanDescPtr indexScanDescs;
257                 int                     i;
258
259                 indexstate = iscan->indxstate;
260                 numIndices = indexstate->iss_NumIndices;
261                 indexRelationDescs = indexstate->iss_RelationDescs;
262                 indexScanDescs = indexstate->iss_ScanDescs;
263
264                 for (i = 0; i < numIndices; i++)
265                 {
266                         /* ----------------
267                          *      shut down each of the scans and
268                          *      close each of the index relations
269                          * ----------------
270                          */
271                         if (indexScanDescs[i] != NULL)
272                                 index_endscan(indexScanDescs[i]);
273
274                         if (indexRelationDescs[i] != NULL)
275                                 index_close(indexRelationDescs[i]);
276                 }
277         }
278 }
279
280 /* ----------------------------------------------------------------
281  *              ExecReScan
282  *
283  *              XXX this should be extended to cope with all the node types..
284  *
285  *              takes the new expression context as an argument, so that
286  *              index scans needn't have their scan keys updated separately
287  *              - marcel 09/20/94
288  * ----------------------------------------------------------------
289  */
290 void
291 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
292 {
293
294         if (node->chgParam != NULL) /* Wow! */
295         {
296                 List       *lst;
297
298                 foreach(lst, node->initPlan)
299                 {
300                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
301
302                         if (splan->extParam != NULL)            /* don't care about child
303                                                                                                  * locParam */
304                                 SetChangedParamList(splan, node->chgParam);
305                         if (splan->chgParam != NULL)
306                                 ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
307                 }
308                 foreach(lst, node->subPlan)
309                 {
310                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
311
312                         if (splan->extParam != NULL)
313                                 SetChangedParamList(splan, node->chgParam);
314                 }
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);
320         }
321
322         switch (nodeTag(node))
323         {
324                 case T_SeqScan:
325                         ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
326                         break;
327
328                 case T_IndexScan:
329                         ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
330                         break;
331
332                 case T_Material:
333                         ExecMaterialReScan((Material *) node, exprCtxt, parent);
334                         break;
335
336                 case T_NestLoop:
337                         ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
338                         break;
339
340                 case T_HashJoin:
341                         ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
342                         break;
343
344                 case T_Hash:
345                         ExecReScanHash((Hash *) node, exprCtxt, parent);
346                         break;
347
348                 case T_Agg:
349                         ExecReScanAgg((Agg *) node, exprCtxt, parent);
350                         break;
351
352                 case T_Group:
353                         ExecReScanGroup((Group *) node, exprCtxt, parent);
354                         break;
355
356                 case T_Result:
357                         ExecReScanResult((Result *) node, exprCtxt, parent);
358                         break;
359
360                 case T_Unique:
361                         ExecReScanUnique((Unique *) node, exprCtxt, parent);
362                         break;
363
364                 case T_Sort:
365                         ExecReScanSort((Sort *) node, exprCtxt, parent);
366                         break;
367
368                 case T_MergeJoin:
369                         ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
370                         break;
371
372                 case T_Append:
373                         ExecReScanAppend((Append *) node, exprCtxt, parent);
374                         break;
375
376                 case T_TidScan:
377                         ExecTidReScan((TidScan *) node, exprCtxt, parent);
378                         break;
379
380                 default:
381                         elog(ERROR, "ExecReScan: node type %u not supported", nodeTag(node));
382                         return;
383         }
384
385         if (node->chgParam != NULL)
386         {
387                 freeList(node->chgParam);
388                 node->chgParam = NULL;
389         }
390 }
391
392 /* ----------------------------------------------------------------
393  *              ExecReScanR
394  *
395  *              XXX this does not do the right thing with indices yet.
396  * ----------------------------------------------------------------
397  */
398 HeapScanDesc
399 ExecReScanR(Relation relDesc,   /* LLL relDesc unused  */
400                         HeapScanDesc scanDesc,
401                         ScanDirection direction,
402                         int nkeys,                      /* LLL nkeys unused  */
403                         ScanKey skeys)
404 {
405         if (scanDesc != NULL)
406                 heap_rescan(scanDesc,   /* scan desc */
407                                         ScanDirectionIsBackward(direction), /* backward flag */
408                                         skeys);         /* scan keys */
409
410         return scanDesc;
411 }
412
413 /* ----------------------------------------------------------------
414  *              ExecMarkPos
415  *
416  *              Marks the current scan position.
417  *
418  *              XXX Needs to be extended to include all the node types.
419  * ----------------------------------------------------------------
420  */
421 void
422 ExecMarkPos(Plan *node)
423 {
424         switch (nodeTag(node))
425         {
426                         case T_SeqScan:
427                         ExecSeqMarkPos((SeqScan *) node);
428                         break;
429
430                 case T_IndexScan:
431                         ExecIndexMarkPos((IndexScan *) node);
432                         break;
433
434                 case T_Sort:
435                         ExecSortMarkPos((Sort *) node);
436                         break;
437
438                 case T_TidScan:
439                         ExecTidMarkPos((TidScan *) node);
440                         break;
441
442                 default:
443                         elog(DEBUG, "ExecMarkPos: node type %u not supported", nodeTag(node));
444                         break;
445         }
446         return;
447 }
448
449 /* ----------------------------------------------------------------
450  *              ExecRestrPos
451  *
452  *              restores the scan position previously saved with ExecMarkPos()
453  * ----------------------------------------------------------------
454  */
455 void
456 ExecRestrPos(Plan *node)
457 {
458         switch (nodeTag(node))
459         {
460                         case T_SeqScan:
461                         ExecSeqRestrPos((SeqScan *) node);
462                         return;
463
464                 case T_IndexScan:
465                         ExecIndexRestrPos((IndexScan *) node);
466                         return;
467
468                 case T_Sort:
469                         ExecSortRestrPos((Sort *) node);
470                         return;
471
472                 default:
473                         elog(DEBUG, "ExecRestrPos: node type %u not supported", nodeTag(node));
474                         return;
475         }
476 }
477
478 /* ----------------------------------------------------------------
479  *              ExecCreatR
480  *
481  * old comments
482  *              Creates a relation.
483  *
484  *              Parameters:
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  * ----------------------------------------------------------------
491  */
492
493 Relation
494 ExecCreatR(TupleDesc tupType,
495                    Oid relationOid)
496 {
497         Relation        relDesc;
498
499         EU3_printf("ExecCreatR: %s type=%d oid=%u\n",
500                            "entering: ", tupType, relationOid);
501         CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext);
502
503         relDesc = NULL;
504
505         if (relationOid == _NONAME_RELATION_ID_)
506         {
507                 /* ----------------
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)
513                  * ----------------
514                  */
515
516                 /*
517                  * heap_create creates a name if the argument to heap_create is
518                  * '\0 '
519                  */
520                 relDesc = heap_create(NULL, tupType, true, false, true);
521         }
522         else
523         {
524                 /* ----------------
525                  *              use a relation from the range table
526                  * ----------------
527                  */
528                 elog(DEBUG, "ExecCreatR: %s",
529                          "stuff using range table id's is not functional");
530         }
531
532         if (relDesc == NULL)
533                 elog(DEBUG, "ExecCreatR: failed to create relation.");
534
535         EU1_printf("ExecCreatR: returning relDesc=%d\n", relDesc);
536
537         return relDesc;
538 }