| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * nodeValuesscan.c |
| 4 | * Support routines for scanning Values lists |
| 5 | * ("VALUES (...), (...), ..." in rangetable). |
| 6 | * |
| 7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 8 | * Portions Copyright (c) 1994, Regents of the University of California |
| 9 | * |
| 10 | * |
| 11 | * IDENTIFICATION |
| 12 | * src/backend/executor/nodeValuesscan.c |
| 13 | * |
| 14 | *------------------------------------------------------------------------- |
| 15 | */ |
| 16 | /* |
| 17 | * INTERFACE ROUTINES |
| 18 | * ExecValuesScan scans a values list. |
| 19 | * ExecValuesNext retrieve next tuple in sequential order. |
| 20 | * ExecInitValuesScan creates and initializes a valuesscan node. |
| 21 | * ExecEndValuesScan releases any storage allocated. |
| 22 | * ExecReScanValuesScan rescans the values list |
| 23 | */ |
| 24 | #include "postgres.h" |
| 25 | |
| 26 | #include "executor/executor.h" |
| 27 | #include "executor/nodeValuesscan.h" |
| 28 | #include "jit/jit.h" |
| 29 | #include "utils/expandeddatum.h" |
| 30 | |
| 31 | |
| 32 | static TupleTableSlot *ValuesNext(ValuesScanState *node); |
| 33 | |
| 34 | |
| 35 | /* ---------------------------------------------------------------- |
| 36 | * Scan Support |
| 37 | * ---------------------------------------------------------------- |
| 38 | */ |
| 39 | |
| 40 | /* ---------------------------------------------------------------- |
| 41 | * ValuesNext |
| 42 | * |
| 43 | * This is a workhorse for ExecValuesScan |
| 44 | * ---------------------------------------------------------------- |
| 45 | */ |
| 46 | static TupleTableSlot * |
| 47 | ValuesNext(ValuesScanState *node) |
| 48 | { |
| 49 | TupleTableSlot *slot; |
| 50 | EState *estate; |
| 51 | ExprContext *econtext; |
| 52 | ScanDirection direction; |
| 53 | List *exprlist; |
| 54 | |
| 55 | /* |
| 56 | * get information from the estate and scan state |
| 57 | */ |
| 58 | estate = node->ss.ps.state; |
| 59 | direction = estate->es_direction; |
| 60 | slot = node->ss.ss_ScanTupleSlot; |
| 61 | econtext = node->rowcontext; |
| 62 | |
| 63 | /* |
| 64 | * Get the next tuple. Return NULL if no more tuples. |
| 65 | */ |
| 66 | if (ScanDirectionIsForward(direction)) |
| 67 | { |
| 68 | if (node->curr_idx < node->array_len) |
| 69 | node->curr_idx++; |
| 70 | if (node->curr_idx < node->array_len) |
| 71 | exprlist = node->exprlists[node->curr_idx]; |
| 72 | else |
| 73 | exprlist = NIL; |
| 74 | } |
| 75 | else |
| 76 | { |
| 77 | if (node->curr_idx >= 0) |
| 78 | node->curr_idx--; |
| 79 | if (node->curr_idx >= 0) |
| 80 | exprlist = node->exprlists[node->curr_idx]; |
| 81 | else |
| 82 | exprlist = NIL; |
| 83 | } |
| 84 | |
| 85 | /* |
| 86 | * Always clear the result slot; this is appropriate if we are at the end |
| 87 | * of the data, and if we're not, we still need it as the first step of |
| 88 | * the store-virtual-tuple protocol. It seems wise to clear the slot |
| 89 | * before we reset the context it might have pointers into. |
| 90 | */ |
| 91 | ExecClearTuple(slot); |
| 92 | |
| 93 | if (exprlist) |
| 94 | { |
| 95 | MemoryContext oldContext; |
| 96 | List *oldsubplans; |
| 97 | List *exprstatelist; |
| 98 | Datum *values; |
| 99 | bool *isnull; |
| 100 | ListCell *lc; |
| 101 | int resind; |
| 102 | int saved_jit_flags; |
| 103 | |
| 104 | /* |
| 105 | * Get rid of any prior cycle's leftovers. We use ReScanExprContext |
| 106 | * not just ResetExprContext because we want any registered shutdown |
| 107 | * callbacks to be called. |
| 108 | */ |
| 109 | ReScanExprContext(econtext); |
| 110 | |
| 111 | /* |
| 112 | * Build the expression eval state in the econtext's per-tuple memory. |
| 113 | * This is a tad unusual, but we want to delete the eval state again |
| 114 | * when we move to the next row, to avoid growth of memory |
| 115 | * requirements over a long values list. |
| 116 | */ |
| 117 | oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); |
| 118 | |
| 119 | /* |
| 120 | * The expressions might contain SubPlans (this is currently only |
| 121 | * possible if there's a sub-select containing a LATERAL reference, |
| 122 | * otherwise sub-selects in a VALUES list should be InitPlans). Those |
| 123 | * subplans will want to hook themselves into our subPlan list, which |
| 124 | * would result in a corrupted list after we delete the eval state. We |
| 125 | * can work around this by saving and restoring the subPlan list. |
| 126 | * (There's no need for the functionality that would be enabled by |
| 127 | * having the list entries, since the SubPlans aren't going to be |
| 128 | * re-executed anyway.) |
| 129 | */ |
| 130 | oldsubplans = node->ss.ps.subPlan; |
| 131 | node->ss.ps.subPlan = NIL; |
| 132 | |
| 133 | /* |
| 134 | * As the expressions are only ever used once, disable JIT for them. |
| 135 | * This is worthwhile because it's common to insert significant |
| 136 | * amounts of data via VALUES(). |
| 137 | */ |
| 138 | saved_jit_flags = econtext->ecxt_estate->es_jit_flags; |
| 139 | econtext->ecxt_estate->es_jit_flags = PGJIT_NONE; |
| 140 | exprstatelist = ExecInitExprList(exprlist, &node->ss.ps); |
| 141 | econtext->ecxt_estate->es_jit_flags = saved_jit_flags; |
| 142 | |
| 143 | node->ss.ps.subPlan = oldsubplans; |
| 144 | |
| 145 | /* parser should have checked all sublists are the same length */ |
| 146 | Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts); |
| 147 | |
| 148 | /* |
| 149 | * Compute the expressions and build a virtual result tuple. We |
| 150 | * already did ExecClearTuple(slot). |
| 151 | */ |
| 152 | values = slot->tts_values; |
| 153 | isnull = slot->tts_isnull; |
| 154 | |
| 155 | resind = 0; |
| 156 | foreach(lc, exprstatelist) |
| 157 | { |
| 158 | ExprState *estate = (ExprState *) lfirst(lc); |
| 159 | Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor, |
| 160 | resind); |
| 161 | |
| 162 | values[resind] = ExecEvalExpr(estate, |
| 163 | econtext, |
| 164 | &isnull[resind]); |
| 165 | |
| 166 | /* |
| 167 | * We must force any R/W expanded datums to read-only state, in |
| 168 | * case they are multiply referenced in the plan node's output |
| 169 | * expressions, or in case we skip the output projection and the |
| 170 | * output column is multiply referenced in higher plan nodes. |
| 171 | */ |
| 172 | values[resind] = MakeExpandedObjectReadOnly(values[resind], |
| 173 | isnull[resind], |
| 174 | attr->attlen); |
| 175 | |
| 176 | resind++; |
| 177 | } |
| 178 | |
| 179 | MemoryContextSwitchTo(oldContext); |
| 180 | |
| 181 | /* |
| 182 | * And return the virtual tuple. |
| 183 | */ |
| 184 | ExecStoreVirtualTuple(slot); |
| 185 | } |
| 186 | |
| 187 | return slot; |
| 188 | } |
| 189 | |
| 190 | /* |
| 191 | * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual |
| 192 | */ |
| 193 | static bool |
| 194 | ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot) |
| 195 | { |
| 196 | /* nothing to check */ |
| 197 | return true; |
| 198 | } |
| 199 | |
| 200 | /* ---------------------------------------------------------------- |
| 201 | * ExecValuesScan(node) |
| 202 | * |
| 203 | * Scans the values lists sequentially and returns the next qualifying |
| 204 | * tuple. |
| 205 | * We call the ExecScan() routine and pass it the appropriate |
| 206 | * access method functions. |
| 207 | * ---------------------------------------------------------------- |
| 208 | */ |
| 209 | static TupleTableSlot * |
| 210 | ExecValuesScan(PlanState *pstate) |
| 211 | { |
| 212 | ValuesScanState *node = castNode(ValuesScanState, pstate); |
| 213 | |
| 214 | return ExecScan(&node->ss, |
| 215 | (ExecScanAccessMtd) ValuesNext, |
| 216 | (ExecScanRecheckMtd) ValuesRecheck); |
| 217 | } |
| 218 | |
| 219 | /* ---------------------------------------------------------------- |
| 220 | * ExecInitValuesScan |
| 221 | * ---------------------------------------------------------------- |
| 222 | */ |
| 223 | ValuesScanState * |
| 224 | ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) |
| 225 | { |
| 226 | ValuesScanState *scanstate; |
| 227 | TupleDesc tupdesc; |
| 228 | ListCell *vtl; |
| 229 | int i; |
| 230 | PlanState *planstate; |
| 231 | |
| 232 | /* |
| 233 | * ValuesScan should not have any children. |
| 234 | */ |
| 235 | Assert(outerPlan(node) == NULL); |
| 236 | Assert(innerPlan(node) == NULL); |
| 237 | |
| 238 | /* |
| 239 | * create new ScanState for node |
| 240 | */ |
| 241 | scanstate = makeNode(ValuesScanState); |
| 242 | scanstate->ss.ps.plan = (Plan *) node; |
| 243 | scanstate->ss.ps.state = estate; |
| 244 | scanstate->ss.ps.ExecProcNode = ExecValuesScan; |
| 245 | |
| 246 | /* |
| 247 | * Miscellaneous initialization |
| 248 | */ |
| 249 | planstate = &scanstate->ss.ps; |
| 250 | |
| 251 | /* |
| 252 | * Create expression contexts. We need two, one for per-sublist |
| 253 | * processing and one for execScan.c to use for quals and projections. We |
| 254 | * cheat a little by using ExecAssignExprContext() to build both. |
| 255 | */ |
| 256 | ExecAssignExprContext(estate, planstate); |
| 257 | scanstate->rowcontext = planstate->ps_ExprContext; |
| 258 | ExecAssignExprContext(estate, planstate); |
| 259 | |
| 260 | /* |
| 261 | * Get info about values list, initialize scan slot with it. |
| 262 | */ |
| 263 | tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists)); |
| 264 | ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual); |
| 265 | |
| 266 | /* |
| 267 | * Initialize result type and projection. |
| 268 | */ |
| 269 | ExecInitResultTypeTL(&scanstate->ss.ps); |
| 270 | ExecAssignScanProjectionInfo(&scanstate->ss); |
| 271 | |
| 272 | /* |
| 273 | * initialize child expressions |
| 274 | */ |
| 275 | scanstate->ss.ps.qual = |
| 276 | ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); |
| 277 | |
| 278 | /* |
| 279 | * Other node-specific setup |
| 280 | */ |
| 281 | scanstate->curr_idx = -1; |
| 282 | scanstate->array_len = list_length(node->values_lists); |
| 283 | |
| 284 | /* convert list of sublists into array of sublists for easy addressing */ |
| 285 | scanstate->exprlists = (List **) |
| 286 | palloc(scanstate->array_len * sizeof(List *)); |
| 287 | i = 0; |
| 288 | foreach(vtl, node->values_lists) |
| 289 | { |
| 290 | scanstate->exprlists[i++] = (List *) lfirst(vtl); |
| 291 | } |
| 292 | |
| 293 | return scanstate; |
| 294 | } |
| 295 | |
| 296 | /* ---------------------------------------------------------------- |
| 297 | * ExecEndValuesScan |
| 298 | * |
| 299 | * frees any storage allocated through C routines. |
| 300 | * ---------------------------------------------------------------- |
| 301 | */ |
| 302 | void |
| 303 | ExecEndValuesScan(ValuesScanState *node) |
| 304 | { |
| 305 | /* |
| 306 | * Free both exprcontexts |
| 307 | */ |
| 308 | ExecFreeExprContext(&node->ss.ps); |
| 309 | node->ss.ps.ps_ExprContext = node->rowcontext; |
| 310 | ExecFreeExprContext(&node->ss.ps); |
| 311 | |
| 312 | /* |
| 313 | * clean out the tuple table |
| 314 | */ |
| 315 | if (node->ss.ps.ps_ResultTupleSlot) |
| 316 | ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); |
| 317 | ExecClearTuple(node->ss.ss_ScanTupleSlot); |
| 318 | } |
| 319 | |
| 320 | /* ---------------------------------------------------------------- |
| 321 | * ExecReScanValuesScan |
| 322 | * |
| 323 | * Rescans the relation. |
| 324 | * ---------------------------------------------------------------- |
| 325 | */ |
| 326 | void |
| 327 | ExecReScanValuesScan(ValuesScanState *node) |
| 328 | { |
| 329 | if (node->ss.ps.ps_ResultTupleSlot) |
| 330 | ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); |
| 331 | |
| 332 | ExecScanReScan(&node->ss); |
| 333 | |
| 334 | node->curr_idx = -1; |
| 335 | } |
| 336 | |