Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * nodeResult.c 4 : * support for constant nodes needing special code. 5 : * 6 : * DESCRIPTION 7 : * 8 : * Result nodes are used in queries where no relations are scanned. 9 : * Examples of such queries are: 10 : * 11 : * select 1 * 2 12 : * 13 : * insert into emp values ('mike', 15000) 14 : * 15 : * (Remember that in an INSERT or UPDATE, we need a plan tree that 16 : * generates the new rows.) 17 : * 18 : * Result nodes are also used to optimise queries with constant 19 : * qualifications (ie, quals that do not depend on the scanned data), 20 : * such as: 21 : * 22 : * select * from emp where 2 > 1 23 : * 24 : * In this case, the plan generated is 25 : * 26 : * Result (with 2 > 1 qual) 27 : * / 28 : * SeqScan (emp.*) 29 : * 30 : * At runtime, the Result node evaluates the constant qual once, 31 : * which is shown by EXPLAIN as a One-Time Filter. If it's 32 : * false, we can return an empty result set without running the 33 : * controlled plan at all. If it's true, we run the controlled 34 : * plan normally and pass back the results. 35 : * 36 : * 37 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group 38 : * Portions Copyright (c) 1994, Regents of the University of California 39 : * 40 : * IDENTIFICATION 41 : * src/backend/executor/nodeResult.c 42 : * 43 : *------------------------------------------------------------------------- 44 : */ 45 : 46 : #include "postgres.h" 47 : 48 : #include "executor/executor.h" 49 : #include "executor/nodeResult.h" 50 : #include "miscadmin.h" 51 : #include "utils/memutils.h" 52 : 53 : 54 : /* ---------------------------------------------------------------- 55 : * ExecResult(node) 56 : * 57 : * returns the tuples from the outer plan which satisfy the 58 : * qualification clause. Since result nodes with right 59 : * subtrees are never planned, we ignore the right subtree 60 : * entirely (for now).. -cim 10/7/89 61 : * 62 : * The qualification containing only constant clauses are 63 : * checked first before any processing is done. It always returns 64 : * 'nil' if the constant qualification is not satisfied. 65 : * ---------------------------------------------------------------- 66 : */ 67 : static TupleTableSlot * 68 1351234 : ExecResult(PlanState *pstate) 69 : { 70 1351234 : ResultState *node = castNode(ResultState, pstate); 71 : TupleTableSlot *outerTupleSlot; 72 : PlanState *outerPlan; 73 : ExprContext *econtext; 74 : 75 1351234 : CHECK_FOR_INTERRUPTS(); 76 : 77 1351230 : econtext = node->ps.ps_ExprContext; 78 : 79 : /* 80 : * check constant qualifications like (2 > 1), if not already done 81 : */ 82 1351230 : if (node->rs_checkqual) 83 : { 84 12156 : bool qualResult = ExecQual(node->resconstantqual, econtext); 85 : 86 12156 : node->rs_checkqual = false; 87 12156 : if (!qualResult) 88 : { 89 7660 : node->rs_done = true; 90 7660 : return NULL; 91 : } 92 : } 93 : 94 : /* 95 : * Reset per-tuple memory context to free any expression evaluation 96 : * storage allocated in the previous tuple cycle. 97 : */ 98 1343570 : ResetExprContext(econtext); 99 : 100 : /* 101 : * if rs_done is true then it means that we were asked to return a 102 : * constant tuple and we already did the last time ExecResult() was 103 : * called, OR that we failed the constant qual check. Either way, now we 104 : * are through. 105 : */ 106 1343570 : if (!node->rs_done) 107 : { 108 972118 : outerPlan = outerPlanState(node); 109 : 110 972118 : if (outerPlan != NULL) 111 : { 112 : /* 113 : * retrieve tuples from the outer plan until there are no more. 114 : */ 115 530096 : outerTupleSlot = ExecProcNode(outerPlan); 116 : 117 530082 : if (TupIsNull(outerTupleSlot)) 118 5754 : return NULL; 119 : 120 : /* 121 : * prepare to compute projection expressions, which will expect to 122 : * access the input tuples as varno OUTER. 123 : */ 124 524328 : econtext->ecxt_outertuple = outerTupleSlot; 125 : } 126 : else 127 : { 128 : /* 129 : * if we don't have an outer plan, then we are just generating the 130 : * results from a constant target list. Do it only once. 131 : */ 132 442022 : node->rs_done = true; 133 : } 134 : 135 : /* form the result tuple using ExecProject(), and return it */ 136 966350 : return ExecProject(node->ps.ps_ProjInfo); 137 : } 138 : 139 371452 : return NULL; 140 : } 141 : 142 : /* ---------------------------------------------------------------- 143 : * ExecResultMarkPos 144 : * ---------------------------------------------------------------- 145 : */ 146 : void 147 0 : ExecResultMarkPos(ResultState *node) 148 : { 149 0 : PlanState *outerPlan = outerPlanState(node); 150 : 151 0 : if (outerPlan != NULL) 152 0 : ExecMarkPos(outerPlan); 153 : else 154 0 : elog(DEBUG2, "Result nodes do not support mark/restore"); 155 0 : } 156 : 157 : /* ---------------------------------------------------------------- 158 : * ExecResultRestrPos 159 : * ---------------------------------------------------------------- 160 : */ 161 : void 162 0 : ExecResultRestrPos(ResultState *node) 163 : { 164 0 : PlanState *outerPlan = outerPlanState(node); 165 : 166 0 : if (outerPlan != NULL) 167 0 : ExecRestrPos(outerPlan); 168 : else 169 0 : elog(ERROR, "Result nodes do not support mark/restore"); 170 0 : } 171 : 172 : /* ---------------------------------------------------------------- 173 : * ExecInitResult 174 : * 175 : * Creates the run-time state information for the result node 176 : * produced by the planner and initializes outer relations 177 : * (child nodes). 178 : * ---------------------------------------------------------------- 179 : */ 180 : ResultState * 181 297912 : ExecInitResult(Result *node, EState *estate, int eflags) 182 : { 183 : ResultState *resstate; 184 : 185 : /* check for unsupported flags */ 186 : Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) || 187 : outerPlan(node) != NULL); 188 : 189 : /* 190 : * create state structure 191 : */ 192 297912 : resstate = makeNode(ResultState); 193 297912 : resstate->ps.plan = (Plan *) node; 194 297912 : resstate->ps.state = estate; 195 297912 : resstate->ps.ExecProcNode = ExecResult; 196 : 197 297912 : resstate->rs_done = false; 198 297912 : resstate->rs_checkqual = (node->resconstantqual != NULL); 199 : 200 : /* 201 : * Miscellaneous initialization 202 : * 203 : * create expression context for node 204 : */ 205 297912 : ExecAssignExprContext(estate, &resstate->ps); 206 : 207 : /* 208 : * initialize child nodes 209 : */ 210 297912 : outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags); 211 : 212 : /* 213 : * we don't use inner plan 214 : */ 215 : Assert(innerPlan(node) == NULL); 216 : 217 : /* 218 : * Initialize result slot, type and projection. 219 : */ 220 297912 : ExecInitResultTupleSlotTL(&resstate->ps, &TTSOpsVirtual); 221 297912 : ExecAssignProjectionInfo(&resstate->ps, NULL); 222 : 223 : /* 224 : * initialize child expressions 225 : */ 226 297842 : resstate->ps.qual = 227 297842 : ExecInitQual(node->plan.qual, (PlanState *) resstate); 228 297842 : resstate->resconstantqual = 229 297842 : ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate); 230 : 231 297842 : return resstate; 232 : } 233 : 234 : /* ---------------------------------------------------------------- 235 : * ExecEndResult 236 : * 237 : * frees up storage allocated through C routines 238 : * ---------------------------------------------------------------- 239 : */ 240 : void 241 282444 : ExecEndResult(ResultState *node) 242 : { 243 : /* 244 : * Free the exprcontext 245 : */ 246 282444 : ExecFreeExprContext(&node->ps); 247 : 248 : /* 249 : * clean out the tuple table 250 : */ 251 282444 : ExecClearTuple(node->ps.ps_ResultTupleSlot); 252 : 253 : /* 254 : * shut down subplans 255 : */ 256 282444 : ExecEndNode(outerPlanState(node)); 257 282444 : } 258 : 259 : void 260 164834 : ExecReScanResult(ResultState *node) 261 : { 262 164834 : PlanState *outerPlan = outerPlanState(node); 263 : 264 164834 : node->rs_done = false; 265 164834 : node->rs_checkqual = (node->resconstantqual != NULL); 266 : 267 : /* 268 : * If chgParam of subnode is not null then plan will be re-scanned by 269 : * first ExecProcNode. 270 : */ 271 164834 : if (outerPlan && outerPlan->chgParam == NULL) 272 78 : ExecReScan(outerPlan); 273 164834 : }