~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/executor/nodeSubqueryscan.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
 * nodeSubqueryscan.c
 
4
 *        Support routines for scanning subqueries (subselects in rangetable).
 
5
 *
 
6
 * This is just enough different from sublinks (nodeSubplan.c) to mean that
 
7
 * we need two sets of code.  Ought to look at trying to unify the cases.
 
8
 *
 
9
 *
 
10
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
11
 * Portions Copyright (c) 1994, Regents of the University of California
 
12
 *
 
13
 *
 
14
 * IDENTIFICATION
 
15
 *        $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.25 2004-12-31 21:59:45 pgsql Exp $
 
16
 *
 
17
 *-------------------------------------------------------------------------
 
18
 */
 
19
/*
 
20
 * INTERFACE ROUTINES
 
21
 *              ExecSubqueryScan                        scans a subquery.
 
22
 *              ExecSubqueryNext                        retrieve next tuple in sequential order.
 
23
 *              ExecInitSubqueryScan            creates and initializes a subqueryscan node.
 
24
 *              ExecEndSubqueryScan                     releases any storage allocated.
 
25
 *              ExecSubqueryReScan                      rescans the relation
 
26
 *
 
27
 */
 
28
#include "postgres.h"
 
29
 
 
30
#include "catalog/pg_type.h"
 
31
#include "executor/execdebug.h"
 
32
#include "executor/execdefs.h"
 
33
#include "executor/execdesc.h"
 
34
#include "executor/nodeSubqueryscan.h"
 
35
#include "parser/parsetree.h"
 
36
#include "tcop/pquery.h"
 
37
 
 
38
static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
 
39
 
 
40
/* ----------------------------------------------------------------
 
41
 *                                              Scan Support
 
42
 * ----------------------------------------------------------------
 
43
 */
 
44
/* ----------------------------------------------------------------
 
45
 *              SubqueryNext
 
46
 *
 
47
 *              This is a workhorse for ExecSubqueryScan
 
48
 * ----------------------------------------------------------------
 
49
 */
 
50
static TupleTableSlot *
 
51
SubqueryNext(SubqueryScanState *node)
 
52
{
 
53
        EState     *estate;
 
54
        ScanDirection direction;
 
55
        TupleTableSlot *slot;
 
56
        MemoryContext oldcontext;
 
57
 
 
58
        /*
 
59
         * get information from the estate and scan state
 
60
         */
 
61
        estate = node->ss.ps.state;
 
62
        direction = estate->es_direction;
 
63
 
 
64
        /*
 
65
         * We need not support EvalPlanQual here, since we are not scanning a
 
66
         * real relation.
 
67
         */
 
68
 
 
69
        /*
 
70
         * Get the next tuple from the sub-query.  We have to be careful to
 
71
         * run it in its appropriate memory context.
 
72
         */
 
73
        node->sss_SubEState->es_direction = direction;
 
74
 
 
75
        oldcontext = MemoryContextSwitchTo(node->sss_SubEState->es_query_cxt);
 
76
 
 
77
        slot = ExecProcNode(node->subplan);
 
78
 
 
79
        MemoryContextSwitchTo(oldcontext);
 
80
 
 
81
        node->ss.ss_ScanTupleSlot = slot;
 
82
 
 
83
        return slot;
 
84
}
 
85
 
 
86
/* ----------------------------------------------------------------
 
87
 *              ExecSubqueryScan(node)
 
88
 *
 
89
 *              Scans the subquery sequentially and returns the next qualifying
 
90
 *              tuple.
 
91
 *              It calls the ExecScan() routine and passes it the access method
 
92
 *              which retrieve tuples sequentially.
 
93
 *
 
94
 */
 
95
 
 
96
TupleTableSlot *
 
97
ExecSubqueryScan(SubqueryScanState *node)
 
98
{
 
99
        /*
 
100
         * use SubqueryNext as access method
 
101
         */
 
102
        return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext);
 
103
}
 
104
 
 
105
/* ----------------------------------------------------------------
 
106
 *              ExecInitSubqueryScan
 
107
 * ----------------------------------------------------------------
 
108
 */
 
109
SubqueryScanState *
 
110
ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
 
111
{
 
112
        SubqueryScanState *subquerystate;
 
113
        RangeTblEntry *rte;
 
114
        EState     *sp_estate;
 
115
        MemoryContext oldcontext;
 
116
 
 
117
        /*
 
118
         * SubqueryScan should not have any "normal" children.
 
119
         */
 
120
        Assert(outerPlan(node) == NULL);
 
121
        Assert(innerPlan(node) == NULL);
 
122
 
 
123
        /*
 
124
         * create state structure
 
125
         */
 
126
        subquerystate = makeNode(SubqueryScanState);
 
127
        subquerystate->ss.ps.plan = (Plan *) node;
 
128
        subquerystate->ss.ps.state = estate;
 
129
 
 
130
        /*
 
131
         * Miscellaneous initialization
 
132
         *
 
133
         * create expression context for node
 
134
         */
 
135
        ExecAssignExprContext(estate, &subquerystate->ss.ps);
 
136
 
 
137
        /*
 
138
         * initialize child expressions
 
139
         */
 
140
        subquerystate->ss.ps.targetlist = (List *)
 
141
                ExecInitExpr((Expr *) node->scan.plan.targetlist,
 
142
                                         (PlanState *) subquerystate);
 
143
        subquerystate->ss.ps.qual = (List *)
 
144
                ExecInitExpr((Expr *) node->scan.plan.qual,
 
145
                                         (PlanState *) subquerystate);
 
146
 
 
147
#define SUBQUERYSCAN_NSLOTS 1
 
148
 
 
149
        /*
 
150
         * tuple table initialization
 
151
         */
 
152
        ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
 
153
 
 
154
        /*
 
155
         * initialize subquery
 
156
         *
 
157
         * This should agree with ExecInitSubPlan
 
158
         */
 
159
        rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
 
160
        Assert(rte->rtekind == RTE_SUBQUERY);
 
161
 
 
162
        /*
 
163
         * The subquery needs its own EState because it has its own
 
164
         * rangetable. It shares our Param ID space, however.  XXX if
 
165
         * rangetable access were done differently, the subquery could share
 
166
         * our EState, which would eliminate some thrashing about in this
 
167
         * module...
 
168
         */
 
169
        sp_estate = CreateExecutorState();
 
170
        subquerystate->sss_SubEState = sp_estate;
 
171
 
 
172
        oldcontext = MemoryContextSwitchTo(sp_estate->es_query_cxt);
 
173
 
 
174
        sp_estate->es_range_table = rte->subquery->rtable;
 
175
        sp_estate->es_param_list_info = estate->es_param_list_info;
 
176
        sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
 
177
        sp_estate->es_tupleTable =
 
178
                ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
 
179
        sp_estate->es_snapshot = estate->es_snapshot;
 
180
        sp_estate->es_crosscheck_snapshot = estate->es_crosscheck_snapshot;
 
181
        sp_estate->es_instrument = estate->es_instrument;
 
182
 
 
183
        /*
 
184
         * Start up the subplan (this is a very cut-down form of InitPlan())
 
185
         */
 
186
        subquerystate->subplan = ExecInitNode(node->subplan, sp_estate);
 
187
 
 
188
        MemoryContextSwitchTo(oldcontext);
 
189
 
 
190
        subquerystate->ss.ss_ScanTupleSlot = NULL;
 
191
        subquerystate->ss.ps.ps_TupFromTlist = false;
 
192
 
 
193
        /*
 
194
         * Initialize result tuple type and projection info.
 
195
         */
 
196
        ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
 
197
        ExecAssignProjectionInfo(&subquerystate->ss.ps);
 
198
 
 
199
        return subquerystate;
 
200
}
 
201
 
 
202
int
 
203
ExecCountSlotsSubqueryScan(SubqueryScan *node)
 
204
{
 
205
        /*
 
206
         * The subplan has its own tuple table and must not be counted here!
 
207
         */
 
208
        return ExecCountSlotsNode(outerPlan(node)) +
 
209
                ExecCountSlotsNode(innerPlan(node)) +
 
210
                SUBQUERYSCAN_NSLOTS;
 
211
}
 
212
 
 
213
/* ----------------------------------------------------------------
 
214
 *              ExecEndSubqueryScan
 
215
 *
 
216
 *              frees any storage allocated through C routines.
 
217
 * ----------------------------------------------------------------
 
218
 */
 
219
void
 
220
ExecEndSubqueryScan(SubqueryScanState *node)
 
221
{
 
222
        MemoryContext oldcontext;
 
223
 
 
224
        /*
 
225
         * Free the exprcontext
 
226
         */
 
227
        ExecFreeExprContext(&node->ss.ps);
 
228
 
 
229
        /*
 
230
         * clean out the upper tuple table
 
231
         */
 
232
        ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
233
 
 
234
        /*
 
235
         * close down subquery
 
236
         */
 
237
        oldcontext = MemoryContextSwitchTo(node->sss_SubEState->es_query_cxt);
 
238
 
 
239
        ExecEndPlan(node->subplan, node->sss_SubEState);
 
240
 
 
241
        MemoryContextSwitchTo(oldcontext);
 
242
 
 
243
        FreeExecutorState(node->sss_SubEState);
 
244
}
 
245
 
 
246
/* ----------------------------------------------------------------
 
247
 *              ExecSubqueryReScan
 
248
 *
 
249
 *              Rescans the relation.
 
250
 * ----------------------------------------------------------------
 
251
 */
 
252
void
 
253
ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
 
254
{
 
255
        EState     *estate;
 
256
        MemoryContext oldcontext;
 
257
 
 
258
        estate = node->ss.ps.state;
 
259
 
 
260
        oldcontext = MemoryContextSwitchTo(node->sss_SubEState->es_query_cxt);
 
261
 
 
262
        /*
 
263
         * ExecReScan doesn't know about my subplan, so I have to do
 
264
         * changed-parameter signaling myself.  This is just as well, because
 
265
         * the subplan has its own memory context in which its chgParam state
 
266
         * lives.
 
267
         */
 
268
        if (node->ss.ps.chgParam != NULL)
 
269
                UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
 
270
 
 
271
        /*
 
272
         * if chgParam of subnode is not null then plan will be re-scanned by
 
273
         * first ExecProcNode.
 
274
         */
 
275
        if (node->subplan->chgParam == NULL)
 
276
                ExecReScan(node->subplan, NULL);
 
277
 
 
278
        MemoryContextSwitchTo(oldcontext);
 
279
 
 
280
        node->ss.ss_ScanTupleSlot = NULL;
 
281
}