1 /*-------------------------------------------------------------------------
2 *
3 * execUtils.c
4 * miscellaneous executor utility routines
5 *
6 * Portions Copyright (c) 1996-2017, 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 * ExecAssignResultType
26 * etc
27 *
28 * ExecOpenScanRelation Common code for scan node init routines.
29 * ExecCloseScanRelation
30 *
31 * executor_errposition Report syntactic position of an error.
32 *
33 * RegisterExprContextCallback Register function shutdown callback
34 * UnregisterExprContextCallback Deregister function shutdown callback
35 *
36 * GetAttributeByName Runtime extraction of columns from tuples.
37 * GetAttributeByNum
38 *
39 * NOTES
40 * This file has traditionally been the place to stick misc.
41 * executor support stuff that doesn't really go anyplace else.
42 */
43
44 #include "postgres.h"
45
46 #include "access/relscan.h"
47 #include "access/transam.h"
48 #include "executor/executor.h"
49 #include "mb/pg_wchar.h"
50 #include "nodes/nodeFuncs.h"
51 #include "parser/parsetree.h"
52 #include "storage/lmgr.h"
53 #include "utils/builtins.h"
54 #include "utils/memutils.h"
55 #include "utils/rel.h"
56 #include "utils/typcache.h"
57
58
59 static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
60
61
62 /* ----------------------------------------------------------------
63 * Executor state and memory management functions
64 * ----------------------------------------------------------------
65 */
66
67 /* ----------------
68 * CreateExecutorState
69 *
70 * Create and initialize an EState node, which is the root of
71 * working storage for an entire Executor invocation.
72 *
73 * Principally, this creates the per-query memory context that will be
74 * used to hold all working data that lives till the end of the query.
75 * Note that the per-query context will become a child of the caller's
76 * CurrentMemoryContext.
77 * ----------------
78 */
79 EState *
CreateExecutorState(void)80 CreateExecutorState(void)
81 {
82 EState *estate;
83 MemoryContext qcontext;
84 MemoryContext oldcontext;
85
86 /*
87 * Create the per-query context for this Executor run.
88 */
89 qcontext = AllocSetContextCreate(CurrentMemoryContext,
90 "ExecutorState",
91 ALLOCSET_DEFAULT_SIZES);
92
93 /*
94 * Make the EState node within the per-query context. This way, we don't
95 * need a separate pfree() operation for it at shutdown.
96 */
97 oldcontext = MemoryContextSwitchTo(qcontext);
98
99 estate = makeNode(EState);
100
101 /*
102 * Initialize all fields of the Executor State structure
103 */
104 estate->es_direction = ForwardScanDirection;
105 estate->es_snapshot = InvalidSnapshot; /* caller must initialize this */
106 estate->es_crosscheck_snapshot = InvalidSnapshot; /* no crosscheck */
107 estate->es_range_table = NIL;
108 estate->es_plannedstmt = NULL;
109
110 estate->es_junkFilter = NULL;
111
112 estate->es_output_cid = (CommandId) 0;
113
114 estate->es_result_relations = NULL;
115 estate->es_num_result_relations = 0;
116 estate->es_result_relation_info = NULL;
117
118 estate->es_root_result_relations = NULL;
119 estate->es_num_root_result_relations = 0;
120
121 estate->es_leaf_result_relations = NIL;
122
123 estate->es_trig_target_relations = NIL;
124 estate->es_trig_tuple_slot = NULL;
125 estate->es_trig_oldtup_slot = NULL;
126 estate->es_trig_newtup_slot = NULL;
127
128 estate->es_param_list_info = NULL;
129 estate->es_param_exec_vals = NULL;
130
131 estate->es_queryEnv = NULL;
132
133 estate->es_query_cxt = qcontext;
134
135 estate->es_tupleTable = NIL;
136
137 estate->es_rowMarks = NIL;
138
139 estate->es_processed = 0;
140 estate->es_lastoid = InvalidOid;
141
142 estate->es_top_eflags = 0;
143 estate->es_instrument = 0;
144 estate->es_finished = false;
145
146 estate->es_exprcontexts = NIL;
147
148 estate->es_subplanstates = NIL;
149
150 estate->es_auxmodifytables = NIL;
151
152 estate->es_per_tuple_exprcontext = NULL;
153
154 estate->es_epqTuple = NULL;
155 estate->es_epqTupleSet = NULL;
156 estate->es_epqScanDone = NULL;
157 estate->es_sourceText = NULL;
158
159 estate->es_use_parallel_mode = false;
160
161 /*
162 * Return the executor state structure
163 */
164 MemoryContextSwitchTo(oldcontext);
165
166 return estate;
167 }
168
169 /* ----------------
170 * FreeExecutorState
171 *
172 * Release an EState along with all remaining working storage.
173 *
174 * Note: this is not responsible for releasing non-memory resources,
175 * such as open relations or buffer pins. But it will shut down any
176 * still-active ExprContexts within the EState. That is sufficient
177 * cleanup for situations where the EState has only been used for expression
178 * evaluation, and not to run a complete Plan.
179 *
180 * This can be called in any memory context ... so long as it's not one
181 * of the ones to be freed.
182 * ----------------
183 */
184 void
FreeExecutorState(EState * estate)185 FreeExecutorState(EState *estate)
186 {
187 /*
188 * Shut down and free any remaining ExprContexts. We do this explicitly
189 * to ensure that any remaining shutdown callbacks get called (since they
190 * might need to release resources that aren't simply memory within the
191 * per-query memory context).
192 */
193 while (estate->es_exprcontexts)
194 {
195 /*
196 * XXX: seems there ought to be a faster way to implement this than
197 * repeated list_delete(), no?
198 */
199 FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
200 true);
201 /* FreeExprContext removed the list link for us */
202 }
203
204 /*
205 * Free the per-query memory context, thereby releasing all working
206 * memory, including the EState node itself.
207 */
208 MemoryContextDelete(estate->es_query_cxt);
209 }
210
211 /* ----------------
212 * CreateExprContext
213 *
214 * Create a context for expression evaluation within an EState.
215 *
216 * An executor run may require multiple ExprContexts (we usually make one
217 * for each Plan node, and a separate one for per-output-tuple processing
218 * such as constraint checking). Each ExprContext has its own "per-tuple"
219 * memory context.
220 *
221 * Note we make no assumption about the caller's memory context.
222 * ----------------
223 */
224 ExprContext *
CreateExprContext(EState * estate)225 CreateExprContext(EState *estate)
226 {
227 ExprContext *econtext;
228 MemoryContext oldcontext;
229
230 /* Create the ExprContext node within the per-query memory context */
231 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
232
233 econtext = makeNode(ExprContext);
234
235 /* Initialize fields of ExprContext */
236 econtext->ecxt_scantuple = NULL;
237 econtext->ecxt_innertuple = NULL;
238 econtext->ecxt_outertuple = NULL;
239
240 econtext->ecxt_per_query_memory = estate->es_query_cxt;
241
242 /*
243 * Create working memory for expression evaluation in this context.
244 */
245 econtext->ecxt_per_tuple_memory =
246 AllocSetContextCreate(estate->es_query_cxt,
247 "ExprContext",
248 ALLOCSET_DEFAULT_SIZES);
249
250 econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
251 econtext->ecxt_param_list_info = estate->es_param_list_info;
252
253 econtext->ecxt_aggvalues = NULL;
254 econtext->ecxt_aggnulls = NULL;
255
256 econtext->caseValue_datum = (Datum) 0;
257 econtext->caseValue_isNull = true;
258
259 econtext->domainValue_datum = (Datum) 0;
260 econtext->domainValue_isNull = true;
261
262 econtext->ecxt_estate = estate;
263
264 econtext->ecxt_callbacks = NULL;
265
266 /*
267 * Link the ExprContext into the EState to ensure it is shut down when the
268 * EState is freed. Because we use lcons(), shutdowns will occur in
269 * reverse order of creation, which may not be essential but can't hurt.
270 */
271 estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
272
273 MemoryContextSwitchTo(oldcontext);
274
275 return econtext;
276 }
277
278 /* ----------------
279 * CreateStandaloneExprContext
280 *
281 * Create a context for standalone expression evaluation.
282 *
283 * An ExprContext made this way can be used for evaluation of expressions
284 * that contain no Params, subplans, or Var references (it might work to
285 * put tuple references into the scantuple field, but it seems unwise).
286 *
287 * The ExprContext struct is allocated in the caller's current memory
288 * context, which also becomes its "per query" context.
289 *
290 * It is caller's responsibility to free the ExprContext when done,
291 * or at least ensure that any shutdown callbacks have been called
292 * (ReScanExprContext() is suitable). Otherwise, non-memory resources
293 * might be leaked.
294 * ----------------
295 */
296 ExprContext *
CreateStandaloneExprContext(void)297 CreateStandaloneExprContext(void)
298 {
299 ExprContext *econtext;
300
301 /* Create the ExprContext node within the caller's memory context */
302 econtext = makeNode(ExprContext);
303
304 /* Initialize fields of ExprContext */
305 econtext->ecxt_scantuple = NULL;
306 econtext->ecxt_innertuple = NULL;
307 econtext->ecxt_outertuple = NULL;
308
309 econtext->ecxt_per_query_memory = CurrentMemoryContext;
310
311 /*
312 * Create working memory for expression evaluation in this context.
313 */
314 econtext->ecxt_per_tuple_memory =
315 AllocSetContextCreate(CurrentMemoryContext,
316 "ExprContext",
317 ALLOCSET_DEFAULT_SIZES);
318
319 econtext->ecxt_param_exec_vals = NULL;
320 econtext->ecxt_param_list_info = NULL;
321
322 econtext->ecxt_aggvalues = NULL;
323 econtext->ecxt_aggnulls = NULL;
324
325 econtext->caseValue_datum = (Datum) 0;
326 econtext->caseValue_isNull = true;
327
328 econtext->domainValue_datum = (Datum) 0;
329 econtext->domainValue_isNull = true;
330
331 econtext->ecxt_estate = NULL;
332
333 econtext->ecxt_callbacks = NULL;
334
335 return econtext;
336 }
337
338 /* ----------------
339 * FreeExprContext
340 *
341 * Free an expression context, including calling any remaining
342 * shutdown callbacks.
343 *
344 * Since we free the temporary context used for expression evaluation,
345 * any previously computed pass-by-reference expression result will go away!
346 *
347 * If isCommit is false, we are being called in error cleanup, and should
348 * not call callbacks but only release memory. (It might be better to call
349 * the callbacks and pass the isCommit flag to them, but that would require
350 * more invasive code changes than currently seems justified.)
351 *
352 * Note we make no assumption about the caller's memory context.
353 * ----------------
354 */
355 void
FreeExprContext(ExprContext * econtext,bool isCommit)356 FreeExprContext(ExprContext *econtext, bool isCommit)
357 {
358 EState *estate;
359
360 /* Call any registered callbacks */
361 ShutdownExprContext(econtext, isCommit);
362 /* And clean up the memory used */
363 MemoryContextDelete(econtext->ecxt_per_tuple_memory);
364 /* Unlink self from owning EState, if any */
365 estate = econtext->ecxt_estate;
366 if (estate)
367 estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
368 econtext);
369 /* And delete the ExprContext node */
370 pfree(econtext);
371 }
372
373 /*
374 * ReScanExprContext
375 *
376 * Reset an expression context in preparation for a rescan of its
377 * plan node. This requires calling any registered shutdown callbacks,
378 * since any partially complete set-returning-functions must be canceled.
379 *
380 * Note we make no assumption about the caller's memory context.
381 */
382 void
ReScanExprContext(ExprContext * econtext)383 ReScanExprContext(ExprContext *econtext)
384 {
385 /* Call any registered callbacks */
386 ShutdownExprContext(econtext, true);
387 /* And clean up the memory used */
388 MemoryContextReset(econtext->ecxt_per_tuple_memory);
389 }
390
391 /*
392 * Build a per-output-tuple ExprContext for an EState.
393 *
394 * This is normally invoked via GetPerTupleExprContext() macro,
395 * not directly.
396 */
397 ExprContext *
MakePerTupleExprContext(EState * estate)398 MakePerTupleExprContext(EState *estate)
399 {
400 if (estate->es_per_tuple_exprcontext == NULL)
401 estate->es_per_tuple_exprcontext = CreateExprContext(estate);
402
403 return estate->es_per_tuple_exprcontext;
404 }
405
406
407 /* ----------------------------------------------------------------
408 * miscellaneous node-init support functions
409 *
410 * Note: all of these are expected to be called with CurrentMemoryContext
411 * equal to the per-query memory context.
412 * ----------------------------------------------------------------
413 */
414
415 /* ----------------
416 * ExecAssignExprContext
417 *
418 * This initializes the ps_ExprContext field. It is only necessary
419 * to do this for nodes which use ExecQual or ExecProject
420 * because those routines require an econtext. Other nodes that
421 * don't have to evaluate expressions don't need to do this.
422 * ----------------
423 */
424 void
ExecAssignExprContext(EState * estate,PlanState * planstate)425 ExecAssignExprContext(EState *estate, PlanState *planstate)
426 {
427 planstate->ps_ExprContext = CreateExprContext(estate);
428 }
429
430 /* ----------------
431 * ExecAssignResultType
432 * ----------------
433 */
434 void
ExecAssignResultType(PlanState * planstate,TupleDesc tupDesc)435 ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
436 {
437 TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
438
439 ExecSetSlotDescriptor(slot, tupDesc);
440 }
441
442 /* ----------------
443 * ExecAssignResultTypeFromTL
444 * ----------------
445 */
446 void
ExecAssignResultTypeFromTL(PlanState * planstate)447 ExecAssignResultTypeFromTL(PlanState *planstate)
448 {
449 bool hasoid;
450 TupleDesc tupDesc;
451
452 if (ExecContextForcesOids(planstate, &hasoid))
453 {
454 /* context forces OID choice; hasoid is now set correctly */
455 }
456 else
457 {
458 /* given free choice, don't leave space for OIDs in result tuples */
459 hasoid = false;
460 }
461
462 /*
463 * ExecTypeFromTL needs the parse-time representation of the tlist, not a
464 * list of ExprStates. This is good because some plan nodes don't bother
465 * to set up planstate->targetlist ...
466 */
467 tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
468 ExecAssignResultType(planstate, tupDesc);
469 }
470
471 /* ----------------
472 * ExecGetResultType
473 * ----------------
474 */
475 TupleDesc
ExecGetResultType(PlanState * planstate)476 ExecGetResultType(PlanState *planstate)
477 {
478 TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
479
480 return slot->tts_tupleDescriptor;
481 }
482
483
484 /* ----------------
485 * ExecAssignProjectionInfo
486 *
487 * forms the projection information from the node's targetlist
488 *
489 * Notes for inputDesc are same as for ExecBuildProjectionInfo: supply it
490 * for a relation-scan node, can pass NULL for upper-level nodes
491 * ----------------
492 */
493 void
ExecAssignProjectionInfo(PlanState * planstate,TupleDesc inputDesc)494 ExecAssignProjectionInfo(PlanState *planstate,
495 TupleDesc inputDesc)
496 {
497 planstate->ps_ProjInfo =
498 ExecBuildProjectionInfo(planstate->plan->targetlist,
499 planstate->ps_ExprContext,
500 planstate->ps_ResultTupleSlot,
501 planstate,
502 inputDesc);
503 }
504
505
506 /* ----------------
507 * ExecFreeExprContext
508 *
509 * A plan node's ExprContext should be freed explicitly during executor
510 * shutdown because there may be shutdown callbacks to call. (Other resources
511 * made by the above routines, such as projection info, don't need to be freed
512 * explicitly because they're just memory in the per-query memory context.)
513 *
514 * However ... there is no particular need to do it during ExecEndNode,
515 * because FreeExecutorState will free any remaining ExprContexts within
516 * the EState. Letting FreeExecutorState do it allows the ExprContexts to
517 * be freed in reverse order of creation, rather than order of creation as
518 * will happen if we delete them here, which saves O(N^2) work in the list
519 * cleanup inside FreeExprContext.
520 * ----------------
521 */
522 void
ExecFreeExprContext(PlanState * planstate)523 ExecFreeExprContext(PlanState *planstate)
524 {
525 /*
526 * Per above discussion, don't actually delete the ExprContext. We do
527 * unlink it from the plan node, though.
528 */
529 planstate->ps_ExprContext = NULL;
530 }
531
532 /* ----------------------------------------------------------------
533 * the following scan type support functions are for
534 * those nodes which are stubborn and return tuples in
535 * their Scan tuple slot instead of their Result tuple
536 * slot.. luck fur us, these nodes do not do projections
537 * so we don't have to worry about getting the ProjectionInfo
538 * right for them... -cim 6/3/91
539 * ----------------------------------------------------------------
540 */
541
542 /* ----------------
543 * ExecAssignScanType
544 * ----------------
545 */
546 void
ExecAssignScanType(ScanState * scanstate,TupleDesc tupDesc)547 ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
548 {
549 TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
550
551 ExecSetSlotDescriptor(slot, tupDesc);
552 }
553
554 /* ----------------
555 * ExecAssignScanTypeFromOuterPlan
556 * ----------------
557 */
558 void
ExecAssignScanTypeFromOuterPlan(ScanState * scanstate)559 ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
560 {
561 PlanState *outerPlan;
562 TupleDesc tupDesc;
563
564 outerPlan = outerPlanState(scanstate);
565 tupDesc = ExecGetResultType(outerPlan);
566
567 ExecAssignScanType(scanstate, tupDesc);
568 }
569
570
571 /* ----------------------------------------------------------------
572 * Scan node support
573 * ----------------------------------------------------------------
574 */
575
576 /* ----------------------------------------------------------------
577 * ExecRelationIsTargetRelation
578 *
579 * Detect whether a relation (identified by rangetable index)
580 * is one of the target relations of the query.
581 * ----------------------------------------------------------------
582 */
583 bool
ExecRelationIsTargetRelation(EState * estate,Index scanrelid)584 ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
585 {
586 ResultRelInfo *resultRelInfos;
587 int i;
588
589 resultRelInfos = estate->es_result_relations;
590 for (i = 0; i < estate->es_num_result_relations; i++)
591 {
592 if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
593 return true;
594 }
595 return false;
596 }
597
598 /* ----------------------------------------------------------------
599 * ExecOpenScanRelation
600 *
601 * Open the heap relation to be scanned by a base-level scan plan node.
602 * This should be called during the node's ExecInit routine.
603 *
604 * By default, this acquires AccessShareLock on the relation. However,
605 * if the relation was already locked by InitPlan, we don't need to acquire
606 * any additional lock. This saves trips to the shared lock manager.
607 * ----------------------------------------------------------------
608 */
609 Relation
ExecOpenScanRelation(EState * estate,Index scanrelid,int eflags)610 ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
611 {
612 Relation rel;
613 Oid reloid;
614 LOCKMODE lockmode;
615
616 /*
617 * Determine the lock type we need. First, scan to see if target relation
618 * is a result relation. If not, check if it's a FOR UPDATE/FOR SHARE
619 * relation. In either of those cases, we got the lock already.
620 */
621 lockmode = AccessShareLock;
622 if (ExecRelationIsTargetRelation(estate, scanrelid))
623 lockmode = NoLock;
624 else
625 {
626 /* Keep this check in sync with InitPlan! */
627 ExecRowMark *erm = ExecFindRowMark(estate, scanrelid, true);
628
629 if (erm != NULL && erm->relation != NULL)
630 lockmode = NoLock;
631 }
632
633 /* Open the relation and acquire lock as needed */
634 reloid = getrelid(scanrelid, estate->es_range_table);
635 rel = heap_open(reloid, lockmode);
636
637 /*
638 * Complain if we're attempting a scan of an unscannable relation, except
639 * when the query won't actually be run. This is a slightly klugy place
640 * to do this, perhaps, but there is no better place.
641 */
642 if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
643 !RelationIsScannable(rel))
644 ereport(ERROR,
645 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
646 errmsg("materialized view \"%s\" has not been populated",
647 RelationGetRelationName(rel)),
648 errhint("Use the REFRESH MATERIALIZED VIEW command.")));
649
650 return rel;
651 }
652
653 /* ----------------------------------------------------------------
654 * ExecCloseScanRelation
655 *
656 * Close the heap relation scanned by a base-level scan plan node.
657 * This should be called during the node's ExecEnd routine.
658 *
659 * Currently, we do not release the lock acquired by ExecOpenScanRelation.
660 * This lock should be held till end of transaction. (There is a faction
661 * that considers this too much locking, however.)
662 *
663 * If we did want to release the lock, we'd have to repeat the logic in
664 * ExecOpenScanRelation in order to figure out what to release.
665 * ----------------------------------------------------------------
666 */
667 void
ExecCloseScanRelation(Relation scanrel)668 ExecCloseScanRelation(Relation scanrel)
669 {
670 heap_close(scanrel, NoLock);
671 }
672
673 /*
674 * UpdateChangedParamSet
675 * Add changed parameters to a plan node's chgParam set
676 */
677 void
UpdateChangedParamSet(PlanState * node,Bitmapset * newchg)678 UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
679 {
680 Bitmapset *parmset;
681
682 /*
683 * The plan node only depends on params listed in its allParam set. Don't
684 * include anything else into its chgParam set.
685 */
686 parmset = bms_intersect(node->plan->allParam, newchg);
687
688 /*
689 * Keep node->chgParam == NULL if there's not actually any members; this
690 * allows the simplest possible tests in executor node files.
691 */
692 if (!bms_is_empty(parmset))
693 node->chgParam = bms_join(node->chgParam, parmset);
694 else
695 bms_free(parmset);
696 }
697
698 /*
699 * executor_errposition
700 * Report an execution-time cursor position, if possible.
701 *
702 * This is expected to be used within an ereport() call. The return value
703 * is a dummy (always 0, in fact).
704 *
705 * The locations stored in parsetrees are byte offsets into the source string.
706 * We have to convert them to 1-based character indexes for reporting to
707 * clients. (We do things this way to avoid unnecessary overhead in the
708 * normal non-error case: computing character indexes would be much more
709 * expensive than storing token offsets.)
710 */
711 int
executor_errposition(EState * estate,int location)712 executor_errposition(EState *estate, int location)
713 {
714 int pos;
715
716 /* No-op if location was not provided */
717 if (location < 0)
718 return 0;
719 /* Can't do anything if source text is not available */
720 if (estate == NULL || estate->es_sourceText == NULL)
721 return 0;
722 /* Convert offset to character number */
723 pos = pg_mbstrlen_with_len(estate->es_sourceText, location) + 1;
724 /* And pass it to the ereport mechanism */
725 return errposition(pos);
726 }
727
728 /*
729 * Register a shutdown callback in an ExprContext.
730 *
731 * Shutdown callbacks will be called (in reverse order of registration)
732 * when the ExprContext is deleted or rescanned. This provides a hook
733 * for functions called in the context to do any cleanup needed --- it's
734 * particularly useful for functions returning sets. Note that the
735 * callback will *not* be called in the event that execution is aborted
736 * by an error.
737 */
738 void
RegisterExprContextCallback(ExprContext * econtext,ExprContextCallbackFunction function,Datum arg)739 RegisterExprContextCallback(ExprContext *econtext,
740 ExprContextCallbackFunction function,
741 Datum arg)
742 {
743 ExprContext_CB *ecxt_callback;
744
745 /* Save the info in appropriate memory context */
746 ecxt_callback = (ExprContext_CB *)
747 MemoryContextAlloc(econtext->ecxt_per_query_memory,
748 sizeof(ExprContext_CB));
749
750 ecxt_callback->function = function;
751 ecxt_callback->arg = arg;
752
753 /* link to front of list for appropriate execution order */
754 ecxt_callback->next = econtext->ecxt_callbacks;
755 econtext->ecxt_callbacks = ecxt_callback;
756 }
757
758 /*
759 * Deregister a shutdown callback in an ExprContext.
760 *
761 * Any list entries matching the function and arg will be removed.
762 * This can be used if it's no longer necessary to call the callback.
763 */
764 void
UnregisterExprContextCallback(ExprContext * econtext,ExprContextCallbackFunction function,Datum arg)765 UnregisterExprContextCallback(ExprContext *econtext,
766 ExprContextCallbackFunction function,
767 Datum arg)
768 {
769 ExprContext_CB **prev_callback;
770 ExprContext_CB *ecxt_callback;
771
772 prev_callback = &econtext->ecxt_callbacks;
773
774 while ((ecxt_callback = *prev_callback) != NULL)
775 {
776 if (ecxt_callback->function == function && ecxt_callback->arg == arg)
777 {
778 *prev_callback = ecxt_callback->next;
779 pfree(ecxt_callback);
780 }
781 else
782 prev_callback = &ecxt_callback->next;
783 }
784 }
785
786 /*
787 * Call all the shutdown callbacks registered in an ExprContext.
788 *
789 * The callback list is emptied (important in case this is only a rescan
790 * reset, and not deletion of the ExprContext).
791 *
792 * If isCommit is false, just clean the callback list but don't call 'em.
793 * (See comment for FreeExprContext.)
794 */
795 static void
ShutdownExprContext(ExprContext * econtext,bool isCommit)796 ShutdownExprContext(ExprContext *econtext, bool isCommit)
797 {
798 ExprContext_CB *ecxt_callback;
799 MemoryContext oldcontext;
800
801 /* Fast path in normal case where there's nothing to do. */
802 if (econtext->ecxt_callbacks == NULL)
803 return;
804
805 /*
806 * Call the callbacks in econtext's per-tuple context. This ensures that
807 * any memory they might leak will get cleaned up.
808 */
809 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
810
811 /*
812 * Call each callback function in reverse registration order.
813 */
814 while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
815 {
816 econtext->ecxt_callbacks = ecxt_callback->next;
817 if (isCommit)
818 (*ecxt_callback->function) (ecxt_callback->arg);
819 pfree(ecxt_callback);
820 }
821
822 MemoryContextSwitchTo(oldcontext);
823 }
824
825 /*
826 * ExecLockNonLeafAppendTables
827 *
828 * Locks, if necessary, the tables indicated by the RT indexes contained in
829 * the partitioned_rels list. These are the non-leaf tables in the partition
830 * tree controlled by a given Append or MergeAppend node.
831 */
832 void
ExecLockNonLeafAppendTables(List * partitioned_rels,EState * estate)833 ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
834 {
835 PlannedStmt *stmt = estate->es_plannedstmt;
836 ListCell *lc;
837
838 foreach(lc, partitioned_rels)
839 {
840 ListCell *l;
841 Index rti = lfirst_int(lc);
842 bool is_result_rel = false;
843 Oid relid = getrelid(rti, estate->es_range_table);
844
845 /* If this is a result relation, already locked in InitPlan */
846 foreach(l, stmt->nonleafResultRelations)
847 {
848 if (rti == lfirst_int(l))
849 {
850 is_result_rel = true;
851 break;
852 }
853 }
854
855 /*
856 * Not a result relation; check if there is a RowMark that requires
857 * taking a RowShareLock on this rel.
858 */
859 if (!is_result_rel)
860 {
861 PlanRowMark *rc = NULL;
862
863 foreach(l, stmt->rowMarks)
864 {
865 if (((PlanRowMark *) lfirst(l))->rti == rti)
866 {
867 rc = lfirst(l);
868 break;
869 }
870 }
871
872 if (rc && RowMarkRequiresRowShareLock(rc->markType))
873 LockRelationOid(relid, RowShareLock);
874 else
875 LockRelationOid(relid, AccessShareLock);
876 }
877 }
878 }
879
880 /*
881 * GetAttributeByName
882 * GetAttributeByNum
883 *
884 * These functions return the value of the requested attribute
885 * out of the given tuple Datum.
886 * C functions which take a tuple as an argument are expected
887 * to use these. Ex: overpaid(EMP) might call GetAttributeByNum().
888 * Note: these are actually rather slow because they do a typcache
889 * lookup on each call.
890 */
891 Datum
GetAttributeByName(HeapTupleHeader tuple,const char * attname,bool * isNull)892 GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
893 {
894 AttrNumber attrno;
895 Datum result;
896 Oid tupType;
897 int32 tupTypmod;
898 TupleDesc tupDesc;
899 HeapTupleData tmptup;
900 int i;
901
902 if (attname == NULL)
903 elog(ERROR, "invalid attribute name");
904
905 if (isNull == NULL)
906 elog(ERROR, "a NULL isNull pointer was passed");
907
908 if (tuple == NULL)
909 {
910 /* Kinda bogus but compatible with old behavior... */
911 *isNull = true;
912 return (Datum) 0;
913 }
914
915 tupType = HeapTupleHeaderGetTypeId(tuple);
916 tupTypmod = HeapTupleHeaderGetTypMod(tuple);
917 tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
918
919 attrno = InvalidAttrNumber;
920 for (i = 0; i < tupDesc->natts; i++)
921 {
922 if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0)
923 {
924 attrno = tupDesc->attrs[i]->attnum;
925 break;
926 }
927 }
928
929 if (attrno == InvalidAttrNumber)
930 elog(ERROR, "attribute \"%s\" does not exist", attname);
931
932 /*
933 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
934 * the fields in the struct just in case user tries to inspect system
935 * columns.
936 */
937 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
938 ItemPointerSetInvalid(&(tmptup.t_self));
939 tmptup.t_tableOid = InvalidOid;
940 tmptup.t_data = tuple;
941
942 result = heap_getattr(&tmptup,
943 attrno,
944 tupDesc,
945 isNull);
946
947 ReleaseTupleDesc(tupDesc);
948
949 return result;
950 }
951
952 Datum
GetAttributeByNum(HeapTupleHeader tuple,AttrNumber attrno,bool * isNull)953 GetAttributeByNum(HeapTupleHeader tuple,
954 AttrNumber attrno,
955 bool *isNull)
956 {
957 Datum result;
958 Oid tupType;
959 int32 tupTypmod;
960 TupleDesc tupDesc;
961 HeapTupleData tmptup;
962
963 if (!AttributeNumberIsValid(attrno))
964 elog(ERROR, "invalid attribute number %d", attrno);
965
966 if (isNull == NULL)
967 elog(ERROR, "a NULL isNull pointer was passed");
968
969 if (tuple == NULL)
970 {
971 /* Kinda bogus but compatible with old behavior... */
972 *isNull = true;
973 return (Datum) 0;
974 }
975
976 tupType = HeapTupleHeaderGetTypeId(tuple);
977 tupTypmod = HeapTupleHeaderGetTypMod(tuple);
978 tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
979
980 /*
981 * heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
982 * the fields in the struct just in case user tries to inspect system
983 * columns.
984 */
985 tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
986 ItemPointerSetInvalid(&(tmptup.t_self));
987 tmptup.t_tableOid = InvalidOid;
988 tmptup.t_data = tuple;
989
990 result = heap_getattr(&tmptup,
991 attrno,
992 tupDesc,
993 isNull);
994
995 ReleaseTupleDesc(tupDesc);
996
997 return result;
998 }
999
1000 /*
1001 * Number of items in a tlist (including any resjunk items!)
1002 */
1003 int
ExecTargetListLength(List * targetlist)1004 ExecTargetListLength(List *targetlist)
1005 {
1006 /* This used to be more complex, but fjoins are dead */
1007 return list_length(targetlist);
1008 }
1009
1010 /*
1011 * Number of items in a tlist, not including any resjunk items
1012 */
1013 int
ExecCleanTargetListLength(List * targetlist)1014 ExecCleanTargetListLength(List *targetlist)
1015 {
1016 int len = 0;
1017 ListCell *tl;
1018
1019 foreach(tl, targetlist)
1020 {
1021 TargetEntry *curTle = lfirst_node(TargetEntry, tl);
1022
1023 if (!curTle->resjunk)
1024 len++;
1025 }
1026 return len;
1027 }
1028