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-2024, 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 *
7801 tgl@sss.pgh.pa.us 46 :CBC 993194 : SubqueryNext(SubqueryScanState *node)
47 : : {
48 : : TupleTableSlot *slot;
49 : :
50 : : /*
51 : : * Get the next tuple from the sub-query.
52 : : */
53 : 993194 : 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 : : */
8598 60 : 993194 : return slot;
61 : : }
62 : :
63 : : /*
64 : : * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
65 : : */
66 : : static bool
5284 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 *
2463 andres@anarazel.de 83 :CBC 896140 : ExecSubqueryScan(PlanState *pstate)
84 : : {
85 : 896140 : SubqueryScanState *node = castNode(SubqueryScanState, pstate);
86 : :
5284 tgl@sss.pgh.pa.us 87 : 896140 : return ExecScan(&node->ss,
88 : : (ExecScanAccessMtd) SubqueryNext,
89 : : (ExecScanRecheckMtd) SubqueryRecheck);
90 : : }
91 : :
92 : : /* ----------------------------------------------------------------
93 : : * ExecInitSubqueryScan
94 : : * ----------------------------------------------------------------
95 : : */
96 : : SubqueryScanState *
6620 97 : 5229 : ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
98 : : {
99 : : SubqueryScanState *subquerystate;
100 : :
101 : : /* check for unsupported flags */
102 [ - + ]: 5229 : Assert(!(eflags & EXEC_FLAG_MARK));
103 : :
104 : : /* SubqueryScan should not have any "normal" children */
7801 105 [ - + ]: 5229 : Assert(outerPlan(node) == NULL);
106 [ - + ]: 5229 : Assert(innerPlan(node) == NULL);
107 : :
108 : : /*
109 : : * create state structure
110 : : */
8598 111 : 5229 : subquerystate = makeNode(SubqueryScanState);
7801 112 : 5229 : subquerystate->ss.ps.plan = (Plan *) node;
113 : 5229 : subquerystate->ss.ps.state = estate;
2463 andres@anarazel.de 114 : 5229 : subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan;
115 : :
116 : : /*
117 : : * Miscellaneous initialization
118 : : *
119 : : * create expression context for node
120 : : */
7801 tgl@sss.pgh.pa.us 121 : 5229 : ExecAssignExprContext(estate, &subquerystate->ss.ps);
122 : :
123 : : /*
124 : : * initialize subquery
125 : : */
6256 126 : 5229 : subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
127 : :
128 : : /*
129 : : * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
130 : : */
2249 andres@anarazel.de 131 : 5229 : 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 : : */
1977 139 : 5229 : subquerystate->ss.ps.scanopsset = true;
140 : 5229 : subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan,
141 : : &subquerystate->ss.ps.scanopsfixed);
142 : 5229 : subquerystate->ss.ps.resultopsset = true;
143 : 5229 : subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops;
144 : 5229 : subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed;
145 : :
146 : : /*
147 : : * Initialize result type and projection.
148 : : */
1983 149 : 5229 : ExecInitResultTypeTL(&subquerystate->ss.ps);
6902 tgl@sss.pgh.pa.us 150 : 5229 : ExecAssignScanProjectionInfo(&subquerystate->ss);
151 : :
152 : : /*
153 : : * initialize child expressions
154 : : */
2249 andres@anarazel.de 155 : 5229 : subquerystate->ss.ps.qual =
156 : 5229 : ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate);
157 : :
7801 tgl@sss.pgh.pa.us 158 : 5229 : return subquerystate;
159 : : }
160 : :
161 : : /* ----------------------------------------------------------------
162 : : * ExecEndSubqueryScan
163 : : *
164 : : * frees any storage allocated through C routines.
165 : : * ----------------------------------------------------------------
166 : : */
167 : : void
168 : 5229 : ExecEndSubqueryScan(SubqueryScanState *node)
169 : : {
170 : : /*
171 : : * close down subquery
172 : : */
6256 173 : 5229 : ExecEndNode(node->subplan);
8598 174 : 5229 : }
175 : :
176 : : /* ----------------------------------------------------------------
177 : : * ExecReScanSubqueryScan
178 : : *
179 : : * Rescans the relation.
180 : : * ----------------------------------------------------------------
181 : : */
182 : : void
5025 183 : 1093 : ExecReScanSubqueryScan(SubqueryScanState *node)
184 : : {
5284 185 : 1093 : ExecScanReScan(&node->ss);
186 : :
187 : : /*
188 : : * ExecReScan doesn't know about my subplan, so I have to do
189 : : * changed-parameter signaling myself. This is just as well, because the
190 : : * subplan has its own memory context in which its chgParam state lives.
191 : : */
7801 192 [ + + ]: 1093 : if (node->ss.ps.chgParam != NULL)
7735 193 : 1086 : UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
194 : :
195 : : /*
196 : : * if chgParam of subnode is not null then plan will be re-scanned by
197 : : * first ExecProcNode.
198 : : */
8377 199 [ + + ]: 1093 : if (node->subplan->chgParam == NULL)
5025 200 : 34 : ExecReScan(node->subplan);
8598 201 : 1093 : }
|