Line data Source code
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-2017, PostgreSQL Global Development Group
11 : * Portions Copyright (c) 1994, Regents of the University of California
12 : *
13 : *
14 : * IDENTIFICATION
15 : * src/backend/executor/nodeSubqueryscan.c
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 : * ExecReScanSubqueryScan rescans the relation
26 : *
27 : */
28 : #include "postgres.h"
29 :
30 : #include "executor/execdebug.h"
31 : #include "executor/nodeSubqueryscan.h"
32 :
33 : static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
34 :
35 : /* ----------------------------------------------------------------
36 : * Scan Support
37 : * ----------------------------------------------------------------
38 : */
39 : /* ----------------------------------------------------------------
40 : * SubqueryNext
41 : *
42 : * This is a workhorse for ExecSubqueryScan
43 : * ----------------------------------------------------------------
44 : */
45 : static TupleTableSlot *
46 125046 : SubqueryNext(SubqueryScanState *node)
47 : {
48 : TupleTableSlot *slot;
49 :
50 : /*
51 : * Get the next tuple from the sub-query.
52 : */
53 125046 : slot = ExecProcNode(node->subplan);
54 :
55 : /*
56 : * We just return the subplan's result slot, rather than expending extra
57 : * cycles for ExecCopySlot(). (Our own ScanTupleSlot is used only for
58 : * EvalPlanQual rechecks.)
59 : */
60 125046 : return slot;
61 : }
62 :
63 : /*
64 : * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
65 : */
66 : static bool
67 0 : SubqueryRecheck(SubqueryScanState *node, TupleTableSlot *slot)
68 : {
69 : /* nothing to check */
70 0 : return true;
71 : }
72 :
73 : /* ----------------------------------------------------------------
74 : * ExecSubqueryScan(node)
75 : *
76 : * Scans the subquery sequentially and returns the next qualifying
77 : * tuple.
78 : * We call the ExecScan() routine and pass it the appropriate
79 : * access method functions.
80 : * ----------------------------------------------------------------
81 : */
82 : static TupleTableSlot *
83 94761 : ExecSubqueryScan(PlanState *pstate)
84 : {
85 94761 : SubqueryScanState *node = castNode(SubqueryScanState, pstate);
86 :
87 94761 : return ExecScan(&node->ss,
88 : (ExecScanAccessMtd) SubqueryNext,
89 : (ExecScanRecheckMtd) SubqueryRecheck);
90 : }
91 :
92 : /* ----------------------------------------------------------------
93 : * ExecInitSubqueryScan
94 : * ----------------------------------------------------------------
95 : */
96 : SubqueryScanState *
97 287 : ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
98 : {
99 : SubqueryScanState *subquerystate;
100 :
101 : /* check for unsupported flags */
102 287 : Assert(!(eflags & EXEC_FLAG_MARK));
103 :
104 : /* SubqueryScan should not have any "normal" children */
105 287 : Assert(outerPlan(node) == NULL);
106 287 : Assert(innerPlan(node) == NULL);
107 :
108 : /*
109 : * create state structure
110 : */
111 287 : subquerystate = makeNode(SubqueryScanState);
112 287 : subquerystate->ss.ps.plan = (Plan *) node;
113 287 : subquerystate->ss.ps.state = estate;
114 287 : subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
115 :
116 : /*
117 : * Miscellaneous initialization
118 : *
119 : * create expression context for node
120 : */
121 287 : ExecAssignExprContext(estate, &subquerystate->ss.ps);
122 :
123 : /*
124 : * initialize child expressions
125 : */
126 287 : subquerystate->ss.ps.qual =
127 287 : ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
128 :
129 : /*
130 : * tuple table initialization
131 : */
132 287 : ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
133 287 : ExecInitScanTupleSlot(estate, &subquerystate->ss);
134 :
135 : /*
136 : * initialize subquery
137 : */
138 287 : subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
139 :
140 : /*
141 : * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
142 : */
143 287 : ExecAssignScanType(&subquerystate->ss,
144 : ExecGetResultType(subquerystate->subplan));
145 :
146 : /*
147 : * Initialize result tuple type and projection info.
148 : */
149 287 : ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
150 287 : ExecAssignScanProjectionInfo(&subquerystate->ss);
151 :
152 287 : return subquerystate;
153 : }
154 :
155 : /* ----------------------------------------------------------------
156 : * ExecEndSubqueryScan
157 : *
158 : * frees any storage allocated through C routines.
159 : * ----------------------------------------------------------------
160 : */
161 : void
162 287 : ExecEndSubqueryScan(SubqueryScanState *node)
163 : {
164 : /*
165 : * Free the exprcontext
166 : */
167 287 : ExecFreeExprContext(&node->ss.ps);
168 :
169 : /*
170 : * clean out the upper tuple table
171 : */
172 287 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
173 287 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
174 :
175 : /*
176 : * close down subquery
177 : */
178 287 : ExecEndNode(node->subplan);
179 287 : }
180 :
181 : /* ----------------------------------------------------------------
182 : * ExecReScanSubqueryScan
183 : *
184 : * Rescans the relation.
185 : * ----------------------------------------------------------------
186 : */
187 : void
188 49 : ExecReScanSubqueryScan(SubqueryScanState *node)
189 : {
190 49 : ExecScanReScan(&node->ss);
191 :
192 : /*
193 : * ExecReScan doesn't know about my subplan, so I have to do
194 : * changed-parameter signaling myself. This is just as well, because the
195 : * subplan has its own memory context in which its chgParam state lives.
196 : */
197 49 : if (node->ss.ps.chgParam != NULL)
198 44 : UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
199 :
200 : /*
201 : * if chgParam of subnode is not null then plan will be re-scanned by
202 : * first ExecProcNode.
203 : */
204 49 : if (node->subplan->chgParam == NULL)
205 27 : ExecReScan(node->subplan);
206 49 : }
|