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