~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * nodeValuesscan.c
 
4
 *        Support routines for scanning Values lists
 
5
 *        ("VALUES (...), (...), ..." in rangetable).
 
6
 *
 
7
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
8
 * Portions Copyright (c) 1994, Regents of the University of California
 
9
 *
 
10
 *
 
11
 * IDENTIFICATION
 
12
 *        src/backend/executor/nodeValuesscan.c
 
13
 *
 
14
 *-------------------------------------------------------------------------
 
15
 */
 
16
/*
 
17
 * INTERFACE ROUTINES
 
18
 *              ExecValuesScan                  scans a values list.
 
19
 *              ExecValuesNext                  retrieve next tuple in sequential order.
 
20
 *              ExecInitValuesScan              creates and initializes a valuesscan node.
 
21
 *              ExecEndValuesScan               releases any storage allocated.
 
22
 *              ExecReScanValuesScan    rescans the values list
 
23
 */
 
24
#include "postgres.h"
 
25
 
 
26
#include "executor/executor.h"
 
27
#include "executor/nodeValuesscan.h"
 
28
#include "utils/memutils.h"
 
29
 
 
30
 
 
31
static TupleTableSlot *ValuesNext(ValuesScanState *node);
 
32
 
 
33
 
 
34
/* ----------------------------------------------------------------
 
35
 *                                              Scan Support
 
36
 * ----------------------------------------------------------------
 
37
 */
 
38
 
 
39
/* ----------------------------------------------------------------
 
40
 *              ValuesNext
 
41
 *
 
42
 *              This is a workhorse for ExecValuesScan
 
43
 * ----------------------------------------------------------------
 
44
 */
 
45
static TupleTableSlot *
 
46
ValuesNext(ValuesScanState *node)
 
47
{
 
48
        TupleTableSlot *slot;
 
49
        EState     *estate;
 
50
        ExprContext *econtext;
 
51
        ScanDirection direction;
 
52
        List       *exprlist;
 
53
 
 
54
        /*
 
55
         * get information from the estate and scan state
 
56
         */
 
57
        estate = node->ss.ps.state;
 
58
        direction = estate->es_direction;
 
59
        slot = node->ss.ss_ScanTupleSlot;
 
60
        econtext = node->rowcontext;
 
61
 
 
62
        /*
 
63
         * Get the next tuple. Return NULL if no more tuples.
 
64
         */
 
65
        if (ScanDirectionIsForward(direction))
 
66
        {
 
67
                if (node->curr_idx < node->array_len)
 
68
                        node->curr_idx++;
 
69
                if (node->curr_idx < node->array_len)
 
70
                        exprlist = node->exprlists[node->curr_idx];
 
71
                else
 
72
                        exprlist = NIL;
 
73
        }
 
74
        else
 
75
        {
 
76
                if (node->curr_idx >= 0)
 
77
                        node->curr_idx--;
 
78
                if (node->curr_idx >= 0)
 
79
                        exprlist = node->exprlists[node->curr_idx];
 
80
                else
 
81
                        exprlist = NIL;
 
82
        }
 
83
 
 
84
        /*
 
85
         * Always clear the result slot; this is appropriate if we are at the end
 
86
         * of the data, and if we're not, we still need it as the first step of
 
87
         * the store-virtual-tuple protocol.  It seems wise to clear the slot
 
88
         * before we reset the context it might have pointers into.
 
89
         */
 
90
        ExecClearTuple(slot);
 
91
 
 
92
        if (exprlist)
 
93
        {
 
94
                MemoryContext oldContext;
 
95
                List       *exprstatelist;
 
96
                Datum      *values;
 
97
                bool       *isnull;
 
98
                ListCell   *lc;
 
99
                int                     resind;
 
100
 
 
101
                /*
 
102
                 * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
 
103
                 * not just ResetExprContext because we want any registered shutdown
 
104
                 * callbacks to be called.
 
105
                 */
 
106
                ReScanExprContext(econtext);
 
107
 
 
108
                /*
 
109
                 * Build the expression eval state in the econtext's per-tuple memory.
 
110
                 * This is a tad unusual, but we want to delete the eval state again
 
111
                 * when we move to the next row, to avoid growth of memory
 
112
                 * requirements over a long values list.
 
113
                 */
 
114
                oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
 
115
 
 
116
                /*
 
117
                 * Pass NULL, not my plan node, because we don't want anything in this
 
118
                 * transient state linking into permanent state.  The only possibility
 
119
                 * is a SubPlan, and there shouldn't be any (any subselects in the
 
120
                 * VALUES list should be InitPlans).
 
121
                 */
 
122
                exprstatelist = (List *) ExecInitExpr((Expr *) exprlist, NULL);
 
123
 
 
124
                /* parser should have checked all sublists are the same length */
 
125
                Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
 
126
 
 
127
                /*
 
128
                 * Compute the expressions and build a virtual result tuple. We
 
129
                 * already did ExecClearTuple(slot).
 
130
                 */
 
131
                values = slot->tts_values;
 
132
                isnull = slot->tts_isnull;
 
133
 
 
134
                resind = 0;
 
135
                foreach(lc, exprstatelist)
 
136
                {
 
137
                        ExprState  *estate = (ExprState *) lfirst(lc);
 
138
 
 
139
                        values[resind] = ExecEvalExpr(estate,
 
140
                                                                                  econtext,
 
141
                                                                                  &isnull[resind],
 
142
                                                                                  NULL);
 
143
                        resind++;
 
144
                }
 
145
 
 
146
                MemoryContextSwitchTo(oldContext);
 
147
 
 
148
                /*
 
149
                 * And return the virtual tuple.
 
150
                 */
 
151
                ExecStoreVirtualTuple(slot);
 
152
        }
 
153
 
 
154
        return slot;
 
155
}
 
156
 
 
157
/*
 
158
 * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
 
159
 */
 
160
static bool
 
161
ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
 
162
{
 
163
        /* nothing to check */
 
164
        return true;
 
165
}
 
166
 
 
167
/* ----------------------------------------------------------------
 
168
 *              ExecValuesScan(node)
 
169
 *
 
170
 *              Scans the values lists sequentially and returns the next qualifying
 
171
 *              tuple.
 
172
 *              We call the ExecScan() routine and pass it the appropriate
 
173
 *              access method functions.
 
174
 * ----------------------------------------------------------------
 
175
 */
 
176
TupleTableSlot *
 
177
ExecValuesScan(ValuesScanState *node)
 
178
{
 
179
        return ExecScan(&node->ss,
 
180
                                        (ExecScanAccessMtd) ValuesNext,
 
181
                                        (ExecScanRecheckMtd) ValuesRecheck);
 
182
}
 
183
 
 
184
/* ----------------------------------------------------------------
 
185
 *              ExecInitValuesScan
 
186
 * ----------------------------------------------------------------
 
187
 */
 
188
ValuesScanState *
 
189
ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 
190
{
 
191
        ValuesScanState *scanstate;
 
192
        TupleDesc       tupdesc;
 
193
        ListCell   *vtl;
 
194
        int                     i;
 
195
        PlanState  *planstate;
 
196
 
 
197
        /*
 
198
         * ValuesScan should not have any children.
 
199
         */
 
200
        Assert(outerPlan(node) == NULL);
 
201
        Assert(innerPlan(node) == NULL);
 
202
 
 
203
        /*
 
204
         * create new ScanState for node
 
205
         */
 
206
        scanstate = makeNode(ValuesScanState);
 
207
        scanstate->ss.ps.plan = (Plan *) node;
 
208
        scanstate->ss.ps.state = estate;
 
209
 
 
210
        /*
 
211
         * Miscellaneous initialization
 
212
         */
 
213
        planstate = &scanstate->ss.ps;
 
214
 
 
215
        /*
 
216
         * Create expression contexts.  We need two, one for per-sublist
 
217
         * processing and one for execScan.c to use for quals and projections. We
 
218
         * cheat a little by using ExecAssignExprContext() to build both.
 
219
         */
 
220
        ExecAssignExprContext(estate, planstate);
 
221
        scanstate->rowcontext = planstate->ps_ExprContext;
 
222
        ExecAssignExprContext(estate, planstate);
 
223
 
 
224
        /*
 
225
         * tuple table initialization
 
226
         */
 
227
        ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
 
228
        ExecInitScanTupleSlot(estate, &scanstate->ss);
 
229
 
 
230
        /*
 
231
         * initialize child expressions
 
232
         */
 
233
        scanstate->ss.ps.targetlist = (List *)
 
234
                ExecInitExpr((Expr *) node->scan.plan.targetlist,
 
235
                                         (PlanState *) scanstate);
 
236
        scanstate->ss.ps.qual = (List *)
 
237
                ExecInitExpr((Expr *) node->scan.plan.qual,
 
238
                                         (PlanState *) scanstate);
 
239
 
 
240
        /*
 
241
         * get info about values list
 
242
         */
 
243
        tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
 
244
 
 
245
        ExecAssignScanType(&scanstate->ss, tupdesc);
 
246
 
 
247
        /*
 
248
         * Other node-specific setup
 
249
         */
 
250
        scanstate->marked_idx = -1;
 
251
        scanstate->curr_idx = -1;
 
252
        scanstate->array_len = list_length(node->values_lists);
 
253
 
 
254
        /* convert list of sublists into array of sublists for easy addressing */
 
255
        scanstate->exprlists = (List **)
 
256
                palloc(scanstate->array_len * sizeof(List *));
 
257
        i = 0;
 
258
        foreach(vtl, node->values_lists)
 
259
        {
 
260
                scanstate->exprlists[i++] = (List *) lfirst(vtl);
 
261
        }
 
262
 
 
263
        scanstate->ss.ps.ps_TupFromTlist = false;
 
264
 
 
265
        /*
 
266
         * Initialize result tuple type and projection info.
 
267
         */
 
268
        ExecAssignResultTypeFromTL(&scanstate->ss.ps);
 
269
        ExecAssignScanProjectionInfo(&scanstate->ss);
 
270
 
 
271
        return scanstate;
 
272
}
 
273
 
 
274
/* ----------------------------------------------------------------
 
275
 *              ExecEndValuesScan
 
276
 *
 
277
 *              frees any storage allocated through C routines.
 
278
 * ----------------------------------------------------------------
 
279
 */
 
280
void
 
281
ExecEndValuesScan(ValuesScanState *node)
 
282
{
 
283
        /*
 
284
         * Free both exprcontexts
 
285
         */
 
286
        ExecFreeExprContext(&node->ss.ps);
 
287
        node->ss.ps.ps_ExprContext = node->rowcontext;
 
288
        ExecFreeExprContext(&node->ss.ps);
 
289
 
 
290
        /*
 
291
         * clean out the tuple table
 
292
         */
 
293
        ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
294
        ExecClearTuple(node->ss.ss_ScanTupleSlot);
 
295
}
 
296
 
 
297
/* ----------------------------------------------------------------
 
298
 *              ExecValuesMarkPos
 
299
 *
 
300
 *              Marks scan position.
 
301
 * ----------------------------------------------------------------
 
302
 */
 
303
void
 
304
ExecValuesMarkPos(ValuesScanState *node)
 
305
{
 
306
        node->marked_idx = node->curr_idx;
 
307
}
 
308
 
 
309
/* ----------------------------------------------------------------
 
310
 *              ExecValuesRestrPos
 
311
 *
 
312
 *              Restores scan position.
 
313
 * ----------------------------------------------------------------
 
314
 */
 
315
void
 
316
ExecValuesRestrPos(ValuesScanState *node)
 
317
{
 
318
        node->curr_idx = node->marked_idx;
 
319
}
 
320
 
 
321
/* ----------------------------------------------------------------
 
322
 *              ExecReScanValuesScan
 
323
 *
 
324
 *              Rescans the relation.
 
325
 * ----------------------------------------------------------------
 
326
 */
 
327
void
 
328
ExecReScanValuesScan(ValuesScanState *node)
 
329
{
 
330
        ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
331
 
 
332
        ExecScanReScan(&node->ss);
 
333
 
 
334
        node->curr_idx = -1;
 
335
}