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-2019, 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 *
SubqueryNext(SubqueryScanState * node)46 SubqueryNext(SubqueryScanState *node)
47 {
48 	TupleTableSlot *slot;
49 
50 	/*
51 	 * Get the next tuple from the sub-query.
52 	 */
53 	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 	return slot;
61 }
62 
63 /*
64  * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
65  */
66 static bool
SubqueryRecheck(SubqueryScanState * node,TupleTableSlot * slot)67 SubqueryRecheck(SubqueryScanState *node, TupleTableSlot *slot)
68 {
69 	/* nothing to check */
70 	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 *
ExecSubqueryScan(PlanState * pstate)83 ExecSubqueryScan(PlanState *pstate)
84 {
85 	SubqueryScanState *node = castNode(SubqueryScanState, pstate);
86 
87 	return ExecScan(&node->ss,
88 					(ExecScanAccessMtd) SubqueryNext,
89 					(ExecScanRecheckMtd) SubqueryRecheck);
90 }
91 
92 /* ----------------------------------------------------------------
93  *		ExecInitSubqueryScan
94  * ----------------------------------------------------------------
95  */
96 SubqueryScanState *
ExecInitSubqueryScan(SubqueryScan * node,EState * estate,int eflags)97 ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
98 {
99 	SubqueryScanState *subquerystate;
100 
101 	/* check for unsupported flags */
102 	Assert(!(eflags & EXEC_FLAG_MARK));
103 
104 	/* SubqueryScan should not have any "normal" children */
105 	Assert(outerPlan(node) == NULL);
106 	Assert(innerPlan(node) == NULL);
107 
108 	/*
109 	 * create state structure
110 	 */
111 	subquerystate = makeNode(SubqueryScanState);
112 	subquerystate->ss.ps.plan = (Plan *) node;
113 	subquerystate->ss.ps.state = estate;
114 	subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
115 
116 	/*
117 	 * Miscellaneous initialization
118 	 *
119 	 * create expression context for node
120 	 */
121 	ExecAssignExprContext(estate, &subquerystate->ss.ps);
122 
123 	/*
124 	 * initialize subquery
125 	 */
126 	subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
127 
128 	/*
129 	 * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
130 	 */
131 	ExecInitScanTupleSlot(estate, &subquerystate->ss,
132 						  ExecGetResultType(subquerystate->subplan),
133 						  ExecGetResultSlotOps(subquerystate->subplan, NULL));
134 
135 	/*
136 	 * The slot used as the scantuple isn't the slot above (outside of EPQ),
137 	 * but the one from the node below.
138 	 */
139 	subquerystate->ss.ps.scanopsset = true;
140 	subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
141 														&subquerystate->ss.ps.scanopsfixed);
142 	subquerystate->ss.ps.resultopsset = true;
143 	subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
144 	subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
145 
146 	/*
147 	 * Initialize result type and projection.
148 	 */
149 	ExecInitResultTypeTL(&subquerystate->ss.ps);
150 	ExecAssignScanProjectionInfo(&subquerystate->ss);
151 
152 	/*
153 	 * initialize child expressions
154 	 */
155 	subquerystate->ss.ps.qual =
156 		ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
157 
158 	return subquerystate;
159 }
160 
161 /* ----------------------------------------------------------------
162  *		ExecEndSubqueryScan
163  *
164  *		frees any storage allocated through C routines.
165  * ----------------------------------------------------------------
166  */
167 void
ExecEndSubqueryScan(SubqueryScanState * node)168 ExecEndSubqueryScan(SubqueryScanState *node)
169 {
170 	/*
171 	 * Free the exprcontext
172 	 */
173 	ExecFreeExprContext(&node->ss.ps);
174 
175 	/*
176 	 * clean out the upper tuple table
177 	 */
178 	if (node->ss.ps.ps_ResultTupleSlot)
179 		ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
180 	ExecClearTuple(node->ss.ss_ScanTupleSlot);
181 
182 	/*
183 	 * close down subquery
184 	 */
185 	ExecEndNode(node->subplan);
186 }
187 
188 /* ----------------------------------------------------------------
189  *		ExecReScanSubqueryScan
190  *
191  *		Rescans the relation.
192  * ----------------------------------------------------------------
193  */
194 void
ExecReScanSubqueryScan(SubqueryScanState * node)195 ExecReScanSubqueryScan(SubqueryScanState *node)
196 {
197 	ExecScanReScan(&node->ss);
198 
199 	/*
200 	 * ExecReScan doesn't know about my subplan, so I have to do
201 	 * changed-parameter signaling myself.  This is just as well, because the
202 	 * subplan has its own memory context in which its chgParam state lives.
203 	 */
204 	if (node->ss.ps.chgParam != NULL)
205 		UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
206 
207 	/*
208 	 * if chgParam of subnode is not null then plan will be re-scanned by
209 	 * first ExecProcNode.
210 	 */
211 	if (node->subplan->chgParam == NULL)
212 		ExecReScan(node->subplan);
213 }
214