1 /*-------------------------------------------------------------------------
4 * miscellaneous executor utility routines
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/execUtils.c
13 *-------------------------------------------------------------------------
17 * CreateExecutorState Create/delete executor working state
20 * CreateStandaloneExprContext
24 * ExecAssignExprContext Common code for plan node init routines.
27 * ExecOpenScanRelation Common code for scan node init routines.
29 * ExecInitRangeTable Set up executor's range-table-related data.
31 * ExecGetRangeTableRelation Fetch Relation for a rangetable entry.
33 * executor_errposition Report syntactic position of an error.
35 * RegisterExprContextCallback Register function shutdown callback
36 * UnregisterExprContextCallback Deregister function shutdown callback
38 * GetAttributeByName Runtime extraction of columns from tuples.
42 * This file has traditionally been the place to stick misc.
43 * executor support stuff that doesn't really go anyplace else.
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"
55 #include "mb/pg_wchar.h"
56 #include "nodes/nodeFuncs.h"
57 #include "parser/parsetree.h"
58 #include "partitioning/partdesc.h"
59 #include "storage/lmgr.h"
60 #include "utils/builtins.h"
61 #include "utils/memutils.h"
62 #include "utils/rel.h"
63 #include "utils/typcache.h"
66 static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);
67 static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
70 /* ----------------------------------------------------------------
71 * Executor state and memory management functions
72 * ----------------------------------------------------------------
78 * Create and initialize an EState node, which is the root of
79 * working storage for an entire Executor invocation.
81 * Principally, this creates the per-query memory context that will be
82 * used to hold all working data that lives till the end of the query.
83 * Note that the per-query context will become a child of the caller's
84 * CurrentMemoryContext.
88 CreateExecutorState(void)
91 MemoryContext qcontext;
92 MemoryContext oldcontext;
95 * Create the per-query context for this Executor run.
97 qcontext = AllocSetContextCreate(CurrentMemoryContext,
99 ALLOCSET_DEFAULT_SIZES);
102 * Make the EState node within the per-query context. This way, we don't
103 * need a separate pfree() operation for it at shutdown.
105 oldcontext = MemoryContextSwitchTo(qcontext);
107 estate = makeNode(EState);
110 * Initialize all fields of the Executor State structure
112 estate->es_direction = ForwardScanDirection;
113 estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
114 estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
115 estate->es_range_table = NIL;
116 estate->es_range_table_size = 0;
117 estate->es_relations = NULL;
118 estate->es_rowmarks = NULL;
119 estate->es_plannedstmt = NULL;
121 estate->es_junkFilter = NULL;
123 estate->es_output_cid = (CommandId) 0;
125 estate->es_result_relations = NULL;
126 estate->es_num_result_relations = 0;
127 estate->es_result_relation_info = NULL;
129 estate->es_root_result_relations = NULL;
130 estate->es_num_root_result_relations = 0;
132 estate->es_tuple_routing_result_relations = NIL;
134 estate->es_trig_target_relations = NIL;
136 estate->es_param_list_info = NULL;
137 estate->es_param_exec_vals = NULL;
139 estate->es_queryEnv = NULL;
141 estate->es_query_cxt = qcontext;
143 estate->es_tupleTable = NIL;
145 estate->es_processed = 0;
147 estate->es_top_eflags = 0;
148 estate->es_instrument = 0;
149 estate->es_finished = false;
151 estate->es_exprcontexts = NIL;
153 estate->es_subplanstates = NIL;
155 estate->es_auxmodifytables = NIL;
157 estate->es_per_tuple_exprcontext = NULL;
159 estate->es_sourceText = NULL;
161 estate->es_use_parallel_mode = false;
163 estate->es_jit_flags = 0;
164 estate->es_jit = NULL;
167 * Return the executor state structure
169 MemoryContextSwitchTo(oldcontext);
177 * Release an EState along with all remaining working storage.
179 * Note: this is not responsible for releasing non-memory resources, such as
180 * open relations or buffer pins. But it will shut down any still-active
181 * ExprContexts within the EState and deallocate associated JITed expressions.
182 * That is sufficient cleanup for situations where the EState has only been
183 * used for expression evaluation, and not to run a complete Plan.
185 * This can be called in any memory context ... so long as it's not one
186 * of the ones to be freed.
190 FreeExecutorState(EState *estate)
193 * Shut down and free any remaining ExprContexts. We do this explicitly
194 * to ensure that any remaining shutdown callbacks get called (since they
195 * might need to release resources that aren't simply memory within the
196 * per-query memory context).
198 while (estate->es_exprcontexts)
201 * XXX: seems there ought to be a faster way to implement this than
202 * repeated list_delete(), no?
204 FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
206 /* FreeExprContext removed the list link for us */
209 /* release JIT context, if allocated */
212 jit_release_context(estate->es_jit);
213 estate->es_jit = NULL;
216 /* release partition directory, if allocated */
217 if (estate->es_partition_directory)
219 DestroyPartitionDirectory(estate->es_partition_directory);
220 estate->es_partition_directory = NULL;
224 * Free the per-query memory context, thereby releasing all working
225 * memory, including the EState node itself.
227 MemoryContextDelete(estate->es_query_cxt);
233 * Create a context for expression evaluation within an EState.
235 * An executor run may require multiple ExprContexts (we usually make one
236 * for each Plan node, and a separate one for per-output-tuple processing
237 * such as constraint checking). Each ExprContext has its own "per-tuple"
240 * Note we make no assumption about the caller's memory context.
244 CreateExprContext(EState *estate)
246 ExprContext *econtext;
247 MemoryContext oldcontext;
249 /* Create the ExprContext node within the per-query memory context */
250 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
252 econtext = makeNode(ExprContext);
254 /* Initialize fields of ExprContext */
255 econtext->ecxt_scantuple = NULL;
256 econtext->ecxt_innertuple = NULL;
257 econtext->ecxt_outertuple = NULL;
259 econtext->ecxt_per_query_memory = estate->es_query_cxt;
262 * Create working memory for expression evaluation in this context.
264 econtext->ecxt_per_tuple_memory =
265 AllocSetContextCreate(estate->es_query_cxt,
267 ALLOCSET_DEFAULT_SIZES);
269 econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
270 econtext->ecxt_param_list_info = estate->es_param_list_info;
272 econtext->ecxt_aggvalues = NULL;
273 econtext->ecxt_aggnulls = NULL;
275 econtext->caseValue_datum = (Datum) 0;
276 econtext->caseValue_isNull = true;
278 econtext->domainValue_datum = (Datum) 0;
279 econtext->domainValue_isNull = true;
281 econtext->ecxt_estate = estate;
283 econtext->ecxt_callbacks = NULL;
286 * Link the ExprContext into the EState to ensure it is shut down when the
287 * EState is freed. Because we use lcons(), shutdowns will occur in
288 * reverse order of creation, which may not be essential but can't hurt.
290 estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
292 MemoryContextSwitchTo(oldcontext);
298 * CreateStandaloneExprContext
300 * Create a context for standalone expression evaluation.
302 * An ExprContext made this way can be used for evaluation of expressions
303 * that contain no Params, subplans, or Var references (it might work to
304 * put tuple references into the scantuple field, but it seems unwise).
306 * The ExprContext struct is allocated in the caller's current memory
307 * context, which also becomes its "per query" context.
309 * It is caller's responsibility to free the ExprContext when done,
310 * or at least ensure that any shutdown callbacks have been called
311 * (ReScanExprContext() is suitable). Otherwise, non-memory resources
316 CreateStandaloneExprContext(void)
318 ExprContext *econtext;
320 /* Create the ExprContext node within the caller's memory context */
321 econtext = makeNode(ExprContext);
323 /* Initialize fields of ExprContext */
324 econtext->ecxt_scantuple = NULL;
325 econtext->ecxt_innertuple = NULL;
326 econtext->ecxt_outertuple = NULL;
328 econtext->ecxt_per_query_memory = CurrentMemoryContext;
331 * Create working memory for expression evaluation in this context.
333 econtext->ecxt_per_tuple_memory =
334 AllocSetContextCreate(CurrentMemoryContext,
336 ALLOCSET_DEFAULT_SIZES);
338 econtext->ecxt_param_exec_vals = NULL;
339 econtext->ecxt_param_list_info = NULL;
341 econtext->ecxt_aggvalues = NULL;
342 econtext->ecxt_aggnulls = NULL;
344 econtext->caseValue_datum = (Datum) 0;
345 econtext->caseValue_isNull = true;
347 econtext->domainValue_datum = (Datum) 0;
348 econtext->domainValue_isNull = true;
350 econtext->ecxt_estate = NULL;
352 econtext->ecxt_callbacks = NULL;
360 * Free an expression context, including calling any remaining
361 * shutdown callbacks.
363 * Since we free the temporary context used for expression evaluation,
364 * any previously computed pass-by-reference expression result will go away!
366 * If isCommit is false, we are being called in error cleanup, and should
367 * not call callbacks but only release memory. (It might be better to call
368 * the callbacks and pass the isCommit flag to them, but that would require
369 * more invasive code changes than currently seems justified.)
371 * Note we make no assumption about the caller's memory context.
375 FreeExprContext(ExprContext *econtext, bool isCommit)
379 /* Call any registered callbacks */
380 ShutdownExprContext(econtext, isCommit);
381 /* And clean up the memory used */
382 MemoryContextDelete(econtext->ecxt_per_tuple_memory);
383 /* Unlink self from owning EState, if any */
384 estate = econtext->ecxt_estate;
386 estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
388 /* And delete the ExprContext node */
395 * Reset an expression context in preparation for a rescan of its
396 * plan node. This requires calling any registered shutdown callbacks,
397 * since any partially complete set-returning-functions must be canceled.
399 * Note we make no assumption about the caller's memory context.
402 ReScanExprContext(ExprContext *econtext)
404 /* Call any registered callbacks */
405 ShutdownExprContext(econtext, true);
406 /* And clean up the memory used */
407 MemoryContextReset(econtext->ecxt_per_tuple_memory);
411 * Build a per-output-tuple ExprContext for an EState.
413 * This is normally invoked via GetPerTupleExprContext() macro,
417 MakePerTupleExprContext(EState *estate)
419 if (estate->es_per_tuple_exprcontext == NULL)
420 estate->es_per_tuple_exprcontext = CreateExprContext(estate);
422 return estate->es_per_tuple_exprcontext;
426 /* ----------------------------------------------------------------
427 * miscellaneous node-init support functions
429 * Note: all of these are expected to be called with CurrentMemoryContext
430 * equal to the per-query memory context.
431 * ----------------------------------------------------------------
435 * ExecAssignExprContext
437 * This initializes the ps_ExprContext field. It is only necessary
438 * to do this for nodes which use ExecQual or ExecProject
439 * because those routines require an econtext. Other nodes that
440 * don't have to evaluate expressions don't need to do this.
444 ExecAssignExprContext(EState *estate, PlanState *planstate)
446 planstate->ps_ExprContext = CreateExprContext(estate);
454 ExecGetResultType(PlanState *planstate)
456 return planstate->ps_ResultTupleDesc;
460 * ExecGetResultSlotOps - information about node's type of result slot
462 const TupleTableSlotOps *
463 ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
465 if (planstate->resultopsset && planstate->resultops)
468 *isfixed = planstate->resultopsfixed;
469 return planstate->resultops;
474 if (planstate->resultopsset)
475 *isfixed = planstate->resultopsfixed;
476 else if (planstate->ps_ResultTupleSlot)
477 *isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
482 if (!planstate->ps_ResultTupleSlot)
483 return &TTSOpsVirtual;
485 return planstate->ps_ResultTupleSlot->tts_ops;
490 * ExecAssignProjectionInfo
492 * forms the projection information from the node's targetlist
494 * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
495 * for a relation-scan node, can pass NULL for upper-level nodes
499 ExecAssignProjectionInfo(PlanState *planstate,
502 planstate->ps_ProjInfo =
503 ExecBuildProjectionInfo(planstate->plan->targetlist,
504 planstate->ps_ExprContext,
505 planstate->ps_ResultTupleSlot,
512 * ExecConditionalAssignProjectionInfo
514 * as ExecAssignProjectionInfo, but store NULL rather than building projection
515 * info if no projection is required
519 ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
522 if (tlist_matches_tupdesc(planstate,
523 planstate->plan->targetlist,
527 planstate->ps_ProjInfo = NULL;
528 planstate->resultopsset = planstate->scanopsset;
529 planstate->resultopsfixed = planstate->scanopsfixed;
530 planstate->resultops = planstate->scanops;
534 if (!planstate->ps_ResultTupleSlot)
536 ExecInitResultSlot(planstate, &TTSOpsVirtual);
537 planstate->resultops = &TTSOpsVirtual;
538 planstate->resultopsfixed = true;
539 planstate->resultopsset = true;
541 ExecAssignProjectionInfo(planstate, inputDesc);
546 tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
548 int numattrs = tupdesc->natts;
550 ListCell *tlist_item = list_head(tlist);
552 /* Check the tlist attributes */
553 for (attrno = 1; attrno <= numattrs; attrno++)
555 Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
558 if (tlist_item == NULL)
559 return false; /* tlist too short */
560 var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
561 if (!var || !IsA(var, Var))
562 return false; /* tlist item not a Var */
563 /* if these Asserts fail, planner messed up */
564 Assert(var->varno == varno);
565 Assert(var->varlevelsup == 0);
566 if (var->varattno != attrno)
567 return false; /* out of order */
568 if (att_tup->attisdropped)
569 return false; /* table contains dropped columns */
570 if (att_tup->atthasmissing)
571 return false; /* table contains cols with missing values */
574 * Note: usually the Var's type should match the tupdesc exactly, but
575 * in situations involving unions of columns that have different
576 * typmods, the Var may have come from above the union and hence have
577 * typmod -1. This is a legitimate situation since the Var still
578 * describes the column, just not as exactly as the tupdesc does. We
579 * could change the planner to prevent it, but it'd then insert
580 * projection steps just to convert from specific typmod to typmod -1,
581 * which is pretty silly.
583 if (var->vartype != att_tup->atttypid ||
584 (var->vartypmod != att_tup->atttypmod &&
585 var->vartypmod != -1))
586 return false; /* type mismatch */
588 tlist_item = lnext(tlist, tlist_item);
592 return false; /* tlist too long */
598 * ExecFreeExprContext
600 * A plan node's ExprContext should be freed explicitly during executor
601 * shutdown because there may be shutdown callbacks to call. (Other resources
602 * made by the above routines, such as projection info, don't need to be freed
603 * explicitly because they're just memory in the per-query memory context.)
605 * However ... there is no particular need to do it during ExecEndNode,
606 * because FreeExecutorState will free any remaining ExprContexts within
607 * the EState. Letting FreeExecutorState do it allows the ExprContexts to
608 * be freed in reverse order of creation, rather than order of creation as
609 * will happen if we delete them here, which saves O(N^2) work in the list
610 * cleanup inside FreeExprContext.
614 ExecFreeExprContext(PlanState *planstate)
617 * Per above discussion, don't actually delete the ExprContext. We do
618 * unlink it from the plan node, though.
620 planstate->ps_ExprContext = NULL;
624 /* ----------------------------------------------------------------
626 * ----------------------------------------------------------------
634 ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
636 TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
638 ExecSetSlotDescriptor(slot, tupDesc);
642 * ExecCreateScanSlotFromOuterPlan
646 ExecCreateScanSlotFromOuterPlan(EState *estate,
647 ScanState *scanstate,
648 const TupleTableSlotOps *tts_ops)
650 PlanState *outerPlan;
653 outerPlan = outerPlanState(scanstate);
654 tupDesc = ExecGetResultType(outerPlan);
656 ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_ops);
659 /* ----------------------------------------------------------------
660 * ExecRelationIsTargetRelation
662 * Detect whether a relation (identified by rangetable index)
663 * is one of the target relations of the query.
665 * Note: This is currently no longer used in core. We keep it around
666 * because FDWs may wish to use it to determine if their foreign table
667 * is a target relation.
668 * ----------------------------------------------------------------
671 ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
673 ResultRelInfo *resultRelInfos;
676 resultRelInfos = estate->es_result_relations;
677 for (i = 0; i < estate->es_num_result_relations; i++)
679 if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
685 /* ----------------------------------------------------------------
686 * ExecOpenScanRelation
688 * Open the heap relation to be scanned by a base-level scan plan node.
689 * This should be called during the node's ExecInit routine.
690 * ----------------------------------------------------------------
693 ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
697 /* Open the relation. */
698 rel = ExecGetRangeTableRelation(estate, scanrelid);
701 * Complain if we're attempting a scan of an unscannable relation, except
702 * when the query won't actually be run. This is a slightly klugy place
703 * to do this, perhaps, but there is no better place.
705 if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
706 !RelationIsScannable(rel))
708 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
709 errmsg("materialized view \"%s\" has not been populated",
710 RelationGetRelationName(rel)),
711 errhint("Use the REFRESH MATERIALIZED VIEW command.")));
718 * Set up executor's range-table-related data
720 * In addition to the range table proper, initialize arrays that are
721 * indexed by rangetable index.
724 ExecInitRangeTable(EState *estate, List *rangeTable)
726 /* Remember the range table List as-is */
727 estate->es_range_table = rangeTable;
729 /* Set size of associated arrays */
730 estate->es_range_table_size = list_length(rangeTable);
733 * Allocate an array to store an open Relation corresponding to each
734 * rangetable entry, and initialize entries to NULL. Relations are opened
735 * and stored here as needed.
737 estate->es_relations = (Relation *)
738 palloc0(estate->es_range_table_size * sizeof(Relation));
741 * es_rowmarks is also parallel to the es_range_table, but it's allocated
744 estate->es_rowmarks = NULL;
748 * ExecGetRangeTableRelation
749 * Open the Relation for a range table entry, if not already done
751 * The Relations will be closed again in ExecEndPlan().
754 ExecGetRangeTableRelation(EState *estate, Index rti)
758 Assert(rti > 0 && rti <= estate->es_range_table_size);
760 rel = estate->es_relations[rti - 1];
763 /* First time through, so open the relation */
764 RangeTblEntry *rte = exec_rt_fetch(rti, estate);
766 Assert(rte->rtekind == RTE_RELATION);
768 if (!IsParallelWorker())
771 * In a normal query, we should already have the appropriate lock,
772 * but verify that through an Assert. Since there's already an
773 * Assert inside table_open that insists on holding some lock, it
774 * seems sufficient to check this only when rellockmode is higher
777 rel = table_open(rte->relid, NoLock);
778 Assert(rte->rellockmode == AccessShareLock ||
779 CheckRelationLockedByMe(rel, rte->rellockmode, false));
784 * If we are a parallel worker, we need to obtain our own local
785 * lock on the relation. This ensures sane behavior in case the
786 * parent process exits before we do.
788 rel = table_open(rte->relid, rte->rellockmode);
791 estate->es_relations[rti - 1] = rel;
798 * UpdateChangedParamSet
799 * Add changed parameters to a plan node's chgParam set
802 UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
807 * The plan node only depends on params listed in its allParam set. Don't
808 * include anything else into its chgParam set.
810 parmset = bms_intersect(node->plan->allParam, newchg);
813 * Keep node->chgParam == NULL if there's not actually any members; this
814 * allows the simplest possible tests in executor node files.
816 if (!bms_is_empty(parmset))
817 node->chgParam = bms_join(node->chgParam, parmset);
823 * executor_errposition
824 * Report an execution-time cursor position, if possible.
826 * This is expected to be used within an ereport() call. The return value
827 * is a dummy (always 0, in fact).
829 * The locations stored in parsetrees are byte offsets into the source string.
830 * We have to convert them to 1-based character indexes for reporting to
831 * clients. (We do things this way to avoid unnecessary overhead in the
832 * normal non-error case: computing character indexes would be much more
833 * expensive than storing token offsets.)
836 executor_errposition(EState *estate, int location)
840 /* No-op if location was not provided */
843 /* Can't do anything if source text is not available */
844 if (estate == NULL || estate->es_sourceText == NULL)
846 /* Convert offset to character number */
847 pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
848 /* And pass it to the ereport mechanism */
849 return errposition(pos);
853 * Register a shutdown callback in an ExprContext.
855 * Shutdown callbacks will be called (in reverse order of registration)
856 * when the ExprContext is deleted or rescanned. This provides a hook
857 * for functions called in the context to do any cleanup needed --- it's
858 * particularly useful for functions returning sets. Note that the
859 * callback will *not* be called in the event that execution is aborted
863 RegisterExprContextCallback(ExprContext *econtext,
864 ExprContextCallbackFunction function,
867 ExprContext_CB *ecxt_callback;
869 /* Save the info in appropriate memory context */
870 ecxt_callback = (ExprContext_CB *)
871 MemoryContextAlloc(econtext->ecxt_per_query_memory,
872 sizeof(ExprContext_CB));
874 ecxt_callback->function = function;
875 ecxt_callback->arg = arg;
877 /* link to front of list for appropriate execution order */
878 ecxt_callback->next = econtext->ecxt_callbacks;
879 econtext->ecxt_callbacks = ecxt_callback;
883 * Deregister a shutdown callback in an ExprContext.
885 * Any list entries matching the function and arg will be removed.
886 * This can be used if it's no longer necessary to call the callback.
889 UnregisterExprContextCallback(ExprContext *econtext,
890 ExprContextCallbackFunction function,
893 ExprContext_CB **prev_callback;
894 ExprContext_CB *ecxt_callback;
896 prev_callback = &econtext->ecxt_callbacks;
898 while ((ecxt_callback = *prev_callback) != NULL)
900 if (ecxt_callback->function == function && ecxt_callback->arg == arg)
902 *prev_callback = ecxt_callback->next;
903 pfree(ecxt_callback);
906 prev_callback = &ecxt_callback->next;
911 * Call all the shutdown callbacks registered in an ExprContext.
913 * The callback list is emptied (important in case this is only a rescan
914 * reset, and not deletion of the ExprContext).
916 * If isCommit is false, just clean the callback list but don't call 'em.
917 * (See comment for FreeExprContext.)
920 ShutdownExprContext(ExprContext *econtext, bool isCommit)
922 ExprContext_CB *ecxt_callback;
923 MemoryContext oldcontext;
925 /* Fast path in normal case where there's nothing to do. */
926 if (econtext->ecxt_callbacks == NULL)
930 * Call the callbacks in econtext's per-tuple context. This ensures that
931 * any memory they might leak will get cleaned up.
933 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
936 * Call each callback function in reverse registration order.
938 while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
940 econtext->ecxt_callbacks = ecxt_callback->next;
942 ecxt_callback->function(ecxt_callback->arg);
943 pfree(ecxt_callback);
946 MemoryContextSwitchTo(oldcontext);
953 * These functions return the value of the requested attribute
954 * out of the given tuple Datum.
955 * C functions which take a tuple as an argument are expected
956 * to use these. Ex: overpaid(EMP) might call GetAttributeByNum().
957 * Note: these are actually rather slow because they do a typcache
958 * lookup on each call.
961 GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
968 HeapTupleData tmptup;
972 elog(ERROR, "invalid attribute name");
975 elog(ERROR, "a NULL isNull pointer was passed");
979 /* Kinda bogus but compatible with old behavior... */
984 tupType = HeapTupleHeaderGetTypeId(tuple);
985 tupTypmod = HeapTupleHeaderGetTypMod(tuple);
986 tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
988 attrno = InvalidAttrNumber;
989 for (i = 0; i < tupDesc->natts; i++)
991 Form_pg_attribute att = TupleDescAttr(tupDesc, i);
993 if (namestrcmp(&(att->attname), attname) == 0)
995 attrno = att->attnum;
1000 if (attrno == InvalidAttrNumber)
1001 elog(ERROR, "attribute \"%s\" does not exist", attname);
1004 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1005 * the fields in the struct just in case user tries to inspect system
1008 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1009 ItemPointerSetInvalid(&(tmptup.t_self));
1010 tmptup.t_tableOid = InvalidOid;
1011 tmptup.t_data = tuple;
1013 result = heap_getattr(&tmptup,
1018 ReleaseTupleDesc(tupDesc);
1024 GetAttributeByNum(HeapTupleHeader tuple,
1032 HeapTupleData tmptup;
1034 if (!AttributeNumberIsValid(attrno))
1035 elog(ERROR, "invalid attribute number %d", attrno);
1038 elog(ERROR, "a NULL isNull pointer was passed");
1042 /* Kinda bogus but compatible with old behavior... */
1047 tupType = HeapTupleHeaderGetTypeId(tuple);
1048 tupTypmod = HeapTupleHeaderGetTypMod(tuple);
1049 tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1052 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
1053 * the fields in the struct just in case user tries to inspect system
1056 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
1057 ItemPointerSetInvalid(&(tmptup.t_self));
1058 tmptup.t_tableOid = InvalidOid;
1059 tmptup.t_data = tuple;
1061 result = heap_getattr(&tmptup,
1066 ReleaseTupleDesc(tupDesc);
1072 * Number of items in a tlist (including any resjunk items!)
1075 ExecTargetListLength(List *targetlist)
1077 /* This used to be more complex, but fjoins are dead */
1078 return list_length(targetlist);
1082 * Number of items in a tlist, not including any resjunk items
1085 ExecCleanTargetListLength(List *targetlist)
1090 foreach(tl, targetlist)
1092 TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1094 if (!curTle->resjunk)
1101 * Return a relInfo's tuple slot for a trigger's OLD tuples.
1104 ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
1106 if (relInfo->ri_TrigOldSlot == NULL)
1108 Relation rel = relInfo->ri_RelationDesc;
1109 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1111 relInfo->ri_TrigOldSlot =
1112 ExecInitExtraTupleSlot(estate,
1113 RelationGetDescr(rel),
1114 table_slot_callbacks(rel));
1116 MemoryContextSwitchTo(oldcontext);
1119 return relInfo->ri_TrigOldSlot;
1123 * Return a relInfo's tuple slot for a trigger's NEW tuples.
1126 ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
1128 if (relInfo->ri_TrigNewSlot == NULL)
1130 Relation rel = relInfo->ri_RelationDesc;
1131 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1133 relInfo->ri_TrigNewSlot =
1134 ExecInitExtraTupleSlot(estate,
1135 RelationGetDescr(rel),
1136 table_slot_callbacks(rel));
1138 MemoryContextSwitchTo(oldcontext);
1141 return relInfo->ri_TrigNewSlot;
1145 * Return a relInfo's tuple slot for processing returning tuples.
1148 ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
1150 if (relInfo->ri_ReturningSlot == NULL)
1152 Relation rel = relInfo->ri_RelationDesc;
1153 MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1155 relInfo->ri_ReturningSlot =
1156 ExecInitExtraTupleSlot(estate,
1157 RelationGetDescr(rel),
1158 table_slot_callbacks(rel));
1160 MemoryContextSwitchTo(oldcontext);
1163 return relInfo->ri_ReturningSlot;