]> granicus.if.org Git - postgresql/blob - src/backend/executor/execAmi.c
Goodbye register keyword. Compiler knows better.
[postgresql] / 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  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.16 1998/01/16 23:19:47 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 /*
15  *       INTERFACE ROUTINES
16  *
17  *              ExecOpenScanR   \                                                         / amopen
18  *              ExecBeginScan    \                                                       /      ambeginscan
19  *              ExecCloseR                \                                                     /       amclose
20  *              ExecInsert                 \  executor interface   /    aminsert
21  *              ExecReScanNode     /  to access methods    \    amrescan
22  *              ExecReScanR               /                                                     \       amrescan
23  *              ExecMarkPos              /                                                       \      ammarkpos
24  *              ExecRestrPos    /                                                         \ amrestpos
25  *
26  *              ExecCreatR              function to create temporary relations
27  *
28  */
29 #include <stdio.h>                              /* for sprintf() */
30
31 #include "postgres.h"
32
33 #include "executor/executor.h"
34 #include "storage/smgr.h"
35 #include "utils/mcxt.h"
36 #include "executor/nodeSeqscan.h"
37 #include "executor/nodeIndexscan.h"
38 #include "executor/nodeSort.h"
39 #include "executor/nodeTee.h"
40 #include "executor/execdebug.h"
41 #include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */
42 #include "access/genam.h"
43 #include "access/heapam.h"
44 #include "catalog/heap.h"
45
46 static Pointer
47 ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
48                           bool isindex, ScanDirection dir);
49 static Relation ExecOpenR(Oid relationOid, bool isindex);
50
51 /* ----------------------------------------------------------------
52  *              ExecOpenScanR
53  *
54  * old comments:
55  *              Parameters:
56  *                relation -- relation to be opened and scanned.
57  *                nkeys    -- number of keys
58  *                skeys    -- keys to restrict scanning
59  *                       isindex  -- if this is true, the relation is the relid of
60  *                                               an index relation, else it is an index into the
61  *                                               range table.
62  *              Returns the relation as(relDesc scanDesc)
63  *                 If this structure is changed, need to modify the access macros
64  *              defined in execInt.h.
65  * ----------------------------------------------------------------
66  */
67 void
68 ExecOpenScanR(Oid relOid,
69                           int nkeys,
70                           ScanKey skeys,
71                           bool isindex,
72                           ScanDirection dir,
73                           Relation *returnRelation, /* return */
74                           Pointer *returnScanDesc)      /* return */
75 {
76         Relation        relation;
77         Pointer         scanDesc;
78
79         /* ----------------
80          *      note: scanDesc returned by ExecBeginScan can be either
81          *                a HeapScanDesc or an IndexScanDesc so for now we
82          *                make it a Pointer.  There should be a better scan
83          *                abstraction someday -cim 9/9/89
84          * ----------------
85          */
86         relation = ExecOpenR(relOid, isindex);
87         scanDesc = ExecBeginScan(relation,
88                                                          nkeys,
89                                                          skeys,
90                                                          isindex,
91                                                          dir);
92
93         if (returnRelation != NULL)
94                 *returnRelation = relation;
95         if (scanDesc != NULL)
96                 *returnScanDesc = scanDesc;
97 }
98
99 /* ----------------------------------------------------------------
100  *              ExecOpenR
101  *
102  *              returns a relation descriptor given an object id.
103  * ----------------------------------------------------------------
104  */
105 static Relation
106 ExecOpenR(Oid relationOid, bool isindex)
107 {
108         Relation        relation;
109
110         relation = (Relation) NULL;
111
112         /* ----------------
113          *      open the relation with the correct call depending
114          *      on whether this is a heap relation or an index relation.
115          * ----------------
116          */
117         if (isindex)
118         {
119                 relation = index_open(relationOid);
120         }
121         else
122                 relation = heap_open(relationOid);
123
124         if (relation == NULL)
125                 elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");
126
127         return relation;
128 }
129
130 /* ----------------------------------------------------------------
131  *              ExecBeginScan
132  *
133  *              beginscans a relation in current direction.
134  *
135  *              XXX fix parameters to AMbeginscan (and btbeginscan)
136  *                              currently we need to pass a flag stating whether
137  *                              or not the scan should begin at an endpoint of
138  *                              the relation.. Right now we always pass false
139  *                              -cim 9/14/89
140  * ----------------------------------------------------------------
141  */
142 static Pointer
143 ExecBeginScan(Relation relation,
144                           int nkeys,
145                           ScanKey skeys,
146                           bool isindex,
147                           ScanDirection dir)
148 {
149         Pointer         scanDesc;
150
151         scanDesc = NULL;
152
153         /* ----------------
154          *      open the appropriate type of scan.
155          *
156          *      Note: ambeginscan()'s second arg is a boolean indicating
157          *                that the scan should be done in reverse..  That is,
158          *                if you pass it true, then the scan is backward.
159          * ----------------
160          */
161         if (isindex)
162         {
163                 scanDesc = (Pointer) index_beginscan(relation,
164                                                                                          false,         /* see above comment */
165                                                                                          nkeys,
166                                                                                          skeys);
167         }
168         else
169         {
170                 scanDesc = (Pointer) heap_beginscan(relation,
171                                                                                         ScanDirectionIsBackward(dir),
172                                                                                         false,
173                                                                                         nkeys,
174                                                                                         skeys);
175         }
176
177         if (scanDesc == NULL)
178                 elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
179
180
181         return scanDesc;
182 }
183
184 /* ----------------------------------------------------------------
185  *              ExecCloseR
186  *
187  *              closes the relation and scan descriptor for a scan or sort
188  *              node.  Also closes index relations and scans for index scans.
189  *
190  * old comments
191  *              closes the relation indicated in 'relID'
192  * ----------------------------------------------------------------
193  */
194 void
195 ExecCloseR(Plan *node)
196 {
197         CommonScanState *state;
198         Relation        relation;
199         HeapScanDesc scanDesc;
200
201         /* ----------------
202          *      shut down the heap scan and close the heap relation
203          * ----------------
204          */
205         switch (nodeTag(node))
206         {
207
208                 case T_SeqScan:
209                         state = ((SeqScan *) node)->scanstate;
210                         break;
211
212                 case T_IndexScan:
213                         state = ((IndexScan *) node)->scan.scanstate;
214                         break;
215
216                 case T_Material:
217                         state = &(((Material *) node)->matstate->csstate);
218                         break;
219
220                 case T_Sort:
221                         state = &(((Sort *) node)->sortstate->csstate);
222                         break;
223
224                 case T_Agg:
225                         state = &(((Agg *) node)->aggstate->csstate);
226                         break;
227
228                 default:
229                         elog(DEBUG, "ExecCloseR: not a scan, material, or sort node!");
230                         return;
231         }
232
233         relation = state->css_currentRelation;
234         scanDesc = state->css_currentScanDesc;
235
236         if (scanDesc != NULL)
237                 heap_endscan(scanDesc);
238
239         if (relation != NULL)
240                 heap_close(relation);
241
242         /* ----------------
243          *      if this is an index scan then we have to take care
244          *      of the index relations as well..
245          * ----------------
246          */
247         if (nodeTag(node) == T_IndexScan)
248         {
249                 IndexScan  *iscan = (IndexScan *) node;
250                 IndexScanState *indexstate;
251                 int                     numIndices;
252                 RelationPtr indexRelationDescs;
253                 IndexScanDescPtr indexScanDescs;
254                 int                     i;
255
256                 indexstate = iscan->indxstate;
257                 numIndices = indexstate->iss_NumIndices;
258                 indexRelationDescs = indexstate->iss_RelationDescs;
259                 indexScanDescs = indexstate->iss_ScanDescs;
260
261                 for (i = 0; i < numIndices; i++)
262                 {
263                         /* ----------------
264                          *      shut down each of the scans and
265                          *      close each of the index relations
266                          * ----------------
267                          */
268                         if (indexScanDescs[i] != NULL)
269                                 index_endscan(indexScanDescs[i]);
270
271                         if (indexRelationDescs[i] != NULL)
272                                 index_close(indexRelationDescs[i]);
273                 }
274         }
275 }
276
277 /* ----------------------------------------------------------------
278  *              ExecReScan
279  *
280  *              XXX this should be extended to cope with all the node types..
281  *
282  *              takes the new expression context as an argument, so that
283  *              index scans needn't have their scan keys updated separately
284  *              - marcel 09/20/94
285  * ----------------------------------------------------------------
286  */
287 void
288 ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
289 {
290         switch (nodeTag(node))
291         {
292                         case T_SeqScan:
293                         ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
294                         return;
295
296                 case T_IndexScan:
297                         ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
298                         return;
299
300                 case T_Material:
301
302                         /*
303                          * the first call to ExecReScan should have no effect because
304                          * everything is initialized properly already.  the following
305                          * calls will be handled by ExecSeqReScan() because the nodes
306                          * below the Material node have already been materialized into
307                          * a temp relation.
308                          */
309                         return;
310
311                 case T_Tee:
312                         ExecTeeReScan((Tee *) node, exprCtxt, parent);
313                         break;
314
315                 default:
316                         elog(ERROR, "ExecReScan: not a seqscan or indexscan node.");
317                         return;
318         }
319 }
320
321 /* ----------------------------------------------------------------
322  *              ExecReScanR
323  *
324  *              XXX this does not do the right thing with indices yet.
325  * ----------------------------------------------------------------
326  */
327 HeapScanDesc
328 ExecReScanR(Relation relDesc,   /* LLL relDesc unused  */
329                         HeapScanDesc scanDesc,
330                         ScanDirection direction,
331                         int nkeys,                      /* LLL nkeys unused  */
332                         ScanKey skeys)
333 {
334         if (scanDesc != NULL)
335                 heap_rescan(scanDesc,   /* scan desc */
336                                         ScanDirectionIsBackward(direction), /* backward flag */
337                                         skeys);         /* scan keys */
338
339         return scanDesc;
340 }
341
342 /* ----------------------------------------------------------------
343  *              ExecMarkPos
344  *
345  *              Marks the current scan position.
346  *
347  *              XXX Needs to be extended to include all the node types.
348  * ----------------------------------------------------------------
349  */
350 void
351 ExecMarkPos(Plan *node)
352 {
353         switch (nodeTag(node))
354         {
355                         case T_SeqScan:
356                         ExecSeqMarkPos((SeqScan *) node);
357                         break;
358
359                 case T_IndexScan:
360                         ExecIndexMarkPos((IndexScan *) node);
361                         break;
362
363                 case T_Sort:
364                         ExecSortMarkPos((Sort *) node);
365                         break;
366
367                 default:
368                         /* elog(DEBUG, "ExecMarkPos: unsupported node type"); */
369                         break;
370         }
371         return;
372 }
373
374 /* ----------------------------------------------------------------
375  *              ExecRestrPos
376  *
377  *              restores the scan position previously saved with ExecMarkPos()
378  * ----------------------------------------------------------------
379  */
380 void
381 ExecRestrPos(Plan *node)
382 {
383         switch (nodeTag(node))
384         {
385                         case T_SeqScan:
386                         ExecSeqRestrPos((SeqScan *) node);
387                         return;
388
389                 case T_IndexScan:
390                         ExecIndexRestrPos((IndexScan *) node);
391                         return;
392
393                 case T_Sort:
394                         ExecSortRestrPos((Sort *) node);
395                         return;
396
397                 default:
398                         /* elog(DEBUG, "ExecRestrPos: node type not supported"); */
399                         return;
400         }
401 }
402
403 /* ----------------------------------------------------------------
404  *              ExecCreatR
405  *
406  * old comments
407  *              Creates a relation.
408  *
409  *              Parameters:
410  *                attrType      -- type information on the attributes.
411  *                accessMtd -- access methods used to access the created relation.
412  *                relation      -- optional. Either an index to the range table or
413  *                                         negative number indicating a temporary relation.
414  *                                         A temporary relation is assume if this field is absent.
415  * ----------------------------------------------------------------
416  */
417
418 Relation
419 ExecCreatR(TupleDesc tupType,
420                    Oid relationOid)
421 {
422         Relation        relDesc;
423
424         EU3_printf("ExecCreatR: %s type=%d oid=%d\n",
425                            "entering: ", tupType, relationOid);
426         CXT1_printf("ExecCreatR: context is %d\n", CurrentMemoryContext);
427
428         relDesc = NULL;
429
430         if (relationOid == _TEMP_RELATION_ID_)
431         {
432                 /* ----------------
433                  *       create a temporary relation
434                  *       (currently the planner always puts a _TEMP_RELATION_ID
435                  *       in the relation argument so we expect this to be the case although
436                  *       it's possible that someday we'll get the name from
437                  *       from the range table.. -cim 10/12/89)
438                  * ----------------
439                  */
440 /*
441                 sprintf(tempname, "temp_%d.%d", getpid(), tmpcnt++);
442                 EU1_printf("ExecCreatR: attempting to create %s\n", tempname);
443 */
444
445                 /*
446                  * heap_create creates a name if the argument to heap_create is
447                  * '\0 '
448                  */
449                 relDesc = heap_create("", tupType);
450         }
451         else
452         {
453                 /* ----------------
454                  *              use a relation from the range table
455                  * ----------------
456                  */
457                 elog(DEBUG, "ExecCreatR: %s",
458                          "stuff using range table id's is not functional");
459         }
460
461         if (relDesc == NULL)
462                 elog(DEBUG, "ExecCreatR: failed to create relation.");
463
464         EU1_printf("ExecCreatR: returning relDesc=%d\n", relDesc);
465
466         return relDesc;
467 }