Add support for user-defined I/O conversion casts.
[PostgreSQL.git] / src / backend / executor / nodeSeqscan.c
blobbcbcbdc4578f832fbca93864d123c483eb41ef6c
1 /*-------------------------------------------------------------------------
3 * nodeSeqscan.c
4 * Support routines for sequential scans of relations.
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
16 * INTERFACE ROUTINES
17 * ExecSeqScan sequentially scans a relation.
18 * ExecSeqNext retrieve next tuple in sequential order.
19 * ExecInitSeqScan creates and initializes a seqscan node.
20 * ExecEndSeqScan releases any storage allocated.
21 * ExecSeqReScan rescans the relation
22 * ExecSeqMarkPos marks scan position
23 * ExecSeqRestrPos restores scan position
25 #include "postgres.h"
27 #include "access/heapam.h"
28 #include "access/relscan.h"
29 #include "executor/execdebug.h"
30 #include "executor/nodeSeqscan.h"
32 static void InitScanRelation(SeqScanState *node, EState *estate);
33 static TupleTableSlot *SeqNext(SeqScanState *node);
35 /* ----------------------------------------------------------------
36 * Scan Support
37 * ----------------------------------------------------------------
39 /* ----------------------------------------------------------------
40 * SeqNext
42 * This is a workhorse for ExecSeqScan
43 * ----------------------------------------------------------------
45 static TupleTableSlot *
46 SeqNext(SeqScanState *node)
48 HeapTuple tuple;
49 HeapScanDesc scandesc;
50 Index scanrelid;
51 EState *estate;
52 ScanDirection direction;
53 TupleTableSlot *slot;
56 * get information from the estate and scan state
58 estate = node->ps.state;
59 scandesc = node->ss_currentScanDesc;
60 scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
61 direction = estate->es_direction;
62 slot = node->ss_ScanTupleSlot;
65 * Check if we are evaluating PlanQual for tuple of this relation.
66 * Additional checking is not good, but no other way for now. We could
67 * introduce new nodes for this case and handle SeqScan --> NewNode
68 * switching in Init/ReScan plan...
70 if (estate->es_evTuple != NULL &&
71 estate->es_evTuple[scanrelid - 1] != NULL)
73 if (estate->es_evTupleNull[scanrelid - 1])
74 return ExecClearTuple(slot);
76 ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
77 slot, InvalidBuffer, false);
80 * Note that unlike IndexScan, SeqScan never use keys in
81 * heap_beginscan (and this is very bad) - so, here we do not check
82 * are keys ok or not.
85 /* Flag for the next call that no more tuples */
86 estate->es_evTupleNull[scanrelid - 1] = true;
87 return slot;
91 * get the next tuple from the access methods
93 tuple = heap_getnext(scandesc, direction);
96 * save the tuple and the buffer returned to us by the access methods in
97 * our scan tuple slot and return the slot. Note: we pass 'false' because
98 * tuples returned by heap_getnext() are pointers onto disk pages and were
99 * not created with palloc() and so should not be pfree()'d. Note also
100 * that ExecStoreTuple will increment the refcount of the buffer; the
101 * refcount will not be dropped until the tuple table slot is cleared.
103 if (tuple)
104 ExecStoreTuple(tuple, /* tuple to store */
105 slot, /* slot to store in */
106 scandesc->rs_cbuf, /* buffer associated with this
107 * tuple */
108 false); /* don't pfree this pointer */
109 else
110 ExecClearTuple(slot);
112 return slot;
115 /* ----------------------------------------------------------------
116 * ExecSeqScan(node)
118 * Scans the relation sequentially and returns the next qualifying
119 * tuple.
120 * It calls the ExecScan() routine and passes it the access method
121 * which retrieve tuples sequentially.
125 TupleTableSlot *
126 ExecSeqScan(SeqScanState *node)
129 * use SeqNext as access method
131 return ExecScan((ScanState *) node, (ExecScanAccessMtd) SeqNext);
134 /* ----------------------------------------------------------------
135 * InitScanRelation
137 * This does the initialization for scan relations and
138 * subplans of scans.
139 * ----------------------------------------------------------------
141 static void
142 InitScanRelation(SeqScanState *node, EState *estate)
144 Relation currentRelation;
145 HeapScanDesc currentScanDesc;
148 * get the relation object id from the relid'th entry in the range table,
149 * open that relation and acquire appropriate lock on it.
151 currentRelation = ExecOpenScanRelation(estate,
152 ((SeqScan *) node->ps.plan)->scanrelid);
154 currentScanDesc = heap_beginscan(currentRelation,
155 estate->es_snapshot,
157 NULL);
159 node->ss_currentRelation = currentRelation;
160 node->ss_currentScanDesc = currentScanDesc;
162 ExecAssignScanType(node, RelationGetDescr(currentRelation));
166 /* ----------------------------------------------------------------
167 * ExecInitSeqScan
168 * ----------------------------------------------------------------
170 SeqScanState *
171 ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
173 SeqScanState *scanstate;
176 * Once upon a time it was possible to have an outerPlan of a SeqScan, but
177 * not any more.
179 Assert(outerPlan(node) == NULL);
180 Assert(innerPlan(node) == NULL);
183 * create state structure
185 scanstate = makeNode(SeqScanState);
186 scanstate->ps.plan = (Plan *) node;
187 scanstate->ps.state = estate;
190 * Miscellaneous initialization
192 * create expression context for node
194 ExecAssignExprContext(estate, &scanstate->ps);
197 * initialize child expressions
199 scanstate->ps.targetlist = (List *)
200 ExecInitExpr((Expr *) node->plan.targetlist,
201 (PlanState *) scanstate);
202 scanstate->ps.qual = (List *)
203 ExecInitExpr((Expr *) node->plan.qual,
204 (PlanState *) scanstate);
206 #define SEQSCAN_NSLOTS 2
209 * tuple table initialization
211 ExecInitResultTupleSlot(estate, &scanstate->ps);
212 ExecInitScanTupleSlot(estate, scanstate);
215 * initialize scan relation
217 InitScanRelation(scanstate, estate);
219 scanstate->ps.ps_TupFromTlist = false;
222 * Initialize result tuple type and projection info.
224 ExecAssignResultTypeFromTL(&scanstate->ps);
225 ExecAssignScanProjectionInfo(scanstate);
227 return scanstate;
231 ExecCountSlotsSeqScan(SeqScan *node)
233 return ExecCountSlotsNode(outerPlan(node)) +
234 ExecCountSlotsNode(innerPlan(node)) +
235 SEQSCAN_NSLOTS;
238 /* ----------------------------------------------------------------
239 * ExecEndSeqScan
241 * frees any storage allocated through C routines.
242 * ----------------------------------------------------------------
244 void
245 ExecEndSeqScan(SeqScanState *node)
247 Relation relation;
248 HeapScanDesc scanDesc;
251 * get information from node
253 relation = node->ss_currentRelation;
254 scanDesc = node->ss_currentScanDesc;
257 * Free the exprcontext
259 ExecFreeExprContext(&node->ps);
262 * clean out the tuple table
264 ExecClearTuple(node->ps.ps_ResultTupleSlot);
265 ExecClearTuple(node->ss_ScanTupleSlot);
268 * close heap scan
270 heap_endscan(scanDesc);
273 * close the heap relation.
275 ExecCloseScanRelation(relation);
278 /* ----------------------------------------------------------------
279 * Join Support
280 * ----------------------------------------------------------------
283 /* ----------------------------------------------------------------
284 * ExecSeqReScan
286 * Rescans the relation.
287 * ----------------------------------------------------------------
289 void
290 ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt)
292 EState *estate;
293 Index scanrelid;
294 HeapScanDesc scan;
296 estate = node->ps.state;
297 scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
299 node->ps.ps_TupFromTlist = false;
301 /* If this is re-scanning of PlanQual ... */
302 if (estate->es_evTuple != NULL &&
303 estate->es_evTuple[scanrelid - 1] != NULL)
305 estate->es_evTupleNull[scanrelid - 1] = false;
306 return;
309 scan = node->ss_currentScanDesc;
311 heap_rescan(scan, /* scan desc */
312 NULL); /* new scan keys */
315 /* ----------------------------------------------------------------
316 * ExecSeqMarkPos(node)
318 * Marks scan position.
319 * ----------------------------------------------------------------
321 void
322 ExecSeqMarkPos(SeqScanState *node)
324 HeapScanDesc scan = node->ss_currentScanDesc;
326 heap_markpos(scan);
329 /* ----------------------------------------------------------------
330 * ExecSeqRestrPos
332 * Restores scan position.
333 * ----------------------------------------------------------------
335 void
336 ExecSeqRestrPos(SeqScanState *node)
338 HeapScanDesc scan = node->ss_currentScanDesc;
341 * Clear any reference to the previously returned tuple. This is needed
342 * because the slot is simply pointing at scan->rs_cbuf, which
343 * heap_restrpos will change; we'd have an internally inconsistent slot if
344 * we didn't do this.
346 ExecClearTuple(node->ss_ScanTupleSlot);
348 heap_restrpos(scan);