/Users/deen/code/yugabyte-db/src/postgres/src/backend/executor/execUtils.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * execUtils.c |
4 | | * miscellaneous executor utility routines |
5 | | * |
6 | | * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group |
7 | | * Portions Copyright (c) 1994, Regents of the University of California |
8 | | * |
9 | | * |
10 | | * IDENTIFICATION |
11 | | * src/backend/executor/execUtils.c |
12 | | * |
13 | | *------------------------------------------------------------------------- |
14 | | */ |
15 | | /* |
16 | | * INTERFACE ROUTINES |
17 | | * CreateExecutorState Create/delete executor working state |
18 | | * FreeExecutorState |
19 | | * CreateExprContext |
20 | | * CreateStandaloneExprContext |
21 | | * FreeExprContext |
22 | | * ReScanExprContext |
23 | | * |
24 | | * ExecAssignExprContext Common code for plan node init routines. |
25 | | * etc |
26 | | * |
27 | | * ExecOpenScanRelation Common code for scan node init routines. |
28 | | * ExecCloseScanRelation |
29 | | * |
30 | | * executor_errposition Report syntactic position of an error. |
31 | | * |
32 | | * RegisterExprContextCallback Register function shutdown callback |
33 | | * UnregisterExprContextCallback Deregister function shutdown callback |
34 | | * |
35 | | * GetAttributeByName Runtime extraction of columns from tuples. |
36 | | * GetAttributeByNum |
37 | | * |
38 | | * NOTES |
39 | | * This file has traditionally been the place to stick misc. |
40 | | * executor support stuff that doesn't really go anyplace else. |
41 | | */ |
42 | | |
43 | | #include "postgres.h" |
44 | | |
45 | | #include "access/relscan.h" |
46 | | #include "access/transam.h" |
47 | | #include "executor/executor.h" |
48 | | #include "jit/jit.h" |
49 | | #include "mb/pg_wchar.h" |
50 | | #include "nodes/nodeFuncs.h" |
51 | | #include "parser/parsetree.h" |
52 | | #include "storage/lmgr.h" |
53 | | #include "utils/builtins.h" |
54 | | #include "utils/memutils.h" |
55 | | #include "utils/rel.h" |
56 | | #include "utils/typcache.h" |
57 | | |
58 | | |
59 | | static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc); |
60 | | static void ShutdownExprContext(ExprContext *econtext, bool isCommit); |
61 | | |
62 | | |
63 | | /* ---------------------------------------------------------------- |
64 | | * Executor state and memory management functions |
65 | | * ---------------------------------------------------------------- |
66 | | */ |
67 | | |
68 | | /* ---------------- |
69 | | * CreateExecutorState |
70 | | * |
71 | | * Create and initialize an EState node, which is the root of |
72 | | * working storage for an entire Executor invocation. |
73 | | * |
74 | | * Principally, this creates the per-query memory context that will be |
75 | | * used to hold all working data that lives till the end of the query. |
76 | | * Note that the per-query context will become a child of the caller's |
77 | | * GetCurrentMemoryContext(). |
78 | | * ---------------- |
79 | | */ |
80 | | EState * |
81 | | CreateExecutorState(void) |
82 | 696k | { |
83 | 696k | EState *estate; |
84 | 696k | MemoryContext qcontext; |
85 | 696k | MemoryContext oldcontext; |
86 | | |
87 | | /* |
88 | | * Create the per-query context for this Executor run. |
89 | | */ |
90 | 696k | qcontext = AllocSetContextCreate(GetCurrentMemoryContext(), |
91 | 696k | "ExecutorState", |
92 | 696k | ALLOCSET_DEFAULT_SIZES); |
93 | | |
94 | | /* |
95 | | * Make the EState node within the per-query context. This way, we don't |
96 | | * need a separate pfree() operation for it at shutdown. |
97 | | */ |
98 | 696k | oldcontext = MemoryContextSwitchTo(qcontext); |
99 | | |
100 | 696k | estate = makeNode(EState); |
101 | | |
102 | | /* |
103 | | * Initialize all fields of the Executor State structure |
104 | | */ |
105 | 0 | estate->es_direction = ForwardScanDirection; |
106 | 696k | estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */ |
107 | 696k | estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */ |
108 | 696k | estate->es_range_table = NIL; |
109 | 696k | estate->es_plannedstmt = NULL; |
110 | | |
111 | 696k | estate->es_junkFilter = NULL; |
112 | | |
113 | 696k | estate->es_output_cid = (CommandId) 0; |
114 | | |
115 | 696k | estate->es_result_relations = NULL; |
116 | 696k | estate->es_num_result_relations = 0; |
117 | 696k | estate->es_result_relation_info = NULL; |
118 | | |
119 | 696k | estate->es_root_result_relations = NULL; |
120 | 696k | estate->es_num_root_result_relations = 0; |
121 | | |
122 | 696k | estate->es_tuple_routing_result_relations = NIL; |
123 | | |
124 | 696k | estate->es_trig_target_relations = NIL; |
125 | 696k | estate->es_trig_tuple_slot = NULL; |
126 | 696k | estate->es_trig_oldtup_slot = NULL; |
127 | 696k | estate->es_trig_newtup_slot = NULL; |
128 | | |
129 | 696k | estate->es_param_list_info = NULL; |
130 | 696k | estate->es_param_exec_vals = NULL; |
131 | | |
132 | 696k | estate->es_queryEnv = NULL; |
133 | | |
134 | 696k | estate->es_query_cxt = qcontext; |
135 | | |
136 | 696k | estate->es_tupleTable = NIL; |
137 | | |
138 | 696k | estate->es_rowMarks = NIL; |
139 | | |
140 | 696k | estate->es_processed = 0; |
141 | 696k | estate->es_lastoid = InvalidOid; |
142 | | |
143 | 696k | estate->es_top_eflags = 0; |
144 | 696k | estate->es_instrument = 0; |
145 | 696k | estate->es_finished = false; |
146 | | |
147 | 696k | estate->es_exprcontexts = NIL; |
148 | | |
149 | 696k | estate->es_subplanstates = NIL; |
150 | | |
151 | 696k | estate->es_auxmodifytables = NIL; |
152 | | |
153 | 696k | estate->es_per_tuple_exprcontext = NULL; |
154 | | |
155 | 696k | estate->es_epqTuple = NULL; |
156 | 696k | estate->es_epqTupleSet = NULL; |
157 | 696k | estate->es_epqScanDone = NULL; |
158 | 696k | estate->es_sourceText = NULL; |
159 | | |
160 | 696k | estate->es_use_parallel_mode = false; |
161 | | |
162 | 696k | estate->es_jit_flags = 0; |
163 | 696k | estate->es_jit = NULL; |
164 | | |
165 | | /* |
166 | | * Return the executor state structure |
167 | | */ |
168 | 696k | MemoryContextSwitchTo(oldcontext); |
169 | | |
170 | | /* |
171 | | * YugaByte-specific fields |
172 | | */ |
173 | 696k | estate->yb_es_is_single_row_modify_txn = false; |
174 | 696k | estate->yb_conflict_slot = NULL; |
175 | | /* |
176 | | * The read hybrid time used for this query. This will be initialized |
177 | | * by the first read operation invoked for this query, and all later |
178 | | * reads performed by this query will not read any data written past this time. |
179 | | */ |
180 | 696k | estate->yb_es_read_ht = 0; |
181 | | |
182 | 696k | estate->yb_exec_params.limit_count = 0; |
183 | 696k | estate->yb_exec_params.limit_offset = 0; |
184 | 696k | estate->yb_exec_params.limit_use_default = true; |
185 | 696k | estate->yb_exec_params.rowmark = -1; |
186 | 696k | estate->yb_exec_params.is_index_backfill = false; |
187 | | /* |
188 | | * Pointer to the query read hybrid time. This pointer is passed |
189 | | * down to all the DocDB read operations invoked for this query. Only |
190 | | * the first read operation initializes its value, and all the other |
191 | | * operations ensure that they don't read any value written past this time. |
192 | | */ |
193 | 696k | estate->yb_exec_params.statement_read_time = &estate->yb_es_read_ht; |
194 | | |
195 | 696k | return estate; |
196 | 696k | } |
197 | | |
198 | | /* ---------------- |
199 | | * FreeExecutorState |
200 | | * |
201 | | * Release an EState along with all remaining working storage. |
202 | | * |
203 | | * Note: this is not responsible for releasing non-memory resources, such as |
204 | | * open relations or buffer pins. But it will shut down any still-active |
205 | | * ExprContexts within the EState and deallocate associated JITed expressions. |
206 | | * That is sufficient cleanup for situations where the EState has only been |
207 | | * used for expression evaluation, and not to run a complete Plan. |
208 | | * |
209 | | * This can be called in any memory context ... so long as it's not one |
210 | | * of the ones to be freed. |
211 | | * ---------------- |
212 | | */ |
213 | | void |
214 | | FreeExecutorState(EState *estate) |
215 | 587k | { |
216 | | /* |
217 | | * Shut down and free any remaining ExprContexts. We do this explicitly |
218 | | * to ensure that any remaining shutdown callbacks get called (since they |
219 | | * might need to release resources that aren't simply memory within the |
220 | | * per-query memory context). |
221 | | */ |
222 | 1.37M | while (estate->es_exprcontexts) |
223 | 784k | { |
224 | | /* |
225 | | * XXX: seems there ought to be a faster way to implement this than |
226 | | * repeated list_delete(), no? |
227 | | */ |
228 | 784k | FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts), |
229 | 784k | true); |
230 | | /* FreeExprContext removed the list link for us */ |
231 | 784k | } |
232 | | |
233 | | /* release JIT context, if allocated */ |
234 | 587k | if (estate->es_jit) |
235 | 0 | { |
236 | 0 | jit_release_context(estate->es_jit); |
237 | 0 | estate->es_jit = NULL; |
238 | 0 | } |
239 | | |
240 | | /* |
241 | | * Free the per-query memory context, thereby releasing all working |
242 | | * memory, including the EState node itself. |
243 | | */ |
244 | 587k | MemoryContextDelete(estate->es_query_cxt); |
245 | 587k | } |
246 | | |
247 | | /* ---------------- |
248 | | * CreateExprContext |
249 | | * |
250 | | * Create a context for expression evaluation within an EState. |
251 | | * |
252 | | * An executor run may require multiple ExprContexts (we usually make one |
253 | | * for each Plan node, and a separate one for per-output-tuple processing |
254 | | * such as constraint checking). Each ExprContext has its own "per-tuple" |
255 | | * memory context. |
256 | | * |
257 | | * Note we make no assumption about the caller's memory context. |
258 | | * ---------------- |
259 | | */ |
260 | | ExprContext * |
261 | | CreateExprContext(EState *estate) |
262 | 935k | { |
263 | 935k | ExprContext *econtext; |
264 | 935k | MemoryContext oldcontext; |
265 | | |
266 | | /* Create the ExprContext node within the per-query memory context */ |
267 | 935k | oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); |
268 | | |
269 | 935k | econtext = makeNode(ExprContext); |
270 | | |
271 | | /* Initialize fields of ExprContext */ |
272 | 0 | econtext->ecxt_scantuple = NULL; |
273 | 935k | econtext->ecxt_innertuple = NULL; |
274 | 935k | econtext->ecxt_outertuple = NULL; |
275 | | |
276 | 935k | econtext->ecxt_per_query_memory = estate->es_query_cxt; |
277 | | |
278 | | /* |
279 | | * Create working memory for expression evaluation in this context. |
280 | | */ |
281 | 935k | econtext->ecxt_per_tuple_memory = |
282 | 935k | AllocSetContextCreate(estate->es_query_cxt, |
283 | 935k | "ExprContext", |
284 | 935k | ALLOCSET_DEFAULT_SIZES); |
285 | | |
286 | 935k | econtext->ecxt_param_exec_vals = estate->es_param_exec_vals; |
287 | 935k | econtext->ecxt_param_list_info = estate->es_param_list_info; |
288 | | |
289 | 935k | econtext->ecxt_aggvalues = NULL; |
290 | 935k | econtext->ecxt_aggnulls = NULL; |
291 | | |
292 | 935k | econtext->caseValue_datum = (Datum) 0; |
293 | 935k | econtext->caseValue_isNull = true; |
294 | | |
295 | 935k | econtext->domainValue_datum = (Datum) 0; |
296 | 935k | econtext->domainValue_isNull = true; |
297 | | |
298 | 935k | econtext->ecxt_estate = estate; |
299 | | |
300 | 935k | econtext->ecxt_callbacks = NULL; |
301 | | |
302 | | /* |
303 | | * Link the ExprContext into the EState to ensure it is shut down when the |
304 | | * EState is freed. Because we use lcons(), shutdowns will occur in |
305 | | * reverse order of creation, which may not be essential but can't hurt. |
306 | | */ |
307 | 935k | estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts); |
308 | | |
309 | 935k | MemoryContextSwitchTo(oldcontext); |
310 | | |
311 | 935k | return econtext; |
312 | 935k | } |
313 | | |
314 | | /* ---------------- |
315 | | * CreateStandaloneExprContext |
316 | | * |
317 | | * Create a context for standalone expression evaluation. |
318 | | * |
319 | | * An ExprContext made this way can be used for evaluation of expressions |
320 | | * that contain no Params, subplans, or Var references (it might work to |
321 | | * put tuple references into the scantuple field, but it seems unwise). |
322 | | * |
323 | | * The ExprContext struct is allocated in the caller's current memory |
324 | | * context, which also becomes its "per query" context. |
325 | | * |
326 | | * It is caller's responsibility to free the ExprContext when done, |
327 | | * or at least ensure that any shutdown callbacks have been called |
328 | | * (ReScanExprContext() is suitable). Otherwise, non-memory resources |
329 | | * might be leaked. |
330 | | * ---------------- |
331 | | */ |
332 | | ExprContext * |
333 | | CreateStandaloneExprContext(void) |
334 | 781 | { |
335 | 781 | ExprContext *econtext; |
336 | | |
337 | | /* Create the ExprContext node within the caller's memory context */ |
338 | 781 | econtext = makeNode(ExprContext); |
339 | | |
340 | | /* Initialize fields of ExprContext */ |
341 | 0 | econtext->ecxt_scantuple = NULL; |
342 | 781 | econtext->ecxt_innertuple = NULL; |
343 | 781 | econtext->ecxt_outertuple = NULL; |
344 | | |
345 | 781 | econtext->ecxt_per_query_memory = GetCurrentMemoryContext(); |
346 | | |
347 | | /* |
348 | | * Create working memory for expression evaluation in this context. |
349 | | */ |
350 | 781 | econtext->ecxt_per_tuple_memory = |
351 | 781 | AllocSetContextCreate(GetCurrentMemoryContext(), |
352 | 781 | "ExprContext", |
353 | 781 | ALLOCSET_DEFAULT_SIZES); |
354 | | |
355 | 781 | econtext->ecxt_param_exec_vals = NULL; |
356 | 781 | econtext->ecxt_param_list_info = NULL; |
357 | | |
358 | 781 | econtext->ecxt_aggvalues = NULL; |
359 | 781 | econtext->ecxt_aggnulls = NULL; |
360 | | |
361 | 781 | econtext->caseValue_datum = (Datum) 0; |
362 | 781 | econtext->caseValue_isNull = true; |
363 | | |
364 | 781 | econtext->domainValue_datum = (Datum) 0; |
365 | 781 | econtext->domainValue_isNull = true; |
366 | | |
367 | 781 | econtext->ecxt_estate = NULL; |
368 | | |
369 | 781 | econtext->ecxt_callbacks = NULL; |
370 | | |
371 | 781 | return econtext; |
372 | 781 | } |
373 | | |
374 | | /* ---------------- |
375 | | * FreeExprContext |
376 | | * |
377 | | * Free an expression context, including calling any remaining |
378 | | * shutdown callbacks. |
379 | | * |
380 | | * Since we free the temporary context used for expression evaluation, |
381 | | * any previously computed pass-by-reference expression result will go away! |
382 | | * |
383 | | * If isCommit is false, we are being called in error cleanup, and should |
384 | | * not call callbacks but only release memory. (It might be better to call |
385 | | * the callbacks and pass the isCommit flag to them, but that would require |
386 | | * more invasive code changes than currently seems justified.) |
387 | | * |
388 | | * Note we make no assumption about the caller's memory context. |
389 | | * ---------------- |
390 | | */ |
391 | | void |
392 | | FreeExprContext(ExprContext *econtext, bool isCommit) |
393 | 792k | { |
394 | 792k | EState *estate; |
395 | | |
396 | | /* Call any registered callbacks */ |
397 | 792k | ShutdownExprContext(econtext, isCommit); |
398 | | /* And clean up the memory used */ |
399 | 792k | MemoryContextDelete(econtext->ecxt_per_tuple_memory); |
400 | | /* Unlink self from owning EState, if any */ |
401 | 792k | estate = econtext->ecxt_estate; |
402 | 792k | if (estate) |
403 | 791k | estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts, |
404 | 791k | econtext); |
405 | | /* And delete the ExprContext node */ |
406 | 792k | pfree(econtext); |
407 | 792k | } |
408 | | |
409 | | /* |
410 | | * ReScanExprContext |
411 | | * |
412 | | * Reset an expression context in preparation for a rescan of its |
413 | | * plan node. This requires calling any registered shutdown callbacks, |
414 | | * since any partially complete set-returning-functions must be canceled. |
415 | | * |
416 | | * Note we make no assumption about the caller's memory context. |
417 | | */ |
418 | | void |
419 | | ReScanExprContext(ExprContext *econtext) |
420 | 636k | { |
421 | | /* Call any registered callbacks */ |
422 | 636k | ShutdownExprContext(econtext, true); |
423 | | /* And clean up the memory used */ |
424 | 636k | MemoryContextReset(econtext->ecxt_per_tuple_memory); |
425 | 636k | } |
426 | | |
427 | | /* |
428 | | * Build a per-output-tuple ExprContext for an EState. |
429 | | * |
430 | | * This is normally invoked via GetPerTupleExprContext() macro, |
431 | | * not directly. |
432 | | */ |
433 | | ExprContext * |
434 | | MakePerTupleExprContext(EState *estate) |
435 | 194k | { |
436 | 194k | if (estate->es_per_tuple_exprcontext == NULL) |
437 | 194k | estate->es_per_tuple_exprcontext = CreateExprContext(estate); |
438 | | |
439 | 194k | return estate->es_per_tuple_exprcontext; |
440 | 194k | } |
441 | | |
442 | | |
443 | | /* ---------------------------------------------------------------- |
444 | | * miscellaneous node-init support functions |
445 | | * |
446 | | * Note: all of these are expected to be called with GetCurrentMemoryContext() |
447 | | * equal to the per-query memory context. |
448 | | * ---------------------------------------------------------------- |
449 | | */ |
450 | | |
451 | | /* ---------------- |
452 | | * ExecAssignExprContext |
453 | | * |
454 | | * This initializes the ps_ExprContext field. It is only necessary |
455 | | * to do this for nodes which use ExecQual or ExecProject |
456 | | * because those routines require an econtext. Other nodes that |
457 | | * don't have to evaluate expressions don't need to do this. |
458 | | * ---------------- |
459 | | */ |
460 | | void |
461 | | ExecAssignExprContext(EState *estate, PlanState *planstate) |
462 | 727k | { |
463 | 727k | planstate->ps_ExprContext = CreateExprContext(estate); |
464 | 727k | } |
465 | | |
466 | | /* ---------------- |
467 | | * ExecGetResultType |
468 | | * ---------------- |
469 | | */ |
470 | | TupleDesc |
471 | | ExecGetResultType(PlanState *planstate) |
472 | 633k | { |
473 | 633k | return planstate->ps_ResultTupleDesc; |
474 | 633k | } |
475 | | |
476 | | |
477 | | /* ---------------- |
478 | | * ExecAssignProjectionInfo |
479 | | * |
480 | | * forms the projection information from the node's targetlist |
481 | | * |
482 | | * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it |
483 | | * for a relation-scan node, can pass NULL for upper-level nodes |
484 | | * ---------------- |
485 | | */ |
486 | | void |
487 | | ExecAssignProjectionInfo(PlanState *planstate, |
488 | | TupleDesc inputDesc) |
489 | 479k | { |
490 | 479k | planstate->ps_ProjInfo = |
491 | 479k | ExecBuildProjectionInfo(planstate->plan->targetlist, |
492 | 479k | planstate->ps_ExprContext, |
493 | 479k | planstate->ps_ResultTupleSlot, |
494 | 479k | planstate, |
495 | 479k | inputDesc); |
496 | 479k | } |
497 | | |
498 | | |
499 | | /* ---------------- |
500 | | * ExecConditionalAssignProjectionInfo |
501 | | * |
502 | | * as ExecAssignProjectionInfo, but store NULL rather than building projection |
503 | | * info if no projection is required |
504 | | * ---------------- |
505 | | */ |
506 | | void |
507 | | ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc, |
508 | | Index varno) |
509 | 231k | { |
510 | 231k | if (tlist_matches_tupdesc(planstate, |
511 | 231k | planstate->plan->targetlist, |
512 | 231k | varno, |
513 | 231k | inputDesc)) |
514 | 165k | planstate->ps_ProjInfo = NULL; |
515 | 65.6k | else |
516 | 65.6k | { |
517 | 65.6k | if (!planstate->ps_ResultTupleSlot) |
518 | 65.8k | ExecInitResultSlot(planstate); |
519 | 65.6k | ExecAssignProjectionInfo(planstate, inputDesc); |
520 | 65.6k | } |
521 | 231k | } |
522 | | |
523 | | static bool |
524 | | tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc) |
525 | 231k | { |
526 | 231k | int numattrs = tupdesc->natts; |
527 | 231k | int attrno; |
528 | 231k | bool hasoid; |
529 | 231k | ListCell *tlist_item = list_head(tlist); |
530 | | |
531 | | /* Check the tlist attributes */ |
532 | 739k | for (attrno = 1; attrno <= numattrs; attrno++508k ) |
533 | 567k | { |
534 | 567k | Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1); |
535 | 567k | Var *var; |
536 | | |
537 | 567k | if (tlist_item == NULL) |
538 | 7.50k | return false; /* tlist too short */ |
539 | 559k | var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr; |
540 | 560k | if (!var559k || !IsA(var, Var)) |
541 | 29.9k | return false; /* tlist item not a Var */ |
542 | | /* if these Asserts fail, planner messed up */ |
543 | 529k | Assert(var->varno == varno); |
544 | 529k | Assert(var->varlevelsup == 0); |
545 | 529k | if (var->varattno != attrno) |
546 | 21.3k | return false; /* out of order */ |
547 | 508k | if (att_tup->attisdropped) |
548 | 0 | return false; /* table contains dropped columns */ |
549 | 508k | if (att_tup->atthasmissing) |
550 | 0 | return false; /* table contains cols with missing values */ |
551 | | |
552 | | /* |
553 | | * Note: usually the Var's type should match the tupdesc exactly, but |
554 | | * in situations involving unions of columns that have different |
555 | | * typmods, the Var may have come from above the union and hence have |
556 | | * typmod -1. This is a legitimate situation since the Var still |
557 | | * describes the column, just not as exactly as the tupdesc does. We |
558 | | * could change the planner to prevent it, but it'd then insert |
559 | | * projection steps just to convert from specific typmod to typmod -1, |
560 | | * which is pretty silly. |
561 | | */ |
562 | 508k | if (var->vartype != att_tup->atttypid || |
563 | 508k | (508k var->vartypmod != att_tup->atttypmod508k && |
564 | 508k | var->vartypmod != -10 )) |
565 | 0 | return false; /* type mismatch */ |
566 | | |
567 | 508k | tlist_item = lnext(tlist_item); |
568 | 508k | } |
569 | | |
570 | 172k | if (tlist_item) |
571 | 6.88k | return false; /* tlist too long */ |
572 | | |
573 | | /* |
574 | | * If the plan context requires a particular hasoid setting, then that has |
575 | | * to match, too. |
576 | | */ |
577 | 165k | if (ExecContextForcesOids(ps, &hasoid) && |
578 | 165k | hasoid != tupdesc->tdhasoid1.16k ) |
579 | 121 | return false; |
580 | | |
581 | 165k | return true; |
582 | 165k | } |
583 | | |
584 | | /* ---------------- |
585 | | * ExecFreeExprContext |
586 | | * |
587 | | * A plan node's ExprContext should be freed explicitly during executor |
588 | | * shutdown because there may be shutdown callbacks to call. (Other resources |
589 | | * made by the above routines, such as projection info, don't need to be freed |
590 | | * explicitly because they're just memory in the per-query memory context.) |
591 | | * |
592 | | * However ... there is no particular need to do it during ExecEndNode, |
593 | | * because FreeExecutorState will free any remaining ExprContexts within |
594 | | * the EState. Letting FreeExecutorState do it allows the ExprContexts to |
595 | | * be freed in reverse order of creation, rather than order of creation as |
596 | | * will happen if we delete them here, which saves O(N^2) work in the list |
597 | | * cleanup inside FreeExprContext. |
598 | | * ---------------- |
599 | | */ |
600 | | void |
601 | | ExecFreeExprContext(PlanState *planstate) |
602 | 801k | { |
603 | | /* |
604 | | * Per above discussion, don't actually delete the ExprContext. We do |
605 | | * unlink it from the plan node, though. |
606 | | */ |
607 | 801k | planstate->ps_ExprContext = NULL; |
608 | 801k | } |
609 | | |
610 | | |
611 | | /* ---------------------------------------------------------------- |
612 | | * Scan node support |
613 | | * ---------------------------------------------------------------- |
614 | | */ |
615 | | |
616 | | /* ---------------- |
617 | | * ExecAssignScanType |
618 | | * ---------------- |
619 | | */ |
620 | | void |
621 | | ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc) |
622 | 43 | { |
623 | 43 | TupleTableSlot *slot = scanstate->ss_ScanTupleSlot; |
624 | | |
625 | 43 | ExecSetSlotDescriptor(slot, tupDesc); |
626 | 43 | } |
627 | | |
628 | | /* ---------------- |
629 | | * ExecCreateSlotFromOuterPlan |
630 | | * ---------------- |
631 | | */ |
632 | | void |
633 | | ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate) |
634 | 24.4k | { |
635 | 24.4k | PlanState *outerPlan; |
636 | 24.4k | TupleDesc tupDesc; |
637 | | |
638 | 24.4k | outerPlan = outerPlanState(scanstate); |
639 | 24.4k | tupDesc = ExecGetResultType(outerPlan); |
640 | | |
641 | 24.4k | ExecInitScanTupleSlot(estate, scanstate, tupDesc); |
642 | 24.4k | } |
643 | | |
644 | | /* ---------------------------------------------------------------- |
645 | | * ExecRelationIsTargetRelation |
646 | | * |
647 | | * Detect whether a relation (identified by rangetable index) |
648 | | * is one of the target relations of the query. |
649 | | * ---------------------------------------------------------------- |
650 | | */ |
651 | | bool |
652 | | ExecRelationIsTargetRelation(EState *estate, Index scanrelid) |
653 | 356k | { |
654 | 356k | ResultRelInfo *resultRelInfos; |
655 | 356k | int i; |
656 | | |
657 | 356k | resultRelInfos = estate->es_result_relations; |
658 | 358k | for (i = 0; i < estate->es_num_result_relations; i++2.10k ) |
659 | 46.7k | { |
660 | 46.7k | if (resultRelInfos[i].ri_RangeTableIndex == scanrelid) |
661 | 44.6k | return true; |
662 | 46.7k | } |
663 | 311k | return false; |
664 | 356k | } |
665 | | |
666 | | /* ---------------------------------------------------------------- |
667 | | * ExecOpenScanRelation |
668 | | * |
669 | | * Open the heap relation to be scanned by a base-level scan plan node. |
670 | | * This should be called during the node's ExecInit routine. |
671 | | * |
672 | | * By default, this acquires AccessShareLock on the relation. However, |
673 | | * if the relation was already locked by InitPlan, we don't need to acquire |
674 | | * any additional lock. This saves trips to the shared lock manager. |
675 | | * ---------------------------------------------------------------- |
676 | | */ |
677 | | Relation |
678 | | ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags) |
679 | 217k | { |
680 | 217k | Relation rel; |
681 | 217k | Oid reloid; |
682 | 217k | LOCKMODE lockmode; |
683 | | |
684 | | /* |
685 | | * Determine the lock type we need. First, scan to see if target relation |
686 | | * is a result relation. If not, check if it's a FOR UPDATE/FOR SHARE |
687 | | * relation. In either of those cases, we got the lock already. |
688 | | */ |
689 | 217k | lockmode = AccessShareLock; |
690 | 217k | if (ExecRelationIsTargetRelation(estate, scanrelid)) |
691 | 27.1k | lockmode = NoLock; |
692 | 190k | else |
693 | 190k | { |
694 | | /* Keep this check in sync with InitPlan! */ |
695 | 190k | ExecRowMark *erm = ExecFindRowMark(estate, scanrelid, true); |
696 | | |
697 | 190k | if (erm != NULL && erm->relation != NULL5.75k ) |
698 | 5.72k | lockmode = NoLock; |
699 | 190k | } |
700 | | |
701 | | /* Open the relation and acquire lock as needed */ |
702 | 217k | reloid = getrelid(scanrelid, estate->es_range_table); |
703 | 217k | rel = heap_open(reloid, lockmode); |
704 | | |
705 | | /* |
706 | | * Complain if we're attempting a scan of an unscannable relation, except |
707 | | * when the query won't actually be run. This is a slightly klugy place |
708 | | * to do this, perhaps, but there is no better place. |
709 | | */ |
710 | 217k | if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 && |
711 | 217k | !214k RelationIsScannable214k (rel)) |
712 | 217k | ereport(ERROR, |
713 | 217k | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
714 | 217k | errmsg("materialized view \"%s\" has not been populated", |
715 | 217k | RelationGetRelationName(rel)), |
716 | 217k | errhint("Use the REFRESH MATERIALIZED VIEW command."))); |
717 | | |
718 | 217k | return rel; |
719 | 217k | } |
720 | | |
721 | | /* ---------------------------------------------------------------- |
722 | | * ExecCloseScanRelation |
723 | | * |
724 | | * Close the heap relation scanned by a base-level scan plan node. |
725 | | * This should be called during the node's ExecEnd routine. |
726 | | * |
727 | | * Currently, we do not release the lock acquired by ExecOpenScanRelation. |
728 | | * This lock should be held till end of transaction. (There is a faction |
729 | | * that considers this too much locking, however.) |
730 | | * |
731 | | * If we did want to release the lock, we'd have to repeat the logic in |
732 | | * ExecOpenScanRelation in order to figure out what to release. |
733 | | * ---------------------------------------------------------------- |
734 | | */ |
735 | | void |
736 | | ExecCloseScanRelation(Relation scanrel) |
737 | 160k | { |
738 | 160k | heap_close(scanrel, NoLock); |
739 | 160k | } |
740 | | |
741 | | /* |
742 | | * UpdateChangedParamSet |
743 | | * Add changed parameters to a plan node's chgParam set |
744 | | */ |
745 | | void |
746 | | UpdateChangedParamSet(PlanState *node, Bitmapset *newchg) |
747 | 134k | { |
748 | 134k | Bitmapset *parmset; |
749 | | |
750 | | /* |
751 | | * The plan node only depends on params listed in its allParam set. Don't |
752 | | * include anything else into its chgParam set. |
753 | | */ |
754 | 134k | parmset = bms_intersect(node->plan->allParam, newchg); |
755 | | |
756 | | /* |
757 | | * Keep node->chgParam == NULL if there's not actually any members; this |
758 | | * allows the simplest possible tests in executor node files. |
759 | | */ |
760 | 134k | if (!bms_is_empty(parmset)) |
761 | 117k | node->chgParam = bms_join(node->chgParam, parmset); |
762 | 17.0k | else |
763 | 17.0k | bms_free(parmset); |
764 | 134k | } |
765 | | |
766 | | /* |
767 | | * executor_errposition |
768 | | * Report an execution-time cursor position, if possible. |
769 | | * |
770 | | * This is expected to be used within an ereport() call. The return value |
771 | | * is a dummy (always 0, in fact). |
772 | | * |
773 | | * The locations stored in parsetrees are byte offsets into the source string. |
774 | | * We have to convert them to 1-based character indexes for reporting to |
775 | | * clients. (We do things this way to avoid unnecessary overhead in the |
776 | | * normal non-error case: computing character indexes would be much more |
777 | | * expensive than storing token offsets.) |
778 | | */ |
779 | | int |
780 | | executor_errposition(EState *estate, int location) |
781 | 0 | { |
782 | 0 | int pos; |
783 | | |
784 | | /* No-op if location was not provided */ |
785 | 0 | if (location < 0) |
786 | 0 | return 0; |
787 | | /* Can't do anything if source text is not available */ |
788 | 0 | if (estate == NULL || estate->es_sourceText == NULL) |
789 | 0 | return 0; |
790 | | /* Convert offset to character number */ |
791 | 0 | pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1; |
792 | | /* And pass it to the ereport mechanism */ |
793 | 0 | return errposition(pos); |
794 | 0 | } |
795 | | |
796 | | /* |
797 | | * Register a shutdown callback in an ExprContext. |
798 | | * |
799 | | * Shutdown callbacks will be called (in reverse order of registration) |
800 | | * when the ExprContext is deleted or rescanned. This provides a hook |
801 | | * for functions called in the context to do any cleanup needed --- it's |
802 | | * particularly useful for functions returning sets. Note that the |
803 | | * callback will *not* be called in the event that execution is aborted |
804 | | * by an error. |
805 | | */ |
806 | | void |
807 | | RegisterExprContextCallback(ExprContext *econtext, |
808 | | ExprContextCallbackFunction function, |
809 | | Datum arg) |
810 | 64.2k | { |
811 | 64.2k | ExprContext_CB *ecxt_callback; |
812 | | |
813 | | /* Save the info in appropriate memory context */ |
814 | 64.2k | ecxt_callback = (ExprContext_CB *) |
815 | 64.2k | MemoryContextAlloc(econtext->ecxt_per_query_memory, |
816 | 64.2k | sizeof(ExprContext_CB)); |
817 | | |
818 | 64.2k | ecxt_callback->function = function; |
819 | 64.2k | ecxt_callback->arg = arg; |
820 | | |
821 | | /* link to front of list for appropriate execution order */ |
822 | 64.2k | ecxt_callback->next = econtext->ecxt_callbacks; |
823 | 64.2k | econtext->ecxt_callbacks = ecxt_callback; |
824 | 64.2k | } |
825 | | |
826 | | /* |
827 | | * Deregister a shutdown callback in an ExprContext. |
828 | | * |
829 | | * Any list entries matching the function and arg will be removed. |
830 | | * This can be used if it's no longer necessary to call the callback. |
831 | | */ |
832 | | void |
833 | | UnregisterExprContextCallback(ExprContext *econtext, |
834 | | ExprContextCallbackFunction function, |
835 | | Datum arg) |
836 | 59.2k | { |
837 | 59.2k | ExprContext_CB **prev_callback; |
838 | 59.2k | ExprContext_CB *ecxt_callback; |
839 | | |
840 | 59.2k | prev_callback = &econtext->ecxt_callbacks; |
841 | | |
842 | 140k | while ((ecxt_callback = *prev_callback) != NULL) |
843 | 81.6k | { |
844 | 81.6k | if (ecxt_callback->function == function && ecxt_callback->arg == arg59.2k ) |
845 | 59.2k | { |
846 | 59.2k | *prev_callback = ecxt_callback->next; |
847 | 59.2k | pfree(ecxt_callback); |
848 | 59.2k | } |
849 | 22.4k | else |
850 | 22.4k | prev_callback = &ecxt_callback->next; |
851 | 81.6k | } |
852 | 59.2k | } |
853 | | |
854 | | /* |
855 | | * Call all the shutdown callbacks registered in an ExprContext. |
856 | | * |
857 | | * The callback list is emptied (important in case this is only a rescan |
858 | | * reset, and not deletion of the ExprContext). |
859 | | * |
860 | | * If isCommit is false, just clean the callback list but don't call 'em. |
861 | | * (See comment for FreeExprContext.) |
862 | | */ |
863 | | static void |
864 | | ShutdownExprContext(ExprContext *econtext, bool isCommit) |
865 | 1.42M | { |
866 | 1.42M | ExprContext_CB *ecxt_callback; |
867 | 1.42M | MemoryContext oldcontext; |
868 | | |
869 | | /* Fast path in normal case where there's nothing to do. */ |
870 | 1.42M | if (econtext->ecxt_callbacks == NULL) |
871 | 1.42M | return; |
872 | | |
873 | | /* |
874 | | * Call the callbacks in econtext's per-tuple context. This ensures that |
875 | | * any memory they might leak will get cleaned up. |
876 | | */ |
877 | 2.76k | oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); |
878 | | |
879 | | /* |
880 | | * Call each callback function in reverse registration order. |
881 | | */ |
882 | 7.70k | while ((ecxt_callback = econtext->ecxt_callbacks) != NULL) |
883 | 4.93k | { |
884 | 4.93k | econtext->ecxt_callbacks = ecxt_callback->next; |
885 | 4.93k | if (isCommit) |
886 | 4.93k | ecxt_callback->function(ecxt_callback->arg); |
887 | 4.93k | pfree(ecxt_callback); |
888 | 4.93k | } |
889 | | |
890 | 2.76k | MemoryContextSwitchTo(oldcontext); |
891 | 2.76k | } |
892 | | |
893 | | /* |
894 | | * ExecLockNonLeafAppendTables |
895 | | * |
896 | | * Locks, if necessary, the tables indicated by the RT indexes contained in |
897 | | * the partitioned_rels list. These are the non-leaf tables in the partition |
898 | | * tree controlled by a given Append or MergeAppend node. |
899 | | */ |
900 | | void |
901 | | ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate) |
902 | 1.12k | { |
903 | 1.12k | PlannedStmt *stmt = estate->es_plannedstmt; |
904 | 1.12k | ListCell *lc; |
905 | | |
906 | 1.12k | foreach(lc, partitioned_rels) |
907 | 984 | { |
908 | 984 | ListCell *l; |
909 | 984 | Index rti = lfirst_int(lc); |
910 | 984 | bool is_result_rel = false; |
911 | 984 | Oid relid = getrelid(rti, estate->es_range_table); |
912 | | |
913 | | /* If this is a result relation, already locked in InitPlan */ |
914 | 984 | foreach(l, stmt->nonleafResultRelations) |
915 | 6 | { |
916 | 6 | if (rti == lfirst_int(l)) |
917 | 0 | { |
918 | 0 | is_result_rel = true; |
919 | 0 | break; |
920 | 0 | } |
921 | 6 | } |
922 | | |
923 | | /* |
924 | | * Not a result relation; check if there is a RowMark that requires |
925 | | * taking a RowShareLock on this rel. |
926 | | */ |
927 | 984 | if (!is_result_rel) |
928 | 984 | { |
929 | 984 | PlanRowMark *rc = NULL; |
930 | | |
931 | 984 | foreach(l, stmt->rowMarks) |
932 | 23 | { |
933 | 23 | if (((PlanRowMark *) lfirst(l))->rti == rti) |
934 | 13 | { |
935 | 13 | rc = lfirst(l); |
936 | 13 | break; |
937 | 13 | } |
938 | 23 | } |
939 | | |
940 | 984 | if (rc && RowMarkRequiresRowShareLock13 (rc->markType)) |
941 | 7 | LockRelationOid(relid, RowShareLock); |
942 | 977 | else |
943 | 977 | LockRelationOid(relid, AccessShareLock); |
944 | 984 | } |
945 | 984 | } |
946 | 1.12k | } |
947 | | |
948 | | /* |
949 | | * GetAttributeByName |
950 | | * GetAttributeByNum |
951 | | * |
952 | | * These functions return the value of the requested attribute |
953 | | * out of the given tuple Datum. |
954 | | * C functions which take a tuple as an argument are expected |
955 | | * to use these. Ex: overpaid(EMP) might call GetAttributeByNum(). |
956 | | * Note: these are actually rather slow because they do a typcache |
957 | | * lookup on each call. |
958 | | */ |
959 | | Datum |
960 | | GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull) |
961 | 0 | { |
962 | 0 | AttrNumber attrno; |
963 | 0 | Datum result; |
964 | 0 | Oid tupType; |
965 | 0 | int32 tupTypmod; |
966 | 0 | TupleDesc tupDesc; |
967 | 0 | HeapTupleData tmptup; |
968 | 0 | int i; |
969 | |
|
970 | 0 | if (attname == NULL) |
971 | 0 | elog(ERROR, "invalid attribute name"); |
972 | | |
973 | 0 | if (isNull == NULL) |
974 | 0 | elog(ERROR, "a NULL isNull pointer was passed"); |
975 | | |
976 | 0 | if (tuple == NULL) |
977 | 0 | { |
978 | | /* Kinda bogus but compatible with old behavior... */ |
979 | 0 | *isNull = true; |
980 | 0 | return (Datum) 0; |
981 | 0 | } |
982 | | |
983 | 0 | tupType = HeapTupleHeaderGetTypeId(tuple); |
984 | 0 | tupTypmod = HeapTupleHeaderGetTypMod(tuple); |
985 | 0 | tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod); |
986 | |
|
987 | 0 | attrno = InvalidAttrNumber; |
988 | 0 | for (i = 0; i < tupDesc->natts; i++) |
989 | 0 | { |
990 | 0 | Form_pg_attribute att = TupleDescAttr(tupDesc, i); |
991 | |
|
992 | 0 | if (namestrcmp(&(att->attname), attname) == 0) |
993 | 0 | { |
994 | 0 | attrno = att->attnum; |
995 | 0 | break; |
996 | 0 | } |
997 | 0 | } |
998 | |
|
999 | 0 | if (attrno == InvalidAttrNumber) |
1000 | 0 | elog(ERROR, "attribute \"%s\" does not exist", attname); |
1001 | | |
1002 | | /* |
1003 | | * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all |
1004 | | * the fields in the struct just in case user tries to inspect system |
1005 | | * columns. |
1006 | | */ |
1007 | 0 | tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); |
1008 | 0 | ItemPointerSetInvalid(&(tmptup.t_self)); |
1009 | 0 | tmptup.t_tableOid = InvalidOid; |
1010 | 0 | tmptup.t_data = tuple; |
1011 | |
|
1012 | 0 | result = heap_getattr(&tmptup, |
1013 | 0 | attrno, |
1014 | 0 | tupDesc, |
1015 | 0 | isNull); |
1016 | | |
1017 | 0 | ReleaseTupleDesc(tupDesc); |
1018 | |
|
1019 | 0 | return result; |
1020 | 0 | } |
1021 | | |
1022 | | Datum |
1023 | | GetAttributeByNum(HeapTupleHeader tuple, |
1024 | | AttrNumber attrno, |
1025 | | bool *isNull) |
1026 | 0 | { |
1027 | 0 | Datum result; |
1028 | 0 | Oid tupType; |
1029 | 0 | int32 tupTypmod; |
1030 | 0 | TupleDesc tupDesc; |
1031 | 0 | HeapTupleData tmptup; |
1032 | |
|
1033 | 0 | if (!AttributeNumberIsValid(attrno)) |
1034 | 0 | elog(ERROR, "invalid attribute number %d", attrno); |
1035 | | |
1036 | 0 | if (isNull == NULL) |
1037 | 0 | elog(ERROR, "a NULL isNull pointer was passed"); |
1038 | | |
1039 | 0 | if (tuple == NULL) |
1040 | 0 | { |
1041 | | /* Kinda bogus but compatible with old behavior... */ |
1042 | 0 | *isNull = true; |
1043 | 0 | return (Datum) 0; |
1044 | 0 | } |
1045 | | |
1046 | 0 | tupType = HeapTupleHeaderGetTypeId(tuple); |
1047 | 0 | tupTypmod = HeapTupleHeaderGetTypMod(tuple); |
1048 | 0 | tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod); |
1049 | | |
1050 | | /* |
1051 | | * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all |
1052 | | * the fields in the struct just in case user tries to inspect system |
1053 | | * columns. |
1054 | | */ |
1055 | 0 | tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); |
1056 | 0 | ItemPointerSetInvalid(&(tmptup.t_self)); |
1057 | 0 | tmptup.t_tableOid = InvalidOid; |
1058 | 0 | tmptup.t_data = tuple; |
1059 | |
|
1060 | 0 | result = heap_getattr(&tmptup, |
1061 | 0 | attrno, |
1062 | 0 | tupDesc, |
1063 | 0 | isNull); |
1064 | | |
1065 | 0 | ReleaseTupleDesc(tupDesc); |
1066 | |
|
1067 | 0 | return result; |
1068 | 0 | } |
1069 | | |
1070 | | /* |
1071 | | * Number of items in a tlist (including any resjunk items!) |
1072 | | */ |
1073 | | int |
1074 | | ExecTargetListLength(List *targetlist) |
1075 | 1.18M | { |
1076 | | /* This used to be more complex, but fjoins are dead */ |
1077 | 1.18M | return list_length(targetlist); |
1078 | 1.18M | } |
1079 | | |
1080 | | /* |
1081 | | * Number of items in a tlist, not including any resjunk items |
1082 | | */ |
1083 | | int |
1084 | | ExecCleanTargetListLength(List *targetlist) |
1085 | 128k | { |
1086 | 128k | int len = 0; |
1087 | 128k | ListCell *tl; |
1088 | | |
1089 | 128k | foreach(tl, targetlist) |
1090 | 304k | { |
1091 | 304k | TargetEntry *curTle = lfirst_node(TargetEntry, tl); |
1092 | | |
1093 | 304k | if (!curTle->resjunk) |
1094 | 268k | len++; |
1095 | 304k | } |
1096 | 128k | return len; |
1097 | 128k | } |