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 * 46 1743344 : SubqueryNext(SubqueryScanState *node) 47 : { 48 : TupleTableSlot *slot; 49 : 50 : /* 51 : * Get the next tuple from the sub-query. 52 : */ 53 1743344 : 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 1743344 : 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 1552438 : ExecSubqueryScan(PlanState *pstate) 84 : { 85 1552438 : SubqueryScanState *node = castNode(SubqueryScanState, pstate); 86 : 87 1552438 : return ExecScan(&node->ss, 88 : (ExecScanAccessMtd) SubqueryNext, 89 : (ExecScanRecheckMtd) SubqueryRecheck); 90 : } 91 : 92 : /* ---------------------------------------------------------------- 93 : * ExecInitSubqueryScan 94 : * ---------------------------------------------------------------- 95 : */ 96 : SubqueryScanState * 97 9050 : 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 9050 : subquerystate = makeNode(SubqueryScanState); 112 9050 : subquerystate->ss.ps.plan = (Plan *) node; 113 9050 : subquerystate->ss.ps.state = estate; 114 9050 : subquerystate->ss.ps.ExecProcNode = ExecSubqueryScan; 115 : 116 : /* 117 : * Miscellaneous initialization 118 : * 119 : * create expression context for node 120 : */ 121 9050 : ExecAssignExprContext(estate, &subquerystate->ss.ps); 122 : 123 : /* 124 : * initialize subquery 125 : */ 126 9050 : subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags); 127 : 128 : /* 129 : * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo) 130 : */ 131 9050 : 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 9050 : subquerystate->ss.ps.scanopsset = true; 140 9050 : subquerystate->ss.ps.scanops = ExecGetResultSlotOps(subquerystate->subplan, 141 : &subquerystate->ss.ps.scanopsfixed); 142 9050 : subquerystate->ss.ps.resultopsset = true; 143 9050 : subquerystate->ss.ps.resultops = subquerystate->ss.ps.scanops; 144 9050 : subquerystate->ss.ps.resultopsfixed = subquerystate->ss.ps.scanopsfixed; 145 : 146 : /* 147 : * Initialize result type and projection. 148 : */ 149 9050 : ExecInitResultTypeTL(&subquerystate->ss.ps); 150 9050 : ExecAssignScanProjectionInfo(&subquerystate->ss); 151 : 152 : /* 153 : * initialize child expressions 154 : */ 155 9050 : subquerystate->ss.ps.qual = 156 9050 : ExecInitQual(node->scan.plan.qual, (PlanState *) subquerystate); 157 : 158 9050 : return subquerystate; 159 : } 160 : 161 : /* ---------------------------------------------------------------- 162 : * ExecEndSubqueryScan 163 : * 164 : * frees any storage allocated through C routines. 165 : * ---------------------------------------------------------------- 166 : */ 167 : void 168 9050 : ExecEndSubqueryScan(SubqueryScanState *node) 169 : { 170 : /* 171 : * Free the exprcontext 172 : */ 173 9050 : ExecFreeExprContext(&node->ss.ps); 174 : 175 : /* 176 : * clean out the upper tuple table 177 : */ 178 9050 : if (node->ss.ps.ps_ResultTupleSlot) 179 8644 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); 180 9050 : ExecClearTuple(node->ss.ss_ScanTupleSlot); 181 : 182 : /* 183 : * close down subquery 184 : */ 185 9050 : ExecEndNode(node->subplan); 186 9050 : } 187 : 188 : /* ---------------------------------------------------------------- 189 : * ExecReScanSubqueryScan 190 : * 191 : * Rescans the relation. 192 : * ---------------------------------------------------------------- 193 : */ 194 : void 195 2164 : ExecReScanSubqueryScan(SubqueryScanState *node) 196 : { 197 2164 : 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 2164 : if (node->ss.ps.chgParam != NULL) 205 2148 : 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 2164 : if (node->subplan->chgParam == NULL) 212 70 : ExecReScan(node->subplan); 213 2164 : }