Age Owner TLA 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-2023, 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 *
7430 tgl 46 CBC 872607 : SubqueryNext(SubqueryScanState *node)
47 : {
48 : TupleTableSlot *slot;
49 :
50 : /*
51 : * Get the next tuple from the sub-query.
52 : */
53 872607 : 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 : */
8227 60 872607 : return slot;
61 : }
62 :
63 : /*
64 : * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
65 : */
66 : static bool
4913 tgl 67 UBC 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 *
2092 andres 83 CBC 776947 : ExecSubqueryScan(PlanState *pstate)
84 : {
85 776947 : SubqueryScanState *node = castNode(SubqueryScanState, pstate);
86 :
4913 tgl 87 776947 : return ExecScan(&node->ss,
88 : (ExecScanAccessMtd) SubqueryNext,
89 : (ExecScanRecheckMtd) SubqueryRecheck);
90 : }
91 :
92 : /* ----------------------------------------------------------------
93 : * ExecInitSubqueryScan
94 : * ----------------------------------------------------------------
95 : */
96 : SubqueryScanState *
6249 97 4701 : ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
98 : {
99 : SubqueryScanState *subquerystate;
100 :
101 : /* check for unsupported flags */
102 4701 : Assert(!(eflags & EXEC_FLAG_MARK));
103 :
104 : /* SubqueryScan should not have any "normal" children */
7430 105 4701 : Assert(outerPlan(node) == NULL);
106 4701 : Assert(innerPlan(node) == NULL);
107 :
108 : /*
109 : * create state structure
110 : */
8227 111 4701 : subquerystate = makeNode(SubqueryScanState);
7430 112 4701 : subquerystate->ss.ps.plan = (Plan *) node;
113 4701 : subquerystate->ss.ps.state = estate;
2092 andres 114 4701 : subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
115 :
116 : /*
117 : * Miscellaneous initialization
118 : *
119 : * create expression context for node
120 : */
7430 tgl 121 4701 : ExecAssignExprContext(estate, &subquerystate->ss.ps);
122 :
123 : /*
124 : * initialize subquery
125 : */
5885 126 4701 : subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
127 :
128 : /*
129 : * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
130 : */
1878 andres 131 4701 : 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 : */
1606 139 4701 : subquerystate->ss.ps.scanopsset = true;
140 4701 : subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
141 : &subquerystate->ss.ps.scanopsfixed);
142 4701 : subquerystate->ss.ps.resultopsset = true;
143 4701 : subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
144 4701 : subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
145 :
146 : /*
147 : * Initialize result type and projection.
148 : */
1612 149 4701 : ExecInitResultTypeTL(&subquerystate->ss.ps);
6531 tgl 150 4701 : ExecAssignScanProjectionInfo(&subquerystate->ss);
151 :
152 : /*
153 : * initialize child expressions
154 : */
1878 andres 155 4701 : subquerystate->ss.ps.qual =
156 4701 : ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
157 :
7430 tgl 158 4701 : return subquerystate;
159 : }
160 :
161 : /* ----------------------------------------------------------------
162 : * ExecEndSubqueryScan
163 : *
164 : * frees any storage allocated through C routines.
165 : * ----------------------------------------------------------------
166 : */
167 : void
168 4701 : ExecEndSubqueryScan(SubqueryScanState *node)
169 : {
170 : /*
171 : * Free the exprcontext
172 : */
173 4701 : ExecFreeExprContext(&node->ss.ps);
174 :
175 : /*
176 : * clean out the upper tuple table
177 : */
1612 andres 178 4701 : if (node->ss.ps.ps_ResultTupleSlot)
179 4482 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
4913 tgl 180 4701 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
181 :
182 : /*
183 : * close down subquery
184 : */
5885 185 4701 : ExecEndNode(node->subplan);
8227 186 4701 : }
187 :
188 : /* ----------------------------------------------------------------
189 : * ExecReScanSubqueryScan
190 : *
191 : * Rescans the relation.
192 : * ----------------------------------------------------------------
193 : */
194 : void
4654 195 1081 : ExecReScanSubqueryScan(SubqueryScanState *node)
196 : {
4913 197 1081 : 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 : */
7430 204 1081 : if (node->ss.ps.chgParam != NULL)
7364 205 1074 : 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 : */
8006 211 1081 : if (node->subplan->chgParam == NULL)
4654 212 34 : ExecReScan(node->subplan);
8227 213 1081 : }
|