Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * execUtils.c
4 : * miscellaneous executor utility routines
5 : *
6 : * Portions Copyright (c) 1996-2025, 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/table.h"
50 : #include "access/tableam.h"
51 : #include "executor/executor.h"
52 : #include "executor/nodeModifyTable.h"
53 : #include "jit/jit.h"
54 : #include "mb/pg_wchar.h"
55 : #include "miscadmin.h"
56 : #include "parser/parse_relation.h"
57 : #include "partitioning/partdesc.h"
58 : #include "storage/lmgr.h"
59 : #include "utils/builtins.h"
60 : #include "utils/memutils.h"
61 : #include "utils/rel.h"
62 : #include "utils/typcache.h"
63 :
64 :
65 : static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc);
66 : static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
67 : static RTEPermissionInfo *GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate);
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 1312938 : 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 1312938 : 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 1312938 : oldcontext = MemoryContextSwitchTo(qcontext);
106 :
107 1312938 : estate = makeNode(EState);
108 :
109 : /*
110 : * Initialize all fields of the Executor State structure
111 : */
112 1312938 : estate->es_direction = ForwardScanDirection;
113 1312938 : estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
114 1312938 : estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
115 1312938 : estate->es_range_table = NIL;
116 1312938 : estate->es_range_table_size = 0;
117 1312938 : estate->es_relations = NULL;
118 1312938 : estate->es_rowmarks = NULL;
119 1312938 : estate->es_rteperminfos = NIL;
120 1312938 : estate->es_plannedstmt = NULL;
121 1312938 : estate->es_part_prune_infos = NIL;
122 :
123 1312938 : estate->es_junkFilter = NULL;
124 :
125 1312938 : estate->es_output_cid = (CommandId) 0;
126 :
127 1312938 : estate->es_result_relations = NULL;
128 1312938 : estate->es_opened_result_relations = NIL;
129 1312938 : estate->es_tuple_routing_result_relations = NIL;
130 1312938 : estate->es_trig_target_relations = NIL;
131 :
132 1312938 : estate->es_insert_pending_result_relations = NIL;
133 1312938 : estate->es_insert_pending_modifytables = NIL;
134 :
135 1312938 : estate->es_param_list_info = NULL;
136 1312938 : estate->es_param_exec_vals = NULL;
137 :
138 1312938 : estate->es_queryEnv = NULL;
139 :
140 1312938 : estate->es_query_cxt = qcontext;
141 :
142 1312938 : estate->es_tupleTable = NIL;
143 :
144 1312938 : estate->es_processed = 0;
145 1312938 : estate->es_total_processed = 0;
146 :
147 1312938 : estate->es_top_eflags = 0;
148 1312938 : estate->es_instrument = 0;
149 1312938 : estate->es_finished = false;
150 1312938 : estate->es_aborted = false;
151 :
152 1312938 : estate->es_exprcontexts = NIL;
153 :
154 1312938 : estate->es_subplanstates = NIL;
155 :
156 1312938 : estate->es_auxmodifytables = NIL;
157 :
158 1312938 : estate->es_per_tuple_exprcontext = NULL;
159 :
160 1312938 : estate->es_sourceText = NULL;
161 :
162 1312938 : estate->es_use_parallel_mode = false;
163 1312938 : estate->es_parallel_workers_to_launch = 0;
164 1312938 : estate->es_parallel_workers_launched = 0;
165 :
166 1312938 : estate->es_jit_flags = 0;
167 1312938 : estate->es_jit = NULL;
168 :
169 : /*
170 : * Return the executor state structure
171 : */
172 1312938 : MemoryContextSwitchTo(oldcontext);
173 :
174 1312938 : return estate;
175 : }
176 :
177 : /* ----------------
178 : * FreeExecutorState
179 : *
180 : * Release an EState along with all remaining working storage.
181 : *
182 : * Note: this is not responsible for releasing non-memory resources, such as
183 : * open relations or buffer pins. But it will shut down any still-active
184 : * ExprContexts within the EState and deallocate associated JITed expressions.
185 : * That is sufficient cleanup for situations where the EState has only been
186 : * used for expression evaluation, and not to run a complete Plan.
187 : *
188 : * This can be called in any memory context ... so long as it's not one
189 : * of the ones to be freed.
190 : * ----------------
191 : */
192 : void
193 1278160 : FreeExecutorState(EState *estate)
194 : {
195 : /*
196 : * Shut down and free any remaining ExprContexts. We do this explicitly
197 : * to ensure that any remaining shutdown callbacks get called (since they
198 : * might need to release resources that aren't simply memory within the
199 : * per-query memory context).
200 : */
201 3392874 : while (estate->es_exprcontexts)
202 : {
203 : /*
204 : * XXX: seems there ought to be a faster way to implement this than
205 : * repeated list_delete(), no?
206 : */
207 2114714 : FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
208 : true);
209 : /* FreeExprContext removed the list link for us */
210 : }
211 :
212 : /* release JIT context, if allocated */
213 1278160 : if (estate->es_jit)
214 : {
215 1206 : jit_release_context(estate->es_jit);
216 1206 : estate->es_jit = NULL;
217 : }
218 :
219 : /* release partition directory, if allocated */
220 1278160 : if (estate->es_partition_directory)
221 : {
222 6896 : DestroyPartitionDirectory(estate->es_partition_directory);
223 6896 : estate->es_partition_directory = NULL;
224 : }
225 :
226 : /*
227 : * Free the per-query memory context, thereby releasing all working
228 : * memory, including the EState node itself.
229 : */
230 1278160 : MemoryContextDelete(estate->es_query_cxt);
231 1278160 : }
232 :
233 : /*
234 : * Internal implementation for CreateExprContext() and CreateWorkExprContext()
235 : * that allows control over the AllocSet parameters.
236 : */
237 : static ExprContext *
238 2254242 : CreateExprContextInternal(EState *estate, Size minContextSize,
239 : Size initBlockSize, Size maxBlockSize)
240 : {
241 : ExprContext *econtext;
242 : MemoryContext oldcontext;
243 :
244 : /* Create the ExprContext node within the per-query memory context */
245 2254242 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
246 :
247 2254242 : econtext = makeNode(ExprContext);
248 :
249 : /* Initialize fields of ExprContext */
250 2254242 : econtext->ecxt_scantuple = NULL;
251 2254242 : econtext->ecxt_innertuple = NULL;
252 2254242 : econtext->ecxt_outertuple = NULL;
253 :
254 2254242 : econtext->ecxt_per_query_memory = estate->es_query_cxt;
255 :
256 : /*
257 : * Create working memory for expression evaluation in this context.
258 : */
259 2254242 : econtext->ecxt_per_tuple_memory =
260 2254242 : AllocSetContextCreate(estate->es_query_cxt,
261 : "ExprContext",
262 : minContextSize,
263 : initBlockSize,
264 : maxBlockSize);
265 :
266 2254242 : econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
267 2254242 : econtext->ecxt_param_list_info = estate->es_param_list_info;
268 :
269 2254242 : econtext->ecxt_aggvalues = NULL;
270 2254242 : econtext->ecxt_aggnulls = NULL;
271 :
272 2254242 : econtext->caseValue_datum = (Datum) 0;
273 2254242 : econtext->caseValue_isNull = true;
274 :
275 2254242 : econtext->domainValue_datum = (Datum) 0;
276 2254242 : econtext->domainValue_isNull = true;
277 :
278 2254242 : econtext->ecxt_estate = estate;
279 :
280 2254242 : econtext->ecxt_callbacks = NULL;
281 :
282 : /*
283 : * Link the ExprContext into the EState to ensure it is shut down when the
284 : * EState is freed. Because we use lcons(), shutdowns will occur in
285 : * reverse order of creation, which may not be essential but can't hurt.
286 : */
287 2254242 : estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
288 :
289 2254242 : MemoryContextSwitchTo(oldcontext);
290 :
291 2254242 : return econtext;
292 : }
293 :
294 : /* ----------------
295 : * CreateExprContext
296 : *
297 : * Create a context for expression evaluation within an EState.
298 : *
299 : * An executor run may require multiple ExprContexts (we usually make one
300 : * for each Plan node, and a separate one for per-output-tuple processing
301 : * such as constraint checking). Each ExprContext has its own "per-tuple"
302 : * memory context.
303 : *
304 : * Note we make no assumption about the caller's memory context.
305 : * ----------------
306 : */
307 : ExprContext *
308 2248516 : CreateExprContext(EState *estate)
309 : {
310 2248516 : return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
311 : }
312 :
313 :
314 : /* ----------------
315 : * CreateWorkExprContext
316 : *
317 : * Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
318 : * in proportion to work_mem. If the maximum block allocation size is too
319 : * large, it's easy to skip right past work_mem with a single allocation.
320 : * ----------------
321 : */
322 : ExprContext *
323 5726 : CreateWorkExprContext(EState *estate)
324 : {
325 5726 : Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
326 :
327 5726 : maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16);
328 :
329 : /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */
330 5726 : maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE);
331 :
332 : /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */
333 5726 : maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE);
334 :
335 5726 : return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_MINSIZE,
336 : ALLOCSET_DEFAULT_INITSIZE, maxBlockSize);
337 : }
338 :
339 : /* ----------------
340 : * CreateStandaloneExprContext
341 : *
342 : * Create a context for standalone expression evaluation.
343 : *
344 : * An ExprContext made this way can be used for evaluation of expressions
345 : * that contain no Params, subplans, or Var references (it might work to
346 : * put tuple references into the scantuple field, but it seems unwise).
347 : *
348 : * The ExprContext struct is allocated in the caller's current memory
349 : * context, which also becomes its "per query" context.
350 : *
351 : * It is caller's responsibility to free the ExprContext when done,
352 : * or at least ensure that any shutdown callbacks have been called
353 : * (ReScanExprContext() is suitable). Otherwise, non-memory resources
354 : * might be leaked.
355 : * ----------------
356 : */
357 : ExprContext *
358 8832 : CreateStandaloneExprContext(void)
359 : {
360 : ExprContext *econtext;
361 :
362 : /* Create the ExprContext node within the caller's memory context */
363 8832 : econtext = makeNode(ExprContext);
364 :
365 : /* Initialize fields of ExprContext */
366 8832 : econtext->ecxt_scantuple = NULL;
367 8832 : econtext->ecxt_innertuple = NULL;
368 8832 : econtext->ecxt_outertuple = NULL;
369 :
370 8832 : econtext->ecxt_per_query_memory = CurrentMemoryContext;
371 :
372 : /*
373 : * Create working memory for expression evaluation in this context.
374 : */
375 8832 : econtext->ecxt_per_tuple_memory =
376 8832 : AllocSetContextCreate(CurrentMemoryContext,
377 : "ExprContext",
378 : ALLOCSET_DEFAULT_SIZES);
379 :
380 8832 : econtext->ecxt_param_exec_vals = NULL;
381 8832 : econtext->ecxt_param_list_info = NULL;
382 :
383 8832 : econtext->ecxt_aggvalues = NULL;
384 8832 : econtext->ecxt_aggnulls = NULL;
385 :
386 8832 : econtext->caseValue_datum = (Datum) 0;
387 8832 : econtext->caseValue_isNull = true;
388 :
389 8832 : econtext->domainValue_datum = (Datum) 0;
390 8832 : econtext->domainValue_isNull = true;
391 :
392 8832 : econtext->ecxt_estate = NULL;
393 :
394 8832 : econtext->ecxt_callbacks = NULL;
395 :
396 8832 : return econtext;
397 : }
398 :
399 : /* ----------------
400 : * FreeExprContext
401 : *
402 : * Free an expression context, including calling any remaining
403 : * shutdown callbacks.
404 : *
405 : * Since we free the temporary context used for expression evaluation,
406 : * any previously computed pass-by-reference expression result will go away!
407 : *
408 : * If isCommit is false, we are being called in error cleanup, and should
409 : * not call callbacks but only release memory. (It might be better to call
410 : * the callbacks and pass the isCommit flag to them, but that would require
411 : * more invasive code changes than currently seems justified.)
412 : *
413 : * Note we make no assumption about the caller's memory context.
414 : * ----------------
415 : */
416 : void
417 2213438 : FreeExprContext(ExprContext *econtext, bool isCommit)
418 : {
419 : EState *estate;
420 :
421 : /* Call any registered callbacks */
422 2213438 : ShutdownExprContext(econtext, isCommit);
423 : /* And clean up the memory used */
424 2213438 : MemoryContextDelete(econtext->ecxt_per_tuple_memory);
425 : /* Unlink self from owning EState, if any */
426 2213438 : estate = econtext->ecxt_estate;
427 2213438 : if (estate)
428 2213438 : estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
429 : econtext);
430 : /* And delete the ExprContext node */
431 2213438 : pfree(econtext);
432 2213438 : }
433 :
434 : /*
435 : * ReScanExprContext
436 : *
437 : * Reset an expression context in preparation for a rescan of its
438 : * plan node. This requires calling any registered shutdown callbacks,
439 : * since any partially complete set-returning-functions must be canceled.
440 : *
441 : * Note we make no assumption about the caller's memory context.
442 : */
443 : void
444 3861544 : ReScanExprContext(ExprContext *econtext)
445 : {
446 : /* Call any registered callbacks */
447 3861544 : ShutdownExprContext(econtext, true);
448 : /* And clean up the memory used */
449 3861544 : MemoryContextReset(econtext->ecxt_per_tuple_memory);
450 3861544 : }
451 :
452 : /*
453 : * Build a per-output-tuple ExprContext for an EState.
454 : *
455 : * This is normally invoked via GetPerTupleExprContext() macro,
456 : * not directly.
457 : */
458 : ExprContext *
459 670176 : MakePerTupleExprContext(EState *estate)
460 : {
461 670176 : if (estate->es_per_tuple_exprcontext == NULL)
462 670176 : estate->es_per_tuple_exprcontext = CreateExprContext(estate);
463 :
464 670176 : return estate->es_per_tuple_exprcontext;
465 : }
466 :
467 :
468 : /* ----------------------------------------------------------------
469 : * miscellaneous node-init support functions
470 : *
471 : * Note: all of these are expected to be called with CurrentMemoryContext
472 : * equal to the per-query memory context.
473 : * ----------------------------------------------------------------
474 : */
475 :
476 : /* ----------------
477 : * ExecAssignExprContext
478 : *
479 : * This initializes the ps_ExprContext field. It is only necessary
480 : * to do this for nodes which use ExecQual or ExecProject
481 : * because those routines require an econtext. Other nodes that
482 : * don't have to evaluate expressions don't need to do this.
483 : * ----------------
484 : */
485 : void
486 1457380 : ExecAssignExprContext(EState *estate, PlanState *planstate)
487 : {
488 1457380 : planstate->ps_ExprContext = CreateExprContext(estate);
489 1457380 : }
490 :
491 : /* ----------------
492 : * ExecGetResultType
493 : * ----------------
494 : */
495 : TupleDesc
496 1754988 : ExecGetResultType(PlanState *planstate)
497 : {
498 1754988 : return planstate->ps_ResultTupleDesc;
499 : }
500 :
501 : /*
502 : * ExecGetResultSlotOps - information about node's type of result slot
503 : */
504 : const TupleTableSlotOps *
505 738956 : ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
506 : {
507 738956 : if (planstate->resultopsset && planstate->resultops)
508 : {
509 737390 : if (isfixed)
510 675262 : *isfixed = planstate->resultopsfixed;
511 737390 : return planstate->resultops;
512 : }
513 :
514 1566 : if (isfixed)
515 : {
516 1536 : if (planstate->resultopsset)
517 1536 : *isfixed = planstate->resultopsfixed;
518 0 : else if (planstate->ps_ResultTupleSlot)
519 0 : *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
520 : else
521 0 : *isfixed = false;
522 : }
523 :
524 1566 : if (!planstate->ps_ResultTupleSlot)
525 1566 : return &TTSOpsVirtual;
526 :
527 0 : return planstate->ps_ResultTupleSlot->tts_ops;
528 : }
529 :
530 : /*
531 : * ExecGetCommonSlotOps - identify common result slot type, if any
532 : *
533 : * If all the given PlanState nodes return the same fixed tuple slot type,
534 : * return the slot ops struct for that slot type. Else, return NULL.
535 : */
536 : const TupleTableSlotOps *
537 15668 : ExecGetCommonSlotOps(PlanState **planstates, int nplans)
538 : {
539 : const TupleTableSlotOps *result;
540 : bool isfixed;
541 :
542 15668 : if (nplans <= 0)
543 102 : return NULL;
544 15566 : result = ExecGetResultSlotOps(planstates[0], &isfixed);
545 15566 : if (!isfixed)
546 110 : return NULL;
547 42826 : for (int i = 1; i < nplans; i++)
548 : {
549 : const TupleTableSlotOps *thisops;
550 :
551 28330 : thisops = ExecGetResultSlotOps(planstates[i], &isfixed);
552 28330 : if (!isfixed)
553 42 : return NULL;
554 28288 : if (result != thisops)
555 918 : return NULL;
556 : }
557 14496 : return result;
558 : }
559 :
560 : /*
561 : * ExecGetCommonChildSlotOps - as above, for the PlanState's standard children
562 : */
563 : const TupleTableSlotOps *
564 750 : ExecGetCommonChildSlotOps(PlanState *ps)
565 : {
566 : PlanState *planstates[2];
567 :
568 750 : planstates[0] = outerPlanState(ps);
569 750 : planstates[1] = innerPlanState(ps);
570 750 : return ExecGetCommonSlotOps(planstates, 2);
571 : }
572 :
573 :
574 : /* ----------------
575 : * ExecAssignProjectionInfo
576 : *
577 : * forms the projection information from the node's targetlist
578 : *
579 : * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
580 : * for a relation-scan node, can pass NULL for upper-level nodes
581 : * ----------------
582 : */
583 : void
584 833476 : ExecAssignProjectionInfo(PlanState *planstate,
585 : TupleDesc inputDesc)
586 : {
587 833408 : planstate->ps_ProjInfo =
588 833476 : ExecBuildProjectionInfo(planstate->plan->targetlist,
589 : planstate->ps_ExprContext,
590 : planstate->ps_ResultTupleSlot,
591 : planstate,
592 : inputDesc);
593 833408 : }
594 :
595 :
596 : /* ----------------
597 : * ExecConditionalAssignProjectionInfo
598 : *
599 : * as ExecAssignProjectionInfo, but store NULL rather than building projection
600 : * info if no projection is required
601 : * ----------------
602 : */
603 : void
604 577680 : ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
605 : int varno)
606 : {
607 577680 : if (tlist_matches_tupdesc(planstate,
608 577680 : planstate->plan->targetlist,
609 : varno,
610 : inputDesc))
611 : {
612 327162 : planstate->ps_ProjInfo = NULL;
613 327162 : planstate->resultopsset = planstate->scanopsset;
614 327162 : planstate->resultopsfixed = planstate->scanopsfixed;
615 327162 : planstate->resultops = planstate->scanops;
616 : }
617 : else
618 : {
619 250518 : if (!planstate->ps_ResultTupleSlot)
620 : {
621 250518 : ExecInitResultSlot(planstate, &TTSOpsVirtual);
622 250518 : planstate->resultops = &TTSOpsVirtual;
623 250518 : planstate->resultopsfixed = true;
624 250518 : planstate->resultopsset = true;
625 : }
626 250518 : ExecAssignProjectionInfo(planstate, inputDesc);
627 : }
628 577674 : }
629 :
630 : static bool
631 577680 : tlist_matches_tupdesc(PlanState *ps, List *tlist, int varno, TupleDesc tupdesc)
632 : {
633 577680 : int numattrs = tupdesc->natts;
634 : int attrno;
635 577680 : ListCell *tlist_item = list_head(tlist);
636 :
637 : /* Check the tlist attributes */
638 4839518 : for (attrno = 1; attrno <= numattrs; attrno++)
639 : {
640 4499438 : Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
641 : Var *var;
642 :
643 4499438 : if (tlist_item == NULL)
644 27374 : return false; /* tlist too short */
645 4472064 : var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
646 4472064 : if (!var || !IsA(var, Var))
647 62184 : return false; /* tlist item not a Var */
648 : /* if these Asserts fail, planner messed up */
649 : Assert(var->varno == varno);
650 : Assert(var->varlevelsup == 0);
651 4409880 : if (var->varattno != attrno)
652 147712 : return false; /* out of order */
653 4262168 : if (att_tup->attisdropped)
654 0 : return false; /* table contains dropped columns */
655 4262168 : if (att_tup->atthasmissing)
656 324 : return false; /* table contains cols with missing values */
657 :
658 : /*
659 : * Note: usually the Var's type should match the tupdesc exactly, but
660 : * in situations involving unions of columns that have different
661 : * typmods, the Var may have come from above the union and hence have
662 : * typmod -1. This is a legitimate situation since the Var still
663 : * describes the column, just not as exactly as the tupdesc does. We
664 : * could change the planner to prevent it, but it'd then insert
665 : * projection steps just to convert from specific typmod to typmod -1,
666 : * which is pretty silly.
667 : */
668 4261844 : if (var->vartype != att_tup->atttypid ||
669 4261838 : (var->vartypmod != att_tup->atttypmod &&
670 6 : var->vartypmod != -1))
671 6 : return false; /* type mismatch */
672 :
673 4261838 : tlist_item = lnext(tlist, tlist_item);
674 : }
675 :
676 340080 : if (tlist_item)
677 12918 : return false; /* tlist too long */
678 :
679 327162 : return true;
680 : }
681 :
682 :
683 : /* ----------------------------------------------------------------
684 : * Scan node support
685 : * ----------------------------------------------------------------
686 : */
687 :
688 : /* ----------------
689 : * ExecAssignScanType
690 : * ----------------
691 : */
692 : void
693 836 : ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
694 : {
695 836 : TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
696 :
697 836 : ExecSetSlotDescriptor(slot, tupDesc);
698 836 : }
699 :
700 : /* ----------------
701 : * ExecCreateScanSlotFromOuterPlan
702 : * ----------------
703 : */
704 : void
705 142412 : ExecCreateScanSlotFromOuterPlan(EState *estate,
706 : ScanState *scanstate,
707 : const TupleTableSlotOps *tts_ops)
708 : {
709 : PlanState *outerPlan;
710 : TupleDesc tupDesc;
711 :
712 142412 : outerPlan = outerPlanState(scanstate);
713 142412 : tupDesc = ExecGetResultType(outerPlan);
714 :
715 142412 : ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
716 142412 : }
717 :
718 : /* ----------------------------------------------------------------
719 : * ExecRelationIsTargetRelation
720 : *
721 : * Detect whether a relation (identified by rangetable index)
722 : * is one of the target relations of the query.
723 : *
724 : * Note: This is currently no longer used in core. We keep it around
725 : * because FDWs may wish to use it to determine if their foreign table
726 : * is a target relation.
727 : * ----------------------------------------------------------------
728 : */
729 : bool
730 0 : ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
731 : {
732 0 : return list_member_int(estate->es_plannedstmt->resultRelations, scanrelid);
733 : }
734 :
735 : /* ----------------------------------------------------------------
736 : * ExecOpenScanRelation
737 : *
738 : * Open the heap relation to be scanned by a base-level scan plan node.
739 : * This should be called during the node's ExecInit routine.
740 : * ----------------------------------------------------------------
741 : */
742 : Relation
743 469338 : ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
744 : {
745 : Relation rel;
746 :
747 : /* Open the relation. */
748 469338 : rel = ExecGetRangeTableRelation(estate, scanrelid, false);
749 :
750 : /*
751 : * Complain if we're attempting a scan of an unscannable relation, except
752 : * when the query won't actually be run. This is a slightly klugy place
753 : * to do this, perhaps, but there is no better place.
754 : */
755 469338 : if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
756 437120 : !RelationIsScannable(rel))
757 12 : ereport(ERROR,
758 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
759 : errmsg("materialized view \"%s\" has not been populated",
760 : RelationGetRelationName(rel)),
761 : errhint("Use the REFRESH MATERIALIZED VIEW command.")));
762 :
763 469326 : return rel;
764 : }
765 :
766 : /*
767 : * ExecInitRangeTable
768 : * Set up executor's range-table-related data
769 : *
770 : * In addition to the range table proper, initialize arrays that are
771 : * indexed by rangetable index.
772 : */
773 : void
774 967370 : ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos,
775 : Bitmapset *unpruned_relids)
776 : {
777 : /* Remember the range table List as-is */
778 967370 : estate->es_range_table = rangeTable;
779 :
780 : /* ... and the RTEPermissionInfo List too */
781 967370 : estate->es_rteperminfos = permInfos;
782 :
783 : /* Set size of associated arrays */
784 967370 : estate->es_range_table_size = list_length(rangeTable);
785 :
786 : /*
787 : * Initialize the bitmapset of RT indexes (es_unpruned_relids)
788 : * representing relations that will be scanned during execution. This set
789 : * is initially populated by the caller and may be extended later by
790 : * ExecDoInitialPruning() to include RT indexes of unpruned leaf
791 : * partitions.
792 : */
793 967370 : estate->es_unpruned_relids = unpruned_relids;
794 :
795 : /*
796 : * Allocate an array to store an open Relation corresponding to each
797 : * rangetable entry, and initialize entries to NULL. Relations are opened
798 : * and stored here as needed.
799 : */
800 967370 : estate->es_relations = (Relation *)
801 967370 : palloc0(estate->es_range_table_size * sizeof(Relation));
802 :
803 : /*
804 : * es_result_relations and es_rowmarks are also parallel to
805 : * es_range_table, but are allocated only if needed.
806 : */
807 967370 : estate->es_result_relations = NULL;
808 967370 : estate->es_rowmarks = NULL;
809 967370 : }
810 :
811 : /*
812 : * ExecGetRangeTableRelation
813 : * Open the Relation for a range table entry, if not already done
814 : *
815 : * The Relations will be closed in ExecEndPlan().
816 : *
817 : * If isResultRel is true, the relation is being used as a result relation.
818 : * Such a relation might have been pruned, which is OK for result relations,
819 : * but not for scan relations; see the details in ExecInitModifyTable(). If
820 : * isResultRel is false, the caller must ensure that 'rti' refers to an
821 : * unpruned relation (i.e., it is a member of estate->es_unpruned_relids)
822 : * before calling this function. Attempting to open a pruned relation for
823 : * scanning will result in an error.
824 : */
825 : Relation
826 609140 : ExecGetRangeTableRelation(EState *estate, Index rti, bool isResultRel)
827 : {
828 : Relation rel;
829 :
830 : Assert(rti > 0 && rti <= estate->es_range_table_size);
831 :
832 609140 : if (!isResultRel && !bms_is_member(rti, estate->es_unpruned_relids))
833 0 : elog(ERROR, "trying to open a pruned relation");
834 :
835 609140 : rel = estate->es_relations[rti - 1];
836 609140 : if (rel == NULL)
837 : {
838 : /* First time through, so open the relation */
839 568834 : RangeTblEntry *rte = exec_rt_fetch(rti, estate);
840 :
841 : Assert(rte->rtekind == RTE_RELATION);
842 :
843 568834 : if (!IsParallelWorker())
844 : {
845 : /*
846 : * In a normal query, we should already have the appropriate lock,
847 : * but verify that through an Assert. Since there's already an
848 : * Assert inside table_open that insists on holding some lock, it
849 : * seems sufficient to check this only when rellockmode is higher
850 : * than the minimum.
851 : */
852 564224 : rel = table_open(rte->relid, NoLock);
853 : Assert(rte->rellockmode == AccessShareLock ||
854 : CheckRelationLockedByMe(rel, rte->rellockmode, false));
855 : }
856 : else
857 : {
858 : /*
859 : * If we are a parallel worker, we need to obtain our own local
860 : * lock on the relation. This ensures sane behavior in case the
861 : * parent process exits before we do.
862 : */
863 4610 : rel = table_open(rte->relid, rte->rellockmode);
864 : }
865 :
866 568834 : estate->es_relations[rti - 1] = rel;
867 : }
868 :
869 609140 : return rel;
870 : }
871 :
872 : /*
873 : * ExecInitResultRelation
874 : * Open relation given by the passed-in RT index and fill its
875 : * ResultRelInfo node
876 : *
877 : * Here, we also save the ResultRelInfo in estate->es_result_relations array
878 : * such that it can be accessed later using the RT index.
879 : */
880 : void
881 127706 : ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo,
882 : Index rti)
883 : {
884 : Relation resultRelationDesc;
885 :
886 127706 : resultRelationDesc = ExecGetRangeTableRelation(estate, rti, true);
887 127706 : InitResultRelInfo(resultRelInfo,
888 : resultRelationDesc,
889 : rti,
890 : NULL,
891 : estate->es_instrument);
892 :
893 127706 : if (estate->es_result_relations == NULL)
894 122374 : estate->es_result_relations = (ResultRelInfo **)
895 122374 : palloc0(estate->es_range_table_size * sizeof(ResultRelInfo *));
896 127706 : estate->es_result_relations[rti - 1] = resultRelInfo;
897 :
898 : /*
899 : * Saving in the list allows to avoid needlessly traversing the whole
900 : * array when only a few of its entries are possibly non-NULL.
901 : */
902 127706 : estate->es_opened_result_relations =
903 127706 : lappend(estate->es_opened_result_relations, resultRelInfo);
904 127706 : }
905 :
906 : /*
907 : * UpdateChangedParamSet
908 : * Add changed parameters to a plan node's chgParam set
909 : */
910 : void
911 804890 : UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
912 : {
913 : Bitmapset *parmset;
914 :
915 : /*
916 : * The plan node only depends on params listed in its allParam set. Don't
917 : * include anything else into its chgParam set.
918 : */
919 804890 : parmset = bms_intersect(node->plan->allParam, newchg);
920 804890 : node->chgParam = bms_join(node->chgParam, parmset);
921 804890 : }
922 :
923 : /*
924 : * executor_errposition
925 : * Report an execution-time cursor position, if possible.
926 : *
927 : * This is expected to be used within an ereport() call. The return value
928 : * is a dummy (always 0, in fact).
929 : *
930 : * The locations stored in parsetrees are byte offsets into the source string.
931 : * We have to convert them to 1-based character indexes for reporting to
932 : * clients. (We do things this way to avoid unnecessary overhead in the
933 : * normal non-error case: computing character indexes would be much more
934 : * expensive than storing token offsets.)
935 : */
936 : int
937 0 : executor_errposition(EState *estate, int location)
938 : {
939 : int pos;
940 :
941 : /* No-op if location was not provided */
942 0 : if (location < 0)
943 0 : return 0;
944 : /* Can't do anything if source text is not available */
945 0 : if (estate == NULL || estate->es_sourceText == NULL)
946 0 : return 0;
947 : /* Convert offset to character number */
948 0 : pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
949 : /* And pass it to the ereport mechanism */
950 0 : return errposition(pos);
951 : }
952 :
953 : /*
954 : * Register a shutdown callback in an ExprContext.
955 : *
956 : * Shutdown callbacks will be called (in reverse order of registration)
957 : * when the ExprContext is deleted or rescanned. This provides a hook
958 : * for functions called in the context to do any cleanup needed --- it's
959 : * particularly useful for functions returning sets. Note that the
960 : * callback will *not* be called in the event that execution is aborted
961 : * by an error.
962 : */
963 : void
964 157594 : RegisterExprContextCallback(ExprContext *econtext,
965 : ExprContextCallbackFunction function,
966 : Datum arg)
967 : {
968 : ExprContext_CB *ecxt_callback;
969 :
970 : /* Save the info in appropriate memory context */
971 : ecxt_callback = (ExprContext_CB *)
972 157594 : MemoryContextAlloc(econtext->ecxt_per_query_memory,
973 : sizeof(ExprContext_CB));
974 :
975 157594 : ecxt_callback->function = function;
976 157594 : ecxt_callback->arg = arg;
977 :
978 : /* link to front of list for appropriate execution order */
979 157594 : ecxt_callback->next = econtext->ecxt_callbacks;
980 157594 : econtext->ecxt_callbacks = ecxt_callback;
981 157594 : }
982 :
983 : /*
984 : * Deregister a shutdown callback in an ExprContext.
985 : *
986 : * Any list entries matching the function and arg will be removed.
987 : * This can be used if it's no longer necessary to call the callback.
988 : */
989 : void
990 134204 : UnregisterExprContextCallback(ExprContext *econtext,
991 : ExprContextCallbackFunction function,
992 : Datum arg)
993 : {
994 : ExprContext_CB **prev_callback;
995 : ExprContext_CB *ecxt_callback;
996 :
997 134204 : prev_callback = &econtext->ecxt_callbacks;
998 :
999 382774 : while ((ecxt_callback = *prev_callback) != NULL)
1000 : {
1001 248570 : if (ecxt_callback->function == function && ecxt_callback->arg == arg)
1002 : {
1003 134204 : *prev_callback = ecxt_callback->next;
1004 134204 : pfree(ecxt_callback);
1005 : }
1006 : else
1007 114366 : prev_callback = &ecxt_callback->next;
1008 : }
1009 134204 : }
1010 :
1011 : /*
1012 : * Call all the shutdown callbacks registered in an ExprContext.
1013 : *
1014 : * The callback list is emptied (important in case this is only a rescan
1015 : * reset, and not deletion of the ExprContext).
1016 : *
1017 : * If isCommit is false, just clean the callback list but don't call 'em.
1018 : * (See comment for FreeExprContext.)
1019 : */
1020 : static void
1021 6074982 : ShutdownExprContext(ExprContext *econtext, bool isCommit)
1022 : {
1023 : ExprContext_CB *ecxt_callback;
1024 : MemoryContext oldcontext;
1025 :
1026 : /* Fast path in normal case where there's nothing to do. */
1027 6074982 : if (econtext->ecxt_callbacks == NULL)
1028 6053716 : return;
1029 :
1030 : /*
1031 : * Call the callbacks in econtext's per-tuple context. This ensures that
1032 : * any memory they might leak will get cleaned up.
1033 : */
1034 21266 : oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
1035 :
1036 : /*
1037 : * Call each callback function in reverse registration order.
1038 : */
1039 42934 : while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
1040 : {
1041 21668 : econtext->ecxt_callbacks = ecxt_callback->next;
1042 21668 : if (isCommit)
1043 21668 : ecxt_callback->function(ecxt_callback->arg);
1044 21668 : pfree(ecxt_callback);
1045 : }
1046 :
1047 21266 : MemoryContextSwitchTo(oldcontext);
1048 : }
1049 :
1050 : /*
1051 : * GetAttributeByName
1052 : * GetAttributeByNum
1053 : *
1054 : * These functions return the value of the requested attribute
1055 : * out of the given tuple Datum.
1056 : * C functions which take a tuple as an argument are expected
1057 : * to use these. Ex: overpaid(EMP) might call GetAttributeByNum().
1058 : * Note: these are actually rather slow because they do a typcache
1059 : * lookup on each call.
1060 : */
1061 : Datum
1062 36 : GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
1063 : {
1064 : AttrNumber attrno;
1065 : Datum result;
1066 : Oid tupType;
1067 : int32 tupTypmod;
1068 : TupleDesc tupDesc;
1069 : HeapTupleData tmptup;
1070 : int i;
1071 :
1072 36 : if (attname == NULL)
1073 0 : elog(ERROR, "invalid attribute name");
1074 :
1075 36 : if (isNull == NULL)
1076 0 : elog(ERROR, "a NULL isNull pointer was passed");
1077 :
1078 36 : if (tuple == NULL)
1079 : {
1080 : /* Kinda bogus but compatible with old behavior... */
1081 0 : *isNull = true;
1082 0 : return (Datum) 0;
1083 : }
1084 :
1085 36 : tupType = HeapTupleHeaderGetTypeId(tuple);
1086 36 : tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1087 36 : tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1088 :
1089 36 : attrno = InvalidAttrNumber;
1090 144 : for (i = 0; i < tupDesc->natts; i++)
1091 : {
1092 144 : Form_pg_attribute att = TupleDescAttr(tupDesc, i);
1093 :
1094 144 : if (namestrcmp(&(att->attname), attname) == 0)
1095 : {
1096 36 : attrno = att->attnum;
1097 36 : break;
1098 : }
1099 : }
1100 :
1101 36 : if (attrno == InvalidAttrNumber)
1102 0 : elog(ERROR, "attribute \"%s\" does not exist", attname);
1103 :
1104 : /*
1105 : * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1106 : * the fields in the struct just in case user tries to inspect system
1107 : * columns.
1108 : */
1109 36 : tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1110 36 : ItemPointerSetInvalid(&(tmptup.t_self));
1111 36 : tmptup.t_tableOid = InvalidOid;
1112 36 : tmptup.t_data = tuple;
1113 :
1114 36 : result = heap_getattr(&tmptup,
1115 : attrno,
1116 : tupDesc,
1117 : isNull);
1118 :
1119 36 : ReleaseTupleDesc(tupDesc);
1120 :
1121 36 : return result;
1122 : }
1123 :
1124 : Datum
1125 0 : GetAttributeByNum(HeapTupleHeader tuple,
1126 : AttrNumber attrno,
1127 : bool *isNull)
1128 : {
1129 : Datum result;
1130 : Oid tupType;
1131 : int32 tupTypmod;
1132 : TupleDesc tupDesc;
1133 : HeapTupleData tmptup;
1134 :
1135 0 : if (!AttributeNumberIsValid(attrno))
1136 0 : elog(ERROR, "invalid attribute number %d", attrno);
1137 :
1138 0 : if (isNull == NULL)
1139 0 : elog(ERROR, "a NULL isNull pointer was passed");
1140 :
1141 0 : if (tuple == NULL)
1142 : {
1143 : /* Kinda bogus but compatible with old behavior... */
1144 0 : *isNull = true;
1145 0 : return (Datum) 0;
1146 : }
1147 :
1148 0 : tupType = HeapTupleHeaderGetTypeId(tuple);
1149 0 : tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1150 0 : tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1151 :
1152 : /*
1153 : * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1154 : * the fields in the struct just in case user tries to inspect system
1155 : * columns.
1156 : */
1157 0 : tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1158 0 : ItemPointerSetInvalid(&(tmptup.t_self));
1159 0 : tmptup.t_tableOid = InvalidOid;
1160 0 : tmptup.t_data = tuple;
1161 :
1162 0 : result = heap_getattr(&tmptup,
1163 : attrno,
1164 : tupDesc,
1165 : isNull);
1166 :
1167 0 : ReleaseTupleDesc(tupDesc);
1168 :
1169 0 : return result;
1170 : }
1171 :
1172 : /*
1173 : * Number of items in a tlist (including any resjunk items!)
1174 : */
1175 : int
1176 1477310 : ExecTargetListLength(List *targetlist)
1177 : {
1178 : /* This used to be more complex, but fjoins are dead */
1179 1477310 : return list_length(targetlist);
1180 : }
1181 :
1182 : /*
1183 : * Number of items in a tlist, not including any resjunk items
1184 : */
1185 : int
1186 196960 : ExecCleanTargetListLength(List *targetlist)
1187 : {
1188 196960 : int len = 0;
1189 : ListCell *tl;
1190 :
1191 676934 : foreach(tl, targetlist)
1192 : {
1193 479974 : TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1194 :
1195 479974 : if (!curTle->resjunk)
1196 447756 : len++;
1197 : }
1198 196960 : return len;
1199 : }
1200 :
1201 : /*
1202 : * Return a relInfo's tuple slot for a trigger's OLD tuples.
1203 : */
1204 : TupleTableSlot *
1205 23894 : ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
1206 : {
1207 23894 : if (relInfo->ri_TrigOldSlot == NULL)
1208 : {
1209 9860 : Relation rel = relInfo->ri_RelationDesc;
1210 9860 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1211 :
1212 9860 : relInfo->ri_TrigOldSlot =
1213 9860 : ExecInitExtraTupleSlot(estate,
1214 : RelationGetDescr(rel),
1215 : table_slot_callbacks(rel));
1216 :
1217 9860 : MemoryContextSwitchTo(oldcontext);
1218 : }
1219 :
1220 23894 : return relInfo->ri_TrigOldSlot;
1221 : }
1222 :
1223 : /*
1224 : * Return a relInfo's tuple slot for a trigger's NEW tuples.
1225 : */
1226 : TupleTableSlot *
1227 3502 : ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
1228 : {
1229 3502 : if (relInfo->ri_TrigNewSlot == NULL)
1230 : {
1231 2178 : Relation rel = relInfo->ri_RelationDesc;
1232 2178 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1233 :
1234 2178 : relInfo->ri_TrigNewSlot =
1235 2178 : ExecInitExtraTupleSlot(estate,
1236 : RelationGetDescr(rel),
1237 : table_slot_callbacks(rel));
1238 :
1239 2178 : MemoryContextSwitchTo(oldcontext);
1240 : }
1241 :
1242 3502 : return relInfo->ri_TrigNewSlot;
1243 : }
1244 :
1245 : /*
1246 : * Return a relInfo's tuple slot for processing returning tuples.
1247 : */
1248 : TupleTableSlot *
1249 1288 : ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
1250 : {
1251 1288 : if (relInfo->ri_ReturningSlot == NULL)
1252 : {
1253 658 : Relation rel = relInfo->ri_RelationDesc;
1254 658 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1255 :
1256 658 : relInfo->ri_ReturningSlot =
1257 658 : ExecInitExtraTupleSlot(estate,
1258 : RelationGetDescr(rel),
1259 : table_slot_callbacks(rel));
1260 :
1261 658 : MemoryContextSwitchTo(oldcontext);
1262 : }
1263 :
1264 1288 : return relInfo->ri_ReturningSlot;
1265 : }
1266 :
1267 : /*
1268 : * Return a relInfo's all-NULL tuple slot for processing returning tuples.
1269 : *
1270 : * Note: this slot is intentionally filled with NULLs in every column, and
1271 : * should be considered read-only --- the caller must not update it.
1272 : */
1273 : TupleTableSlot *
1274 312 : ExecGetAllNullSlot(EState *estate, ResultRelInfo *relInfo)
1275 : {
1276 312 : if (relInfo->ri_AllNullSlot == NULL)
1277 : {
1278 212 : Relation rel = relInfo->ri_RelationDesc;
1279 212 : MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1280 : TupleTableSlot *slot;
1281 :
1282 212 : slot = ExecInitExtraTupleSlot(estate,
1283 : RelationGetDescr(rel),
1284 : table_slot_callbacks(rel));
1285 212 : ExecStoreAllNullTuple(slot);
1286 :
1287 212 : relInfo->ri_AllNullSlot = slot;
1288 :
1289 212 : MemoryContextSwitchTo(oldcontext);
1290 : }
1291 :
1292 312 : return relInfo->ri_AllNullSlot;
1293 : }
1294 :
1295 : /*
1296 : * Return the map needed to convert given child result relation's tuples to
1297 : * the rowtype of the query's main target ("root") relation. Note that a
1298 : * NULL result is valid and means that no conversion is needed.
1299 : */
1300 : TupleConversionMap *
1301 67888 : ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
1302 : {
1303 : /* If we didn't already do so, compute the map for this child. */
1304 67888 : if (!resultRelInfo->ri_ChildToRootMapValid)
1305 : {
1306 1670 : ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1307 :
1308 1670 : if (rootRelInfo)
1309 1298 : resultRelInfo->ri_ChildToRootMap =
1310 1298 : convert_tuples_by_name(RelationGetDescr(resultRelInfo->ri_RelationDesc),
1311 1298 : RelationGetDescr(rootRelInfo->ri_RelationDesc));
1312 : else /* this isn't a child result rel */
1313 372 : resultRelInfo->ri_ChildToRootMap = NULL;
1314 :
1315 1670 : resultRelInfo->ri_ChildToRootMapValid = true;
1316 : }
1317 :
1318 67888 : return resultRelInfo->ri_ChildToRootMap;
1319 : }
1320 :
1321 : /*
1322 : * Returns the map needed to convert given root result relation's tuples to
1323 : * the rowtype of the given child relation. Note that a NULL result is valid
1324 : * and means that no conversion is needed.
1325 : */
1326 : TupleConversionMap *
1327 1013844 : ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate)
1328 : {
1329 : /* Mustn't get called for a non-child result relation. */
1330 : Assert(resultRelInfo->ri_RootResultRelInfo);
1331 :
1332 : /* If we didn't already do so, compute the map for this child. */
1333 1013844 : if (!resultRelInfo->ri_RootToChildMapValid)
1334 : {
1335 9538 : ResultRelInfo *rootRelInfo = resultRelInfo->ri_RootResultRelInfo;
1336 9538 : TupleDesc indesc = RelationGetDescr(rootRelInfo->ri_RelationDesc);
1337 9538 : TupleDesc outdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
1338 9538 : Relation childrel = resultRelInfo->ri_RelationDesc;
1339 : AttrMap *attrMap;
1340 : MemoryContext oldcontext;
1341 :
1342 : /*
1343 : * When this child table is not a partition (!relispartition), it may
1344 : * have columns that are not present in the root table, which we ask
1345 : * to ignore by passing true for missing_ok.
1346 : */
1347 9538 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1348 9538 : attrMap = build_attrmap_by_name_if_req(indesc, outdesc,
1349 9538 : !childrel->rd_rel->relispartition);
1350 9538 : if (attrMap)
1351 1476 : resultRelInfo->ri_RootToChildMap =
1352 1476 : convert_tuples_by_name_attrmap(indesc, outdesc, attrMap);
1353 9538 : MemoryContextSwitchTo(oldcontext);
1354 9538 : resultRelInfo->ri_RootToChildMapValid = true;
1355 : }
1356 :
1357 1013844 : return resultRelInfo->ri_RootToChildMap;
1358 : }
1359 :
1360 : /* Return a bitmap representing columns being inserted */
1361 : Bitmapset *
1362 1318 : ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
1363 : {
1364 1318 : RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
1365 :
1366 1318 : if (perminfo == NULL)
1367 0 : return NULL;
1368 :
1369 : /* Map the columns to child's attribute numbers if needed. */
1370 1318 : if (relinfo->ri_RootResultRelInfo)
1371 : {
1372 6 : TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1373 :
1374 6 : if (map)
1375 4 : return execute_attr_map_cols(map->attrMap, perminfo->insertedCols);
1376 : }
1377 :
1378 1314 : return perminfo->insertedCols;
1379 : }
1380 :
1381 : /* Return a bitmap representing columns being updated */
1382 : Bitmapset *
1383 59886 : ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
1384 : {
1385 59886 : RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relinfo, estate);
1386 :
1387 59886 : if (perminfo == NULL)
1388 0 : return NULL;
1389 :
1390 : /* Map the columns to child's attribute numbers if needed. */
1391 59886 : if (relinfo->ri_RootResultRelInfo)
1392 : {
1393 1746 : TupleConversionMap *map = ExecGetRootToChildMap(relinfo, estate);
1394 :
1395 1746 : if (map)
1396 490 : return execute_attr_map_cols(map->attrMap, perminfo->updatedCols);
1397 : }
1398 :
1399 59396 : return perminfo->updatedCols;
1400 : }
1401 :
1402 : /* Return a bitmap representing generated columns being updated */
1403 : Bitmapset *
1404 58362 : ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
1405 : {
1406 : /* Compute the info if we didn't already */
1407 58362 : if (!relinfo->ri_extraUpdatedCols_valid)
1408 58164 : ExecInitGenerated(relinfo, estate, CMD_UPDATE);
1409 58362 : return relinfo->ri_extraUpdatedCols;
1410 : }
1411 :
1412 : /*
1413 : * Return columns being updated, including generated columns
1414 : *
1415 : * The bitmap is allocated in per-tuple memory context. It's up to the caller to
1416 : * copy it into a different context with the appropriate lifespan, if needed.
1417 : */
1418 : Bitmapset *
1419 14760 : ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
1420 : {
1421 : Bitmapset *ret;
1422 : MemoryContext oldcxt;
1423 :
1424 14760 : oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
1425 :
1426 14760 : ret = bms_union(ExecGetUpdatedCols(relinfo, estate),
1427 14760 : ExecGetExtraUpdatedCols(relinfo, estate));
1428 :
1429 14760 : MemoryContextSwitchTo(oldcxt);
1430 :
1431 14760 : return ret;
1432 : }
1433 :
1434 : /*
1435 : * GetResultRTEPermissionInfo
1436 : * Looks up RTEPermissionInfo for ExecGet*Cols() routines
1437 : */
1438 : static RTEPermissionInfo *
1439 61550 : GetResultRTEPermissionInfo(ResultRelInfo *relinfo, EState *estate)
1440 : {
1441 : Index rti;
1442 : RangeTblEntry *rte;
1443 61550 : RTEPermissionInfo *perminfo = NULL;
1444 :
1445 61550 : if (relinfo->ri_RootResultRelInfo)
1446 : {
1447 : /*
1448 : * For inheritance child result relations (a partition routing target
1449 : * of an INSERT or a child UPDATE target), this returns the root
1450 : * parent's RTE to fetch the RTEPermissionInfo because that's the only
1451 : * one that has one assigned.
1452 : */
1453 1848 : rti = relinfo->ri_RootResultRelInfo->ri_RangeTableIndex;
1454 : }
1455 59702 : else if (relinfo->ri_RangeTableIndex != 0)
1456 : {
1457 : /*
1458 : * Non-child result relation should have their own RTEPermissionInfo.
1459 : */
1460 59702 : rti = relinfo->ri_RangeTableIndex;
1461 : }
1462 : else
1463 : {
1464 : /*
1465 : * The relation isn't in the range table and it isn't a partition
1466 : * routing target. This ResultRelInfo must've been created only for
1467 : * firing triggers and the relation is not being inserted into. (See
1468 : * ExecGetTriggerResultRel.)
1469 : */
1470 0 : rti = 0;
1471 : }
1472 :
1473 61550 : if (rti > 0)
1474 : {
1475 61550 : rte = exec_rt_fetch(rti, estate);
1476 61550 : perminfo = getRTEPermissionInfo(estate->es_rteperminfos, rte);
1477 : }
1478 :
1479 61550 : return perminfo;
1480 : }
1481 :
1482 : /*
1483 : * ExecGetResultRelCheckAsUser
1484 : * Returns the user to modify passed-in result relation as
1485 : *
1486 : * The user is chosen by looking up the relation's or, if a child table, its
1487 : * root parent's RTEPermissionInfo.
1488 : */
1489 : Oid
1490 346 : ExecGetResultRelCheckAsUser(ResultRelInfo *relInfo, EState *estate)
1491 : {
1492 346 : RTEPermissionInfo *perminfo = GetResultRTEPermissionInfo(relInfo, estate);
1493 :
1494 : /* XXX - maybe ok to return GetUserId() in this case? */
1495 346 : if (perminfo == NULL)
1496 0 : elog(ERROR, "no RTEPermissionInfo found for result relation with OID %u",
1497 : RelationGetRelid(relInfo->ri_RelationDesc));
1498 :
1499 346 : return perminfo->checkAsUser ? perminfo->checkAsUser : GetUserId();
1500 : }
|