Age Owner Branch data 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-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 *
8552 tgl@sss.pgh.pa.us 46 :CBC 943795 : SubqueryNext(SubqueryScanState *node)
47 : : {
48 : : TupleTableSlot *slot;
49 : :
50 : : /*
51 : : * Get the next tuple from the sub-query.
52 : : */
53 : 943795 : 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 : : */
9349 60 : 943789 : return slot;
61 : : }
62 : :
63 : : /*
64 : : * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
65 : : */
66 : : static bool
6035 tgl@sss.pgh.pa.us 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 *
3214 andres@anarazel.de 83 :CBC 784769 : ExecSubqueryScan(PlanState *pstate)
84 : : {
85 : 784769 : SubqueryScanState *node = castNode(SubqueryScanState, pstate);
86 : :
6035 tgl@sss.pgh.pa.us 87 : 784769 : return ExecScan(&node->ss,
88 : : (ExecScanAccessMtd) SubqueryNext,
89 : : (ExecScanRecheckMtd) SubqueryRecheck);
90 : : }
91 : :
92 : : /* ----------------------------------------------------------------
93 : : * ExecInitSubqueryScan
94 : : * ----------------------------------------------------------------
95 : : */
96 : : SubqueryScanState *
7371 97 : 14751 : ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
98 : : {
99 : : SubqueryScanState *subquerystate;
100 : :
101 : : /* check for unsupported flags */
102 [ - + ]: 14751 : Assert(!(eflags & EXEC_FLAG_MARK));
103 : :
104 : : /* SubqueryScan should not have any "normal" children */
8552 105 [ - + ]: 14751 : Assert(outerPlan(node) == NULL);
106 [ - + ]: 14751 : Assert(innerPlan(node) == NULL);
107 : :
108 : : /*
109 : : * create state structure
110 : : */
9349 111 : 14751 : subquerystate = makeNode(SubqueryScanState);
8552 112 : 14751 : subquerystate->ss.ps.plan = (Plan *) node;
113 : 14751 : subquerystate->ss.ps.state = estate;
3214 andres@anarazel.de 114 : 14751 : subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
115 : :
116 : : /*
117 : : * Miscellaneous initialization
118 : : *
119 : : * create expression context for node
120 : : */
8552 tgl@sss.pgh.pa.us 121 : 14751 : ExecAssignExprContext(estate, &subquerystate->ss.ps);
122 : :
123 : : /*
124 : : * initialize subquery
125 : : */
7007 126 : 14751 : subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
127 : :
128 : : /*
129 : : * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
130 : : */
3000 andres@anarazel.de 131 : 14751 : 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 : : */
2728 140 : 14751 : subquerystate->ss.ps.scanopsset = true;
141 : 14751 : subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
142 : : &subquerystate->ss.ps.scanopsfixed);
143 : 14751 : subquerystate->ss.ps.resultopsset = true;
144 : 14751 : subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
145 : 14751 : subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
146 : :
147 : : /*
148 : : * Initialize result type and projection.
149 : : */
2734 150 : 14751 : ExecInitResultTypeTL(&subquerystate->ss.ps);
7653 tgl@sss.pgh.pa.us 151 : 14751 : ExecAssignScanProjectionInfo(&subquerystate->ss);
152 : :
153 : : /*
154 : : * initialize child expressions
155 : : */
3000 andres@anarazel.de 156 : 14751 : subquerystate->ss.ps.qual =
157 : 14751 : ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
158 : :
8552 tgl@sss.pgh.pa.us 159 : 14751 : return subquerystate;
160 : : }
161 : :
162 : : /* ----------------------------------------------------------------
163 : : * ExecEndSubqueryScan
164 : : *
165 : : * frees any storage allocated through C routines.
166 : : * ----------------------------------------------------------------
167 : : */
168 : : void
169 : 14745 : ExecEndSubqueryScan(SubqueryScanState *node)
170 : : {
171 : : /*
172 : : * close down subquery
173 : : */
7007 174 : 14745 : ExecEndNode(node->subplan);
9349 175 : 14745 : }
176 : :
177 : : /* ----------------------------------------------------------------
178 : : * ExecReScanSubqueryScan
179 : : *
180 : : * Rescans the relation.
181 : : * ----------------------------------------------------------------
182 : : */
183 : : void
5776 184 : 464 : ExecReScanSubqueryScan(SubqueryScanState *node)
185 : : {
6035 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 : : */
8552 193 [ + + ]: 464 : if (node->ss.ps.chgParam != NULL)
8486 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 : : */
9128 200 [ + + ]: 464 : if (node->subplan->chgParam == NULL)
5776 201 : 145 : ExecReScan(node->subplan);
9349 202 : 464 : }
|