~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/executor/nodeMaterial.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * nodeMaterial.c
 
4
 *        Routines to handle materialization nodes.
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.48 2004-12-31 21:59:45 pgsql Exp $
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
/*
 
16
 * INTERFACE ROUTINES
 
17
 *              ExecMaterial                    - materialize the result of a subplan
 
18
 *              ExecInitMaterial                - initialize node and subnodes
 
19
 *              ExecEndMaterial                 - shutdown node and subnodes
 
20
 *
 
21
 */
 
22
#include "postgres.h"
 
23
 
 
24
#include "access/heapam.h"
 
25
#include "executor/executor.h"
 
26
#include "executor/nodeMaterial.h"
 
27
#include "miscadmin.h"
 
28
#include "utils/tuplestore.h"
 
29
 
 
30
/* ----------------------------------------------------------------
 
31
 *              ExecMaterial
 
32
 *
 
33
 *              As long as we are at the end of the data collected in the tuplestore,
 
34
 *              we collect one new row from the subplan on each call, and stash it
 
35
 *              aside in the tuplestore before returning it.  The tuplestore is
 
36
 *              only read if we are asked to scan backwards, rescan, or mark/restore.
 
37
 *
 
38
 * ----------------------------------------------------------------
 
39
 */
 
40
TupleTableSlot *                                /* result tuple from subplan */
 
41
ExecMaterial(MaterialState *node)
 
42
{
 
43
        EState     *estate;
 
44
        ScanDirection dir;
 
45
        bool            forward;
 
46
        Tuplestorestate *tuplestorestate;
 
47
        HeapTuple       heapTuple = NULL;
 
48
        bool            should_free = false;
 
49
        bool            eof_tuplestore;
 
50
        TupleTableSlot *slot;
 
51
 
 
52
        /*
 
53
         * get state info from node
 
54
         */
 
55
        estate = node->ss.ps.state;
 
56
        dir = estate->es_direction;
 
57
        forward = ScanDirectionIsForward(dir);
 
58
        tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
 
59
 
 
60
        /*
 
61
         * If first time through, initialize the tuplestore.
 
62
         */
 
63
        if (tuplestorestate == NULL)
 
64
        {
 
65
                tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
 
66
 
 
67
                node->tuplestorestate = (void *) tuplestorestate;
 
68
        }
 
69
 
 
70
        /*
 
71
         * If we are not at the end of the tuplestore, or are going backwards,
 
72
         * try to fetch a tuple from tuplestore.
 
73
         */
 
74
        eof_tuplestore = tuplestore_ateof(tuplestorestate);
 
75
 
 
76
        if (!forward && eof_tuplestore)
 
77
        {
 
78
                if (!node->eof_underlying)
 
79
                {
 
80
                        /*
 
81
                         * When reversing direction at tuplestore EOF, the first
 
82
                         * getheaptuple call will fetch the last-added tuple; but we
 
83
                         * want to return the one before that, if possible. So do an
 
84
                         * extra fetch.
 
85
                         */
 
86
                        heapTuple = tuplestore_getheaptuple(tuplestorestate,
 
87
                                                                                                forward,
 
88
                                                                                                &should_free);
 
89
                        if (heapTuple == NULL)
 
90
                                return NULL;    /* the tuplestore must be empty */
 
91
                        if (should_free)
 
92
                                heap_freetuple(heapTuple);
 
93
                }
 
94
                eof_tuplestore = false;
 
95
        }
 
96
 
 
97
        if (!eof_tuplestore)
 
98
        {
 
99
                heapTuple = tuplestore_getheaptuple(tuplestorestate,
 
100
                                                                                        forward,
 
101
                                                                                        &should_free);
 
102
                if (heapTuple == NULL && forward)
 
103
                        eof_tuplestore = true;
 
104
        }
 
105
 
 
106
        /*
 
107
         * If necessary, try to fetch another row from the subplan.
 
108
         *
 
109
         * Note: the eof_underlying state variable exists to short-circuit
 
110
         * further subplan calls.  It's not optional, unfortunately, because
 
111
         * some plan node types are not robust about being called again when
 
112
         * they've already returned NULL.
 
113
         */
 
114
        if (eof_tuplestore && !node->eof_underlying)
 
115
        {
 
116
                PlanState  *outerNode;
 
117
                TupleTableSlot *outerslot;
 
118
 
 
119
                /*
 
120
                 * We can only get here with forward==true, so no need to worry
 
121
                 * about which direction the subplan will go.
 
122
                 */
 
123
                outerNode = outerPlanState(node);
 
124
                outerslot = ExecProcNode(outerNode);
 
125
                if (TupIsNull(outerslot))
 
126
                {
 
127
                        node->eof_underlying = true;
 
128
                        return NULL;
 
129
                }
 
130
                heapTuple = outerslot->val;
 
131
                should_free = false;
 
132
 
 
133
                /*
 
134
                 * Append returned tuple to tuplestore, too.  NOTE: because the
 
135
                 * tuplestore is certainly in EOF state, its read position will
 
136
                 * move forward over the added tuple.  This is what we want.
 
137
                 */
 
138
                tuplestore_puttuple(tuplestorestate, (void *) heapTuple);
 
139
        }
 
140
 
 
141
        /*
 
142
         * Return the obtained tuple.
 
143
         */
 
144
        slot = (TupleTableSlot *) node->ss.ps.ps_ResultTupleSlot;
 
145
        return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
 
146
}
 
147
 
 
148
/* ----------------------------------------------------------------
 
149
 *              ExecInitMaterial
 
150
 * ----------------------------------------------------------------
 
151
 */
 
152
MaterialState *
 
153
ExecInitMaterial(Material *node, EState *estate)
 
154
{
 
155
        MaterialState *matstate;
 
156
        Plan       *outerPlan;
 
157
 
 
158
        /*
 
159
         * create state structure
 
160
         */
 
161
        matstate = makeNode(MaterialState);
 
162
        matstate->ss.ps.plan = (Plan *) node;
 
163
        matstate->ss.ps.state = estate;
 
164
 
 
165
        matstate->tuplestorestate = NULL;
 
166
        matstate->eof_underlying = false;
 
167
 
 
168
        /*
 
169
         * Miscellaneous initialization
 
170
         *
 
171
         * Materialization nodes don't need ExprContexts because they never call
 
172
         * ExecQual or ExecProject.
 
173
         */
 
174
 
 
175
#define MATERIAL_NSLOTS 2
 
176
 
 
177
        /*
 
178
         * tuple table initialization
 
179
         *
 
180
         * material nodes only return tuples from their materialized relation.
 
181
         */
 
182
        ExecInitResultTupleSlot(estate, &matstate->ss.ps);
 
183
        ExecInitScanTupleSlot(estate, &matstate->ss);
 
184
 
 
185
        /*
 
186
         * initializes child nodes
 
187
         */
 
188
        outerPlan = outerPlan(node);
 
189
        outerPlanState(matstate) = ExecInitNode(outerPlan, estate);
 
190
 
 
191
        /*
 
192
         * initialize tuple type.  no need to initialize projection info
 
193
         * because this node doesn't do projections.
 
194
         */
 
195
        ExecAssignResultTypeFromOuterPlan(&matstate->ss.ps);
 
196
        ExecAssignScanTypeFromOuterPlan(&matstate->ss);
 
197
        matstate->ss.ps.ps_ProjInfo = NULL;
 
198
 
 
199
        return matstate;
 
200
}
 
201
 
 
202
int
 
203
ExecCountSlotsMaterial(Material *node)
 
204
{
 
205
        return ExecCountSlotsNode(outerPlan((Plan *) node)) +
 
206
                ExecCountSlotsNode(innerPlan((Plan *) node)) +
 
207
                MATERIAL_NSLOTS;
 
208
}
 
209
 
 
210
/* ----------------------------------------------------------------
 
211
 *              ExecEndMaterial
 
212
 * ----------------------------------------------------------------
 
213
 */
 
214
void
 
215
ExecEndMaterial(MaterialState *node)
 
216
{
 
217
        /*
 
218
         * clean out the tuple table
 
219
         */
 
220
        ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
221
 
 
222
        /*
 
223
         * Release tuplestore resources
 
224
         */
 
225
        if (node->tuplestorestate != NULL)
 
226
                tuplestore_end((Tuplestorestate *) node->tuplestorestate);
 
227
        node->tuplestorestate = NULL;
 
228
 
 
229
        /*
 
230
         * shut down the subplan
 
231
         */
 
232
        ExecEndNode(outerPlanState(node));
 
233
}
 
234
 
 
235
/* ----------------------------------------------------------------
 
236
 *              ExecMaterialMarkPos
 
237
 *
 
238
 *              Calls tuplestore to save the current position in the stored file.
 
239
 * ----------------------------------------------------------------
 
240
 */
 
241
void
 
242
ExecMaterialMarkPos(MaterialState *node)
 
243
{
 
244
        /*
 
245
         * if we haven't materialized yet, just return.
 
246
         */
 
247
        if (!node->tuplestorestate)
 
248
                return;
 
249
 
 
250
        tuplestore_markpos((Tuplestorestate *) node->tuplestorestate);
 
251
}
 
252
 
 
253
/* ----------------------------------------------------------------
 
254
 *              ExecMaterialRestrPos
 
255
 *
 
256
 *              Calls tuplestore to restore the last saved file position.
 
257
 * ----------------------------------------------------------------
 
258
 */
 
259
void
 
260
ExecMaterialRestrPos(MaterialState *node)
 
261
{
 
262
        /*
 
263
         * if we haven't materialized yet, just return.
 
264
         */
 
265
        if (!node->tuplestorestate)
 
266
                return;
 
267
 
 
268
        /*
 
269
         * restore the scan to the previously marked position
 
270
         */
 
271
        tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate);
 
272
}
 
273
 
 
274
/* ----------------------------------------------------------------
 
275
 *              ExecMaterialReScan
 
276
 *
 
277
 *              Rescans the materialized relation.
 
278
 * ----------------------------------------------------------------
 
279
 */
 
280
void
 
281
ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
 
282
{
 
283
        /*
 
284
         * If we haven't materialized yet, just return. If outerplan' chgParam
 
285
         * is not NULL then it will be re-scanned by ExecProcNode, else - no
 
286
         * reason to re-scan it at all.
 
287
         */
 
288
        if (!node->tuplestorestate)
 
289
                return;
 
290
 
 
291
        ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
292
 
 
293
        /*
 
294
         * If subnode is to be rescanned then we forget previous stored
 
295
         * results; we have to re-read the subplan and re-store.
 
296
         *
 
297
         * Otherwise we can just rewind and rescan the stored output. The state
 
298
         * of the subnode does not change.
 
299
         */
 
300
        if (((PlanState *) node)->lefttree->chgParam != NULL)
 
301
        {
 
302
                tuplestore_end((Tuplestorestate *) node->tuplestorestate);
 
303
                node->tuplestorestate = NULL;
 
304
                node->eof_underlying = false;
 
305
        }
 
306
        else
 
307
                tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
 
308
}