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