1 /*-------------------------------------------------------------------------
2  *
3  * execExpr.c
4  *	  Expression evaluation infrastructure.
5  *
6  *	During executor startup, we compile each expression tree (which has
7  *	previously been processed by the parser and planner) into an ExprState,
8  *	using ExecInitExpr() et al.  This converts the tree into a flat array
9  *	of ExprEvalSteps, which may be thought of as instructions in a program.
10  *	At runtime, we'll execute steps, starting with the first, until we reach
11  *	an EEOP_DONE opcode.
12  *
13  *	This file contains the "compilation" logic.  It is independent of the
14  *	specific execution technology we use (switch statement, computed goto,
15  *	JIT compilation, etc).
16  *
17  *	See src/backend/executor/README for some background, specifically the
18  *	"Expression Trees and ExprState nodes", "Expression Initialization",
19  *	and "Expression Evaluation" sections.
20  *
21  *
22  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
23  * Portions Copyright (c) 1994, Regents of the University of California
24  *
25  *
26  * IDENTIFICATION
27  *	  src/backend/executor/execExpr.c
28  *
29  *-------------------------------------------------------------------------
30  */
31 #include "postgres.h"
32 
33 #include "access/nbtree.h"
34 #include "catalog/objectaccess.h"
35 #include "catalog/pg_type.h"
36 #include "executor/execExpr.h"
37 #include "executor/nodeSubplan.h"
38 #include "funcapi.h"
39 #include "miscadmin.h"
40 #include "nodes/makefuncs.h"
41 #include "nodes/nodeFuncs.h"
42 #include "optimizer/clauses.h"
43 #include "optimizer/planner.h"
44 #include "pgstat.h"
45 #include "utils/builtins.h"
46 #include "utils/lsyscache.h"
47 #include "utils/typcache.h"
48 
49 
50 typedef struct LastAttnumInfo
51 {
52 	AttrNumber	last_inner;
53 	AttrNumber	last_outer;
54 	AttrNumber	last_scan;
55 } LastAttnumInfo;
56 
57 static void ExecReadyExpr(ExprState *state);
58 static void ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
59 				Datum *resv, bool *resnull);
60 static void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
61 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
62 			 Oid funcid, Oid inputcollid, PlanState *parent,
63 			 ExprState *state);
64 static void ExecInitExprSlots(ExprState *state, Node *node);
65 static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
66 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
67 					PlanState *parent);
68 static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
69 				 PlanState *parent, ExprState *state,
70 				 Datum *resv, bool *resnull);
71 static bool isAssignmentIndirectionExpr(Expr *expr);
72 static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
73 					   PlanState *parent, ExprState *state,
74 					   Datum *resv, bool *resnull);
75 
76 
77 /*
78  * ExecInitExpr: prepare an expression tree for execution
79  *
80  * This function builds and returns an ExprState implementing the given
81  * Expr node tree.  The return ExprState can then be handed to ExecEvalExpr
82  * for execution.  Because the Expr tree itself is read-only as far as
83  * ExecInitExpr and ExecEvalExpr are concerned, several different executions
84  * of the same plan tree can occur concurrently.  (But note that an ExprState
85  * does mutate at runtime, so it can't be re-used concurrently.)
86  *
87  * This must be called in a memory context that will last as long as repeated
88  * executions of the expression are needed.  Typically the context will be
89  * the same as the per-query context of the associated ExprContext.
90  *
91  * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
92  * the lists of such nodes held by the parent PlanState (or more accurately,
93  * the AggrefExprState etc. nodes created for them are added).
94  *
95  * Note: there is no ExecEndExpr function; we assume that any resource
96  * cleanup needed will be handled by just releasing the memory context
97  * in which the state tree is built.  Functions that require additional
98  * cleanup work can register a shutdown callback in the ExprContext.
99  *
100  *	'node' is the root of the expression tree to compile.
101  *	'parent' is the PlanState node that owns the expression.
102  *
103  * 'parent' may be NULL if we are preparing an expression that is not
104  * associated with a plan tree.  (If so, it can't have aggs or subplans.)
105  * Such cases should usually come through ExecPrepareExpr, not directly here.
106  *
107  * Also, if 'node' is NULL, we just return NULL.  This is convenient for some
108  * callers that may or may not have an expression that needs to be compiled.
109  * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
110  * although ExecQual and ExecCheck will accept one (and treat it as "true").
111  */
112 ExprState *
ExecInitExpr(Expr * node,PlanState * parent)113 ExecInitExpr(Expr *node, PlanState *parent)
114 {
115 	ExprState  *state;
116 	ExprEvalStep scratch;
117 
118 	/* Special case: NULL expression produces a NULL ExprState pointer */
119 	if (node == NULL)
120 		return NULL;
121 
122 	/* Initialize ExprState with empty step list */
123 	state = makeNode(ExprState);
124 	state->expr = node;
125 
126 	/* Insert EEOP_*_FETCHSOME steps as needed */
127 	ExecInitExprSlots(state, (Node *) node);
128 
129 	/* Compile the expression proper */
130 	ExecInitExprRec(node, parent, state, &state->resvalue, &state->resnull);
131 
132 	/* Finally, append a DONE step */
133 	scratch.opcode = EEOP_DONE;
134 	ExprEvalPushStep(state, &scratch);
135 
136 	ExecReadyExpr(state);
137 
138 	return state;
139 }
140 
141 /*
142  * ExecInitQual: prepare a qual for execution by ExecQual
143  *
144  * Prepares for the evaluation of a conjunctive boolean expression (qual list
145  * with implicit AND semantics) that returns true if none of the
146  * subexpressions are false.
147  *
148  * We must return true if the list is empty.  Since that's a very common case,
149  * we optimize it a bit further by translating to a NULL ExprState pointer
150  * rather than setting up an ExprState that computes constant TRUE.  (Some
151  * especially hot-spot callers of ExecQual detect this and avoid calling
152  * ExecQual at all.)
153  *
154  * If any of the subexpressions yield NULL, then the result of the conjunction
155  * is false.  This makes ExecQual primarily useful for evaluating WHERE
156  * clauses, since SQL specifies that tuples with null WHERE results do not
157  * get selected.
158  */
159 ExprState *
ExecInitQual(List * qual,PlanState * parent)160 ExecInitQual(List *qual, PlanState *parent)
161 {
162 	ExprState  *state;
163 	ExprEvalStep scratch;
164 	List	   *adjust_jumps = NIL;
165 	ListCell   *lc;
166 
167 	/* short-circuit (here and in ExecQual) for empty restriction list */
168 	if (qual == NIL)
169 		return NULL;
170 
171 	Assert(IsA(qual, List));
172 
173 	state = makeNode(ExprState);
174 	state->expr = (Expr *) qual;
175 	/* mark expression as to be used with ExecQual() */
176 	state->flags = EEO_FLAG_IS_QUAL;
177 
178 	/* Insert EEOP_*_FETCHSOME steps as needed */
179 	ExecInitExprSlots(state, (Node *) qual);
180 
181 	/*
182 	 * ExecQual() needs to return false for an expression returning NULL. That
183 	 * allows us to short-circuit the evaluation the first time a NULL is
184 	 * encountered.  As qual evaluation is a hot-path this warrants using a
185 	 * special opcode for qual evaluation that's simpler than BOOL_AND (which
186 	 * has more complex NULL handling).
187 	 */
188 	scratch.opcode = EEOP_QUAL;
189 
190 	/*
191 	 * We can use ExprState's resvalue/resnull as target for each qual expr.
192 	 */
193 	scratch.resvalue = &state->resvalue;
194 	scratch.resnull = &state->resnull;
195 
196 	foreach(lc, qual)
197 	{
198 		Expr	   *node = (Expr *) lfirst(lc);
199 
200 		/* first evaluate expression */
201 		ExecInitExprRec(node, parent, state, &state->resvalue, &state->resnull);
202 
203 		/* then emit EEOP_QUAL to detect if it's false (or null) */
204 		scratch.d.qualexpr.jumpdone = -1;
205 		ExprEvalPushStep(state, &scratch);
206 		adjust_jumps = lappend_int(adjust_jumps,
207 								   state->steps_len - 1);
208 	}
209 
210 	/* adjust jump targets */
211 	foreach(lc, adjust_jumps)
212 	{
213 		ExprEvalStep *as = &state->steps[lfirst_int(lc)];
214 
215 		Assert(as->opcode == EEOP_QUAL);
216 		Assert(as->d.qualexpr.jumpdone == -1);
217 		as->d.qualexpr.jumpdone = state->steps_len;
218 	}
219 
220 	/*
221 	 * At the end, we don't need to do anything more.  The last qual expr must
222 	 * have yielded TRUE, and since its result is stored in the desired output
223 	 * location, we're done.
224 	 */
225 	scratch.opcode = EEOP_DONE;
226 	ExprEvalPushStep(state, &scratch);
227 
228 	ExecReadyExpr(state);
229 
230 	return state;
231 }
232 
233 /*
234  * ExecInitCheck: prepare a check constraint for execution by ExecCheck
235  *
236  * This is much like ExecInitQual/ExecQual, except that a null result from
237  * the conjunction is treated as TRUE.  This behavior is appropriate for
238  * evaluating CHECK constraints, since SQL specifies that NULL constraint
239  * conditions are not failures.
240  *
241  * Note that like ExecInitQual, this expects input in implicit-AND format.
242  * Users of ExecCheck that have expressions in normal explicit-AND format
243  * can just apply ExecInitExpr to produce suitable input for ExecCheck.
244  */
245 ExprState *
ExecInitCheck(List * qual,PlanState * parent)246 ExecInitCheck(List *qual, PlanState *parent)
247 {
248 	/* short-circuit (here and in ExecCheck) for empty restriction list */
249 	if (qual == NIL)
250 		return NULL;
251 
252 	Assert(IsA(qual, List));
253 
254 	/*
255 	 * Just convert the implicit-AND list to an explicit AND (if there's more
256 	 * than one entry), and compile normally.  Unlike ExecQual, we can't
257 	 * short-circuit on NULL results, so the regular AND behavior is needed.
258 	 */
259 	return ExecInitExpr(make_ands_explicit(qual), parent);
260 }
261 
262 /*
263  * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
264  */
265 List *
ExecInitExprList(List * nodes,PlanState * parent)266 ExecInitExprList(List *nodes, PlanState *parent)
267 {
268 	List	   *result = NIL;
269 	ListCell   *lc;
270 
271 	foreach(lc, nodes)
272 	{
273 		Expr	   *e = lfirst(lc);
274 
275 		result = lappend(result, ExecInitExpr(e, parent));
276 	}
277 
278 	return result;
279 }
280 
281 /*
282  *		ExecBuildProjectionInfo
283  *
284  * Build a ProjectionInfo node for evaluating the given tlist in the given
285  * econtext, and storing the result into the tuple slot.  (Caller must have
286  * ensured that tuple slot has a descriptor matching the tlist!)
287  *
288  * inputDesc can be NULL, but if it is not, we check to see whether simple
289  * Vars in the tlist match the descriptor.  It is important to provide
290  * inputDesc for relation-scan plan nodes, as a cross check that the relation
291  * hasn't been changed since the plan was made.  At higher levels of a plan,
292  * there is no need to recheck.
293  *
294  * This is implemented by internally building an ExprState that performs the
295  * whole projection in one go.
296  *
297  * Caution: before PG v10, the targetList was a list of ExprStates; now it
298  * should be the planner-created targetlist, since we do the compilation here.
299  */
300 ProjectionInfo *
ExecBuildProjectionInfo(List * targetList,ExprContext * econtext,TupleTableSlot * slot,PlanState * parent,TupleDesc inputDesc)301 ExecBuildProjectionInfo(List *targetList,
302 						ExprContext *econtext,
303 						TupleTableSlot *slot,
304 						PlanState *parent,
305 						TupleDesc inputDesc)
306 {
307 	return ExecBuildProjectionInfoExt(targetList,
308 									  econtext,
309 									  slot,
310 									  true,
311 									  parent,
312 									  inputDesc);
313 }
314 
315 /*
316  *		ExecBuildProjectionInfoExt
317  *
318  * As above, with one additional option.
319  *
320  * If assignJunkEntries is true (the usual case), resjunk entries in the tlist
321  * are not handled specially: they are evaluated and assigned to the proper
322  * column of the result slot.  If assignJunkEntries is false, resjunk entries
323  * are evaluated, but their result is discarded without assignment.
324  */
325 ProjectionInfo *
ExecBuildProjectionInfoExt(List * targetList,ExprContext * econtext,TupleTableSlot * slot,bool assignJunkEntries,PlanState * parent,TupleDesc inputDesc)326 ExecBuildProjectionInfoExt(List *targetList,
327 						   ExprContext *econtext,
328 						   TupleTableSlot *slot,
329 						   bool assignJunkEntries,
330 						   PlanState *parent,
331 						   TupleDesc inputDesc)
332 {
333 	ProjectionInfo *projInfo = makeNode(ProjectionInfo);
334 	ExprState  *state;
335 	ExprEvalStep scratch;
336 	ListCell   *lc;
337 
338 	projInfo->pi_exprContext = econtext;
339 	/* We embed ExprState into ProjectionInfo instead of doing extra palloc */
340 	projInfo->pi_state.tag.type = T_ExprState;
341 	state = &projInfo->pi_state;
342 	state->expr = (Expr *) targetList;
343 	state->resultslot = slot;
344 
345 	/* Insert EEOP_*_FETCHSOME steps as needed */
346 	ExecInitExprSlots(state, (Node *) targetList);
347 
348 	/* Now compile each tlist column */
349 	foreach(lc, targetList)
350 	{
351 		TargetEntry *tle = lfirst_node(TargetEntry, lc);
352 		Var		   *variable = NULL;
353 		AttrNumber	attnum = 0;
354 		bool		isSafeVar = false;
355 
356 		/*
357 		 * If tlist expression is a safe non-system Var, use the fast-path
358 		 * ASSIGN_*_VAR opcodes.  "Safe" means that we don't need to apply
359 		 * CheckVarSlotCompatibility() during plan startup.  If a source slot
360 		 * was provided, we make the equivalent tests here; if a slot was not
361 		 * provided, we assume that no check is needed because we're dealing
362 		 * with a non-relation-scan-level expression.
363 		 */
364 		if (tle->expr != NULL &&
365 			IsA(tle->expr, Var) &&
366 			((Var *) tle->expr)->varattno > 0 &&
367 			(assignJunkEntries || !tle->resjunk))
368 		{
369 			/* Non-system Var, but how safe is it? */
370 			variable = (Var *) tle->expr;
371 			attnum = variable->varattno;
372 
373 			if (inputDesc == NULL)
374 				isSafeVar = true;	/* can't check, just assume OK */
375 			else if (attnum <= inputDesc->natts)
376 			{
377 				Form_pg_attribute attr = inputDesc->attrs[attnum - 1];
378 
379 				/*
380 				 * If user attribute is dropped or has a type mismatch, don't
381 				 * use ASSIGN_*_VAR.  Instead let the normal expression
382 				 * machinery handle it (which'll possibly error out).
383 				 */
384 				if (!attr->attisdropped && variable->vartype == attr->atttypid)
385 				{
386 					isSafeVar = true;
387 				}
388 			}
389 		}
390 
391 		if (isSafeVar)
392 		{
393 			/* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
394 			switch (variable->varno)
395 			{
396 				case INNER_VAR:
397 					/* get the tuple from the inner node */
398 					scratch.opcode = EEOP_ASSIGN_INNER_VAR;
399 					break;
400 
401 				case OUTER_VAR:
402 					/* get the tuple from the outer node */
403 					scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
404 					break;
405 
406 					/* INDEX_VAR is handled by default case */
407 
408 				default:
409 					/* get the tuple from the relation being scanned */
410 					scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
411 					break;
412 			}
413 
414 			scratch.d.assign_var.attnum = attnum - 1;
415 			scratch.d.assign_var.resultnum = tle->resno - 1;
416 			ExprEvalPushStep(state, &scratch);
417 		}
418 		else
419 		{
420 			/*
421 			 * Otherwise, compile the column expression normally.
422 			 *
423 			 * We can't tell the expression to evaluate directly into the
424 			 * result slot, as the result slot (and the exprstate for that
425 			 * matter) can change between executions.  We instead evaluate
426 			 * into the ExprState's resvalue/resnull and then move.
427 			 */
428 			ExecInitExprRec(tle->expr, parent, state,
429 							&state->resvalue, &state->resnull);
430 
431 			/* This makes it easy to discard resjunk results when told to. */
432 			if (!assignJunkEntries && tle->resjunk)
433 				continue;
434 
435 			/*
436 			 * Column might be referenced multiple times in upper nodes, so
437 			 * force value to R/O - but only if it could be an expanded datum.
438 			 */
439 			if (get_typlen(exprType((Node *) tle->expr)) == -1)
440 				scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO;
441 			else
442 				scratch.opcode = EEOP_ASSIGN_TMP;
443 			scratch.d.assign_tmp.resultnum = tle->resno - 1;
444 			ExprEvalPushStep(state, &scratch);
445 		}
446 	}
447 
448 	scratch.opcode = EEOP_DONE;
449 	ExprEvalPushStep(state, &scratch);
450 
451 	ExecReadyExpr(state);
452 
453 	return projInfo;
454 }
455 
456 /*
457  * ExecPrepareExpr --- initialize for expression execution outside a normal
458  * Plan tree context.
459  *
460  * This differs from ExecInitExpr in that we don't assume the caller is
461  * already running in the EState's per-query context.  Also, we run the
462  * passed expression tree through expression_planner() to prepare it for
463  * execution.  (In ordinary Plan trees the regular planning process will have
464  * made the appropriate transformations on expressions, but for standalone
465  * expressions this won't have happened.)
466  */
467 ExprState *
ExecPrepareExpr(Expr * node,EState * estate)468 ExecPrepareExpr(Expr *node, EState *estate)
469 {
470 	ExprState  *result;
471 	MemoryContext oldcontext;
472 
473 	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
474 
475 	node = expression_planner(node);
476 
477 	result = ExecInitExpr(node, NULL);
478 
479 	MemoryContextSwitchTo(oldcontext);
480 
481 	return result;
482 }
483 
484 /*
485  * ExecPrepareQual --- initialize for qual execution outside a normal
486  * Plan tree context.
487  *
488  * This differs from ExecInitQual in that we don't assume the caller is
489  * already running in the EState's per-query context.  Also, we run the
490  * passed expression tree through expression_planner() to prepare it for
491  * execution.  (In ordinary Plan trees the regular planning process will have
492  * made the appropriate transformations on expressions, but for standalone
493  * expressions this won't have happened.)
494  */
495 ExprState *
ExecPrepareQual(List * qual,EState * estate)496 ExecPrepareQual(List *qual, EState *estate)
497 {
498 	ExprState  *result;
499 	MemoryContext oldcontext;
500 
501 	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
502 
503 	qual = (List *) expression_planner((Expr *) qual);
504 
505 	result = ExecInitQual(qual, NULL);
506 
507 	MemoryContextSwitchTo(oldcontext);
508 
509 	return result;
510 }
511 
512 /*
513  * ExecPrepareCheck -- initialize check constraint for execution outside a
514  * normal Plan tree context.
515  *
516  * See ExecPrepareExpr() and ExecInitCheck() for details.
517  */
518 ExprState *
ExecPrepareCheck(List * qual,EState * estate)519 ExecPrepareCheck(List *qual, EState *estate)
520 {
521 	ExprState  *result;
522 	MemoryContext oldcontext;
523 
524 	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
525 
526 	qual = (List *) expression_planner((Expr *) qual);
527 
528 	result = ExecInitCheck(qual, NULL);
529 
530 	MemoryContextSwitchTo(oldcontext);
531 
532 	return result;
533 }
534 
535 /*
536  * Call ExecPrepareExpr() on each member of a list of Exprs, and return
537  * a list of ExprStates.
538  *
539  * See ExecPrepareExpr() for details.
540  */
541 List *
ExecPrepareExprList(List * nodes,EState * estate)542 ExecPrepareExprList(List *nodes, EState *estate)
543 {
544 	List	   *result = NIL;
545 	MemoryContext oldcontext;
546 	ListCell   *lc;
547 
548 	/* Ensure that the list cell nodes are in the right context too */
549 	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
550 
551 	foreach(lc, nodes)
552 	{
553 		Expr	   *e = (Expr *) lfirst(lc);
554 
555 		result = lappend(result, ExecPrepareExpr(e, estate));
556 	}
557 
558 	MemoryContextSwitchTo(oldcontext);
559 
560 	return result;
561 }
562 
563 /*
564  * ExecCheck - evaluate a check constraint
565  *
566  * For check constraints, a null result is taken as TRUE, ie the constraint
567  * passes.
568  *
569  * The check constraint may have been prepared with ExecInitCheck
570  * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
571  * format, but a regular boolean expression prepared with ExecInitExpr or
572  * ExecPrepareExpr works too.
573  */
574 bool
ExecCheck(ExprState * state,ExprContext * econtext)575 ExecCheck(ExprState *state, ExprContext *econtext)
576 {
577 	Datum		ret;
578 	bool		isnull;
579 
580 	/* short-circuit (here and in ExecInitCheck) for empty restriction list */
581 	if (state == NULL)
582 		return true;
583 
584 	/* verify that expression was not compiled using ExecInitQual */
585 	Assert(!(state->flags & EEO_FLAG_IS_QUAL));
586 
587 	ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
588 
589 	if (isnull)
590 		return true;
591 
592 	return DatumGetBool(ret);
593 }
594 
595 /*
596  * Prepare a compiled expression for execution.  This has to be called for
597  * every ExprState before it can be executed.
598  *
599  * NB: While this currently only calls ExecReadyInterpretedExpr(),
600  * this will likely get extended to further expression evaluation methods.
601  * Therefore this should be used instead of directly calling
602  * ExecReadyInterpretedExpr().
603  */
604 static void
ExecReadyExpr(ExprState * state)605 ExecReadyExpr(ExprState *state)
606 {
607 	ExecReadyInterpretedExpr(state);
608 }
609 
610 /*
611  * Append the steps necessary for the evaluation of node to ExprState->steps,
612  * possibly recursing into sub-expressions of node.
613  *
614  * node - expression to evaluate
615  * parent - parent executor node (or NULL if a standalone expression)
616  * state - ExprState to whose ->steps to append the necessary operations
617  * resv / resnull - where to store the result of the node into
618  */
619 static void
ExecInitExprRec(Expr * node,PlanState * parent,ExprState * state,Datum * resv,bool * resnull)620 ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
621 				Datum *resv, bool *resnull)
622 {
623 	ExprEvalStep scratch;
624 
625 	/* Guard against stack overflow due to overly complex expressions */
626 	check_stack_depth();
627 
628 	/* Step's output location is always what the caller gave us */
629 	Assert(resv != NULL && resnull != NULL);
630 	scratch.resvalue = resv;
631 	scratch.resnull = resnull;
632 
633 	/* cases should be ordered as they are in enum NodeTag */
634 	switch (nodeTag(node))
635 	{
636 		case T_Var:
637 			{
638 				Var		   *variable = (Var *) node;
639 
640 				if (variable->varattno == InvalidAttrNumber)
641 				{
642 					/* whole-row Var */
643 					ExecInitWholeRowVar(&scratch, variable, parent);
644 				}
645 				else if (variable->varattno <= 0)
646 				{
647 					/* system column */
648 					scratch.d.var.attnum = variable->varattno;
649 					scratch.d.var.vartype = variable->vartype;
650 					switch (variable->varno)
651 					{
652 						case INNER_VAR:
653 							scratch.opcode = EEOP_INNER_SYSVAR;
654 							break;
655 						case OUTER_VAR:
656 							scratch.opcode = EEOP_OUTER_SYSVAR;
657 							break;
658 
659 							/* INDEX_VAR is handled by default case */
660 
661 						default:
662 							scratch.opcode = EEOP_SCAN_SYSVAR;
663 							break;
664 					}
665 				}
666 				else
667 				{
668 					/* regular user column */
669 					scratch.d.var.attnum = variable->varattno - 1;
670 					scratch.d.var.vartype = variable->vartype;
671 					/* select EEOP_*_FIRST opcode to force one-time checks */
672 					switch (variable->varno)
673 					{
674 						case INNER_VAR:
675 							scratch.opcode = EEOP_INNER_VAR_FIRST;
676 							break;
677 						case OUTER_VAR:
678 							scratch.opcode = EEOP_OUTER_VAR_FIRST;
679 							break;
680 
681 							/* INDEX_VAR is handled by default case */
682 
683 						default:
684 							scratch.opcode = EEOP_SCAN_VAR_FIRST;
685 							break;
686 					}
687 				}
688 
689 				ExprEvalPushStep(state, &scratch);
690 				break;
691 			}
692 
693 		case T_Const:
694 			{
695 				Const	   *con = (Const *) node;
696 
697 				scratch.opcode = EEOP_CONST;
698 				scratch.d.constval.value = con->constvalue;
699 				scratch.d.constval.isnull = con->constisnull;
700 
701 				ExprEvalPushStep(state, &scratch);
702 				break;
703 			}
704 
705 		case T_Param:
706 			{
707 				Param	   *param = (Param *) node;
708 
709 				switch (param->paramkind)
710 				{
711 					case PARAM_EXEC:
712 						scratch.opcode = EEOP_PARAM_EXEC;
713 						scratch.d.param.paramid = param->paramid;
714 						scratch.d.param.paramtype = param->paramtype;
715 						break;
716 					case PARAM_EXTERN:
717 						scratch.opcode = EEOP_PARAM_EXTERN;
718 						scratch.d.param.paramid = param->paramid;
719 						scratch.d.param.paramtype = param->paramtype;
720 						break;
721 					default:
722 						elog(ERROR, "unrecognized paramkind: %d",
723 							 (int) param->paramkind);
724 						break;
725 				}
726 
727 				ExprEvalPushStep(state, &scratch);
728 				break;
729 			}
730 
731 		case T_Aggref:
732 			{
733 				Aggref	   *aggref = (Aggref *) node;
734 				AggrefExprState *astate = makeNode(AggrefExprState);
735 
736 				scratch.opcode = EEOP_AGGREF;
737 				scratch.d.aggref.astate = astate;
738 				astate->aggref = aggref;
739 
740 				if (parent && IsA(parent, AggState))
741 				{
742 					AggState   *aggstate = (AggState *) parent;
743 
744 					aggstate->aggs = lcons(astate, aggstate->aggs);
745 					aggstate->numaggs++;
746 				}
747 				else
748 				{
749 					/* planner messed up */
750 					elog(ERROR, "Aggref found in non-Agg plan node");
751 				}
752 
753 				ExprEvalPushStep(state, &scratch);
754 				break;
755 			}
756 
757 		case T_GroupingFunc:
758 			{
759 				GroupingFunc *grp_node = (GroupingFunc *) node;
760 				Agg		   *agg;
761 
762 				if (!parent || !IsA(parent, AggState) ||
763 					!IsA(parent->plan, Agg))
764 					elog(ERROR, "GroupingFunc found in non-Agg plan node");
765 
766 				scratch.opcode = EEOP_GROUPING_FUNC;
767 				scratch.d.grouping_func.parent = (AggState *) parent;
768 
769 				agg = (Agg *) (parent->plan);
770 
771 				if (agg->groupingSets)
772 					scratch.d.grouping_func.clauses = grp_node->cols;
773 				else
774 					scratch.d.grouping_func.clauses = NIL;
775 
776 				ExprEvalPushStep(state, &scratch);
777 				break;
778 			}
779 
780 		case T_WindowFunc:
781 			{
782 				WindowFunc *wfunc = (WindowFunc *) node;
783 				WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
784 
785 				wfstate->wfunc = wfunc;
786 
787 				if (parent && IsA(parent, WindowAggState))
788 				{
789 					WindowAggState *winstate = (WindowAggState *) parent;
790 					int			nfuncs;
791 
792 					winstate->funcs = lcons(wfstate, winstate->funcs);
793 					nfuncs = ++winstate->numfuncs;
794 					if (wfunc->winagg)
795 						winstate->numaggs++;
796 
797 					/* for now initialize agg using old style expressions */
798 					wfstate->args = ExecInitExprList(wfunc->args, parent);
799 					wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
800 													  parent);
801 
802 					/*
803 					 * Complain if the windowfunc's arguments contain any
804 					 * windowfuncs; nested window functions are semantically
805 					 * nonsensical.  (This should have been caught earlier,
806 					 * but we defend against it here anyway.)
807 					 */
808 					if (nfuncs != winstate->numfuncs)
809 						ereport(ERROR,
810 								(errcode(ERRCODE_WINDOWING_ERROR),
811 								 errmsg("window function calls cannot be nested")));
812 				}
813 				else
814 				{
815 					/* planner messed up */
816 					elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
817 				}
818 
819 				scratch.opcode = EEOP_WINDOW_FUNC;
820 				scratch.d.window_func.wfstate = wfstate;
821 				ExprEvalPushStep(state, &scratch);
822 				break;
823 			}
824 
825 		case T_ArrayRef:
826 			{
827 				ArrayRef   *aref = (ArrayRef *) node;
828 
829 				ExecInitArrayRef(&scratch, aref, parent, state, resv, resnull);
830 				break;
831 			}
832 
833 		case T_FuncExpr:
834 			{
835 				FuncExpr   *func = (FuncExpr *) node;
836 
837 				ExecInitFunc(&scratch, node,
838 							 func->args, func->funcid, func->inputcollid,
839 							 parent, state);
840 				ExprEvalPushStep(state, &scratch);
841 				break;
842 			}
843 
844 		case T_OpExpr:
845 			{
846 				OpExpr	   *op = (OpExpr *) node;
847 
848 				ExecInitFunc(&scratch, node,
849 							 op->args, op->opfuncid, op->inputcollid,
850 							 parent, state);
851 				ExprEvalPushStep(state, &scratch);
852 				break;
853 			}
854 
855 		case T_DistinctExpr:
856 			{
857 				DistinctExpr *op = (DistinctExpr *) node;
858 
859 				ExecInitFunc(&scratch, node,
860 							 op->args, op->opfuncid, op->inputcollid,
861 							 parent, state);
862 
863 				/*
864 				 * Change opcode of call instruction to EEOP_DISTINCT.
865 				 *
866 				 * XXX: historically we've not called the function usage
867 				 * pgstat infrastructure - that seems inconsistent given that
868 				 * we do so for normal function *and* operator evaluation.  If
869 				 * we decided to do that here, we'd probably want separate
870 				 * opcodes for FUSAGE or not.
871 				 */
872 				scratch.opcode = EEOP_DISTINCT;
873 				ExprEvalPushStep(state, &scratch);
874 				break;
875 			}
876 
877 		case T_NullIfExpr:
878 			{
879 				NullIfExpr *op = (NullIfExpr *) node;
880 
881 				ExecInitFunc(&scratch, node,
882 							 op->args, op->opfuncid, op->inputcollid,
883 							 parent, state);
884 
885 				/*
886 				 * Change opcode of call instruction to EEOP_NULLIF.
887 				 *
888 				 * XXX: historically we've not called the function usage
889 				 * pgstat infrastructure - that seems inconsistent given that
890 				 * we do so for normal function *and* operator evaluation.  If
891 				 * we decided to do that here, we'd probably want separate
892 				 * opcodes for FUSAGE or not.
893 				 */
894 				scratch.opcode = EEOP_NULLIF;
895 				ExprEvalPushStep(state, &scratch);
896 				break;
897 			}
898 
899 		case T_ScalarArrayOpExpr:
900 			{
901 				ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
902 				Expr	   *scalararg;
903 				Expr	   *arrayarg;
904 				FmgrInfo   *finfo;
905 				FunctionCallInfo fcinfo;
906 				AclResult	aclresult;
907 
908 				Assert(list_length(opexpr->args) == 2);
909 				scalararg = (Expr *) linitial(opexpr->args);
910 				arrayarg = (Expr *) lsecond(opexpr->args);
911 
912 				/* Check permission to call function */
913 				aclresult = pg_proc_aclcheck(opexpr->opfuncid,
914 											 GetUserId(),
915 											 ACL_EXECUTE);
916 				if (aclresult != ACLCHECK_OK)
917 					aclcheck_error(aclresult, ACL_KIND_PROC,
918 								   get_func_name(opexpr->opfuncid));
919 				InvokeFunctionExecuteHook(opexpr->opfuncid);
920 
921 				/* Set up the primary fmgr lookup information */
922 				finfo = palloc0(sizeof(FmgrInfo));
923 				fcinfo = palloc0(sizeof(FunctionCallInfoData));
924 				fmgr_info(opexpr->opfuncid, finfo);
925 				fmgr_info_set_expr((Node *) node, finfo);
926 				InitFunctionCallInfoData(*fcinfo, finfo, 2,
927 										 opexpr->inputcollid, NULL, NULL);
928 
929 				/* Evaluate scalar directly into left function argument */
930 				ExecInitExprRec(scalararg, parent, state,
931 								&fcinfo->arg[0], &fcinfo->argnull[0]);
932 
933 				/*
934 				 * Evaluate array argument into our return value.  There's no
935 				 * danger in that, because the return value is guaranteed to
936 				 * be overwritten by EEOP_SCALARARRAYOP, and will not be
937 				 * passed to any other expression.
938 				 */
939 				ExecInitExprRec(arrayarg, parent, state, resv, resnull);
940 
941 				/* And perform the operation */
942 				scratch.opcode = EEOP_SCALARARRAYOP;
943 				scratch.d.scalararrayop.element_type = InvalidOid;
944 				scratch.d.scalararrayop.useOr = opexpr->useOr;
945 				scratch.d.scalararrayop.finfo = finfo;
946 				scratch.d.scalararrayop.fcinfo_data = fcinfo;
947 				scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
948 				ExprEvalPushStep(state, &scratch);
949 				break;
950 			}
951 
952 		case T_BoolExpr:
953 			{
954 				BoolExpr   *boolexpr = (BoolExpr *) node;
955 				int			nargs = list_length(boolexpr->args);
956 				List	   *adjust_jumps = NIL;
957 				int			off;
958 				ListCell   *lc;
959 
960 				/* allocate scratch memory used by all steps of AND/OR */
961 				if (boolexpr->boolop != NOT_EXPR)
962 					scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
963 
964 				/*
965 				 * For each argument evaluate the argument itself, then
966 				 * perform the bool operation's appropriate handling.
967 				 *
968 				 * We can evaluate each argument into our result area, since
969 				 * the short-circuiting logic means we only need to remember
970 				 * previous NULL values.
971 				 *
972 				 * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
973 				 * or more) / STEP_LAST (one) steps, as each of those has to
974 				 * perform different work.  The FIRST/LAST split is valid
975 				 * because AND/OR have at least two arguments.
976 				 */
977 				off = 0;
978 				foreach(lc, boolexpr->args)
979 				{
980 					Expr	   *arg = (Expr *) lfirst(lc);
981 
982 					/* Evaluate argument into our output variable */
983 					ExecInitExprRec(arg, parent, state, resv, resnull);
984 
985 					/* Perform the appropriate step type */
986 					switch (boolexpr->boolop)
987 					{
988 						case AND_EXPR:
989 							Assert(nargs >= 2);
990 
991 							if (off == 0)
992 								scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
993 							else if (off + 1 == nargs)
994 								scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
995 							else
996 								scratch.opcode = EEOP_BOOL_AND_STEP;
997 							break;
998 						case OR_EXPR:
999 							Assert(nargs >= 2);
1000 
1001 							if (off == 0)
1002 								scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1003 							else if (off + 1 == nargs)
1004 								scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1005 							else
1006 								scratch.opcode = EEOP_BOOL_OR_STEP;
1007 							break;
1008 						case NOT_EXPR:
1009 							Assert(nargs == 1);
1010 
1011 							scratch.opcode = EEOP_BOOL_NOT_STEP;
1012 							break;
1013 						default:
1014 							elog(ERROR, "unrecognized boolop: %d",
1015 								 (int) boolexpr->boolop);
1016 							break;
1017 					}
1018 
1019 					scratch.d.boolexpr.jumpdone = -1;
1020 					ExprEvalPushStep(state, &scratch);
1021 					adjust_jumps = lappend_int(adjust_jumps,
1022 											   state->steps_len - 1);
1023 					off++;
1024 				}
1025 
1026 				/* adjust jump targets */
1027 				foreach(lc, adjust_jumps)
1028 				{
1029 					ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1030 
1031 					Assert(as->d.boolexpr.jumpdone == -1);
1032 					as->d.boolexpr.jumpdone = state->steps_len;
1033 				}
1034 
1035 				break;
1036 			}
1037 
1038 		case T_SubPlan:
1039 			{
1040 				SubPlan    *subplan = (SubPlan *) node;
1041 				SubPlanState *sstate;
1042 
1043 				if (!parent)
1044 					elog(ERROR, "SubPlan found with no parent plan");
1045 
1046 				sstate = ExecInitSubPlan(subplan, parent);
1047 
1048 				/* add SubPlanState nodes to parent->subPlan */
1049 				parent->subPlan = lappend(parent->subPlan, sstate);
1050 
1051 				scratch.opcode = EEOP_SUBPLAN;
1052 				scratch.d.subplan.sstate = sstate;
1053 
1054 				ExprEvalPushStep(state, &scratch);
1055 				break;
1056 			}
1057 
1058 		case T_AlternativeSubPlan:
1059 			{
1060 				AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
1061 				AlternativeSubPlanState *asstate;
1062 
1063 				if (!parent)
1064 					elog(ERROR, "AlternativeSubPlan found with no parent plan");
1065 
1066 				asstate = ExecInitAlternativeSubPlan(asplan, parent);
1067 
1068 				scratch.opcode = EEOP_ALTERNATIVE_SUBPLAN;
1069 				scratch.d.alternative_subplan.asstate = asstate;
1070 
1071 				ExprEvalPushStep(state, &scratch);
1072 				break;
1073 			}
1074 
1075 		case T_FieldSelect:
1076 			{
1077 				FieldSelect *fselect = (FieldSelect *) node;
1078 
1079 				/* evaluate row/record argument into result area */
1080 				ExecInitExprRec(fselect->arg, parent, state, resv, resnull);
1081 
1082 				/* and extract field */
1083 				scratch.opcode = EEOP_FIELDSELECT;
1084 				scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1085 				scratch.d.fieldselect.resulttype = fselect->resulttype;
1086 				scratch.d.fieldselect.argdesc = NULL;
1087 
1088 				ExprEvalPushStep(state, &scratch);
1089 				break;
1090 			}
1091 
1092 		case T_FieldStore:
1093 			{
1094 				FieldStore *fstore = (FieldStore *) node;
1095 				TupleDesc	tupDesc;
1096 				TupleDesc  *descp;
1097 				Datum	   *values;
1098 				bool	   *nulls;
1099 				int			ncolumns;
1100 				ListCell   *l1,
1101 						   *l2;
1102 
1103 				/* find out the number of columns in the composite type */
1104 				tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1105 				ncolumns = tupDesc->natts;
1106 				DecrTupleDescRefCount(tupDesc);
1107 
1108 				/* create workspace for column values */
1109 				values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1110 				nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1111 
1112 				/* create workspace for runtime tupdesc cache */
1113 				descp = (TupleDesc *) palloc(sizeof(TupleDesc));
1114 				*descp = NULL;
1115 
1116 				/* emit code to evaluate the composite input value */
1117 				ExecInitExprRec(fstore->arg, parent, state, resv, resnull);
1118 
1119 				/* next, deform the input tuple into our workspace */
1120 				scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1121 				scratch.d.fieldstore.fstore = fstore;
1122 				scratch.d.fieldstore.argdesc = descp;
1123 				scratch.d.fieldstore.values = values;
1124 				scratch.d.fieldstore.nulls = nulls;
1125 				scratch.d.fieldstore.ncolumns = ncolumns;
1126 				ExprEvalPushStep(state, &scratch);
1127 
1128 				/* evaluate new field values, store in workspace columns */
1129 				forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1130 				{
1131 					Expr	   *e = (Expr *) lfirst(l1);
1132 					AttrNumber	fieldnum = lfirst_int(l2);
1133 					Datum	   *save_innermost_caseval;
1134 					bool	   *save_innermost_casenull;
1135 
1136 					if (fieldnum <= 0 || fieldnum > ncolumns)
1137 						elog(ERROR, "field number %d is out of range in FieldStore",
1138 							 fieldnum);
1139 
1140 					/*
1141 					 * Use the CaseTestExpr mechanism to pass down the old
1142 					 * value of the field being replaced; this is needed in
1143 					 * case the newval is itself a FieldStore or ArrayRef that
1144 					 * has to obtain and modify the old value.  It's safe to
1145 					 * reuse the CASE mechanism because there cannot be a CASE
1146 					 * between here and where the value would be needed, and a
1147 					 * field assignment can't be within a CASE either.  (So
1148 					 * saving and restoring innermost_caseval is just
1149 					 * paranoia, but let's do it anyway.)
1150 					 *
1151 					 * Another non-obvious point is that it's safe to use the
1152 					 * field's values[]/nulls[] entries as both the caseval
1153 					 * source and the result address for this subexpression.
1154 					 * That's okay only because (1) both FieldStore and
1155 					 * ArrayRef evaluate their arg or refexpr inputs first,
1156 					 * and (2) any such CaseTestExpr is directly the arg or
1157 					 * refexpr input.  So any read of the caseval will occur
1158 					 * before there's a chance to overwrite it.  Also, if
1159 					 * multiple entries in the newvals/fieldnums lists target
1160 					 * the same field, they'll effectively be applied
1161 					 * left-to-right which is what we want.
1162 					 */
1163 					save_innermost_caseval = state->innermost_caseval;
1164 					save_innermost_casenull = state->innermost_casenull;
1165 					state->innermost_caseval = &values[fieldnum - 1];
1166 					state->innermost_casenull = &nulls[fieldnum - 1];
1167 
1168 					ExecInitExprRec(e, parent, state,
1169 									&values[fieldnum - 1],
1170 									&nulls[fieldnum - 1]);
1171 
1172 					state->innermost_caseval = save_innermost_caseval;
1173 					state->innermost_casenull = save_innermost_casenull;
1174 				}
1175 
1176 				/* finally, form result tuple */
1177 				scratch.opcode = EEOP_FIELDSTORE_FORM;
1178 				scratch.d.fieldstore.fstore = fstore;
1179 				scratch.d.fieldstore.argdesc = descp;
1180 				scratch.d.fieldstore.values = values;
1181 				scratch.d.fieldstore.nulls = nulls;
1182 				scratch.d.fieldstore.ncolumns = ncolumns;
1183 				ExprEvalPushStep(state, &scratch);
1184 				break;
1185 			}
1186 
1187 		case T_RelabelType:
1188 			{
1189 				/* relabel doesn't need to do anything at runtime */
1190 				RelabelType *relabel = (RelabelType *) node;
1191 
1192 				ExecInitExprRec(relabel->arg, parent, state, resv, resnull);
1193 				break;
1194 			}
1195 
1196 		case T_CoerceViaIO:
1197 			{
1198 				CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1199 				Oid			iofunc;
1200 				bool		typisvarlena;
1201 				Oid			typioparam;
1202 				FunctionCallInfo fcinfo_in;
1203 
1204 				/* evaluate argument into step's result area */
1205 				ExecInitExprRec(iocoerce->arg, parent, state, resv, resnull);
1206 
1207 				/*
1208 				 * Prepare both output and input function calls, to be
1209 				 * evaluated inside a single evaluation step for speed - this
1210 				 * can be a very common operation.
1211 				 *
1212 				 * We don't check permissions here as a type's input/output
1213 				 * function are assumed to be executable by everyone.
1214 				 */
1215 				scratch.opcode = EEOP_IOCOERCE;
1216 
1217 				/* lookup the source type's output function */
1218 				scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1219 				scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData));
1220 
1221 				getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1222 								  &iofunc, &typisvarlena);
1223 				fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1224 				fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1225 				InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1226 										 scratch.d.iocoerce.finfo_out,
1227 										 1, InvalidOid, NULL, NULL);
1228 
1229 				/* lookup the result type's input function */
1230 				scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1231 				scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData));
1232 
1233 				getTypeInputInfo(iocoerce->resulttype,
1234 								 &iofunc, &typioparam);
1235 				fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1236 				fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1237 				InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1238 										 scratch.d.iocoerce.finfo_in,
1239 										 3, InvalidOid, NULL, NULL);
1240 
1241 				/*
1242 				 * We can preload the second and third arguments for the input
1243 				 * function, since they're constants.
1244 				 */
1245 				fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1246 				fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam);
1247 				fcinfo_in->argnull[1] = false;
1248 				fcinfo_in->arg[2] = Int32GetDatum(-1);
1249 				fcinfo_in->argnull[2] = false;
1250 
1251 				ExprEvalPushStep(state, &scratch);
1252 				break;
1253 			}
1254 
1255 		case T_ArrayCoerceExpr:
1256 			{
1257 				ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1258 				Oid			resultelemtype;
1259 
1260 				/* evaluate argument into step's result area */
1261 				ExecInitExprRec(acoerce->arg, parent, state, resv, resnull);
1262 
1263 				resultelemtype = get_element_type(acoerce->resulttype);
1264 				if (!OidIsValid(resultelemtype))
1265 					ereport(ERROR,
1266 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1267 							 errmsg("target type is not an array")));
1268 				/* Arrays over domains aren't supported yet */
1269 				Assert(getBaseType(resultelemtype) == resultelemtype);
1270 
1271 				scratch.opcode = EEOP_ARRAYCOERCE;
1272 				scratch.d.arraycoerce.coerceexpr = acoerce;
1273 				scratch.d.arraycoerce.resultelemtype = resultelemtype;
1274 
1275 				if (OidIsValid(acoerce->elemfuncid))
1276 				{
1277 					AclResult	aclresult;
1278 
1279 					/* Check permission to call function */
1280 					aclresult = pg_proc_aclcheck(acoerce->elemfuncid,
1281 												 GetUserId(),
1282 												 ACL_EXECUTE);
1283 					if (aclresult != ACLCHECK_OK)
1284 						aclcheck_error(aclresult, ACL_KIND_PROC,
1285 									   get_func_name(acoerce->elemfuncid));
1286 					InvokeFunctionExecuteHook(acoerce->elemfuncid);
1287 
1288 					/* Set up the primary fmgr lookup information */
1289 					scratch.d.arraycoerce.elemfunc =
1290 						(FmgrInfo *) palloc0(sizeof(FmgrInfo));
1291 					fmgr_info(acoerce->elemfuncid,
1292 							  scratch.d.arraycoerce.elemfunc);
1293 					fmgr_info_set_expr((Node *) acoerce,
1294 									   scratch.d.arraycoerce.elemfunc);
1295 
1296 					/* Set up workspace for array_map */
1297 					scratch.d.arraycoerce.amstate =
1298 						(ArrayMapState *) palloc0(sizeof(ArrayMapState));
1299 				}
1300 				else
1301 				{
1302 					/* Don't need workspace if there's no conversion func */
1303 					scratch.d.arraycoerce.elemfunc = NULL;
1304 					scratch.d.arraycoerce.amstate = NULL;
1305 				}
1306 
1307 				ExprEvalPushStep(state, &scratch);
1308 				break;
1309 			}
1310 
1311 		case T_ConvertRowtypeExpr:
1312 			{
1313 				ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
1314 
1315 				/* evaluate argument into step's result area */
1316 				ExecInitExprRec(convert->arg, parent, state, resv, resnull);
1317 
1318 				/* and push conversion step */
1319 				scratch.opcode = EEOP_CONVERT_ROWTYPE;
1320 				scratch.d.convert_rowtype.convert = convert;
1321 				scratch.d.convert_rowtype.indesc = NULL;
1322 				scratch.d.convert_rowtype.outdesc = NULL;
1323 				scratch.d.convert_rowtype.map = NULL;
1324 				scratch.d.convert_rowtype.initialized = false;
1325 
1326 				ExprEvalPushStep(state, &scratch);
1327 				break;
1328 			}
1329 
1330 			/* note that CaseWhen expressions are handled within this block */
1331 		case T_CaseExpr:
1332 			{
1333 				CaseExpr   *caseExpr = (CaseExpr *) node;
1334 				List	   *adjust_jumps = NIL;
1335 				Datum	   *caseval = NULL;
1336 				bool	   *casenull = NULL;
1337 				ListCell   *lc;
1338 
1339 				/*
1340 				 * If there's a test expression, we have to evaluate it and
1341 				 * save the value where the CaseTestExpr placeholders can find
1342 				 * it.
1343 				 */
1344 				if (caseExpr->arg != NULL)
1345 				{
1346 					/* Evaluate testexpr into caseval/casenull workspace */
1347 					caseval = palloc(sizeof(Datum));
1348 					casenull = palloc(sizeof(bool));
1349 
1350 					ExecInitExprRec(caseExpr->arg, parent, state,
1351 									caseval, casenull);
1352 
1353 					/*
1354 					 * Since value might be read multiple times, force to R/O
1355 					 * - but only if it could be an expanded datum.
1356 					 */
1357 					if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
1358 					{
1359 						/* change caseval in-place */
1360 						scratch.opcode = EEOP_MAKE_READONLY;
1361 						scratch.resvalue = caseval;
1362 						scratch.resnull = casenull;
1363 						scratch.d.make_readonly.value = caseval;
1364 						scratch.d.make_readonly.isnull = casenull;
1365 						ExprEvalPushStep(state, &scratch);
1366 						/* restore normal settings of scratch fields */
1367 						scratch.resvalue = resv;
1368 						scratch.resnull = resnull;
1369 					}
1370 				}
1371 
1372 				/*
1373 				 * Prepare to evaluate each of the WHEN clauses in turn; as
1374 				 * soon as one is true we return the value of the
1375 				 * corresponding THEN clause.  If none are true then we return
1376 				 * the value of the ELSE clause, or NULL if there is none.
1377 				 */
1378 				foreach(lc, caseExpr->args)
1379 				{
1380 					CaseWhen   *when = (CaseWhen *) lfirst(lc);
1381 					Datum	   *save_innermost_caseval;
1382 					bool	   *save_innermost_casenull;
1383 					int			whenstep;
1384 
1385 					/*
1386 					 * Make testexpr result available to CaseTestExpr nodes
1387 					 * within the condition.  We must save and restore prior
1388 					 * setting of innermost_caseval fields, in case this node
1389 					 * is itself within a larger CASE.
1390 					 *
1391 					 * If there's no test expression, we don't actually need
1392 					 * to save and restore these fields; but it's less code to
1393 					 * just do so unconditionally.
1394 					 */
1395 					save_innermost_caseval = state->innermost_caseval;
1396 					save_innermost_casenull = state->innermost_casenull;
1397 					state->innermost_caseval = caseval;
1398 					state->innermost_casenull = casenull;
1399 
1400 					/* evaluate condition into CASE's result variables */
1401 					ExecInitExprRec(when->expr, parent, state, resv, resnull);
1402 
1403 					state->innermost_caseval = save_innermost_caseval;
1404 					state->innermost_casenull = save_innermost_casenull;
1405 
1406 					/* If WHEN result isn't true, jump to next CASE arm */
1407 					scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
1408 					scratch.d.jump.jumpdone = -1;	/* computed later */
1409 					ExprEvalPushStep(state, &scratch);
1410 					whenstep = state->steps_len - 1;
1411 
1412 					/*
1413 					 * If WHEN result is true, evaluate THEN result, storing
1414 					 * it into the CASE's result variables.
1415 					 */
1416 					ExecInitExprRec(when->result, parent, state, resv, resnull);
1417 
1418 					/* Emit JUMP step to jump to end of CASE's code */
1419 					scratch.opcode = EEOP_JUMP;
1420 					scratch.d.jump.jumpdone = -1;	/* computed later */
1421 					ExprEvalPushStep(state, &scratch);
1422 
1423 					/*
1424 					 * Don't know address for that jump yet, compute once the
1425 					 * whole CASE expression is built.
1426 					 */
1427 					adjust_jumps = lappend_int(adjust_jumps,
1428 											   state->steps_len - 1);
1429 
1430 					/*
1431 					 * But we can set WHEN test's jump target now, to make it
1432 					 * jump to the next WHEN subexpression or the ELSE.
1433 					 */
1434 					state->steps[whenstep].d.jump.jumpdone = state->steps_len;
1435 				}
1436 
1437 				/* transformCaseExpr always adds a default */
1438 				Assert(caseExpr->defresult);
1439 
1440 				/* evaluate ELSE expr into CASE's result variables */
1441 				ExecInitExprRec(caseExpr->defresult, parent, state,
1442 								resv, resnull);
1443 
1444 				/* adjust jump targets */
1445 				foreach(lc, adjust_jumps)
1446 				{
1447 					ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1448 
1449 					Assert(as->opcode == EEOP_JUMP);
1450 					Assert(as->d.jump.jumpdone == -1);
1451 					as->d.jump.jumpdone = state->steps_len;
1452 				}
1453 
1454 				break;
1455 			}
1456 
1457 		case T_CaseTestExpr:
1458 			{
1459 				/*
1460 				 * Read from location identified by innermost_caseval.  Note
1461 				 * that innermost_caseval could be NULL, if this node isn't
1462 				 * actually within a CASE structure; some parts of the system
1463 				 * abuse CaseTestExpr to cause a read of a value externally
1464 				 * supplied in econtext->caseValue_datum.  We'll take care of
1465 				 * that scenario at runtime.
1466 				 */
1467 				scratch.opcode = EEOP_CASE_TESTVAL;
1468 				scratch.d.casetest.value = state->innermost_caseval;
1469 				scratch.d.casetest.isnull = state->innermost_casenull;
1470 
1471 				ExprEvalPushStep(state, &scratch);
1472 				break;
1473 			}
1474 
1475 		case T_ArrayExpr:
1476 			{
1477 				ArrayExpr  *arrayexpr = (ArrayExpr *) node;
1478 				int			nelems = list_length(arrayexpr->elements);
1479 				ListCell   *lc;
1480 				int			elemoff;
1481 
1482 				/*
1483 				 * Evaluate by computing each element, and then forming the
1484 				 * array.  Elements are computed into scratch arrays
1485 				 * associated with the ARRAYEXPR step.
1486 				 */
1487 				scratch.opcode = EEOP_ARRAYEXPR;
1488 				scratch.d.arrayexpr.elemvalues =
1489 					(Datum *) palloc(sizeof(Datum) * nelems);
1490 				scratch.d.arrayexpr.elemnulls =
1491 					(bool *) palloc(sizeof(bool) * nelems);
1492 				scratch.d.arrayexpr.nelems = nelems;
1493 
1494 				/* fill remaining fields of step */
1495 				scratch.d.arrayexpr.multidims = arrayexpr->multidims;
1496 				scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
1497 
1498 				/* do one-time catalog lookup for type info */
1499 				get_typlenbyvalalign(arrayexpr->element_typeid,
1500 									 &scratch.d.arrayexpr.elemlength,
1501 									 &scratch.d.arrayexpr.elembyval,
1502 									 &scratch.d.arrayexpr.elemalign);
1503 
1504 				/* prepare to evaluate all arguments */
1505 				elemoff = 0;
1506 				foreach(lc, arrayexpr->elements)
1507 				{
1508 					Expr	   *e = (Expr *) lfirst(lc);
1509 
1510 					ExecInitExprRec(e, parent, state,
1511 									&scratch.d.arrayexpr.elemvalues[elemoff],
1512 									&scratch.d.arrayexpr.elemnulls[elemoff]);
1513 					elemoff++;
1514 				}
1515 
1516 				/* and then collect all into an array */
1517 				ExprEvalPushStep(state, &scratch);
1518 				break;
1519 			}
1520 
1521 		case T_RowExpr:
1522 			{
1523 				RowExpr    *rowexpr = (RowExpr *) node;
1524 				int			nelems = list_length(rowexpr->args);
1525 				TupleDesc	tupdesc;
1526 				Form_pg_attribute *attrs;
1527 				int			i;
1528 				ListCell   *l;
1529 
1530 				/* Build tupdesc to describe result tuples */
1531 				if (rowexpr->row_typeid == RECORDOID)
1532 				{
1533 					/* generic record, use types of given expressions */
1534 					tupdesc = ExecTypeFromExprList(rowexpr->args);
1535 				}
1536 				else
1537 				{
1538 					/* it's been cast to a named type, use that */
1539 					tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
1540 				}
1541 				/* In either case, adopt RowExpr's column aliases */
1542 				ExecTypeSetColNames(tupdesc, rowexpr->colnames);
1543 				/* Bless the tupdesc in case it's now of type RECORD */
1544 				BlessTupleDesc(tupdesc);
1545 
1546 				/*
1547 				 * In the named-type case, the tupdesc could have more columns
1548 				 * than are in the args list, since the type might have had
1549 				 * columns added since the ROW() was parsed.  We want those
1550 				 * extra columns to go to nulls, so we make sure that the
1551 				 * workspace arrays are large enough and then initialize any
1552 				 * extra columns to read as NULLs.
1553 				 */
1554 				Assert(nelems <= tupdesc->natts);
1555 				nelems = Max(nelems, tupdesc->natts);
1556 
1557 				/*
1558 				 * Evaluate by first building datums for each field, and then
1559 				 * a final step forming the composite datum.
1560 				 */
1561 				scratch.opcode = EEOP_ROW;
1562 				scratch.d.row.tupdesc = tupdesc;
1563 
1564 				/* space for the individual field datums */
1565 				scratch.d.row.elemvalues =
1566 					(Datum *) palloc(sizeof(Datum) * nelems);
1567 				scratch.d.row.elemnulls =
1568 					(bool *) palloc(sizeof(bool) * nelems);
1569 				/* as explained above, make sure any extra columns are null */
1570 				memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
1571 
1572 				/* Set up evaluation, skipping any deleted columns */
1573 				attrs = tupdesc->attrs;
1574 				i = 0;
1575 				foreach(l, rowexpr->args)
1576 				{
1577 					Expr	   *e = (Expr *) lfirst(l);
1578 
1579 					if (!attrs[i]->attisdropped)
1580 					{
1581 						/*
1582 						 * Guard against ALTER COLUMN TYPE on rowtype since
1583 						 * the RowExpr was created.  XXX should we check
1584 						 * typmod too?	Not sure we can be sure it'll be the
1585 						 * same.
1586 						 */
1587 						if (exprType((Node *) e) != attrs[i]->atttypid)
1588 							ereport(ERROR,
1589 									(errcode(ERRCODE_DATATYPE_MISMATCH),
1590 									 errmsg("ROW() column has type %s instead of type %s",
1591 											format_type_be(exprType((Node *) e)),
1592 											format_type_be(attrs[i]->atttypid))));
1593 					}
1594 					else
1595 					{
1596 						/*
1597 						 * Ignore original expression and insert a NULL. We
1598 						 * don't really care what type of NULL it is, so
1599 						 * always make an int4 NULL.
1600 						 */
1601 						e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
1602 					}
1603 
1604 					/* Evaluate column expr into appropriate workspace slot */
1605 					ExecInitExprRec(e, parent, state,
1606 									&scratch.d.row.elemvalues[i],
1607 									&scratch.d.row.elemnulls[i]);
1608 					i++;
1609 				}
1610 
1611 				/* And finally build the row value */
1612 				ExprEvalPushStep(state, &scratch);
1613 				break;
1614 			}
1615 
1616 		case T_RowCompareExpr:
1617 			{
1618 				RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1619 				int			nopers = list_length(rcexpr->opnos);
1620 				List	   *adjust_jumps = NIL;
1621 				ListCell   *l_left_expr,
1622 						   *l_right_expr,
1623 						   *l_opno,
1624 						   *l_opfamily,
1625 						   *l_inputcollid;
1626 				ListCell   *lc;
1627 				int			off;
1628 
1629 				/*
1630 				 * Iterate over each field, prepare comparisons.  To handle
1631 				 * NULL results, prepare jumps to after the expression.  If a
1632 				 * comparison yields a != 0 result, jump to the final step.
1633 				 */
1634 				Assert(list_length(rcexpr->largs) == nopers);
1635 				Assert(list_length(rcexpr->rargs) == nopers);
1636 				Assert(list_length(rcexpr->opfamilies) == nopers);
1637 				Assert(list_length(rcexpr->inputcollids) == nopers);
1638 
1639 				off = 0;
1640 				for (off = 0,
1641 					 l_left_expr = list_head(rcexpr->largs),
1642 					 l_right_expr = list_head(rcexpr->rargs),
1643 					 l_opno = list_head(rcexpr->opnos),
1644 					 l_opfamily = list_head(rcexpr->opfamilies),
1645 					 l_inputcollid = list_head(rcexpr->inputcollids);
1646 					 off < nopers;
1647 					 off++,
1648 					 l_left_expr = lnext(l_left_expr),
1649 					 l_right_expr = lnext(l_right_expr),
1650 					 l_opno = lnext(l_opno),
1651 					 l_opfamily = lnext(l_opfamily),
1652 					 l_inputcollid = lnext(l_inputcollid))
1653 				{
1654 					Expr	   *left_expr = (Expr *) lfirst(l_left_expr);
1655 					Expr	   *right_expr = (Expr *) lfirst(l_right_expr);
1656 					Oid			opno = lfirst_oid(l_opno);
1657 					Oid			opfamily = lfirst_oid(l_opfamily);
1658 					Oid			inputcollid = lfirst_oid(l_inputcollid);
1659 					int			strategy;
1660 					Oid			lefttype;
1661 					Oid			righttype;
1662 					Oid			proc;
1663 					FmgrInfo   *finfo;
1664 					FunctionCallInfo fcinfo;
1665 
1666 					get_op_opfamily_properties(opno, opfamily, false,
1667 											   &strategy,
1668 											   &lefttype,
1669 											   &righttype);
1670 					proc = get_opfamily_proc(opfamily,
1671 											 lefttype,
1672 											 righttype,
1673 											 BTORDER_PROC);
1674 					if (!OidIsValid(proc))
1675 						elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1676 							 BTORDER_PROC, lefttype, righttype, opfamily);
1677 
1678 					/* Set up the primary fmgr lookup information */
1679 					finfo = palloc0(sizeof(FmgrInfo));
1680 					fcinfo = palloc0(sizeof(FunctionCallInfoData));
1681 					fmgr_info(proc, finfo);
1682 					fmgr_info_set_expr((Node *) node, finfo);
1683 					InitFunctionCallInfoData(*fcinfo, finfo, 2,
1684 											 inputcollid, NULL, NULL);
1685 
1686 					/*
1687 					 * If we enforced permissions checks on index support
1688 					 * functions, we'd need to make a check here.  But the
1689 					 * index support machinery doesn't do that, and thus
1690 					 * neither does this code.
1691 					 */
1692 
1693 					/* evaluate left and right args directly into fcinfo */
1694 					ExecInitExprRec(left_expr, parent, state,
1695 									&fcinfo->arg[0], &fcinfo->argnull[0]);
1696 					ExecInitExprRec(right_expr, parent, state,
1697 									&fcinfo->arg[1], &fcinfo->argnull[1]);
1698 
1699 					scratch.opcode = EEOP_ROWCOMPARE_STEP;
1700 					scratch.d.rowcompare_step.finfo = finfo;
1701 					scratch.d.rowcompare_step.fcinfo_data = fcinfo;
1702 					scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
1703 					/* jump targets filled below */
1704 					scratch.d.rowcompare_step.jumpnull = -1;
1705 					scratch.d.rowcompare_step.jumpdone = -1;
1706 
1707 					ExprEvalPushStep(state, &scratch);
1708 					adjust_jumps = lappend_int(adjust_jumps,
1709 											   state->steps_len - 1);
1710 				}
1711 
1712 				/*
1713 				 * We could have a zero-column rowtype, in which case the rows
1714 				 * necessarily compare equal.
1715 				 */
1716 				if (nopers == 0)
1717 				{
1718 					scratch.opcode = EEOP_CONST;
1719 					scratch.d.constval.value = Int32GetDatum(0);
1720 					scratch.d.constval.isnull = false;
1721 					ExprEvalPushStep(state, &scratch);
1722 				}
1723 
1724 				/* Finally, examine the last comparison result */
1725 				scratch.opcode = EEOP_ROWCOMPARE_FINAL;
1726 				scratch.d.rowcompare_final.rctype = rcexpr->rctype;
1727 				ExprEvalPushStep(state, &scratch);
1728 
1729 				/* adjust jump targetss */
1730 				foreach(lc, adjust_jumps)
1731 				{
1732 					ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1733 
1734 					Assert(as->opcode == EEOP_ROWCOMPARE_STEP);
1735 					Assert(as->d.rowcompare_step.jumpdone == -1);
1736 					Assert(as->d.rowcompare_step.jumpnull == -1);
1737 
1738 					/* jump to comparison evaluation */
1739 					as->d.rowcompare_step.jumpdone = state->steps_len - 1;
1740 					/* jump to the following expression */
1741 					as->d.rowcompare_step.jumpnull = state->steps_len;
1742 				}
1743 
1744 				break;
1745 			}
1746 
1747 		case T_CoalesceExpr:
1748 			{
1749 				CoalesceExpr *coalesce = (CoalesceExpr *) node;
1750 				List	   *adjust_jumps = NIL;
1751 				ListCell   *lc;
1752 
1753 				/* We assume there's at least one arg */
1754 				Assert(coalesce->args != NIL);
1755 
1756 				/*
1757 				 * Prepare evaluation of all coalesced arguments, after each
1758 				 * one push a step that short-circuits if not null.
1759 				 */
1760 				foreach(lc, coalesce->args)
1761 				{
1762 					Expr	   *e = (Expr *) lfirst(lc);
1763 
1764 					/* evaluate argument, directly into result datum */
1765 					ExecInitExprRec(e, parent, state, resv, resnull);
1766 
1767 					/* if it's not null, skip to end of COALESCE expr */
1768 					scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
1769 					scratch.d.jump.jumpdone = -1;	/* adjust later */
1770 					ExprEvalPushStep(state, &scratch);
1771 
1772 					adjust_jumps = lappend_int(adjust_jumps,
1773 											   state->steps_len - 1);
1774 				}
1775 
1776 				/*
1777 				 * No need to add a constant NULL return - we only can get to
1778 				 * the end of the expression if a NULL already is being
1779 				 * returned.
1780 				 */
1781 
1782 				/* adjust jump targets */
1783 				foreach(lc, adjust_jumps)
1784 				{
1785 					ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1786 
1787 					Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL);
1788 					Assert(as->d.jump.jumpdone == -1);
1789 					as->d.jump.jumpdone = state->steps_len;
1790 				}
1791 
1792 				break;
1793 			}
1794 
1795 		case T_MinMaxExpr:
1796 			{
1797 				MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1798 				int			nelems = list_length(minmaxexpr->args);
1799 				TypeCacheEntry *typentry;
1800 				FmgrInfo   *finfo;
1801 				FunctionCallInfo fcinfo;
1802 				ListCell   *lc;
1803 				int			off;
1804 
1805 				/* Look up the btree comparison function for the datatype */
1806 				typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1807 											 TYPECACHE_CMP_PROC);
1808 				if (!OidIsValid(typentry->cmp_proc))
1809 					ereport(ERROR,
1810 							(errcode(ERRCODE_UNDEFINED_FUNCTION),
1811 							 errmsg("could not identify a comparison function for type %s",
1812 									format_type_be(minmaxexpr->minmaxtype))));
1813 
1814 				/*
1815 				 * If we enforced permissions checks on index support
1816 				 * functions, we'd need to make a check here.  But the index
1817 				 * support machinery doesn't do that, and thus neither does
1818 				 * this code.
1819 				 */
1820 
1821 				/* Perform function lookup */
1822 				finfo = palloc0(sizeof(FmgrInfo));
1823 				fcinfo = palloc0(sizeof(FunctionCallInfoData));
1824 				fmgr_info(typentry->cmp_proc, finfo);
1825 				fmgr_info_set_expr((Node *) node, finfo);
1826 				InitFunctionCallInfoData(*fcinfo, finfo, 2,
1827 										 minmaxexpr->inputcollid, NULL, NULL);
1828 
1829 				scratch.opcode = EEOP_MINMAX;
1830 				/* allocate space to store arguments */
1831 				scratch.d.minmax.values =
1832 					(Datum *) palloc(sizeof(Datum) * nelems);
1833 				scratch.d.minmax.nulls =
1834 					(bool *) palloc(sizeof(bool) * nelems);
1835 				scratch.d.minmax.nelems = nelems;
1836 
1837 				scratch.d.minmax.op = minmaxexpr->op;
1838 				scratch.d.minmax.finfo = finfo;
1839 				scratch.d.minmax.fcinfo_data = fcinfo;
1840 
1841 				/* evaluate expressions into minmax->values/nulls */
1842 				off = 0;
1843 				foreach(lc, minmaxexpr->args)
1844 				{
1845 					Expr	   *e = (Expr *) lfirst(lc);
1846 
1847 					ExecInitExprRec(e, parent, state,
1848 									&scratch.d.minmax.values[off],
1849 									&scratch.d.minmax.nulls[off]);
1850 					off++;
1851 				}
1852 
1853 				/* and push the final comparison */
1854 				ExprEvalPushStep(state, &scratch);
1855 				break;
1856 			}
1857 
1858 		case T_SQLValueFunction:
1859 			{
1860 				SQLValueFunction *svf = (SQLValueFunction *) node;
1861 
1862 				scratch.opcode = EEOP_SQLVALUEFUNCTION;
1863 				scratch.d.sqlvaluefunction.svf = svf;
1864 
1865 				ExprEvalPushStep(state, &scratch);
1866 				break;
1867 			}
1868 
1869 		case T_XmlExpr:
1870 			{
1871 				XmlExpr    *xexpr = (XmlExpr *) node;
1872 				int			nnamed = list_length(xexpr->named_args);
1873 				int			nargs = list_length(xexpr->args);
1874 				int			off;
1875 				ListCell   *arg;
1876 
1877 				scratch.opcode = EEOP_XMLEXPR;
1878 				scratch.d.xmlexpr.xexpr = xexpr;
1879 
1880 				/* allocate space for storing all the arguments */
1881 				if (nnamed)
1882 				{
1883 					scratch.d.xmlexpr.named_argvalue =
1884 						(Datum *) palloc(sizeof(Datum) * nnamed);
1885 					scratch.d.xmlexpr.named_argnull =
1886 						(bool *) palloc(sizeof(bool) * nnamed);
1887 				}
1888 				else
1889 				{
1890 					scratch.d.xmlexpr.named_argvalue = NULL;
1891 					scratch.d.xmlexpr.named_argnull = NULL;
1892 				}
1893 
1894 				if (nargs)
1895 				{
1896 					scratch.d.xmlexpr.argvalue =
1897 						(Datum *) palloc(sizeof(Datum) * nargs);
1898 					scratch.d.xmlexpr.argnull =
1899 						(bool *) palloc(sizeof(bool) * nargs);
1900 				}
1901 				else
1902 				{
1903 					scratch.d.xmlexpr.argvalue = NULL;
1904 					scratch.d.xmlexpr.argnull = NULL;
1905 				}
1906 
1907 				/* prepare argument execution */
1908 				off = 0;
1909 				foreach(arg, xexpr->named_args)
1910 				{
1911 					Expr	   *e = (Expr *) lfirst(arg);
1912 
1913 					ExecInitExprRec(e, parent, state,
1914 									&scratch.d.xmlexpr.named_argvalue[off],
1915 									&scratch.d.xmlexpr.named_argnull[off]);
1916 					off++;
1917 				}
1918 
1919 				off = 0;
1920 				foreach(arg, xexpr->args)
1921 				{
1922 					Expr	   *e = (Expr *) lfirst(arg);
1923 
1924 					ExecInitExprRec(e, parent, state,
1925 									&scratch.d.xmlexpr.argvalue[off],
1926 									&scratch.d.xmlexpr.argnull[off]);
1927 					off++;
1928 				}
1929 
1930 				/* and evaluate the actual XML expression */
1931 				ExprEvalPushStep(state, &scratch);
1932 				break;
1933 			}
1934 
1935 		case T_NullTest:
1936 			{
1937 				NullTest   *ntest = (NullTest *) node;
1938 
1939 				if (ntest->nulltesttype == IS_NULL)
1940 				{
1941 					if (ntest->argisrow)
1942 						scratch.opcode = EEOP_NULLTEST_ROWISNULL;
1943 					else
1944 						scratch.opcode = EEOP_NULLTEST_ISNULL;
1945 				}
1946 				else if (ntest->nulltesttype == IS_NOT_NULL)
1947 				{
1948 					if (ntest->argisrow)
1949 						scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL;
1950 					else
1951 						scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
1952 				}
1953 				else
1954 				{
1955 					elog(ERROR, "unrecognized nulltesttype: %d",
1956 						 (int) ntest->nulltesttype);
1957 				}
1958 				/* initialize cache in case it's a row test */
1959 				scratch.d.nulltest_row.argdesc = NULL;
1960 
1961 				/* first evaluate argument into result variable */
1962 				ExecInitExprRec(ntest->arg, parent, state,
1963 								resv, resnull);
1964 
1965 				/* then push the test of that argument */
1966 				ExprEvalPushStep(state, &scratch);
1967 				break;
1968 			}
1969 
1970 		case T_BooleanTest:
1971 			{
1972 				BooleanTest *btest = (BooleanTest *) node;
1973 
1974 				/*
1975 				 * Evaluate argument, directly into result datum.  That's ok,
1976 				 * because resv/resnull is definitely not used anywhere else,
1977 				 * and will get overwritten by the below EEOP_BOOLTEST_IS_*
1978 				 * step.
1979 				 */
1980 				ExecInitExprRec(btest->arg, parent, state, resv, resnull);
1981 
1982 				switch (btest->booltesttype)
1983 				{
1984 					case IS_TRUE:
1985 						scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
1986 						break;
1987 					case IS_NOT_TRUE:
1988 						scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE;
1989 						break;
1990 					case IS_FALSE:
1991 						scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
1992 						break;
1993 					case IS_NOT_FALSE:
1994 						scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE;
1995 						break;
1996 					case IS_UNKNOWN:
1997 						/* Same as scalar IS NULL test */
1998 						scratch.opcode = EEOP_NULLTEST_ISNULL;
1999 						break;
2000 					case IS_NOT_UNKNOWN:
2001 						/* Same as scalar IS NOT NULL test */
2002 						scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2003 						break;
2004 					default:
2005 						elog(ERROR, "unrecognized booltesttype: %d",
2006 							 (int) btest->booltesttype);
2007 				}
2008 
2009 				ExprEvalPushStep(state, &scratch);
2010 				break;
2011 			}
2012 
2013 		case T_CoerceToDomain:
2014 			{
2015 				CoerceToDomain *ctest = (CoerceToDomain *) node;
2016 
2017 				ExecInitCoerceToDomain(&scratch, ctest, parent, state,
2018 									   resv, resnull);
2019 				break;
2020 			}
2021 
2022 		case T_CoerceToDomainValue:
2023 			{
2024 				/*
2025 				 * Read from location identified by innermost_domainval.  Note
2026 				 * that innermost_domainval could be NULL, if we're compiling
2027 				 * a standalone domain check rather than one embedded in a
2028 				 * larger expression.  In that case we must read from
2029 				 * econtext->domainValue_datum.  We'll take care of that
2030 				 * scenario at runtime.
2031 				 */
2032 				scratch.opcode = EEOP_DOMAIN_TESTVAL;
2033 				/* we share instruction union variant with case testval */
2034 				scratch.d.casetest.value = state->innermost_domainval;
2035 				scratch.d.casetest.isnull = state->innermost_domainnull;
2036 
2037 				ExprEvalPushStep(state, &scratch);
2038 				break;
2039 			}
2040 
2041 		case T_CurrentOfExpr:
2042 			{
2043 				scratch.opcode = EEOP_CURRENTOFEXPR;
2044 				ExprEvalPushStep(state, &scratch);
2045 				break;
2046 			}
2047 
2048 		case T_NextValueExpr:
2049 			{
2050 				NextValueExpr *nve = (NextValueExpr *) node;
2051 
2052 				scratch.opcode = EEOP_NEXTVALUEEXPR;
2053 				scratch.d.nextvalueexpr.seqid = nve->seqid;
2054 				scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2055 
2056 				ExprEvalPushStep(state, &scratch);
2057 				break;
2058 			}
2059 
2060 		default:
2061 			elog(ERROR, "unrecognized node type: %d",
2062 				 (int) nodeTag(node));
2063 			break;
2064 	}
2065 }
2066 
2067 /*
2068  * Add another expression evaluation step to ExprState->steps.
2069  *
2070  * Note that this potentially re-allocates es->steps, therefore no pointer
2071  * into that array may be used while the expression is still being built.
2072  */
2073 static void
ExprEvalPushStep(ExprState * es,const ExprEvalStep * s)2074 ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
2075 {
2076 	if (es->steps_alloc == 0)
2077 	{
2078 		es->steps_alloc = 16;
2079 		es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2080 	}
2081 	else if (es->steps_alloc == es->steps_len)
2082 	{
2083 		es->steps_alloc *= 2;
2084 		es->steps = repalloc(es->steps,
2085 							 sizeof(ExprEvalStep) * es->steps_alloc);
2086 	}
2087 
2088 	memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2089 }
2090 
2091 /*
2092  * Perform setup necessary for the evaluation of a function-like expression,
2093  * appending argument evaluation steps to the steps list in *state, and
2094  * setting up *scratch so it is ready to be pushed.
2095  *
2096  * *scratch is not pushed here, so that callers may override the opcode,
2097  * which is useful for function-like cases like DISTINCT.
2098  */
2099 static void
ExecInitFunc(ExprEvalStep * scratch,Expr * node,List * args,Oid funcid,Oid inputcollid,PlanState * parent,ExprState * state)2100 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2101 			 Oid inputcollid, PlanState *parent, ExprState *state)
2102 {
2103 	int			nargs = list_length(args);
2104 	AclResult	aclresult;
2105 	FmgrInfo   *flinfo;
2106 	FunctionCallInfo fcinfo;
2107 	int			argno;
2108 	ListCell   *lc;
2109 
2110 	/* Check permission to call function */
2111 	aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
2112 	if (aclresult != ACLCHECK_OK)
2113 		aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(funcid));
2114 	InvokeFunctionExecuteHook(funcid);
2115 
2116 	/*
2117 	 * Safety check on nargs.  Under normal circumstances this should never
2118 	 * fail, as parser should check sooner.  But possibly it might fail if
2119 	 * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2120 	 * declared in pg_proc?
2121 	 */
2122 	if (nargs > FUNC_MAX_ARGS)
2123 		ereport(ERROR,
2124 				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2125 				 errmsg_plural("cannot pass more than %d argument to a function",
2126 							   "cannot pass more than %d arguments to a function",
2127 							   FUNC_MAX_ARGS,
2128 							   FUNC_MAX_ARGS)));
2129 
2130 	/* Allocate function lookup data and parameter workspace for this call */
2131 	scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2132 	scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
2133 	flinfo = scratch->d.func.finfo;
2134 	fcinfo = scratch->d.func.fcinfo_data;
2135 
2136 	/* Set up the primary fmgr lookup information */
2137 	fmgr_info(funcid, flinfo);
2138 	fmgr_info_set_expr((Node *) node, flinfo);
2139 
2140 	/* Initialize function call parameter structure too */
2141 	InitFunctionCallInfoData(*fcinfo, flinfo,
2142 							 nargs, inputcollid, NULL, NULL);
2143 
2144 	/* Keep extra copies of this info to save an indirection at runtime */
2145 	scratch->d.func.fn_addr = flinfo->fn_addr;
2146 	scratch->d.func.nargs = nargs;
2147 
2148 	/* We only support non-set functions here */
2149 	if (flinfo->fn_retset)
2150 		ereport(ERROR,
2151 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2152 				 errmsg("set-valued function called in context that cannot accept a set"),
2153 				 parent ? executor_errposition(parent->state,
2154 											   exprLocation((Node *) node)) : 0));
2155 
2156 	/* Build code to evaluate arguments directly into the fcinfo struct */
2157 	argno = 0;
2158 	foreach(lc, args)
2159 	{
2160 		Expr	   *arg = (Expr *) lfirst(lc);
2161 
2162 		if (IsA(arg, Const))
2163 		{
2164 			/*
2165 			 * Don't evaluate const arguments every round; especially
2166 			 * interesting for constants in comparisons.
2167 			 */
2168 			Const	   *con = (Const *) arg;
2169 
2170 			fcinfo->arg[argno] = con->constvalue;
2171 			fcinfo->argnull[argno] = con->constisnull;
2172 		}
2173 		else
2174 		{
2175 			ExecInitExprRec(arg, parent, state,
2176 							&fcinfo->arg[argno], &fcinfo->argnull[argno]);
2177 		}
2178 		argno++;
2179 	}
2180 
2181 	/* Insert appropriate opcode depending on strictness and stats level */
2182 	if (pgstat_track_functions <= flinfo->fn_stats)
2183 	{
2184 		if (flinfo->fn_strict && nargs > 0)
2185 			scratch->opcode = EEOP_FUNCEXPR_STRICT;
2186 		else
2187 			scratch->opcode = EEOP_FUNCEXPR;
2188 	}
2189 	else
2190 	{
2191 		if (flinfo->fn_strict && nargs > 0)
2192 			scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE;
2193 		else
2194 			scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2195 	}
2196 }
2197 
2198 /*
2199  * Add expression steps deforming the ExprState's inner/outer/scan slots
2200  * as much as required by the expression.
2201  */
2202 static void
ExecInitExprSlots(ExprState * state,Node * node)2203 ExecInitExprSlots(ExprState *state, Node *node)
2204 {
2205 	LastAttnumInfo info = {0, 0, 0};
2206 	ExprEvalStep scratch;
2207 
2208 	/*
2209 	 * Figure out which attributes we're going to need.
2210 	 */
2211 	get_last_attnums_walker(node, &info);
2212 
2213 	/* Emit steps as needed */
2214 	if (info.last_inner > 0)
2215 	{
2216 		scratch.opcode = EEOP_INNER_FETCHSOME;
2217 		scratch.d.fetch.last_var = info.last_inner;
2218 		ExprEvalPushStep(state, &scratch);
2219 	}
2220 	if (info.last_outer > 0)
2221 	{
2222 		scratch.opcode = EEOP_OUTER_FETCHSOME;
2223 		scratch.d.fetch.last_var = info.last_outer;
2224 		ExprEvalPushStep(state, &scratch);
2225 	}
2226 	if (info.last_scan > 0)
2227 	{
2228 		scratch.opcode = EEOP_SCAN_FETCHSOME;
2229 		scratch.d.fetch.last_var = info.last_scan;
2230 		ExprEvalPushStep(state, &scratch);
2231 	}
2232 }
2233 
2234 /*
2235  * get_last_attnums_walker: expression walker for ExecInitExprSlots
2236  */
2237 static bool
get_last_attnums_walker(Node * node,LastAttnumInfo * info)2238 get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2239 {
2240 	if (node == NULL)
2241 		return false;
2242 	if (IsA(node, Var))
2243 	{
2244 		Var		   *variable = (Var *) node;
2245 		AttrNumber	attnum = variable->varattno;
2246 
2247 		switch (variable->varno)
2248 		{
2249 			case INNER_VAR:
2250 				info->last_inner = Max(info->last_inner, attnum);
2251 				break;
2252 
2253 			case OUTER_VAR:
2254 				info->last_outer = Max(info->last_outer, attnum);
2255 				break;
2256 
2257 				/* INDEX_VAR is handled by default case */
2258 
2259 			default:
2260 				info->last_scan = Max(info->last_scan, attnum);
2261 				break;
2262 		}
2263 		return false;
2264 	}
2265 
2266 	/*
2267 	 * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2268 	 * because those do not represent expressions to be evaluated within the
2269 	 * calling expression's econtext.  GroupingFunc arguments are never
2270 	 * evaluated at all.
2271 	 */
2272 	if (IsA(node, Aggref))
2273 		return false;
2274 	if (IsA(node, WindowFunc))
2275 		return false;
2276 	if (IsA(node, GroupingFunc))
2277 		return false;
2278 	return expression_tree_walker(node, get_last_attnums_walker,
2279 								  (void *) info);
2280 }
2281 
2282 /*
2283  * Prepare step for the evaluation of a whole-row variable.
2284  * The caller still has to push the step.
2285  */
2286 static void
ExecInitWholeRowVar(ExprEvalStep * scratch,Var * variable,PlanState * parent)2287 ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, PlanState *parent)
2288 {
2289 	/* fill in all but the target */
2290 	scratch->opcode = EEOP_WHOLEROW;
2291 	scratch->d.wholerow.var = variable;
2292 	scratch->d.wholerow.first = true;
2293 	scratch->d.wholerow.slow = false;
2294 	scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
2295 	scratch->d.wholerow.junkFilter = NULL;
2296 
2297 	/*
2298 	 * If the input tuple came from a subquery, it might contain "resjunk"
2299 	 * columns (such as GROUP BY or ORDER BY columns), which we don't want to
2300 	 * keep in the whole-row result.  We can get rid of such columns by
2301 	 * passing the tuple through a JunkFilter --- but to make one, we have to
2302 	 * lay our hands on the subquery's targetlist.  Fortunately, there are not
2303 	 * very many cases where this can happen, and we can identify all of them
2304 	 * by examining our parent PlanState.  We assume this is not an issue in
2305 	 * standalone expressions that don't have parent plans.  (Whole-row Vars
2306 	 * can occur in such expressions, but they will always be referencing
2307 	 * table rows.)
2308 	 */
2309 	if (parent)
2310 	{
2311 		PlanState  *subplan = NULL;
2312 
2313 		switch (nodeTag(parent))
2314 		{
2315 			case T_SubqueryScanState:
2316 				subplan = ((SubqueryScanState *) parent)->subplan;
2317 				break;
2318 			case T_CteScanState:
2319 				subplan = ((CteScanState *) parent)->cteplanstate;
2320 				break;
2321 			default:
2322 				break;
2323 		}
2324 
2325 		if (subplan)
2326 		{
2327 			bool		junk_filter_needed = false;
2328 			ListCell   *tlist;
2329 
2330 			/* Detect whether subplan tlist actually has any junk columns */
2331 			foreach(tlist, subplan->plan->targetlist)
2332 			{
2333 				TargetEntry *tle = (TargetEntry *) lfirst(tlist);
2334 
2335 				if (tle->resjunk)
2336 				{
2337 					junk_filter_needed = true;
2338 					break;
2339 				}
2340 			}
2341 
2342 			/* If so, build the junkfilter now */
2343 			if (junk_filter_needed)
2344 			{
2345 				scratch->d.wholerow.junkFilter =
2346 					ExecInitJunkFilter(subplan->plan->targetlist,
2347 									   ExecGetResultType(subplan)->tdhasoid,
2348 									   ExecInitExtraTupleSlot(parent->state));
2349 			}
2350 		}
2351 	}
2352 }
2353 
2354 /*
2355  * Prepare evaluation of an ArrayRef expression.
2356  */
2357 static void
ExecInitArrayRef(ExprEvalStep * scratch,ArrayRef * aref,PlanState * parent,ExprState * state,Datum * resv,bool * resnull)2358 ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, PlanState *parent,
2359 				 ExprState *state, Datum *resv, bool *resnull)
2360 {
2361 	bool		isAssignment = (aref->refassgnexpr != NULL);
2362 	ArrayRefState *arefstate = palloc0(sizeof(ArrayRefState));
2363 	List	   *adjust_jumps = NIL;
2364 	ListCell   *lc;
2365 	int			i;
2366 
2367 	/* Fill constant fields of ArrayRefState */
2368 	arefstate->isassignment = isAssignment;
2369 	arefstate->refelemtype = aref->refelemtype;
2370 	arefstate->refattrlength = get_typlen(aref->refarraytype);
2371 	get_typlenbyvalalign(aref->refelemtype,
2372 						 &arefstate->refelemlength,
2373 						 &arefstate->refelembyval,
2374 						 &arefstate->refelemalign);
2375 
2376 	/*
2377 	 * Evaluate array input.  It's safe to do so into resv/resnull, because we
2378 	 * won't use that as target for any of the other subexpressions, and it'll
2379 	 * be overwritten by the final EEOP_ARRAYREF_FETCH/ASSIGN step, which is
2380 	 * pushed last.
2381 	 */
2382 	ExecInitExprRec(aref->refexpr, parent, state, resv, resnull);
2383 
2384 	/*
2385 	 * If refexpr yields NULL, and it's a fetch, then result is NULL.  We can
2386 	 * implement this with just JUMP_IF_NULL, since we evaluated the array
2387 	 * into the desired target location.
2388 	 */
2389 	if (!isAssignment)
2390 	{
2391 		scratch->opcode = EEOP_JUMP_IF_NULL;
2392 		scratch->d.jump.jumpdone = -1;	/* adjust later */
2393 		ExprEvalPushStep(state, scratch);
2394 		adjust_jumps = lappend_int(adjust_jumps,
2395 								   state->steps_len - 1);
2396 	}
2397 
2398 	/* Verify subscript list lengths are within limit */
2399 	if (list_length(aref->refupperindexpr) > MAXDIM)
2400 		ereport(ERROR,
2401 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2402 				 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2403 						list_length(aref->refupperindexpr), MAXDIM)));
2404 
2405 	if (list_length(aref->reflowerindexpr) > MAXDIM)
2406 		ereport(ERROR,
2407 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2408 				 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2409 						list_length(aref->reflowerindexpr), MAXDIM)));
2410 
2411 	/* Evaluate upper subscripts */
2412 	i = 0;
2413 	foreach(lc, aref->refupperindexpr)
2414 	{
2415 		Expr	   *e = (Expr *) lfirst(lc);
2416 
2417 		/* When slicing, individual subscript bounds can be omitted */
2418 		if (!e)
2419 		{
2420 			arefstate->upperprovided[i] = false;
2421 			i++;
2422 			continue;
2423 		}
2424 
2425 		arefstate->upperprovided[i] = true;
2426 
2427 		/* Each subscript is evaluated into subscriptvalue/subscriptnull */
2428 		ExecInitExprRec(e, parent, state,
2429 						&arefstate->subscriptvalue, &arefstate->subscriptnull);
2430 
2431 		/* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */
2432 		scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT;
2433 		scratch->d.arrayref_subscript.state = arefstate;
2434 		scratch->d.arrayref_subscript.off = i;
2435 		scratch->d.arrayref_subscript.isupper = true;
2436 		scratch->d.arrayref_subscript.jumpdone = -1;	/* adjust later */
2437 		ExprEvalPushStep(state, scratch);
2438 		adjust_jumps = lappend_int(adjust_jumps,
2439 								   state->steps_len - 1);
2440 		i++;
2441 	}
2442 	arefstate->numupper = i;
2443 
2444 	/* Evaluate lower subscripts similarly */
2445 	i = 0;
2446 	foreach(lc, aref->reflowerindexpr)
2447 	{
2448 		Expr	   *e = (Expr *) lfirst(lc);
2449 
2450 		/* When slicing, individual subscript bounds can be omitted */
2451 		if (!e)
2452 		{
2453 			arefstate->lowerprovided[i] = false;
2454 			i++;
2455 			continue;
2456 		}
2457 
2458 		arefstate->lowerprovided[i] = true;
2459 
2460 		/* Each subscript is evaluated into subscriptvalue/subscriptnull */
2461 		ExecInitExprRec(e, parent, state,
2462 						&arefstate->subscriptvalue, &arefstate->subscriptnull);
2463 
2464 		/* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */
2465 		scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT;
2466 		scratch->d.arrayref_subscript.state = arefstate;
2467 		scratch->d.arrayref_subscript.off = i;
2468 		scratch->d.arrayref_subscript.isupper = false;
2469 		scratch->d.arrayref_subscript.jumpdone = -1;	/* adjust later */
2470 		ExprEvalPushStep(state, scratch);
2471 		adjust_jumps = lappend_int(adjust_jumps,
2472 								   state->steps_len - 1);
2473 		i++;
2474 	}
2475 	arefstate->numlower = i;
2476 
2477 	/* Should be impossible if parser is sane, but check anyway: */
2478 	if (arefstate->numlower != 0 &&
2479 		arefstate->numupper != arefstate->numlower)
2480 		elog(ERROR, "upper and lower index lists are not same length");
2481 
2482 	if (isAssignment)
2483 	{
2484 		Datum	   *save_innermost_caseval;
2485 		bool	   *save_innermost_casenull;
2486 
2487 		/*
2488 		 * We might have a nested-assignment situation, in which the
2489 		 * refassgnexpr is itself a FieldStore or ArrayRef that needs to
2490 		 * obtain and modify the previous value of the array element or slice
2491 		 * being replaced.  If so, we have to extract that value from the
2492 		 * array and pass it down via the CaseTestExpr mechanism.  It's safe
2493 		 * to reuse the CASE mechanism because there cannot be a CASE between
2494 		 * here and where the value would be needed, and an array assignment
2495 		 * can't be within a CASE either.  (So saving and restoring
2496 		 * innermost_caseval is just paranoia, but let's do it anyway.)
2497 		 *
2498 		 * Since fetching the old element might be a nontrivial expense, do it
2499 		 * only if the argument actually needs it.
2500 		 */
2501 		if (isAssignmentIndirectionExpr(aref->refassgnexpr))
2502 		{
2503 			scratch->opcode = EEOP_ARRAYREF_OLD;
2504 			scratch->d.arrayref.state = arefstate;
2505 			ExprEvalPushStep(state, scratch);
2506 		}
2507 
2508 		/* ARRAYREF_OLD puts extracted value into prevvalue/prevnull */
2509 		save_innermost_caseval = state->innermost_caseval;
2510 		save_innermost_casenull = state->innermost_casenull;
2511 		state->innermost_caseval = &arefstate->prevvalue;
2512 		state->innermost_casenull = &arefstate->prevnull;
2513 
2514 		/* evaluate replacement value into replacevalue/replacenull */
2515 		ExecInitExprRec(aref->refassgnexpr, parent, state,
2516 						&arefstate->replacevalue, &arefstate->replacenull);
2517 
2518 		state->innermost_caseval = save_innermost_caseval;
2519 		state->innermost_casenull = save_innermost_casenull;
2520 
2521 		/* and perform the assignment */
2522 		scratch->opcode = EEOP_ARRAYREF_ASSIGN;
2523 		scratch->d.arrayref.state = arefstate;
2524 		ExprEvalPushStep(state, scratch);
2525 	}
2526 	else
2527 	{
2528 		/* array fetch is much simpler */
2529 		scratch->opcode = EEOP_ARRAYREF_FETCH;
2530 		scratch->d.arrayref.state = arefstate;
2531 		ExprEvalPushStep(state, scratch);
2532 	}
2533 
2534 	/* adjust jump targets */
2535 	foreach(lc, adjust_jumps)
2536 	{
2537 		ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2538 
2539 		if (as->opcode == EEOP_ARRAYREF_SUBSCRIPT)
2540 		{
2541 			Assert(as->d.arrayref_subscript.jumpdone == -1);
2542 			as->d.arrayref_subscript.jumpdone = state->steps_len;
2543 		}
2544 		else
2545 		{
2546 			Assert(as->opcode == EEOP_JUMP_IF_NULL);
2547 			Assert(as->d.jump.jumpdone == -1);
2548 			as->d.jump.jumpdone = state->steps_len;
2549 		}
2550 	}
2551 }
2552 
2553 /*
2554  * Helper for preparing ArrayRef expressions for evaluation: is expr a nested
2555  * FieldStore or ArrayRef that needs the old element value passed down?
2556  *
2557  * (We could use this in FieldStore too, but in that case passing the old
2558  * value is so cheap there's no need.)
2559  *
2560  * Note: it might seem that this needs to recurse, but it does not; the
2561  * CaseTestExpr, if any, will be directly the arg or refexpr of the top-level
2562  * node.  Nested-assignment situations give rise to expression trees in which
2563  * each level of assignment has its own CaseTestExpr, and the recursive
2564  * structure appears within the newvals or refassgnexpr field.
2565  */
2566 static bool
isAssignmentIndirectionExpr(Expr * expr)2567 isAssignmentIndirectionExpr(Expr *expr)
2568 {
2569 	if (expr == NULL)
2570 		return false;			/* just paranoia */
2571 	if (IsA(expr, FieldStore))
2572 	{
2573 		FieldStore *fstore = (FieldStore *) expr;
2574 
2575 		if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
2576 			return true;
2577 	}
2578 	else if (IsA(expr, ArrayRef))
2579 	{
2580 		ArrayRef   *arrayRef = (ArrayRef *) expr;
2581 
2582 		if (arrayRef->refexpr && IsA(arrayRef->refexpr, CaseTestExpr))
2583 			return true;
2584 	}
2585 	return false;
2586 }
2587 
2588 /*
2589  * Prepare evaluation of a CoerceToDomain expression.
2590  */
2591 static void
ExecInitCoerceToDomain(ExprEvalStep * scratch,CoerceToDomain * ctest,PlanState * parent,ExprState * state,Datum * resv,bool * resnull)2592 ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
2593 					   PlanState *parent, ExprState *state,
2594 					   Datum *resv, bool *resnull)
2595 {
2596 	ExprEvalStep scratch2;
2597 	DomainConstraintRef *constraint_ref;
2598 	Datum	   *domainval = NULL;
2599 	bool	   *domainnull = NULL;
2600 	Datum	   *save_innermost_domainval;
2601 	bool	   *save_innermost_domainnull;
2602 	ListCell   *l;
2603 
2604 	scratch->d.domaincheck.resulttype = ctest->resulttype;
2605 	/* we'll allocate workspace only if needed */
2606 	scratch->d.domaincheck.checkvalue = NULL;
2607 	scratch->d.domaincheck.checknull = NULL;
2608 
2609 	/*
2610 	 * Evaluate argument - it's fine to directly store it into resv/resnull,
2611 	 * if there's constraint failures there'll be errors, otherwise it's what
2612 	 * needs to be returned.
2613 	 */
2614 	ExecInitExprRec(ctest->arg, parent, state, resv, resnull);
2615 
2616 	/*
2617 	 * Note: if the argument is of varlena type, it could be a R/W expanded
2618 	 * object.  We want to return the R/W pointer as the final result, but we
2619 	 * have to pass a R/O pointer as the value to be tested by any functions
2620 	 * in check expressions.  We don't bother to emit a MAKE_READONLY step
2621 	 * unless there's actually at least one check expression, though.  Until
2622 	 * we've tested that, domainval/domainnull are NULL.
2623 	 */
2624 
2625 	/*
2626 	 * Collect the constraints associated with the domain.
2627 	 *
2628 	 * Note: before PG v10 we'd recheck the set of constraints during each
2629 	 * evaluation of the expression.  Now we bake them into the ExprState
2630 	 * during executor initialization.  That means we don't need typcache.c to
2631 	 * provide compiled exprs.
2632 	 */
2633 	constraint_ref = (DomainConstraintRef *)
2634 		palloc(sizeof(DomainConstraintRef));
2635 	InitDomainConstraintRef(ctest->resulttype,
2636 							constraint_ref,
2637 							CurrentMemoryContext,
2638 							false);
2639 
2640 	/*
2641 	 * Compile code to check each domain constraint.  NOTNULL constraints can
2642 	 * just be applied on the resv/resnull value, but for CHECK constraints we
2643 	 * need more pushups.
2644 	 */
2645 	foreach(l, constraint_ref->constraints)
2646 	{
2647 		DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
2648 
2649 		scratch->d.domaincheck.constraintname = con->name;
2650 
2651 		switch (con->constrainttype)
2652 		{
2653 			case DOM_CONSTRAINT_NOTNULL:
2654 				scratch->opcode = EEOP_DOMAIN_NOTNULL;
2655 				ExprEvalPushStep(state, scratch);
2656 				break;
2657 			case DOM_CONSTRAINT_CHECK:
2658 				/* Allocate workspace for CHECK output if we didn't yet */
2659 				if (scratch->d.domaincheck.checkvalue == NULL)
2660 				{
2661 					scratch->d.domaincheck.checkvalue =
2662 						(Datum *) palloc(sizeof(Datum));
2663 					scratch->d.domaincheck.checknull =
2664 						(bool *) palloc(sizeof(bool));
2665 				}
2666 
2667 				/*
2668 				 * If first time through, determine where CoerceToDomainValue
2669 				 * nodes should read from.
2670 				 */
2671 				if (domainval == NULL)
2672 				{
2673 					/*
2674 					 * Since value might be read multiple times, force to R/O
2675 					 * - but only if it could be an expanded datum.
2676 					 */
2677 					if (get_typlen(ctest->resulttype) == -1)
2678 					{
2679 						/* Yes, so make output workspace for MAKE_READONLY */
2680 						domainval = (Datum *) palloc(sizeof(Datum));
2681 						domainnull = (bool *) palloc(sizeof(bool));
2682 
2683 						/* Emit MAKE_READONLY */
2684 						scratch2.opcode = EEOP_MAKE_READONLY;
2685 						scratch2.resvalue = domainval;
2686 						scratch2.resnull = domainnull;
2687 						scratch2.d.make_readonly.value = resv;
2688 						scratch2.d.make_readonly.isnull = resnull;
2689 						ExprEvalPushStep(state, &scratch2);
2690 					}
2691 					else
2692 					{
2693 						/* No, so it's fine to read from resv/resnull */
2694 						domainval = resv;
2695 						domainnull = resnull;
2696 					}
2697 				}
2698 
2699 				/*
2700 				 * Set up value to be returned by CoerceToDomainValue nodes.
2701 				 * We must save and restore innermost_domainval/null fields,
2702 				 * in case this node is itself within a check expression for
2703 				 * another domain.
2704 				 */
2705 				save_innermost_domainval = state->innermost_domainval;
2706 				save_innermost_domainnull = state->innermost_domainnull;
2707 				state->innermost_domainval = domainval;
2708 				state->innermost_domainnull = domainnull;
2709 
2710 				/* evaluate check expression value */
2711 				ExecInitExprRec(con->check_expr, parent, state,
2712 								scratch->d.domaincheck.checkvalue,
2713 								scratch->d.domaincheck.checknull);
2714 
2715 				state->innermost_domainval = save_innermost_domainval;
2716 				state->innermost_domainnull = save_innermost_domainnull;
2717 
2718 				/* now test result */
2719 				scratch->opcode = EEOP_DOMAIN_CHECK;
2720 				ExprEvalPushStep(state, scratch);
2721 
2722 				break;
2723 			default:
2724 				elog(ERROR, "unrecognized constraint type: %d",
2725 					 (int) con->constrainttype);
2726 				break;
2727 		}
2728 	}
2729 }
2730