]> granicus.if.org Git - postgresql/blob - src/backend/executor/execScan.c
Update copyright to 2002.
[postgresql] / src / backend / executor / execScan.c
1 /*-------------------------------------------------------------------------
2  *
3  * execScan.c
4  *        This code provides support for generalized relation scans. ExecScan
5  *        is passed a node and a pointer to a function to "do the right thing"
6  *        and return a tuple from the relation. ExecScan then does the tedious
7  *        stuff - checking the qualification and projecting the tuple
8  *        appropriately.
9  *
10  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
11  * Portions Copyright (c) 1994, Regents of the University of California
12  *
13  *
14  * IDENTIFICATION
15  *        $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.20 2002/06/20 20:29:27 momjian Exp $
16  *
17  *-------------------------------------------------------------------------
18  */
19 #include "postgres.h"
20
21 #include <sys/types.h>
22 #include <sys/file.h>
23
24 #include "executor/executor.h"
25 #include "miscadmin.h"
26 #include "utils/memutils.h"
27
28
29 /* ----------------------------------------------------------------
30  *              ExecScan
31  *
32  *              Scans the relation using the 'access method' indicated and
33  *              returns the next qualifying tuple in the direction specified
34  *              in the global variable ExecDirection.
35  *              The access method returns the next tuple and execScan() is
36  *              responsible for checking the tuple returned against the qual-clause.
37  *
38  *              Conditions:
39  *                -- the "cursor" maintained by the AMI is positioned at the tuple
40  *                       returned previously.
41  *
42  *              Initial States:
43  *                -- the relation indicated is opened for scanning so that the
44  *                       "cursor" is positioned before the first qualifying tuple.
45  * ----------------------------------------------------------------
46  */
47 TupleTableSlot *
48 ExecScan(Scan *node,
49                  ExecScanAccessMtd accessMtd)   /* function returning a tuple */
50 {
51         CommonScanState *scanstate;
52         EState     *estate;
53         ExprContext *econtext;
54         List       *qual;
55         ExprDoneCond isDone;
56         TupleTableSlot *resultSlot;
57
58         /*
59          * Fetch data from node
60          */
61         estate = node->plan.state;
62         scanstate = node->scanstate;
63         econtext = scanstate->cstate.cs_ExprContext;
64         qual = node->plan.qual;
65
66         /*
67          * Check to see if we're still projecting out tuples from a previous
68          * scan tuple (because there is a function-returning-set in the
69          * projection expressions).  If so, try to project another one.
70          */
71         if (scanstate->cstate.cs_TupFromTlist)
72         {
73                 resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
74                 if (isDone == ExprMultipleResult)
75                         return resultSlot;
76                 /* Done with that source tuple... */
77                 scanstate->cstate.cs_TupFromTlist = false;
78         }
79
80         /*
81          * Reset per-tuple memory context to free any expression evaluation
82          * storage allocated in the previous tuple cycle.  Note this can't
83          * happen until we're done projecting out tuples from a scan tuple.
84          */
85         ResetExprContext(econtext);
86
87         /*
88          * get a tuple from the access method loop until we obtain a tuple
89          * which passes the qualification.
90          */
91         for (;;)
92         {
93                 TupleTableSlot *slot;
94
95                 CHECK_FOR_INTERRUPTS();
96
97                 slot = (*accessMtd) (node);
98
99                 /*
100                  * if the slot returned by the accessMtd contains NULL, then it
101                  * means there is nothing more to scan so we just return an empty
102                  * slot, being careful to use the projection result slot so it has
103                  * correct tupleDesc.
104                  */
105                 if (TupIsNull(slot))
106                 {
107                         return ExecStoreTuple(NULL,
108                                                                   scanstate->cstate.cs_ProjInfo->pi_slot,
109                                                                   InvalidBuffer,
110                                                                   true);
111                 }
112
113                 /*
114                  * place the current tuple into the expr context
115                  */
116                 econtext->ecxt_scantuple = slot;
117
118                 /*
119                  * check that the current tuple satisfies the qual-clause
120                  *
121                  * check for non-nil qual here to avoid a function call to ExecQual()
122                  * when the qual is nil ... saves only a few cycles, but they add
123                  * up ...
124                  */
125                 if (!qual || ExecQual(qual, econtext, false))
126                 {
127                         /*
128                          * Found a satisfactory scan tuple.
129                          *
130                          * Form a projection tuple, store it in the result tuple slot and
131                          * return it --- unless we find we can project no tuples from
132                          * this scan tuple, in which case continue scan.
133                          */
134                         resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
135                         if (isDone != ExprEndResult)
136                         {
137                                 scanstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult);
138                                 return resultSlot;
139                         }
140                 }
141
142                 /*
143                  * Tuple fails qual, so free per-tuple memory and try again.
144                  */
145                 ResetExprContext(econtext);
146         }
147 }