OSDN Git Service

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