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