OSDN Git Service

ba0ed8635b72580e5a7c735f5e9241103e383bc5
[pg-rex/syncrep.git] / src / backend / executor / nodeSubqueryscan.c
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-2002, 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/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl 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
57         /*
58          * get information from the estate and scan state
59          */
60         estate = node->ss.ps.state;
61         direction = estate->es_direction;
62
63         /*
64          * We need not support EvalPlanQual here, since we are not scanning a
65          * real relation.
66          */
67
68         /*
69          * get the next tuple from the sub-query
70          */
71         node->sss_SubEState->es_direction = direction;
72
73         slot = ExecProcNode(node->subplan);
74
75         node->ss.ss_ScanTupleSlot = slot;
76
77         return slot;
78 }
79
80 /* ----------------------------------------------------------------
81  *              ExecSubqueryScan(node)
82  *
83  *              Scans the subquery sequentially and returns the next qualifying
84  *              tuple.
85  *              It calls the ExecScan() routine and passes it the access method
86  *              which retrieve tuples sequentially.
87  *
88  */
89
90 TupleTableSlot *
91 ExecSubqueryScan(SubqueryScanState *node)
92 {
93         /*
94          * use SubqueryNext as access method
95          */
96         return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext);
97 }
98
99 /* ----------------------------------------------------------------
100  *              ExecInitSubqueryScan
101  * ----------------------------------------------------------------
102  */
103 SubqueryScanState *
104 ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
105 {
106         SubqueryScanState *subquerystate;
107         RangeTblEntry *rte;
108         EState     *sp_estate;
109
110         /*
111          * SubqueryScan should not have any "normal" children.
112          */
113         Assert(outerPlan(node) == NULL);
114         Assert(innerPlan(node) == NULL);
115
116         /*
117          * create state structure
118          */
119         subquerystate = makeNode(SubqueryScanState);
120         subquerystate->ss.ps.plan = (Plan *) node;
121         subquerystate->ss.ps.state = estate;
122
123         /*
124          * Miscellaneous initialization
125          *
126          * create expression context for node
127          */
128         ExecAssignExprContext(estate, &subquerystate->ss.ps);
129
130         /*
131          * initialize child expressions
132          */
133         subquerystate->ss.ps.targetlist = (List *)
134                 ExecInitExpr((Node *) node->scan.plan.targetlist,
135                                          (PlanState *) subquerystate);
136         subquerystate->ss.ps.qual = (List *)
137                 ExecInitExpr((Node *) node->scan.plan.qual,
138                                          (PlanState *) subquerystate);
139
140 #define SUBQUERYSCAN_NSLOTS 1
141
142         /*
143          * tuple table initialization
144          */
145         ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
146
147         /*
148          * initialize subquery
149          *
150          * This should agree with ExecInitSubPlan
151          */
152         rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
153         Assert(rte->rtekind == RTE_SUBQUERY);
154
155         sp_estate = CreateExecutorState();
156         subquerystate->sss_SubEState = sp_estate;
157
158         sp_estate->es_range_table = rte->subquery->rtable;
159         sp_estate->es_param_list_info = estate->es_param_list_info;
160         sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
161         sp_estate->es_tupleTable =
162                 ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
163         sp_estate->es_snapshot = estate->es_snapshot;
164         sp_estate->es_instrument = estate->es_instrument;
165
166         subquerystate->subplan = ExecInitNode(node->subplan, sp_estate);
167
168         subquerystate->ss.ss_ScanTupleSlot = NULL;
169         subquerystate->ss.ps.ps_TupFromTlist = false;
170
171         /*
172          * initialize tuple type
173          */
174         ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
175         ExecAssignProjectionInfo(&subquerystate->ss.ps);
176
177         return subquerystate;
178 }
179
180 int
181 ExecCountSlotsSubqueryScan(SubqueryScan *node)
182 {
183         /*
184          * The subplan has its own tuple table and must not be counted here!
185          */
186         return ExecCountSlotsNode(outerPlan(node)) +
187                 ExecCountSlotsNode(innerPlan(node)) +
188                 SUBQUERYSCAN_NSLOTS;
189 }
190
191 /* ----------------------------------------------------------------
192  *              ExecEndSubqueryScan
193  *
194  *              frees any storage allocated through C routines.
195  * ----------------------------------------------------------------
196  */
197 void
198 ExecEndSubqueryScan(SubqueryScanState *node)
199 {
200         /*
201          * Free the projection info and the scan attribute info
202          */
203         ExecFreeProjectionInfo(&node->ss.ps);
204         ExecFreeExprContext(&node->ss.ps);
205
206         /*
207          * clean out the upper tuple table
208          */
209         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
210
211         /*
212          * close down subquery
213          */
214         ExecEndNode(node->subplan);
215
216         /*
217          * clean up subquery's tuple table
218          */
219         node->ss.ss_ScanTupleSlot = NULL;
220         ExecDropTupleTable(node->sss_SubEState->es_tupleTable, true);
221
222         /* XXX we seem to be leaking the sub-EState... */
223 }
224
225 /* ----------------------------------------------------------------
226  *              ExecSubqueryReScan
227  *
228  *              Rescans the relation.
229  * ----------------------------------------------------------------
230  */
231 void
232 ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
233 {
234         EState     *estate;
235
236         estate = node->ss.ps.state;
237
238         /*
239          * ExecReScan doesn't know about my subplan, so I have to do
240          * changed-parameter signaling myself.
241          */
242         if (node->ss.ps.chgParam != NULL)
243                 SetChangedParamList(node->subplan, node->ss.ps.chgParam);
244
245         /*
246          * if chgParam of subnode is not null then plan will be re-scanned by
247          * first ExecProcNode.
248          */
249         if (node->subplan->chgParam == NULL)
250                 ExecReScan(node->subplan, NULL);
251
252         node->ss.ss_ScanTupleSlot = NULL;
253 }