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