]> granicus.if.org Git - postgresql/blob - src/backend/executor/execScan.c
pgindent run. Make it all clean.
[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-2001, 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.16 2001/03/22 03:59:26 momjian Exp $
16  *
17  *-------------------------------------------------------------------------
18  */
19
20 #include <sys/types.h>
21 #include <sys/file.h>
22
23 #include "postgres.h"
24
25 #include "executor/executor.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          */
62         estate = node->plan.state;
63         scanstate = node->scanstate;
64         econtext = scanstate->cstate.cs_ExprContext;
65         qual = node->plan.qual;
66
67         /* ----------------
68          *      Check to see if we're still projecting out tuples from a previous
69          *      scan tuple (because there is a function-returning-set in the
70          *      projection expressions).  If so, try to project another one.
71          * ----------------
72          */
73         if (scanstate->cstate.cs_TupFromTlist)
74         {
75                 resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
76                 if (isDone == ExprMultipleResult)
77                         return resultSlot;
78                 /* Done with that source tuple... */
79                 scanstate->cstate.cs_TupFromTlist = false;
80         }
81
82         /* ----------------
83          *      Reset per-tuple memory context to free any expression evaluation
84          *      storage allocated in the previous tuple cycle.  Note this can't
85          *      happen until we're done projecting out tuples from a scan tuple.
86          * ----------------
87          */
88         ResetExprContext(econtext);
89
90         /*
91          * get a tuple from the access method loop until we obtain a tuple
92          * which passes the qualification.
93          */
94         for (;;)
95         {
96                 TupleTableSlot *slot;
97
98                 slot = (*accessMtd) (node);
99
100                 /* ----------------
101                  *      if the slot returned by the accessMtd contains
102                  *      NULL, then it means there is nothing more to scan
103                  *      so we just return an empty slot, being careful to use
104                  *      the projection result slot so it has correct tupleDesc.
105                  * ----------------
106                  */
107                 if (TupIsNull(slot))
108                 {
109                         return ExecStoreTuple(NULL,
110                                                                   scanstate->cstate.cs_ProjInfo->pi_slot,
111                                                                   InvalidBuffer,
112                                                                   true);
113                 }
114
115                 /* ----------------
116                  *       place the current tuple into the expr context
117                  * ----------------
118                  */
119                 econtext->ecxt_scantuple = slot;
120
121                 /* ----------------
122                  *      check that the current tuple satisfies the qual-clause
123                  *
124                  * check for non-nil qual here to avoid a function call to
125                  * ExecQual() when the qual is nil ... saves only a few cycles,
126                  * but they add up ...
127                  * ----------------
128                  */
129                 if (!qual || ExecQual(qual, econtext, false))
130                 {
131                         /* ----------------
132                          *      Found a satisfactory scan tuple.
133                          *
134                          *      Form a projection tuple, store it in the result tuple
135                          *      slot and return it --- unless we find we can project no
136                          *      tuples from this scan tuple, in which case continue scan.
137                          * ----------------
138                          */
139                         resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
140                         if (isDone != ExprEndResult)
141                         {
142                                 scanstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult);
143                                 return resultSlot;
144                         }
145                 }
146
147                 /* ----------------
148                  *      Tuple fails qual, so free per-tuple memory and try again.
149                  * ----------------
150                  */
151                 ResetExprContext(econtext);
152         }
153 }