OSDN Git Service

83d0c3b6cad75c347c8004475d42949f5a980345
[pg-rex/syncrep.git] / src / backend / executor / execAmi.c
1 /*-------------------------------------------------------------------------
2  *
3  * execAmi.c
4  *        miscellanious executor access method routines
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *  $Id: execAmi.c,v 1.33 1999/03/23 16:50:47 momjian Exp $
9  *
10  *-------------------------------------------------------------------------
11  */
12 /*
13  *       INTERFACE ROUTINES
14  *
15  *              ExecOpenScanR   \                                                         / amopen
16  *              ExecBeginScan    \                                                       /      ambeginscan
17  *              ExecCloseR                \                                                     /       amclose
18  *              ExecInsert                 \  executor interface   /    aminsert
19  *              ExecReScanNode     /  to access methods    \    amrescan
20  *              ExecReScanR               /                                                     \       amrescan
21  *              ExecMarkPos              /                                                       \      ammarkpos
22  *              ExecRestrPos    /                                                         \ amrestpos
23  *
24  *              ExecCreatR              function to create temporary relations
25  *
26  */
27 #include <stdio.h>                      
28
29 #include "postgres.h"
30
31 #include "executor/executor.h"
32 #include "storage/smgr.h"
33 #include "utils/mcxt.h"
34 #include "executor/nodeSeqscan.h"
35 #include "executor/nodeIndexscan.h"
36 #include "executor/nodeSort.h"
37 #include "executor/nodeMaterial.h"
38 #include "executor/nodeNestloop.h"
39 #include "executor/nodeHashjoin.h"
40 #include "executor/nodeHash.h"
41 /***S*I***/
42 #include "executor/nodeGroup.h"
43
44 #include "executor/nodeAgg.h"
45 #include "executor/nodeGroup.h"
46 #include "executor/nodeResult.h"
47 #include "executor/nodeUnique.h"
48 #include "executor/nodeMergejoin.h"
49 #include "executor/nodeAppend.h"
50 #include "executor/nodeSubplan.h"
51 #include "executor/execdebug.h"
52 #include "optimizer/internal.h" /* for _NONAME_RELATION_ID_ */
53 #include "access/genam.h"
54 #include "access/heapam.h"
55 #include "catalog/heap.h"
56
57 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
58                           bool isindex, ScanDirection dir, Snapshot snapshot);
59 static Relation ExecOpenR(Oid relationOid, bool isindex);
60
61 /* ----------------------------------------------------------------
62  *              ExecOpenScanR
63  *
64  * old comments:
65  *              Parameters:
66  *                relation -- relation to be opened and scanned.
67  *                nkeys    -- number of keys
68  *                skeys    -- keys to restrict scanning
69  *                       isindex  -- if this is true, the relation is the relid of
70  *                                               an index relation, else it is an index into the
71  *                                               range table.
72  *              Returns the relation as(relDesc scanDesc)
73  *                 If this structure is changed, need to modify the access macros
74  *              defined in execInt.h.
75  * ----------------------------------------------------------------
76  */
77 void
78 ExecOpenScanR(Oid relOid,
79                           int nkeys,
80                           ScanKey skeys,
81                           bool isindex,
82                           ScanDirection dir,
83                           Snapshot snapshot,
84                           Relation *returnRelation, /* return */
85                           Pointer *returnScanDesc)      /* return */
86 {
87         Relation        relation;
88         Pointer         scanDesc;
89
90         /* ----------------
91          *      note: scanDesc returned by ExecBeginScan can be either
92          *                a HeapScanDesc or an IndexScanDesc so for now we
93          *                make it a Pointer.  There should be a better scan
94          *                abstraction someday -cim 9/9/89
95          * ----------------
96          */
97         relation = ExecOpenR(relOid, isindex);
98         scanDesc = ExecBeginScan(relation,
99                                                          nkeys,
100                                                          skeys,
101                                                          isindex,
102                                                          dir,
103                                                          snapshot);
104
105         if (returnRelation != NULL)
106                 *returnRelation = relation;
107         if (scanDesc != NULL)
108                 *returnScanDesc = scanDesc;
109 }
110
111 /* ----------------------------------------------------------------
112  *              ExecOpenR
113  *
114  *              returns a relation descriptor given an object id.
115  * ----------------------------------------------------------------
116  */
117 static Relation
118 ExecOpenR(Oid relationOid, bool isindex)
119 {
120         Relation        relation;
121
122         relation = (Relation) NULL;
123
124         /* ----------------
125          *      open the relation with the correct call depending
126          *      on whether this is a heap relation or an index relation.
127          * ----------------
128          */
129         if (isindex)
130                 relation = index_open(relationOid);
131         else
132                 relation = heap_open(relationOid);
133
134         if (relation == NULL)
135                 elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");
136
137         return relation;
138 }
139
140 /* ----------------------------------------------------------------
141  *              ExecBeginScan
142  *
143  *              beginscans a relation in current direction.
144  *
145  *              XXX fix parameters to AMbeginscan (and btbeginscan)
146  *                              currently we need to pass a flag stating whether
147  *                              or not the scan should begin at an endpoint of
148  *                              the relation.. Right now we always pass false
149  *                              -cim 9/14/89
150  * ----------------------------------------------------------------
151  */
152 static Pointer
153 ExecBeginScan(Relation relation,
154                           int nkeys,
155                           ScanKey skeys,
156                           bool isindex,
157                           ScanDirection dir,
158                           Snapshot snapshot)
159 {
160         Pointer         scanDesc;
161
162         scanDesc = NULL;
163
164         /* ----------------
165          *      open the appropriate type of scan.
166          *
167          *      Note: ambeginscan()'s second arg is a boolean indicating
168          *                that the scan should be done in reverse..  That is,
169          *                if you pass it true, then the scan is backward.
170          * ----------------
171          */
172         if (isindex)
173         {
174                 scanDesc = (Pointer) index_beginscan(relation,
175                                                                                          false,         /* see above comment */
176                                                                                          nkeys,
177                                                                                          skeys);
178         }
179         else
180         {
181                 scanDesc = (Pointer) heap_beginscan(relation,
182                                                                                         ScanDirectionIsBackward(dir),
183                                                                                         snapshot,
184                                                                                         nkeys,
185                                                                                         skeys);
186         }
187
188         if (scanDesc == NULL)
189                 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
190
191
192         return scanDesc;
193 }
194
195 /* ----------------------------------------------------------------
196  *              ExecCloseR
197  *
198  *              closes the relation and scan descriptor for a scan or sort
199  *              node.  Also closes index relations and scans for index scans.
200  *
201  * old comments
202  *              closes the relation indicated in 'relID'
203  * ----------------------------------------------------------------
204  */
205 void
206 ExecCloseR(Plan *node)
207 {
208         CommonScanState *state;
209         Relation        relation;
210         HeapScanDesc scanDesc;
211
212         /* ----------------
213          *      shut down the heap scan and close the heap relation
214          * ----------------
215          */
216         switch (nodeTag(node))
217         {
218
219                 case T_SeqScan:
220                         state = ((SeqScan *) node)->scanstate;
221                         break;
222
223                 case T_IndexScan:
224                         state = ((IndexScan *) node)->scan.scanstate;
225                         break;
226
227                 case T_Material:
228                         state = &(((Material *) node)->matstate->csstate);
229                         break;
230
231                 case T_Sort:
232                         state = &(((Sort *) node)->sortstate->csstate);
233                         break;
234
235                 case T_Agg:
236                         state = &(((Agg *) node)->aggstate->csstate);
237                         break;
238
239                 default:
240                         elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
241                         return;
242         }
243
244         relation = state->css_currentRelation;
245         scanDesc = state->css_currentScanDesc;
246
247         if (scanDesc != NULL)
248                 heap_endscan(scanDesc);
249
250         if (relation != NULL)
251                 heap_close(relation);
252
253         /* ----------------
254          *      if this is an index scan then we have to take care
255          *      of the index relations as well..
256          * ----------------
257          */
258         if (nodeTag(node) == T_IndexScan)
259         {
260                 IndexScan  *iscan = (IndexScan *) node;
261                 IndexScanState *indexstate;
262                 int                     numIndices;
263                 RelationPtr indexRelationDescs;
264                 IndexScanDescPtr indexScanDescs;
265                 int                     i;
266
267                 indexstate = iscan->indxstate;
268                 numIndices = indexstate->iss_NumIndices;
269                 indexRelationDescs = indexstate->iss_RelationDescs;
270                 indexScanDescs = indexstate->iss_ScanDescs;
271
272                 for (i = 0; i < numIndices; i++)
273                 {
274                         /* ----------------
275                          *      shut down each of the scans and
276                          *      close each of the index relations
277                          * ----------------
278                          */
279                         if (indexScanDescs[i] != NULL)
280                                 index_endscan(indexScanDescs[i]);
281
282                         if (indexRelationDescs[i] != NULL)
283                                 index_close(indexRelationDescs[i]);
284                 }
285         }
286 }
287
288 /* ----------------------------------------------------------------
289  *              ExecReScan
290  *
291  *              XXX this should be extended to cope with all the node types..
292  *
293  *              takes the new expression context as an argument, so that
294  *              index scans needn't have their scan keys updated separately
295  *              - marcel 09/20/94
296  * ----------------------------------------------------------------
297  */
298 void
299 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
300 {
301
302         if (node->chgParam != NULL) /* Wow! */
303         {
304                 List       *lst;
305
306                 foreach(lst, node->initPlan)
307                 {
308                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
309
310                         if (splan->extParam != NULL)            /* don't care about child
311                                                                                                  * locParam */
312                                 SetChangedParamList(splan, node->chgParam);
313                         if (splan->chgParam != NULL)
314                                 ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
315                 }
316                 foreach(lst, node->subPlan)
317                 {
318                         Plan       *splan = ((SubPlan *) lfirst(lst))->plan;
319
320                         if (splan->extParam != NULL)
321                                 SetChangedParamList(splan, node->chgParam);
322                 }
323                 /* Well. Now set chgParam for left/right trees. */
324                 if (node->lefttree != NULL)
325                         SetChangedParamList(node->lefttree, node->chgParam);
326                 if (node->righttree != NULL)
327                         SetChangedParamList(node->righttree, node->chgParam);
328         }
329
330         switch (nodeTag(node))
331         {
332                 case T_SeqScan:
333                         ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
334                         break;
335
336                 case T_IndexScan:
337                         ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
338                         break;
339
340                 case T_Material:
341                         ExecMaterialReScan((Material *) node, exprCtxt, parent);
342                         break;
343
344                 case T_NestLoop:
345                         ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
346                         break;
347
348                 case T_HashJoin:
349                         ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
350                         break;
351
352                 case T_Hash:
353                         ExecReScanHash((Hash *) node, exprCtxt, parent);
354                         break;
355
356                 case T_Agg:
357                         ExecReScanAgg((Agg *) node, exprCtxt, parent);
358                         break;
359
360                 case T_Group:
361                         ExecReScanGroup((Group *) node, exprCtxt, parent);
362                         break;
363
364                 case T_Result:
365                         ExecReScanResult((Result *) node, exprCtxt, parent);
366                         break;
367
368                 case T_Unique:
369                         ExecReScanUnique((Unique *) node, exprCtxt, parent);
370                         break;
371
372                 case T_Sort:
373                         ExecReScanSort((Sort *) node, exprCtxt, parent);
374                         break;
375
376                 case T_MergeJoin:
377                         ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
378                         break;
379
380                 case T_Append:
381                         ExecReScanAppend((Append *) node, exprCtxt, parent);
382                         break;
383
384                 default:
385                         elog(ERROR, "ExecReScan: node type %u not supported", nodeTag(node));
386                         return;
387         }
388
389         if (node->chgParam != NULL)
390         {
391                 freeList(node->chgParam);
392                 node->chgParam = NULL;
393         }
394 }
395
396 /* ----------------------------------------------------------------
397  *              ExecReScanR
398  *
399  *              XXX this does not do the right thing with indices yet.
400  * ----------------------------------------------------------------
401  */
402 HeapScanDesc
403 ExecReScanR(Relation relDesc,   /* LLL relDesc unused  */
404                         HeapScanDesc scanDesc,
405                         ScanDirection direction,
406                         int nkeys,                      /* LLL nkeys unused  */
407                         ScanKey skeys)
408 {
409         if (scanDesc != NULL)
410                 heap_rescan(scanDesc,   /* scan desc */
411                                         ScanDirectionIsBackward(direction), /* backward flag */
412                                         skeys);         /* scan keys */
413
414         return scanDesc;
415 }
416
417 /* ----------------------------------------------------------------
418  *              ExecMarkPos
419  *
420  *              Marks the current scan position.
421  *
422  *              XXX Needs to be extended to include all the node types.
423  * ----------------------------------------------------------------
424  */
425 void
426 ExecMarkPos(Plan *node)
427 {
428         switch (nodeTag(node))
429         {
430                         case T_SeqScan:
431                         ExecSeqMarkPos((SeqScan *) node);
432                         break;
433
434                 case T_IndexScan:
435                         ExecIndexMarkPos((IndexScan *) node);
436                         break;
437
438                 case T_Sort:
439                         ExecSortMarkPos((Sort *) 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=%d\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);
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 }