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