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-2026, 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/executor.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 1019393 : SubqueryNext(SubqueryScanState *node)
47 : {
48 : TupleTableSlot *slot;
49 :
50 : /*
51 : * Get the next tuple from the sub-query.
52 : */
53 1019393 : 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 1019387 : 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 862213 : ExecSubqueryScan(PlanState *pstate)
84 : {
85 862213 : SubqueryScanState *node = castNode(SubqueryScanState, pstate);
86 :
87 862213 : return ExecScan(&node->ss,
88 : (ExecScanAccessMtd) SubqueryNext,
89 : (ExecScanRecheckMtd) SubqueryRecheck);
90 : }
91 :
92 : /* ----------------------------------------------------------------
93 : * ExecInitSubqueryScan
94 : * ----------------------------------------------------------------
95 : */
96 : SubqueryScanState *
97 14552 : 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 14552 : subquerystate = makeNode(SubqueryScanState);
112 14552 : subquerystate->ss.ps.plan = (Plan *) node;
113 14552 : subquerystate->ss.ps.state = estate;
114 14552 : subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
115 :
116 : /*
117 : * Miscellaneous initialization
118 : *
119 : * create expression context for node
120 : */
121 14552 : ExecAssignExprContext(estate, &subquerystate->ss.ps);
122 :
123 : /*
124 : * initialize subquery
125 : */
126 14552 : subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
127 :
128 : /*
129 : * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
130 : */
131 14552 : ExecInitScanTupleSlot(estate, &subquerystate->ss,
132 : ExecGetResultType(subquerystate->subplan),
133 : ExecGetResultSlotOps(subquerystate->subplan, NULL),
134 : 0);
135 :
136 : /*
137 : * The slot used as the scantuple isn't the slot above (outside of EPQ),
138 : * but the one from the node below.
139 : */
140 14552 : subquerystate->ss.ps.scanopsset = true;
141 14552 : subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
142 : &subquerystate->ss.ps.scanopsfixed);
143 14552 : subquerystate->ss.ps.resultopsset = true;
144 14552 : subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
145 14552 : subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
146 :
147 : /*
148 : * Initialize result type and projection.
149 : */
150 14552 : ExecInitResultTypeTL(&subquerystate->ss.ps);
151 14552 : ExecAssignScanProjectionInfo(&subquerystate->ss);
152 :
153 : /*
154 : * initialize child expressions
155 : */
156 14552 : subquerystate->ss.ps.qual =
157 14552 : ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
158 :
159 14552 : return subquerystate;
160 : }
161 :
162 : /* ----------------------------------------------------------------
163 : * ExecEndSubqueryScan
164 : *
165 : * frees any storage allocated through C routines.
166 : * ----------------------------------------------------------------
167 : */
168 : void
169 14546 : ExecEndSubqueryScan(SubqueryScanState *node)
170 : {
171 : /*
172 : * close down subquery
173 : */
174 14546 : ExecEndNode(node->subplan);
175 14546 : }
176 :
177 : /* ----------------------------------------------------------------
178 : * ExecReScanSubqueryScan
179 : *
180 : * Rescans the relation.
181 : * ----------------------------------------------------------------
182 : */
183 : void
184 464 : ExecReScanSubqueryScan(SubqueryScanState *node)
185 : {
186 464 : ExecScanReScan(&node->ss);
187 :
188 : /*
189 : * ExecReScan doesn't know about my subplan, so I have to do
190 : * changed-parameter signaling myself. This is just as well, because the
191 : * subplan has its own memory context in which its chgParam state lives.
192 : */
193 464 : if (node->ss.ps.chgParam != NULL)
194 379 : UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
195 :
196 : /*
197 : * if chgParam of subnode is not null then plan will be re-scanned by
198 : * first ExecProcNode.
199 : */
200 464 : if (node->subplan->chgParam == NULL)
201 145 : ExecReScan(node->subplan);
202 464 : }
|