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