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