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-2024, 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 : 52 : 53 : /* ---------------------------------------------------------------- 54 : * ExecResult(node) 55 : * 56 : * returns the tuples from the outer plan which satisfy the 57 : * qualification clause. Since result nodes with right 58 : * subtrees are never planned, we ignore the right subtree 59 : * entirely (for now).. -cim 10/7/89 60 : * 61 : * The qualification containing only constant clauses are 62 : * checked first before any processing is done. It always returns 63 : * 'nil' if the constant qualification is not satisfied. 64 : * ---------------------------------------------------------------- 65 : */ 66 : static TupleTableSlot * 67 1168274 : ExecResult(PlanState *pstate) 68 : { 69 1168274 : ResultState *node = castNode(ResultState, pstate); 70 : TupleTableSlot *outerTupleSlot; 71 : PlanState *outerPlan; 72 : ExprContext *econtext; 73 : 74 1168274 : CHECK_FOR_INTERRUPTS(); 75 : 76 1168270 : econtext = node->ps.ps_ExprContext; 77 : 78 : /* 79 : * check constant qualifications like (2 > 1), if not already done 80 : */ 81 1168270 : if (node->rs_checkqual) 82 : { 83 15274 : bool qualResult = ExecQual(node->resconstantqual, econtext); 84 : 85 15274 : node->rs_checkqual = false; 86 15274 : if (!qualResult) 87 : { 88 9370 : node->rs_done = true; 89 9370 : return NULL; 90 : } 91 : } 92 : 93 : /* 94 : * Reset per-tuple memory context to free any expression evaluation 95 : * storage allocated in the previous tuple cycle. 96 : */ 97 1158900 : ResetExprContext(econtext); 98 : 99 : /* 100 : * if rs_done is true then it means that we were asked to return a 101 : * constant tuple and we already did the last time ExecResult() was 102 : * called, OR that we failed the constant qual check. Either way, now we 103 : * are through. 104 : */ 105 1158900 : if (!node->rs_done) 106 : { 107 911868 : outerPlan = outerPlanState(node); 108 : 109 911868 : if (outerPlan != NULL) 110 : { 111 : /* 112 : * retrieve tuples from the outer plan until there are no more. 113 : */ 114 531954 : outerTupleSlot = ExecProcNode(outerPlan); 115 : 116 531940 : if (TupIsNull(outerTupleSlot)) 117 7222 : return NULL; 118 : 119 : /* 120 : * prepare to compute projection expressions, which will expect to 121 : * access the input tuples as varno OUTER. 122 : */ 123 524718 : econtext->ecxt_outertuple = outerTupleSlot; 124 : } 125 : else 126 : { 127 : /* 128 : * if we don't have an outer plan, then we are just generating the 129 : * results from a constant target list. Do it only once. 130 : */ 131 379914 : node->rs_done = true; 132 : } 133 : 134 : /* form the result tuple using ExecProject(), and return it */ 135 904632 : return ExecProject(node->ps.ps_ProjInfo); 136 : } 137 : 138 247032 : return NULL; 139 : } 140 : 141 : /* ---------------------------------------------------------------- 142 : * ExecResultMarkPos 143 : * ---------------------------------------------------------------- 144 : */ 145 : void 146 0 : ExecResultMarkPos(ResultState *node) 147 : { 148 0 : PlanState *outerPlan = outerPlanState(node); 149 : 150 0 : if (outerPlan != NULL) 151 0 : ExecMarkPos(outerPlan); 152 : else 153 0 : elog(DEBUG2, "Result nodes do not support mark/restore"); 154 0 : } 155 : 156 : /* ---------------------------------------------------------------- 157 : * ExecResultRestrPos 158 : * ---------------------------------------------------------------- 159 : */ 160 : void 161 0 : ExecResultRestrPos(ResultState *node) 162 : { 163 0 : PlanState *outerPlan = outerPlanState(node); 164 : 165 0 : if (outerPlan != NULL) 166 0 : ExecRestrPos(outerPlan); 167 : else 168 0 : elog(ERROR, "Result nodes do not support mark/restore"); 169 0 : } 170 : 171 : /* ---------------------------------------------------------------- 172 : * ExecInitResult 173 : * 174 : * Creates the run-time state information for the result node 175 : * produced by the planner and initializes outer relations 176 : * (child nodes). 177 : * ---------------------------------------------------------------- 178 : */ 179 : ResultState * 180 358654 : ExecInitResult(Result *node, EState *estate, int eflags) 181 : { 182 : ResultState *resstate; 183 : 184 : /* check for unsupported flags */ 185 : Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) || 186 : outerPlan(node) != NULL); 187 : 188 : /* 189 : * create state structure 190 : */ 191 358654 : resstate = makeNode(ResultState); 192 358654 : resstate->ps.plan = (Plan *) node; 193 358654 : resstate->ps.state = estate; 194 358654 : resstate->ps.ExecProcNode = ExecResult; 195 : 196 358654 : resstate->rs_done = false; 197 358654 : resstate->rs_checkqual = (node->resconstantqual != NULL); 198 : 199 : /* 200 : * Miscellaneous initialization 201 : * 202 : * create expression context for node 203 : */ 204 358654 : ExecAssignExprContext(estate, &resstate->ps); 205 : 206 : /* 207 : * initialize child nodes 208 : */ 209 358654 : outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags); 210 : 211 : /* 212 : * we don't use inner plan 213 : */ 214 : Assert(innerPlan(node) == NULL); 215 : 216 : /* 217 : * Initialize result slot, type and projection. 218 : */ 219 358654 : ExecInitResultTupleSlotTL(&resstate->ps, &TTSOpsVirtual); 220 358654 : ExecAssignProjectionInfo(&resstate->ps, NULL); 221 : 222 : /* 223 : * initialize child expressions 224 : */ 225 358592 : resstate->ps.qual = 226 358592 : ExecInitQual(node->plan.qual, (PlanState *) resstate); 227 358592 : resstate->resconstantqual = 228 358592 : ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate); 229 : 230 358592 : return resstate; 231 : } 232 : 233 : /* ---------------------------------------------------------------- 234 : * ExecEndResult 235 : * 236 : * frees up storage allocated through C routines 237 : * ---------------------------------------------------------------- 238 : */ 239 : void 240 341554 : ExecEndResult(ResultState *node) 241 : { 242 : /* 243 : * shut down subplans 244 : */ 245 341554 : ExecEndNode(outerPlanState(node)); 246 341554 : } 247 : 248 : void 249 46112 : ExecReScanResult(ResultState *node) 250 : { 251 46112 : PlanState *outerPlan = outerPlanState(node); 252 : 253 46112 : node->rs_done = false; 254 46112 : node->rs_checkqual = (node->resconstantqual != NULL); 255 : 256 : /* 257 : * If chgParam of subnode is not null then plan will be re-scanned by 258 : * first ExecProcNode. 259 : */ 260 46112 : if (outerPlan && outerPlan->chgParam == NULL) 261 78 : ExecReScan(outerPlan); 262 46112 : }