1 /*-------------------------------------------------------------------------
2  *
3  * execExprInterp.c
4  *	  Interpreted evaluation of an expression step list.
5  *
6  * This file provides either a "direct threaded" (for gcc, clang and
7  * compatible) or a "switch threaded" (for all compilers) implementation of
8  * expression evaluation.  The former is amongst the fastest known methods
9  * of interpreting programs without resorting to assembly level work, or
10  * just-in-time compilation, but it requires support for computed gotos.
11  * The latter is amongst the fastest approaches doable in standard C.
12  *
13  * In either case we use ExprEvalStep->opcode to dispatch to the code block
14  * within ExecInterpExpr() that implements the specific opcode type.
15  *
16  * Switch-threading uses a plain switch() statement to perform the
17  * dispatch.  This has the advantages of being plain C and allowing the
18  * compiler to warn if implementation of a specific opcode has been forgotten.
19  * The disadvantage is that dispatches will, as commonly implemented by
20  * compilers, happen from a single location, requiring more jumps and causing
21  * bad branch prediction.
22  *
23  * In direct threading, we use gcc's label-as-values extension - also adopted
24  * by some other compilers - to replace ExprEvalStep->opcode with the address
25  * of the block implementing the instruction. Dispatch to the next instruction
26  * is done by a "computed goto".  This allows for better branch prediction
27  * (as the jumps are happening from different locations) and fewer jumps
28  * (as no preparatory jump to a common dispatch location is needed).
29  *
30  * When using direct threading, ExecReadyInterpretedExpr will replace
31  * each step's opcode field with the address of the relevant code block and
32  * ExprState->flags will contain EEO_FLAG_DIRECT_THREADED to remember that
33  * that's been done.
34  *
35  * For very simple instructions the overhead of the full interpreter
36  * "startup", as minimal as it is, is noticeable.  Therefore
37  * ExecReadyInterpretedExpr will choose to implement certain simple
38  * opcode patterns using special fast-path routines (ExecJust*).
39  *
40  * Complex or uncommon instructions are not implemented in-line in
41  * ExecInterpExpr(), rather we call out to a helper function appearing later
42  * in this file.  For one reason, there'd not be a noticeable performance
43  * benefit, but more importantly those complex routines are intended to be
44  * shared between different expression evaluation approaches.  For instance
45  * a JIT compiler would generate calls to them.  (This is why they are
46  * exported rather than being "static" in this file.)
47  *
48  *
49  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
50  * Portions Copyright (c) 1994, Regents of the University of California
51  *
52  * IDENTIFICATION
53  *	  src/backend/executor/execExprInterp.c
54  *
55  *-------------------------------------------------------------------------
56  */
57 #include "postgres.h"
58 
59 #include "access/heaptoast.h"
60 #include "catalog/pg_type.h"
61 #include "commands/sequence.h"
62 #include "executor/execExpr.h"
63 #include "executor/nodeSubplan.h"
64 #include "funcapi.h"
65 #include "miscadmin.h"
66 #include "nodes/nodeFuncs.h"
67 #include "parser/parsetree.h"
68 #include "pgstat.h"
69 #include "utils/array.h"
70 #include "utils/builtins.h"
71 #include "utils/date.h"
72 #include "utils/datum.h"
73 #include "utils/expandedrecord.h"
74 #include "utils/lsyscache.h"
75 #include "utils/memutils.h"
76 #include "utils/timestamp.h"
77 #include "utils/typcache.h"
78 #include "utils/xml.h"
79 
80 /*
81  * Use computed-goto-based opcode dispatch when computed gotos are available.
82  * But use a separate symbol so that it's easy to adjust locally in this file
83  * for development and testing.
84  */
85 #ifdef HAVE_COMPUTED_GOTO
86 #define EEO_USE_COMPUTED_GOTO
87 #endif							/* HAVE_COMPUTED_GOTO */
88 
89 /*
90  * Macros for opcode dispatch.
91  *
92  * EEO_SWITCH - just hides the switch if not in use.
93  * EEO_CASE - labels the implementation of named expression step type.
94  * EEO_DISPATCH - jump to the implementation of the step type for 'op'.
95  * EEO_OPCODE - compute opcode required by used expression evaluation method.
96  * EEO_NEXT - increment 'op' and jump to correct next step type.
97  * EEO_JUMP - jump to the specified step number within the current expression.
98  */
99 #if defined(EEO_USE_COMPUTED_GOTO)
100 
101 /* struct for jump target -> opcode lookup table */
102 typedef struct ExprEvalOpLookup
103 {
104 	const void *opcode;
105 	ExprEvalOp	op;
106 } ExprEvalOpLookup;
107 
108 /* to make dispatch_table accessible outside ExecInterpExpr() */
109 static const void **dispatch_table = NULL;
110 
111 /* jump target -> opcode lookup table */
112 static ExprEvalOpLookup reverse_dispatch_table[EEOP_LAST];
113 
114 #define EEO_SWITCH()
115 #define EEO_CASE(name)		CASE_##name:
116 #define EEO_DISPATCH()		goto *((void *) op->opcode)
117 #define EEO_OPCODE(opcode)	((intptr_t) dispatch_table[opcode])
118 
119 #else							/* !EEO_USE_COMPUTED_GOTO */
120 
121 #define EEO_SWITCH()		starteval: switch ((ExprEvalOp) op->opcode)
122 #define EEO_CASE(name)		case name:
123 #define EEO_DISPATCH()		goto starteval
124 #define EEO_OPCODE(opcode)	(opcode)
125 
126 #endif							/* EEO_USE_COMPUTED_GOTO */
127 
128 #define EEO_NEXT() \
129 	do { \
130 		op++; \
131 		EEO_DISPATCH(); \
132 	} while (0)
133 
134 #define EEO_JUMP(stepno) \
135 	do { \
136 		op = &state->steps[stepno]; \
137 		EEO_DISPATCH(); \
138 	} while (0)
139 
140 
141 static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull);
142 static void ExecInitInterpreter(void);
143 
144 /* support functions */
145 static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype);
146 static void CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot);
147 static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
148 									ExprEvalRowtypeCache *rowcache,
149 									bool *changed);
150 static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
151 							   ExprContext *econtext, bool checkisnull);
152 
153 /* fast-path evaluation functions */
154 static Datum ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
155 static Datum ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
156 static Datum ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
157 static Datum ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
158 static Datum ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
159 static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
160 static Datum ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull);
161 static Datum ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull);
162 static Datum ExecJustInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
163 static Datum ExecJustOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
164 static Datum ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
165 static Datum ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
166 static Datum ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
167 static Datum ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
168 
169 /* execution helper functions */
170 static pg_attribute_always_inline void ExecAggPlainTransByVal(AggState *aggstate,
171 															  AggStatePerTrans pertrans,
172 															  AggStatePerGroup pergroup,
173 															  ExprContext *aggcontext,
174 															  int setno);
175 static pg_attribute_always_inline void ExecAggPlainTransByRef(AggState *aggstate,
176 															  AggStatePerTrans pertrans,
177 															  AggStatePerGroup pergroup,
178 															  ExprContext *aggcontext,
179 															  int setno);
180 
181 /*
182  * Prepare ExprState for interpreted execution.
183  */
184 void
ExecReadyInterpretedExpr(ExprState * state)185 ExecReadyInterpretedExpr(ExprState *state)
186 {
187 	/* Ensure one-time interpreter setup has been done */
188 	ExecInitInterpreter();
189 
190 	/* Simple validity checks on expression */
191 	Assert(state->steps_len >= 1);
192 	Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE);
193 
194 	/*
195 	 * Don't perform redundant initialization. This is unreachable in current
196 	 * cases, but might be hit if there's additional expression evaluation
197 	 * methods that rely on interpreted execution to work.
198 	 */
199 	if (state->flags & EEO_FLAG_INTERPRETER_INITIALIZED)
200 		return;
201 
202 	/*
203 	 * First time through, check whether attribute matches Var.  Might not be
204 	 * ok anymore, due to schema changes. We do that by setting up a callback
205 	 * that does checking on the first call, which then sets the evalfunc
206 	 * callback to the actual method of execution.
207 	 */
208 	state->evalfunc = ExecInterpExprStillValid;
209 
210 	/* DIRECT_THREADED should not already be set */
211 	Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0);
212 
213 	/*
214 	 * There shouldn't be any errors before the expression is fully
215 	 * initialized, and even if so, it'd lead to the expression being
216 	 * abandoned.  So we can set the flag now and save some code.
217 	 */
218 	state->flags |= EEO_FLAG_INTERPRETER_INITIALIZED;
219 
220 	/*
221 	 * Select fast-path evalfuncs for very simple expressions.  "Starting up"
222 	 * the full interpreter is a measurable overhead for these, and these
223 	 * patterns occur often enough to be worth optimizing.
224 	 */
225 	if (state->steps_len == 3)
226 	{
227 		ExprEvalOp	step0 = state->steps[0].opcode;
228 		ExprEvalOp	step1 = state->steps[1].opcode;
229 
230 		if (step0 == EEOP_INNER_FETCHSOME &&
231 			step1 == EEOP_INNER_VAR)
232 		{
233 			state->evalfunc_private = (void *) ExecJustInnerVar;
234 			return;
235 		}
236 		else if (step0 == EEOP_OUTER_FETCHSOME &&
237 				 step1 == EEOP_OUTER_VAR)
238 		{
239 			state->evalfunc_private = (void *) ExecJustOuterVar;
240 			return;
241 		}
242 		else if (step0 == EEOP_SCAN_FETCHSOME &&
243 				 step1 == EEOP_SCAN_VAR)
244 		{
245 			state->evalfunc_private = (void *) ExecJustScanVar;
246 			return;
247 		}
248 		else if (step0 == EEOP_INNER_FETCHSOME &&
249 				 step1 == EEOP_ASSIGN_INNER_VAR)
250 		{
251 			state->evalfunc_private = (void *) ExecJustAssignInnerVar;
252 			return;
253 		}
254 		else if (step0 == EEOP_OUTER_FETCHSOME &&
255 				 step1 == EEOP_ASSIGN_OUTER_VAR)
256 		{
257 			state->evalfunc_private = (void *) ExecJustAssignOuterVar;
258 			return;
259 		}
260 		else if (step0 == EEOP_SCAN_FETCHSOME &&
261 				 step1 == EEOP_ASSIGN_SCAN_VAR)
262 		{
263 			state->evalfunc_private = (void *) ExecJustAssignScanVar;
264 			return;
265 		}
266 		else if (step0 == EEOP_CASE_TESTVAL &&
267 				 step1 == EEOP_FUNCEXPR_STRICT &&
268 				 state->steps[0].d.casetest.value)
269 		{
270 			state->evalfunc_private = (void *) ExecJustApplyFuncToCase;
271 			return;
272 		}
273 	}
274 	else if (state->steps_len == 2)
275 	{
276 		ExprEvalOp	step0 = state->steps[0].opcode;
277 
278 		if (step0 == EEOP_CONST)
279 		{
280 			state->evalfunc_private = (void *) ExecJustConst;
281 			return;
282 		}
283 		else if (step0 == EEOP_INNER_VAR)
284 		{
285 			state->evalfunc_private = (void *) ExecJustInnerVarVirt;
286 			return;
287 		}
288 		else if (step0 == EEOP_OUTER_VAR)
289 		{
290 			state->evalfunc_private = (void *) ExecJustOuterVarVirt;
291 			return;
292 		}
293 		else if (step0 == EEOP_SCAN_VAR)
294 		{
295 			state->evalfunc_private = (void *) ExecJustScanVarVirt;
296 			return;
297 		}
298 		else if (step0 == EEOP_ASSIGN_INNER_VAR)
299 		{
300 			state->evalfunc_private = (void *) ExecJustAssignInnerVarVirt;
301 			return;
302 		}
303 		else if (step0 == EEOP_ASSIGN_OUTER_VAR)
304 		{
305 			state->evalfunc_private = (void *) ExecJustAssignOuterVarVirt;
306 			return;
307 		}
308 		else if (step0 == EEOP_ASSIGN_SCAN_VAR)
309 		{
310 			state->evalfunc_private = (void *) ExecJustAssignScanVarVirt;
311 			return;
312 		}
313 	}
314 
315 #if defined(EEO_USE_COMPUTED_GOTO)
316 
317 	/*
318 	 * In the direct-threaded implementation, replace each opcode with the
319 	 * address to jump to.  (Use ExecEvalStepOp() to get back the opcode.)
320 	 */
321 	for (int off = 0; off < state->steps_len; off++)
322 	{
323 		ExprEvalStep *op = &state->steps[off];
324 
325 		op->opcode = EEO_OPCODE(op->opcode);
326 	}
327 
328 	state->flags |= EEO_FLAG_DIRECT_THREADED;
329 #endif							/* EEO_USE_COMPUTED_GOTO */
330 
331 	state->evalfunc_private = (void *) ExecInterpExpr;
332 }
333 
334 
335 /*
336  * Evaluate expression identified by "state" in the execution context
337  * given by "econtext".  *isnull is set to the is-null flag for the result,
338  * and the Datum value is the function result.
339  *
340  * As a special case, return the dispatch table's address if state is NULL.
341  * This is used by ExecInitInterpreter to set up the dispatch_table global.
342  * (Only applies when EEO_USE_COMPUTED_GOTO is defined.)
343  */
344 static Datum
ExecInterpExpr(ExprState * state,ExprContext * econtext,bool * isnull)345 ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
346 {
347 	ExprEvalStep *op;
348 	TupleTableSlot *resultslot;
349 	TupleTableSlot *innerslot;
350 	TupleTableSlot *outerslot;
351 	TupleTableSlot *scanslot;
352 
353 	/*
354 	 * This array has to be in the same order as enum ExprEvalOp.
355 	 */
356 #if defined(EEO_USE_COMPUTED_GOTO)
357 	static const void *const dispatch_table[] = {
358 		&&CASE_EEOP_DONE,
359 		&&CASE_EEOP_INNER_FETCHSOME,
360 		&&CASE_EEOP_OUTER_FETCHSOME,
361 		&&CASE_EEOP_SCAN_FETCHSOME,
362 		&&CASE_EEOP_INNER_VAR,
363 		&&CASE_EEOP_OUTER_VAR,
364 		&&CASE_EEOP_SCAN_VAR,
365 		&&CASE_EEOP_INNER_SYSVAR,
366 		&&CASE_EEOP_OUTER_SYSVAR,
367 		&&CASE_EEOP_SCAN_SYSVAR,
368 		&&CASE_EEOP_WHOLEROW,
369 		&&CASE_EEOP_ASSIGN_INNER_VAR,
370 		&&CASE_EEOP_ASSIGN_OUTER_VAR,
371 		&&CASE_EEOP_ASSIGN_SCAN_VAR,
372 		&&CASE_EEOP_ASSIGN_TMP,
373 		&&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
374 		&&CASE_EEOP_CONST,
375 		&&CASE_EEOP_FUNCEXPR,
376 		&&CASE_EEOP_FUNCEXPR_STRICT,
377 		&&CASE_EEOP_FUNCEXPR_FUSAGE,
378 		&&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
379 		&&CASE_EEOP_BOOL_AND_STEP_FIRST,
380 		&&CASE_EEOP_BOOL_AND_STEP,
381 		&&CASE_EEOP_BOOL_AND_STEP_LAST,
382 		&&CASE_EEOP_BOOL_OR_STEP_FIRST,
383 		&&CASE_EEOP_BOOL_OR_STEP,
384 		&&CASE_EEOP_BOOL_OR_STEP_LAST,
385 		&&CASE_EEOP_BOOL_NOT_STEP,
386 		&&CASE_EEOP_QUAL,
387 		&&CASE_EEOP_JUMP,
388 		&&CASE_EEOP_JUMP_IF_NULL,
389 		&&CASE_EEOP_JUMP_IF_NOT_NULL,
390 		&&CASE_EEOP_JUMP_IF_NOT_TRUE,
391 		&&CASE_EEOP_NULLTEST_ISNULL,
392 		&&CASE_EEOP_NULLTEST_ISNOTNULL,
393 		&&CASE_EEOP_NULLTEST_ROWISNULL,
394 		&&CASE_EEOP_NULLTEST_ROWISNOTNULL,
395 		&&CASE_EEOP_BOOLTEST_IS_TRUE,
396 		&&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
397 		&&CASE_EEOP_BOOLTEST_IS_FALSE,
398 		&&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
399 		&&CASE_EEOP_PARAM_EXEC,
400 		&&CASE_EEOP_PARAM_EXTERN,
401 		&&CASE_EEOP_PARAM_CALLBACK,
402 		&&CASE_EEOP_CASE_TESTVAL,
403 		&&CASE_EEOP_MAKE_READONLY,
404 		&&CASE_EEOP_IOCOERCE,
405 		&&CASE_EEOP_DISTINCT,
406 		&&CASE_EEOP_NOT_DISTINCT,
407 		&&CASE_EEOP_NULLIF,
408 		&&CASE_EEOP_SQLVALUEFUNCTION,
409 		&&CASE_EEOP_CURRENTOFEXPR,
410 		&&CASE_EEOP_NEXTVALUEEXPR,
411 		&&CASE_EEOP_ARRAYEXPR,
412 		&&CASE_EEOP_ARRAYCOERCE,
413 		&&CASE_EEOP_ROW,
414 		&&CASE_EEOP_ROWCOMPARE_STEP,
415 		&&CASE_EEOP_ROWCOMPARE_FINAL,
416 		&&CASE_EEOP_MINMAX,
417 		&&CASE_EEOP_FIELDSELECT,
418 		&&CASE_EEOP_FIELDSTORE_DEFORM,
419 		&&CASE_EEOP_FIELDSTORE_FORM,
420 		&&CASE_EEOP_SBSREF_SUBSCRIPT,
421 		&&CASE_EEOP_SBSREF_OLD,
422 		&&CASE_EEOP_SBSREF_ASSIGN,
423 		&&CASE_EEOP_SBSREF_FETCH,
424 		&&CASE_EEOP_DOMAIN_TESTVAL,
425 		&&CASE_EEOP_DOMAIN_NOTNULL,
426 		&&CASE_EEOP_DOMAIN_CHECK,
427 		&&CASE_EEOP_CONVERT_ROWTYPE,
428 		&&CASE_EEOP_SCALARARRAYOP,
429 		&&CASE_EEOP_XMLEXPR,
430 		&&CASE_EEOP_AGGREF,
431 		&&CASE_EEOP_GROUPING_FUNC,
432 		&&CASE_EEOP_WINDOW_FUNC,
433 		&&CASE_EEOP_SUBPLAN,
434 		&&CASE_EEOP_ALTERNATIVE_SUBPLAN,
435 		&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
436 		&&CASE_EEOP_AGG_DESERIALIZE,
437 		&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
438 		&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
439 		&&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
440 		&&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
441 		&&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL,
442 		&&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
443 		&&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
444 		&&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
445 		&&CASE_EEOP_AGG_PLAIN_TRANS_BYREF,
446 		&&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,
447 		&&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,
448 		&&CASE_EEOP_LAST
449 	};
450 
451 	StaticAssertStmt(EEOP_LAST + 1 == lengthof(dispatch_table),
452 					 "dispatch_table out of whack with ExprEvalOp");
453 
454 	if (unlikely(state == NULL))
455 		return PointerGetDatum(dispatch_table);
456 #else
457 	Assert(state != NULL);
458 #endif							/* EEO_USE_COMPUTED_GOTO */
459 
460 	/* setup state */
461 	op = state->steps;
462 	resultslot = state->resultslot;
463 	innerslot = econtext->ecxt_innertuple;
464 	outerslot = econtext->ecxt_outertuple;
465 	scanslot = econtext->ecxt_scantuple;
466 
467 #if defined(EEO_USE_COMPUTED_GOTO)
468 	EEO_DISPATCH();
469 #endif
470 
471 	EEO_SWITCH()
472 	{
473 		EEO_CASE(EEOP_DONE)
474 		{
475 			goto out;
476 		}
477 
478 		EEO_CASE(EEOP_INNER_FETCHSOME)
479 		{
480 			CheckOpSlotCompatibility(op, innerslot);
481 
482 			slot_getsomeattrs(innerslot, op->d.fetch.last_var);
483 
484 			EEO_NEXT();
485 		}
486 
487 		EEO_CASE(EEOP_OUTER_FETCHSOME)
488 		{
489 			CheckOpSlotCompatibility(op, outerslot);
490 
491 			slot_getsomeattrs(outerslot, op->d.fetch.last_var);
492 
493 			EEO_NEXT();
494 		}
495 
496 		EEO_CASE(EEOP_SCAN_FETCHSOME)
497 		{
498 			CheckOpSlotCompatibility(op, scanslot);
499 
500 			slot_getsomeattrs(scanslot, op->d.fetch.last_var);
501 
502 			EEO_NEXT();
503 		}
504 
505 		EEO_CASE(EEOP_INNER_VAR)
506 		{
507 			int			attnum = op->d.var.attnum;
508 
509 			/*
510 			 * Since we already extracted all referenced columns from the
511 			 * tuple with a FETCHSOME step, we can just grab the value
512 			 * directly out of the slot's decomposed-data arrays.  But let's
513 			 * have an Assert to check that that did happen.
514 			 */
515 			Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
516 			*op->resvalue = innerslot->tts_values[attnum];
517 			*op->resnull = innerslot->tts_isnull[attnum];
518 
519 			EEO_NEXT();
520 		}
521 
522 		EEO_CASE(EEOP_OUTER_VAR)
523 		{
524 			int			attnum = op->d.var.attnum;
525 
526 			/* See EEOP_INNER_VAR comments */
527 
528 			Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
529 			*op->resvalue = outerslot->tts_values[attnum];
530 			*op->resnull = outerslot->tts_isnull[attnum];
531 
532 			EEO_NEXT();
533 		}
534 
535 		EEO_CASE(EEOP_SCAN_VAR)
536 		{
537 			int			attnum = op->d.var.attnum;
538 
539 			/* See EEOP_INNER_VAR comments */
540 
541 			Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
542 			*op->resvalue = scanslot->tts_values[attnum];
543 			*op->resnull = scanslot->tts_isnull[attnum];
544 
545 			EEO_NEXT();
546 		}
547 
548 		EEO_CASE(EEOP_INNER_SYSVAR)
549 		{
550 			ExecEvalSysVar(state, op, econtext, innerslot);
551 			EEO_NEXT();
552 		}
553 
554 		EEO_CASE(EEOP_OUTER_SYSVAR)
555 		{
556 			ExecEvalSysVar(state, op, econtext, outerslot);
557 			EEO_NEXT();
558 		}
559 
560 		EEO_CASE(EEOP_SCAN_SYSVAR)
561 		{
562 			ExecEvalSysVar(state, op, econtext, scanslot);
563 			EEO_NEXT();
564 		}
565 
566 		EEO_CASE(EEOP_WHOLEROW)
567 		{
568 			/* too complex for an inline implementation */
569 			ExecEvalWholeRowVar(state, op, econtext);
570 
571 			EEO_NEXT();
572 		}
573 
574 		EEO_CASE(EEOP_ASSIGN_INNER_VAR)
575 		{
576 			int			resultnum = op->d.assign_var.resultnum;
577 			int			attnum = op->d.assign_var.attnum;
578 
579 			/*
580 			 * We do not need CheckVarSlotCompatibility here; that was taken
581 			 * care of at compilation time.  But see EEOP_INNER_VAR comments.
582 			 */
583 			Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
584 			Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
585 			resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
586 			resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
587 
588 			EEO_NEXT();
589 		}
590 
591 		EEO_CASE(EEOP_ASSIGN_OUTER_VAR)
592 		{
593 			int			resultnum = op->d.assign_var.resultnum;
594 			int			attnum = op->d.assign_var.attnum;
595 
596 			/*
597 			 * We do not need CheckVarSlotCompatibility here; that was taken
598 			 * care of at compilation time.  But see EEOP_INNER_VAR comments.
599 			 */
600 			Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
601 			Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
602 			resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
603 			resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
604 
605 			EEO_NEXT();
606 		}
607 
608 		EEO_CASE(EEOP_ASSIGN_SCAN_VAR)
609 		{
610 			int			resultnum = op->d.assign_var.resultnum;
611 			int			attnum = op->d.assign_var.attnum;
612 
613 			/*
614 			 * We do not need CheckVarSlotCompatibility here; that was taken
615 			 * care of at compilation time.  But see EEOP_INNER_VAR comments.
616 			 */
617 			Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
618 			Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
619 			resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
620 			resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
621 
622 			EEO_NEXT();
623 		}
624 
625 		EEO_CASE(EEOP_ASSIGN_TMP)
626 		{
627 			int			resultnum = op->d.assign_tmp.resultnum;
628 
629 			Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
630 			resultslot->tts_values[resultnum] = state->resvalue;
631 			resultslot->tts_isnull[resultnum] = state->resnull;
632 
633 			EEO_NEXT();
634 		}
635 
636 		EEO_CASE(EEOP_ASSIGN_TMP_MAKE_RO)
637 		{
638 			int			resultnum = op->d.assign_tmp.resultnum;
639 
640 			Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
641 			resultslot->tts_isnull[resultnum] = state->resnull;
642 			if (!resultslot->tts_isnull[resultnum])
643 				resultslot->tts_values[resultnum] =
644 					MakeExpandedObjectReadOnlyInternal(state->resvalue);
645 			else
646 				resultslot->tts_values[resultnum] = state->resvalue;
647 
648 			EEO_NEXT();
649 		}
650 
651 		EEO_CASE(EEOP_CONST)
652 		{
653 			*op->resnull = op->d.constval.isnull;
654 			*op->resvalue = op->d.constval.value;
655 
656 			EEO_NEXT();
657 		}
658 
659 		/*
660 		 * Function-call implementations. Arguments have previously been
661 		 * evaluated directly into fcinfo->args.
662 		 *
663 		 * As both STRICT checks and function-usage are noticeable performance
664 		 * wise, and function calls are a very hot-path (they also back
665 		 * operators!), it's worth having so many separate opcodes.
666 		 *
667 		 * Note: the reason for using a temporary variable "d", here and in
668 		 * other places, is that some compilers think "*op->resvalue = f();"
669 		 * requires them to evaluate op->resvalue into a register before
670 		 * calling f(), just in case f() is able to modify op->resvalue
671 		 * somehow.  The extra line of code can save a useless register spill
672 		 * and reload across the function call.
673 		 */
674 		EEO_CASE(EEOP_FUNCEXPR)
675 		{
676 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
677 			Datum		d;
678 
679 			fcinfo->isnull = false;
680 			d = op->d.func.fn_addr(fcinfo);
681 			*op->resvalue = d;
682 			*op->resnull = fcinfo->isnull;
683 
684 			EEO_NEXT();
685 		}
686 
687 		EEO_CASE(EEOP_FUNCEXPR_STRICT)
688 		{
689 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
690 			NullableDatum *args = fcinfo->args;
691 			int			nargs = op->d.func.nargs;
692 			Datum		d;
693 
694 			/* strict function, so check for NULL args */
695 			for (int argno = 0; argno < nargs; argno++)
696 			{
697 				if (args[argno].isnull)
698 				{
699 					*op->resnull = true;
700 					goto strictfail;
701 				}
702 			}
703 			fcinfo->isnull = false;
704 			d = op->d.func.fn_addr(fcinfo);
705 			*op->resvalue = d;
706 			*op->resnull = fcinfo->isnull;
707 
708 	strictfail:
709 			EEO_NEXT();
710 		}
711 
712 		EEO_CASE(EEOP_FUNCEXPR_FUSAGE)
713 		{
714 			/* not common enough to inline */
715 			ExecEvalFuncExprFusage(state, op, econtext);
716 
717 			EEO_NEXT();
718 		}
719 
720 		EEO_CASE(EEOP_FUNCEXPR_STRICT_FUSAGE)
721 		{
722 			/* not common enough to inline */
723 			ExecEvalFuncExprStrictFusage(state, op, econtext);
724 
725 			EEO_NEXT();
726 		}
727 
728 		/*
729 		 * If any of its clauses is FALSE, an AND's result is FALSE regardless
730 		 * of the states of the rest of the clauses, so we can stop evaluating
731 		 * and return FALSE immediately.  If none are FALSE and one or more is
732 		 * NULL, we return NULL; otherwise we return TRUE.  This makes sense
733 		 * when you interpret NULL as "don't know": perhaps one of the "don't
734 		 * knows" would have been FALSE if we'd known its value.  Only when
735 		 * all the inputs are known to be TRUE can we state confidently that
736 		 * the AND's result is TRUE.
737 		 */
738 		EEO_CASE(EEOP_BOOL_AND_STEP_FIRST)
739 		{
740 			*op->d.boolexpr.anynull = false;
741 
742 			/*
743 			 * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
744 			 * same as EEOP_BOOL_AND_STEP - so fall through to that.
745 			 */
746 
747 			/* FALL THROUGH */
748 		}
749 
750 		EEO_CASE(EEOP_BOOL_AND_STEP)
751 		{
752 			if (*op->resnull)
753 			{
754 				*op->d.boolexpr.anynull = true;
755 			}
756 			else if (!DatumGetBool(*op->resvalue))
757 			{
758 				/* result is already set to FALSE, need not change it */
759 				/* bail out early */
760 				EEO_JUMP(op->d.boolexpr.jumpdone);
761 			}
762 
763 			EEO_NEXT();
764 		}
765 
766 		EEO_CASE(EEOP_BOOL_AND_STEP_LAST)
767 		{
768 			if (*op->resnull)
769 			{
770 				/* result is already set to NULL, need not change it */
771 			}
772 			else if (!DatumGetBool(*op->resvalue))
773 			{
774 				/* result is already set to FALSE, need not change it */
775 
776 				/*
777 				 * No point jumping early to jumpdone - would be same target
778 				 * (as this is the last argument to the AND expression),
779 				 * except more expensive.
780 				 */
781 			}
782 			else if (*op->d.boolexpr.anynull)
783 			{
784 				*op->resvalue = (Datum) 0;
785 				*op->resnull = true;
786 			}
787 			else
788 			{
789 				/* result is already set to TRUE, need not change it */
790 			}
791 
792 			EEO_NEXT();
793 		}
794 
795 		/*
796 		 * If any of its clauses is TRUE, an OR's result is TRUE regardless of
797 		 * the states of the rest of the clauses, so we can stop evaluating
798 		 * and return TRUE immediately.  If none are TRUE and one or more is
799 		 * NULL, we return NULL; otherwise we return FALSE.  This makes sense
800 		 * when you interpret NULL as "don't know": perhaps one of the "don't
801 		 * knows" would have been TRUE if we'd known its value.  Only when all
802 		 * the inputs are known to be FALSE can we state confidently that the
803 		 * OR's result is FALSE.
804 		 */
805 		EEO_CASE(EEOP_BOOL_OR_STEP_FIRST)
806 		{
807 			*op->d.boolexpr.anynull = false;
808 
809 			/*
810 			 * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
811 			 * as EEOP_BOOL_OR_STEP - so fall through to that.
812 			 */
813 
814 			/* FALL THROUGH */
815 		}
816 
817 		EEO_CASE(EEOP_BOOL_OR_STEP)
818 		{
819 			if (*op->resnull)
820 			{
821 				*op->d.boolexpr.anynull = true;
822 			}
823 			else if (DatumGetBool(*op->resvalue))
824 			{
825 				/* result is already set to TRUE, need not change it */
826 				/* bail out early */
827 				EEO_JUMP(op->d.boolexpr.jumpdone);
828 			}
829 
830 			EEO_NEXT();
831 		}
832 
833 		EEO_CASE(EEOP_BOOL_OR_STEP_LAST)
834 		{
835 			if (*op->resnull)
836 			{
837 				/* result is already set to NULL, need not change it */
838 			}
839 			else if (DatumGetBool(*op->resvalue))
840 			{
841 				/* result is already set to TRUE, need not change it */
842 
843 				/*
844 				 * No point jumping to jumpdone - would be same target (as
845 				 * this is the last argument to the AND expression), except
846 				 * more expensive.
847 				 */
848 			}
849 			else if (*op->d.boolexpr.anynull)
850 			{
851 				*op->resvalue = (Datum) 0;
852 				*op->resnull = true;
853 			}
854 			else
855 			{
856 				/* result is already set to FALSE, need not change it */
857 			}
858 
859 			EEO_NEXT();
860 		}
861 
862 		EEO_CASE(EEOP_BOOL_NOT_STEP)
863 		{
864 			/*
865 			 * Evaluation of 'not' is simple... if expr is false, then return
866 			 * 'true' and vice versa.  It's safe to do this even on a
867 			 * nominally null value, so we ignore resnull; that means that
868 			 * NULL in produces NULL out, which is what we want.
869 			 */
870 			*op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
871 
872 			EEO_NEXT();
873 		}
874 
875 		EEO_CASE(EEOP_QUAL)
876 		{
877 			/* simplified version of BOOL_AND_STEP for use by ExecQual() */
878 
879 			/* If argument (also result) is false or null ... */
880 			if (*op->resnull ||
881 				!DatumGetBool(*op->resvalue))
882 			{
883 				/* ... bail out early, returning FALSE */
884 				*op->resnull = false;
885 				*op->resvalue = BoolGetDatum(false);
886 				EEO_JUMP(op->d.qualexpr.jumpdone);
887 			}
888 
889 			/*
890 			 * Otherwise, leave the TRUE value in place, in case this is the
891 			 * last qual.  Then, TRUE is the correct answer.
892 			 */
893 
894 			EEO_NEXT();
895 		}
896 
897 		EEO_CASE(EEOP_JUMP)
898 		{
899 			/* Unconditionally jump to target step */
900 			EEO_JUMP(op->d.jump.jumpdone);
901 		}
902 
903 		EEO_CASE(EEOP_JUMP_IF_NULL)
904 		{
905 			/* Transfer control if current result is null */
906 			if (*op->resnull)
907 				EEO_JUMP(op->d.jump.jumpdone);
908 
909 			EEO_NEXT();
910 		}
911 
912 		EEO_CASE(EEOP_JUMP_IF_NOT_NULL)
913 		{
914 			/* Transfer control if current result is non-null */
915 			if (!*op->resnull)
916 				EEO_JUMP(op->d.jump.jumpdone);
917 
918 			EEO_NEXT();
919 		}
920 
921 		EEO_CASE(EEOP_JUMP_IF_NOT_TRUE)
922 		{
923 			/* Transfer control if current result is null or false */
924 			if (*op->resnull || !DatumGetBool(*op->resvalue))
925 				EEO_JUMP(op->d.jump.jumpdone);
926 
927 			EEO_NEXT();
928 		}
929 
930 		EEO_CASE(EEOP_NULLTEST_ISNULL)
931 		{
932 			*op->resvalue = BoolGetDatum(*op->resnull);
933 			*op->resnull = false;
934 
935 			EEO_NEXT();
936 		}
937 
938 		EEO_CASE(EEOP_NULLTEST_ISNOTNULL)
939 		{
940 			*op->resvalue = BoolGetDatum(!*op->resnull);
941 			*op->resnull = false;
942 
943 			EEO_NEXT();
944 		}
945 
946 		EEO_CASE(EEOP_NULLTEST_ROWISNULL)
947 		{
948 			/* out of line implementation: too large */
949 			ExecEvalRowNull(state, op, econtext);
950 
951 			EEO_NEXT();
952 		}
953 
954 		EEO_CASE(EEOP_NULLTEST_ROWISNOTNULL)
955 		{
956 			/* out of line implementation: too large */
957 			ExecEvalRowNotNull(state, op, econtext);
958 
959 			EEO_NEXT();
960 		}
961 
962 		/* BooleanTest implementations for all booltesttypes */
963 
964 		EEO_CASE(EEOP_BOOLTEST_IS_TRUE)
965 		{
966 			if (*op->resnull)
967 			{
968 				*op->resvalue = BoolGetDatum(false);
969 				*op->resnull = false;
970 			}
971 			/* else, input value is the correct output as well */
972 
973 			EEO_NEXT();
974 		}
975 
976 		EEO_CASE(EEOP_BOOLTEST_IS_NOT_TRUE)
977 		{
978 			if (*op->resnull)
979 			{
980 				*op->resvalue = BoolGetDatum(true);
981 				*op->resnull = false;
982 			}
983 			else
984 				*op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
985 
986 			EEO_NEXT();
987 		}
988 
989 		EEO_CASE(EEOP_BOOLTEST_IS_FALSE)
990 		{
991 			if (*op->resnull)
992 			{
993 				*op->resvalue = BoolGetDatum(false);
994 				*op->resnull = false;
995 			}
996 			else
997 				*op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
998 
999 			EEO_NEXT();
1000 		}
1001 
1002 		EEO_CASE(EEOP_BOOLTEST_IS_NOT_FALSE)
1003 		{
1004 			if (*op->resnull)
1005 			{
1006 				*op->resvalue = BoolGetDatum(true);
1007 				*op->resnull = false;
1008 			}
1009 			/* else, input value is the correct output as well */
1010 
1011 			EEO_NEXT();
1012 		}
1013 
1014 		EEO_CASE(EEOP_PARAM_EXEC)
1015 		{
1016 			/* out of line implementation: too large */
1017 			ExecEvalParamExec(state, op, econtext);
1018 
1019 			EEO_NEXT();
1020 		}
1021 
1022 		EEO_CASE(EEOP_PARAM_EXTERN)
1023 		{
1024 			/* out of line implementation: too large */
1025 			ExecEvalParamExtern(state, op, econtext);
1026 			EEO_NEXT();
1027 		}
1028 
1029 		EEO_CASE(EEOP_PARAM_CALLBACK)
1030 		{
1031 			/* allow an extension module to supply a PARAM_EXTERN value */
1032 			op->d.cparam.paramfunc(state, op, econtext);
1033 			EEO_NEXT();
1034 		}
1035 
1036 		EEO_CASE(EEOP_CASE_TESTVAL)
1037 		{
1038 			/*
1039 			 * Normally upper parts of the expression tree have setup the
1040 			 * values to be returned here, but some parts of the system
1041 			 * currently misuse {caseValue,domainValue}_{datum,isNull} to set
1042 			 * run-time data.  So if no values have been set-up, use
1043 			 * ExprContext's.  This isn't pretty, but also not *that* ugly,
1044 			 * and this is unlikely to be performance sensitive enough to
1045 			 * worry about an extra branch.
1046 			 */
1047 			if (op->d.casetest.value)
1048 			{
1049 				*op->resvalue = *op->d.casetest.value;
1050 				*op->resnull = *op->d.casetest.isnull;
1051 			}
1052 			else
1053 			{
1054 				*op->resvalue = econtext->caseValue_datum;
1055 				*op->resnull = econtext->caseValue_isNull;
1056 			}
1057 
1058 			EEO_NEXT();
1059 		}
1060 
1061 		EEO_CASE(EEOP_DOMAIN_TESTVAL)
1062 		{
1063 			/*
1064 			 * See EEOP_CASE_TESTVAL comment.
1065 			 */
1066 			if (op->d.casetest.value)
1067 			{
1068 				*op->resvalue = *op->d.casetest.value;
1069 				*op->resnull = *op->d.casetest.isnull;
1070 			}
1071 			else
1072 			{
1073 				*op->resvalue = econtext->domainValue_datum;
1074 				*op->resnull = econtext->domainValue_isNull;
1075 			}
1076 
1077 			EEO_NEXT();
1078 		}
1079 
1080 		EEO_CASE(EEOP_MAKE_READONLY)
1081 		{
1082 			/*
1083 			 * Force a varlena value that might be read multiple times to R/O
1084 			 */
1085 			if (!*op->d.make_readonly.isnull)
1086 				*op->resvalue =
1087 					MakeExpandedObjectReadOnlyInternal(*op->d.make_readonly.value);
1088 			*op->resnull = *op->d.make_readonly.isnull;
1089 
1090 			EEO_NEXT();
1091 		}
1092 
1093 		EEO_CASE(EEOP_IOCOERCE)
1094 		{
1095 			/*
1096 			 * Evaluate a CoerceViaIO node.  This can be quite a hot path, so
1097 			 * inline as much work as possible.  The source value is in our
1098 			 * result variable.
1099 			 */
1100 			char	   *str;
1101 
1102 			/* call output function (similar to OutputFunctionCall) */
1103 			if (*op->resnull)
1104 			{
1105 				/* output functions are not called on nulls */
1106 				str = NULL;
1107 			}
1108 			else
1109 			{
1110 				FunctionCallInfo fcinfo_out;
1111 
1112 				fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1113 				fcinfo_out->args[0].value = *op->resvalue;
1114 				fcinfo_out->args[0].isnull = false;
1115 
1116 				fcinfo_out->isnull = false;
1117 				str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
1118 
1119 				/* OutputFunctionCall assumes result isn't null */
1120 				Assert(!fcinfo_out->isnull);
1121 			}
1122 
1123 			/* call input function (similar to InputFunctionCall) */
1124 			if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
1125 			{
1126 				FunctionCallInfo fcinfo_in;
1127 				Datum		d;
1128 
1129 				fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1130 				fcinfo_in->args[0].value = PointerGetDatum(str);
1131 				fcinfo_in->args[0].isnull = *op->resnull;
1132 				/* second and third arguments are already set up */
1133 
1134 				fcinfo_in->isnull = false;
1135 				d = FunctionCallInvoke(fcinfo_in);
1136 				*op->resvalue = d;
1137 
1138 				/* Should get null result if and only if str is NULL */
1139 				if (str == NULL)
1140 				{
1141 					Assert(*op->resnull);
1142 					Assert(fcinfo_in->isnull);
1143 				}
1144 				else
1145 				{
1146 					Assert(!*op->resnull);
1147 					Assert(!fcinfo_in->isnull);
1148 				}
1149 			}
1150 
1151 			EEO_NEXT();
1152 		}
1153 
1154 		EEO_CASE(EEOP_DISTINCT)
1155 		{
1156 			/*
1157 			 * IS DISTINCT FROM must evaluate arguments (already done into
1158 			 * fcinfo->args) to determine whether they are NULL; if either is
1159 			 * NULL then the result is determined.  If neither is NULL, then
1160 			 * proceed to evaluate the comparison function, which is just the
1161 			 * type's standard equality operator.  We need not care whether
1162 			 * that function is strict.  Because the handling of nulls is
1163 			 * different, we can't just reuse EEOP_FUNCEXPR.
1164 			 */
1165 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1166 
1167 			/* check function arguments for NULLness */
1168 			if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
1169 			{
1170 				/* Both NULL? Then is not distinct... */
1171 				*op->resvalue = BoolGetDatum(false);
1172 				*op->resnull = false;
1173 			}
1174 			else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
1175 			{
1176 				/* Only one is NULL? Then is distinct... */
1177 				*op->resvalue = BoolGetDatum(true);
1178 				*op->resnull = false;
1179 			}
1180 			else
1181 			{
1182 				/* Neither null, so apply the equality function */
1183 				Datum		eqresult;
1184 
1185 				fcinfo->isnull = false;
1186 				eqresult = op->d.func.fn_addr(fcinfo);
1187 				/* Must invert result of "="; safe to do even if null */
1188 				*op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
1189 				*op->resnull = fcinfo->isnull;
1190 			}
1191 
1192 			EEO_NEXT();
1193 		}
1194 
1195 		/* see EEOP_DISTINCT for comments, this is just inverted */
1196 		EEO_CASE(EEOP_NOT_DISTINCT)
1197 		{
1198 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1199 
1200 			if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
1201 			{
1202 				*op->resvalue = BoolGetDatum(true);
1203 				*op->resnull = false;
1204 			}
1205 			else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
1206 			{
1207 				*op->resvalue = BoolGetDatum(false);
1208 				*op->resnull = false;
1209 			}
1210 			else
1211 			{
1212 				Datum		eqresult;
1213 
1214 				fcinfo->isnull = false;
1215 				eqresult = op->d.func.fn_addr(fcinfo);
1216 				*op->resvalue = eqresult;
1217 				*op->resnull = fcinfo->isnull;
1218 			}
1219 
1220 			EEO_NEXT();
1221 		}
1222 
1223 		EEO_CASE(EEOP_NULLIF)
1224 		{
1225 			/*
1226 			 * The arguments are already evaluated into fcinfo->args.
1227 			 */
1228 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1229 
1230 			/* if either argument is NULL they can't be equal */
1231 			if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
1232 			{
1233 				Datum		result;
1234 
1235 				fcinfo->isnull = false;
1236 				result = op->d.func.fn_addr(fcinfo);
1237 
1238 				/* if the arguments are equal return null */
1239 				if (!fcinfo->isnull && DatumGetBool(result))
1240 				{
1241 					*op->resvalue = (Datum) 0;
1242 					*op->resnull = true;
1243 
1244 					EEO_NEXT();
1245 				}
1246 			}
1247 
1248 			/* Arguments aren't equal, so return the first one */
1249 			*op->resvalue = fcinfo->args[0].value;
1250 			*op->resnull = fcinfo->args[0].isnull;
1251 
1252 			EEO_NEXT();
1253 		}
1254 
1255 		EEO_CASE(EEOP_SQLVALUEFUNCTION)
1256 		{
1257 			/*
1258 			 * Doesn't seem worthwhile to have an inline implementation
1259 			 * efficiency-wise.
1260 			 */
1261 			ExecEvalSQLValueFunction(state, op);
1262 
1263 			EEO_NEXT();
1264 		}
1265 
1266 		EEO_CASE(EEOP_CURRENTOFEXPR)
1267 		{
1268 			/* error invocation uses space, and shouldn't ever occur */
1269 			ExecEvalCurrentOfExpr(state, op);
1270 
1271 			EEO_NEXT();
1272 		}
1273 
1274 		EEO_CASE(EEOP_NEXTVALUEEXPR)
1275 		{
1276 			/*
1277 			 * Doesn't seem worthwhile to have an inline implementation
1278 			 * efficiency-wise.
1279 			 */
1280 			ExecEvalNextValueExpr(state, op);
1281 
1282 			EEO_NEXT();
1283 		}
1284 
1285 		EEO_CASE(EEOP_ARRAYEXPR)
1286 		{
1287 			/* too complex for an inline implementation */
1288 			ExecEvalArrayExpr(state, op);
1289 
1290 			EEO_NEXT();
1291 		}
1292 
1293 		EEO_CASE(EEOP_ARRAYCOERCE)
1294 		{
1295 			/* too complex for an inline implementation */
1296 			ExecEvalArrayCoerce(state, op, econtext);
1297 
1298 			EEO_NEXT();
1299 		}
1300 
1301 		EEO_CASE(EEOP_ROW)
1302 		{
1303 			/* too complex for an inline implementation */
1304 			ExecEvalRow(state, op);
1305 
1306 			EEO_NEXT();
1307 		}
1308 
1309 		EEO_CASE(EEOP_ROWCOMPARE_STEP)
1310 		{
1311 			FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1312 			Datum		d;
1313 
1314 			/* force NULL result if strict fn and NULL input */
1315 			if (op->d.rowcompare_step.finfo->fn_strict &&
1316 				(fcinfo->args[0].isnull || fcinfo->args[1].isnull))
1317 			{
1318 				*op->resnull = true;
1319 				EEO_JUMP(op->d.rowcompare_step.jumpnull);
1320 			}
1321 
1322 			/* Apply comparison function */
1323 			fcinfo->isnull = false;
1324 			d = op->d.rowcompare_step.fn_addr(fcinfo);
1325 			*op->resvalue = d;
1326 
1327 			/* force NULL result if NULL function result */
1328 			if (fcinfo->isnull)
1329 			{
1330 				*op->resnull = true;
1331 				EEO_JUMP(op->d.rowcompare_step.jumpnull);
1332 			}
1333 			*op->resnull = false;
1334 
1335 			/* If unequal, no need to compare remaining columns */
1336 			if (DatumGetInt32(*op->resvalue) != 0)
1337 			{
1338 				EEO_JUMP(op->d.rowcompare_step.jumpdone);
1339 			}
1340 
1341 			EEO_NEXT();
1342 		}
1343 
1344 		EEO_CASE(EEOP_ROWCOMPARE_FINAL)
1345 		{
1346 			int32		cmpresult = DatumGetInt32(*op->resvalue);
1347 			RowCompareType rctype = op->d.rowcompare_final.rctype;
1348 
1349 			*op->resnull = false;
1350 			switch (rctype)
1351 			{
1352 					/* EQ and NE cases aren't allowed here */
1353 				case ROWCOMPARE_LT:
1354 					*op->resvalue = BoolGetDatum(cmpresult < 0);
1355 					break;
1356 				case ROWCOMPARE_LE:
1357 					*op->resvalue = BoolGetDatum(cmpresult <= 0);
1358 					break;
1359 				case ROWCOMPARE_GE:
1360 					*op->resvalue = BoolGetDatum(cmpresult >= 0);
1361 					break;
1362 				case ROWCOMPARE_GT:
1363 					*op->resvalue = BoolGetDatum(cmpresult > 0);
1364 					break;
1365 				default:
1366 					Assert(false);
1367 					break;
1368 			}
1369 
1370 			EEO_NEXT();
1371 		}
1372 
1373 		EEO_CASE(EEOP_MINMAX)
1374 		{
1375 			/* too complex for an inline implementation */
1376 			ExecEvalMinMax(state, op);
1377 
1378 			EEO_NEXT();
1379 		}
1380 
1381 		EEO_CASE(EEOP_FIELDSELECT)
1382 		{
1383 			/* too complex for an inline implementation */
1384 			ExecEvalFieldSelect(state, op, econtext);
1385 
1386 			EEO_NEXT();
1387 		}
1388 
1389 		EEO_CASE(EEOP_FIELDSTORE_DEFORM)
1390 		{
1391 			/* too complex for an inline implementation */
1392 			ExecEvalFieldStoreDeForm(state, op, econtext);
1393 
1394 			EEO_NEXT();
1395 		}
1396 
1397 		EEO_CASE(EEOP_FIELDSTORE_FORM)
1398 		{
1399 			/* too complex for an inline implementation */
1400 			ExecEvalFieldStoreForm(state, op, econtext);
1401 
1402 			EEO_NEXT();
1403 		}
1404 
1405 		EEO_CASE(EEOP_SBSREF_SUBSCRIPT)
1406 		{
1407 			/* Process an array subscript */
1408 
1409 			/* too complex for an inline implementation */
1410 			if (ExecEvalSubscriptingRef(state, op))
1411 			{
1412 				EEO_NEXT();
1413 			}
1414 			else
1415 			{
1416 				/* Subscript is null, short-circuit SubscriptingRef to NULL */
1417 				EEO_JUMP(op->d.sbsref_subscript.jumpdone);
1418 			}
1419 		}
1420 
1421 		EEO_CASE(EEOP_SBSREF_OLD)
1422 		{
1423 			/*
1424 			 * Fetch the old value in an sbsref assignment, in case it's
1425 			 * referenced (via a CaseTestExpr) inside the assignment
1426 			 * expression.
1427 			 */
1428 
1429 			/* too complex for an inline implementation */
1430 			ExecEvalSubscriptingRefOld(state, op);
1431 
1432 			EEO_NEXT();
1433 		}
1434 
1435 		/*
1436 		 * Perform SubscriptingRef assignment
1437 		 */
1438 		EEO_CASE(EEOP_SBSREF_ASSIGN)
1439 		{
1440 			/* too complex for an inline implementation */
1441 			ExecEvalSubscriptingRefAssign(state, op);
1442 
1443 			EEO_NEXT();
1444 		}
1445 
1446 		/*
1447 		 * Fetch subset of an array.
1448 		 */
1449 		EEO_CASE(EEOP_SBSREF_FETCH)
1450 		{
1451 			/* too complex for an inline implementation */
1452 			ExecEvalSubscriptingRefFetch(state, op);
1453 
1454 			EEO_NEXT();
1455 		}
1456 
1457 		EEO_CASE(EEOP_CONVERT_ROWTYPE)
1458 		{
1459 			/* too complex for an inline implementation */
1460 			ExecEvalConvertRowtype(state, op, econtext);
1461 
1462 			EEO_NEXT();
1463 		}
1464 
1465 		EEO_CASE(EEOP_SCALARARRAYOP)
1466 		{
1467 			/* too complex for an inline implementation */
1468 			ExecEvalScalarArrayOp(state, op);
1469 
1470 			EEO_NEXT();
1471 		}
1472 
1473 		EEO_CASE(EEOP_DOMAIN_NOTNULL)
1474 		{
1475 			/* too complex for an inline implementation */
1476 			ExecEvalConstraintNotNull(state, op);
1477 
1478 			EEO_NEXT();
1479 		}
1480 
1481 		EEO_CASE(EEOP_DOMAIN_CHECK)
1482 		{
1483 			/* too complex for an inline implementation */
1484 			ExecEvalConstraintCheck(state, op);
1485 
1486 			EEO_NEXT();
1487 		}
1488 
1489 		EEO_CASE(EEOP_XMLEXPR)
1490 		{
1491 			/* too complex for an inline implementation */
1492 			ExecEvalXmlExpr(state, op);
1493 
1494 			EEO_NEXT();
1495 		}
1496 
1497 		EEO_CASE(EEOP_AGGREF)
1498 		{
1499 			/*
1500 			 * Returns a Datum whose value is the precomputed aggregate value
1501 			 * found in the given expression context.
1502 			 */
1503 			AggrefExprState *aggref = op->d.aggref.astate;
1504 
1505 			Assert(econtext->ecxt_aggvalues != NULL);
1506 
1507 			*op->resvalue = econtext->ecxt_aggvalues[aggref->aggno];
1508 			*op->resnull = econtext->ecxt_aggnulls[aggref->aggno];
1509 
1510 			EEO_NEXT();
1511 		}
1512 
1513 		EEO_CASE(EEOP_GROUPING_FUNC)
1514 		{
1515 			/* too complex/uncommon for an inline implementation */
1516 			ExecEvalGroupingFunc(state, op);
1517 
1518 			EEO_NEXT();
1519 		}
1520 
1521 		EEO_CASE(EEOP_WINDOW_FUNC)
1522 		{
1523 			/*
1524 			 * Like Aggref, just return a precomputed value from the econtext.
1525 			 */
1526 			WindowFuncExprState *wfunc = op->d.window_func.wfstate;
1527 
1528 			Assert(econtext->ecxt_aggvalues != NULL);
1529 
1530 			*op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
1531 			*op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
1532 
1533 			EEO_NEXT();
1534 		}
1535 
1536 		EEO_CASE(EEOP_SUBPLAN)
1537 		{
1538 			/* too complex for an inline implementation */
1539 			ExecEvalSubPlan(state, op, econtext);
1540 
1541 			EEO_NEXT();
1542 		}
1543 
1544 		EEO_CASE(EEOP_ALTERNATIVE_SUBPLAN)
1545 		{
1546 			/* too complex for an inline implementation */
1547 			ExecEvalAlternativeSubPlan(state, op, econtext);
1548 
1549 			EEO_NEXT();
1550 		}
1551 
1552 		/* evaluate a strict aggregate deserialization function */
1553 		EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
1554 		{
1555 			/* Don't call a strict deserialization function with NULL input */
1556 			if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
1557 				EEO_JUMP(op->d.agg_deserialize.jumpnull);
1558 
1559 			/* fallthrough */
1560 		}
1561 
1562 		/* evaluate aggregate deserialization function (non-strict portion) */
1563 		EEO_CASE(EEOP_AGG_DESERIALIZE)
1564 		{
1565 			FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
1566 			AggState   *aggstate = castNode(AggState, state->parent);
1567 			MemoryContext oldContext;
1568 
1569 			/*
1570 			 * We run the deserialization functions in per-input-tuple memory
1571 			 * context.
1572 			 */
1573 			oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
1574 			fcinfo->isnull = false;
1575 			*op->resvalue = FunctionCallInvoke(fcinfo);
1576 			*op->resnull = fcinfo->isnull;
1577 			MemoryContextSwitchTo(oldContext);
1578 
1579 			EEO_NEXT();
1580 		}
1581 
1582 		/*
1583 		 * Check that a strict aggregate transition / combination function's
1584 		 * input is not NULL.
1585 		 */
1586 
1587 		EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS)
1588 		{
1589 			NullableDatum *args = op->d.agg_strict_input_check.args;
1590 			int			nargs = op->d.agg_strict_input_check.nargs;
1591 
1592 			for (int argno = 0; argno < nargs; argno++)
1593 			{
1594 				if (args[argno].isnull)
1595 					EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
1596 			}
1597 			EEO_NEXT();
1598 		}
1599 
1600 		EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
1601 		{
1602 			bool	   *nulls = op->d.agg_strict_input_check.nulls;
1603 			int			nargs = op->d.agg_strict_input_check.nargs;
1604 
1605 			for (int argno = 0; argno < nargs; argno++)
1606 			{
1607 				if (nulls[argno])
1608 					EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
1609 			}
1610 			EEO_NEXT();
1611 		}
1612 
1613 		/*
1614 		 * Check for a NULL pointer to the per-group states.
1615 		 */
1616 
1617 		EEO_CASE(EEOP_AGG_PLAIN_PERGROUP_NULLCHECK)
1618 		{
1619 			AggState   *aggstate = castNode(AggState, state->parent);
1620 			AggStatePerGroup pergroup_allaggs =
1621 			aggstate->all_pergroups[op->d.agg_plain_pergroup_nullcheck.setoff];
1622 
1623 			if (pergroup_allaggs == NULL)
1624 				EEO_JUMP(op->d.agg_plain_pergroup_nullcheck.jumpnull);
1625 
1626 			EEO_NEXT();
1627 		}
1628 
1629 		/*
1630 		 * Different types of aggregate transition functions are implemented
1631 		 * as different types of steps, to avoid incurring unnecessary
1632 		 * overhead.  There's a step type for each valid combination of having
1633 		 * a by value / by reference transition type, [not] needing to the
1634 		 * initialize the transition value for the first row in a group from
1635 		 * input, and [not] strict transition function.
1636 		 *
1637 		 * Could optimize further by splitting off by-reference for
1638 		 * fixed-length types, but currently that doesn't seem worth it.
1639 		 */
1640 
1641 		EEO_CASE(EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL)
1642 		{
1643 			AggState   *aggstate = castNode(AggState, state->parent);
1644 			AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1645 			AggStatePerGroup pergroup =
1646 			&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1647 
1648 			Assert(pertrans->transtypeByVal);
1649 
1650 			if (pergroup->noTransValue)
1651 			{
1652 				/* If transValue has not yet been initialized, do so now. */
1653 				ExecAggInitGroup(aggstate, pertrans, pergroup,
1654 								 op->d.agg_trans.aggcontext);
1655 				/* copied trans value from input, done this round */
1656 			}
1657 			else if (likely(!pergroup->transValueIsNull))
1658 			{
1659 				/* invoke transition function, unless prevented by strictness */
1660 				ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1661 									   op->d.agg_trans.aggcontext,
1662 									   op->d.agg_trans.setno);
1663 			}
1664 
1665 			EEO_NEXT();
1666 		}
1667 
1668 		/* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1669 		EEO_CASE(EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL)
1670 		{
1671 			AggState   *aggstate = castNode(AggState, state->parent);
1672 			AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1673 			AggStatePerGroup pergroup =
1674 			&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1675 
1676 			Assert(pertrans->transtypeByVal);
1677 
1678 			if (likely(!pergroup->transValueIsNull))
1679 				ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1680 									   op->d.agg_trans.aggcontext,
1681 									   op->d.agg_trans.setno);
1682 
1683 			EEO_NEXT();
1684 		}
1685 
1686 		/* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1687 		EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYVAL)
1688 		{
1689 			AggState   *aggstate = castNode(AggState, state->parent);
1690 			AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1691 			AggStatePerGroup pergroup =
1692 			&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1693 
1694 			Assert(pertrans->transtypeByVal);
1695 
1696 			ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1697 								   op->d.agg_trans.aggcontext,
1698 								   op->d.agg_trans.setno);
1699 
1700 			EEO_NEXT();
1701 		}
1702 
1703 		/* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1704 		EEO_CASE(EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF)
1705 		{
1706 			AggState   *aggstate = castNode(AggState, state->parent);
1707 			AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1708 			AggStatePerGroup pergroup =
1709 			&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1710 
1711 			Assert(!pertrans->transtypeByVal);
1712 
1713 			if (pergroup->noTransValue)
1714 				ExecAggInitGroup(aggstate, pertrans, pergroup,
1715 								 op->d.agg_trans.aggcontext);
1716 			else if (likely(!pergroup->transValueIsNull))
1717 				ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1718 									   op->d.agg_trans.aggcontext,
1719 									   op->d.agg_trans.setno);
1720 
1721 			EEO_NEXT();
1722 		}
1723 
1724 		/* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1725 		EEO_CASE(EEOP_AGG_PLAIN_TRANS_STRICT_BYREF)
1726 		{
1727 			AggState   *aggstate = castNode(AggState, state->parent);
1728 			AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1729 			AggStatePerGroup pergroup =
1730 			&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1731 
1732 			Assert(!pertrans->transtypeByVal);
1733 
1734 			if (likely(!pergroup->transValueIsNull))
1735 				ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1736 									   op->d.agg_trans.aggcontext,
1737 									   op->d.agg_trans.setno);
1738 			EEO_NEXT();
1739 		}
1740 
1741 		/* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1742 		EEO_CASE(EEOP_AGG_PLAIN_TRANS_BYREF)
1743 		{
1744 			AggState   *aggstate = castNode(AggState, state->parent);
1745 			AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1746 			AggStatePerGroup pergroup =
1747 			&aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1748 
1749 			Assert(!pertrans->transtypeByVal);
1750 
1751 			ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1752 								   op->d.agg_trans.aggcontext,
1753 								   op->d.agg_trans.setno);
1754 
1755 			EEO_NEXT();
1756 		}
1757 
1758 		/* process single-column ordered aggregate datum */
1759 		EEO_CASE(EEOP_AGG_ORDERED_TRANS_DATUM)
1760 		{
1761 			/* too complex for an inline implementation */
1762 			ExecEvalAggOrderedTransDatum(state, op, econtext);
1763 
1764 			EEO_NEXT();
1765 		}
1766 
1767 		/* process multi-column ordered aggregate tuple */
1768 		EEO_CASE(EEOP_AGG_ORDERED_TRANS_TUPLE)
1769 		{
1770 			/* too complex for an inline implementation */
1771 			ExecEvalAggOrderedTransTuple(state, op, econtext);
1772 
1773 			EEO_NEXT();
1774 		}
1775 
1776 		EEO_CASE(EEOP_LAST)
1777 		{
1778 			/* unreachable */
1779 			Assert(false);
1780 			goto out;
1781 		}
1782 	}
1783 
1784 out:
1785 	*isnull = state->resnull;
1786 	return state->resvalue;
1787 }
1788 
1789 /*
1790  * Expression evaluation callback that performs extra checks before executing
1791  * the expression. Declared extern so other methods of execution can use it
1792  * too.
1793  */
1794 Datum
ExecInterpExprStillValid(ExprState * state,ExprContext * econtext,bool * isNull)1795 ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull)
1796 {
1797 	/*
1798 	 * First time through, check whether attribute matches Var.  Might not be
1799 	 * ok anymore, due to schema changes.
1800 	 */
1801 	CheckExprStillValid(state, econtext);
1802 
1803 	/* skip the check during further executions */
1804 	state->evalfunc = (ExprStateEvalFunc) state->evalfunc_private;
1805 
1806 	/* and actually execute */
1807 	return state->evalfunc(state, econtext, isNull);
1808 }
1809 
1810 /*
1811  * Check that an expression is still valid in the face of potential schema
1812  * changes since the plan has been created.
1813  */
1814 void
CheckExprStillValid(ExprState * state,ExprContext * econtext)1815 CheckExprStillValid(ExprState *state, ExprContext *econtext)
1816 {
1817 	TupleTableSlot *innerslot;
1818 	TupleTableSlot *outerslot;
1819 	TupleTableSlot *scanslot;
1820 
1821 	innerslot = econtext->ecxt_innertuple;
1822 	outerslot = econtext->ecxt_outertuple;
1823 	scanslot = econtext->ecxt_scantuple;
1824 
1825 	for (int i = 0; i < state->steps_len; i++)
1826 	{
1827 		ExprEvalStep *op = &state->steps[i];
1828 
1829 		switch (ExecEvalStepOp(state, op))
1830 		{
1831 			case EEOP_INNER_VAR:
1832 				{
1833 					int			attnum = op->d.var.attnum;
1834 
1835 					CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
1836 					break;
1837 				}
1838 
1839 			case EEOP_OUTER_VAR:
1840 				{
1841 					int			attnum = op->d.var.attnum;
1842 
1843 					CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
1844 					break;
1845 				}
1846 
1847 			case EEOP_SCAN_VAR:
1848 				{
1849 					int			attnum = op->d.var.attnum;
1850 
1851 					CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
1852 					break;
1853 				}
1854 			default:
1855 				break;
1856 		}
1857 	}
1858 }
1859 
1860 /*
1861  * Check whether a user attribute in a slot can be referenced by a Var
1862  * expression.  This should succeed unless there have been schema changes
1863  * since the expression tree has been created.
1864  */
1865 static void
CheckVarSlotCompatibility(TupleTableSlot * slot,int attnum,Oid vartype)1866 CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
1867 {
1868 	/*
1869 	 * What we have to check for here is the possibility of an attribute
1870 	 * having been dropped or changed in type since the plan tree was created.
1871 	 * Ideally the plan will get invalidated and not re-used, but just in
1872 	 * case, we keep these defenses.  Fortunately it's sufficient to check
1873 	 * once on the first time through.
1874 	 *
1875 	 * Note: ideally we'd check typmod as well as typid, but that seems
1876 	 * impractical at the moment: in many cases the tupdesc will have been
1877 	 * generated by ExecTypeFromTL(), and that can't guarantee to generate an
1878 	 * accurate typmod in all cases, because some expression node types don't
1879 	 * carry typmod.  Fortunately, for precisely that reason, there should be
1880 	 * no places with a critical dependency on the typmod of a value.
1881 	 *
1882 	 * System attributes don't require checking since their types never
1883 	 * change.
1884 	 */
1885 	if (attnum > 0)
1886 	{
1887 		TupleDesc	slot_tupdesc = slot->tts_tupleDescriptor;
1888 		Form_pg_attribute attr;
1889 
1890 		if (attnum > slot_tupdesc->natts)	/* should never happen */
1891 			elog(ERROR, "attribute number %d exceeds number of columns %d",
1892 				 attnum, slot_tupdesc->natts);
1893 
1894 		attr = TupleDescAttr(slot_tupdesc, attnum - 1);
1895 
1896 		if (attr->attisdropped)
1897 			ereport(ERROR,
1898 					(errcode(ERRCODE_UNDEFINED_COLUMN),
1899 					 errmsg("attribute %d of type %s has been dropped",
1900 							attnum, format_type_be(slot_tupdesc->tdtypeid))));
1901 
1902 		if (vartype != attr->atttypid)
1903 			ereport(ERROR,
1904 					(errcode(ERRCODE_DATATYPE_MISMATCH),
1905 					 errmsg("attribute %d of type %s has wrong type",
1906 							attnum, format_type_be(slot_tupdesc->tdtypeid)),
1907 					 errdetail("Table has type %s, but query expects %s.",
1908 							   format_type_be(attr->atttypid),
1909 							   format_type_be(vartype))));
1910 	}
1911 }
1912 
1913 /*
1914  * Verify that the slot is compatible with a EEOP_*_FETCHSOME operation.
1915  */
1916 static void
CheckOpSlotCompatibility(ExprEvalStep * op,TupleTableSlot * slot)1917 CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot)
1918 {
1919 #ifdef USE_ASSERT_CHECKING
1920 	/* there's nothing to check */
1921 	if (!op->d.fetch.fixed)
1922 		return;
1923 
1924 	/*
1925 	 * Should probably fixed at some point, but for now it's easier to allow
1926 	 * buffer and heap tuples to be used interchangeably.
1927 	 */
1928 	if (slot->tts_ops == &TTSOpsBufferHeapTuple &&
1929 		op->d.fetch.kind == &TTSOpsHeapTuple)
1930 		return;
1931 	if (slot->tts_ops == &TTSOpsHeapTuple &&
1932 		op->d.fetch.kind == &TTSOpsBufferHeapTuple)
1933 		return;
1934 
1935 	/*
1936 	 * At the moment we consider it OK if a virtual slot is used instead of a
1937 	 * specific type of slot, as a virtual slot never needs to be deformed.
1938 	 */
1939 	if (slot->tts_ops == &TTSOpsVirtual)
1940 		return;
1941 
1942 	Assert(op->d.fetch.kind == slot->tts_ops);
1943 #endif
1944 }
1945 
1946 /*
1947  * get_cached_rowtype: utility function to lookup a rowtype tupdesc
1948  *
1949  * type_id, typmod: identity of the rowtype
1950  * rowcache: space for caching identity info
1951  *		(rowcache->cacheptr must be initialized to NULL)
1952  * changed: if not NULL, *changed is set to true on any update
1953  *
1954  * The returned TupleDesc is not guaranteed pinned; caller must pin it
1955  * to use it across any operation that might incur cache invalidation.
1956  * (The TupleDesc is always refcounted, so just use IncrTupleDescRefCount.)
1957  *
1958  * NOTE: because composite types can change contents, we must be prepared
1959  * to re-do this during any node execution; cannot call just once during
1960  * expression initialization.
1961  */
1962 static TupleDesc
get_cached_rowtype(Oid type_id,int32 typmod,ExprEvalRowtypeCache * rowcache,bool * changed)1963 get_cached_rowtype(Oid type_id, int32 typmod,
1964 				   ExprEvalRowtypeCache *rowcache,
1965 				   bool *changed)
1966 {
1967 	if (type_id != RECORDOID)
1968 	{
1969 		/*
1970 		 * It's a named composite type, so use the regular typcache.  Do a
1971 		 * lookup first time through, or if the composite type changed.  Note:
1972 		 * "tupdesc_id == 0" may look redundant, but it protects against the
1973 		 * admittedly-theoretical possibility that type_id was RECORDOID the
1974 		 * last time through, so that the cacheptr isn't TypeCacheEntry *.
1975 		 */
1976 		TypeCacheEntry *typentry = (TypeCacheEntry *) rowcache->cacheptr;
1977 
1978 		if (unlikely(typentry == NULL ||
1979 					 rowcache->tupdesc_id == 0 ||
1980 					 typentry->tupDesc_identifier != rowcache->tupdesc_id))
1981 		{
1982 			typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1983 			if (typentry->tupDesc == NULL)
1984 				ereport(ERROR,
1985 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1986 						 errmsg("type %s is not composite",
1987 								format_type_be(type_id))));
1988 			rowcache->cacheptr = (void *) typentry;
1989 			rowcache->tupdesc_id = typentry->tupDesc_identifier;
1990 			if (changed)
1991 				*changed = true;
1992 		}
1993 		return typentry->tupDesc;
1994 	}
1995 	else
1996 	{
1997 		/*
1998 		 * A RECORD type, once registered, doesn't change for the life of the
1999 		 * backend.  So we don't need a typcache entry as such, which is good
2000 		 * because there isn't one.  It's possible that the caller is asking
2001 		 * about a different type than before, though.
2002 		 */
2003 		TupleDesc	tupDesc = (TupleDesc) rowcache->cacheptr;
2004 
2005 		if (unlikely(tupDesc == NULL ||
2006 					 rowcache->tupdesc_id != 0 ||
2007 					 type_id != tupDesc->tdtypeid ||
2008 					 typmod != tupDesc->tdtypmod))
2009 		{
2010 			tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
2011 			/* Drop pin acquired by lookup_rowtype_tupdesc */
2012 			ReleaseTupleDesc(tupDesc);
2013 			rowcache->cacheptr = (void *) tupDesc;
2014 			rowcache->tupdesc_id = 0;	/* not a valid value for non-RECORD */
2015 			if (changed)
2016 				*changed = true;
2017 		}
2018 		return tupDesc;
2019 	}
2020 }
2021 
2022 
2023 /*
2024  * Fast-path functions, for very simple expressions
2025  */
2026 
2027 /* implementation of ExecJust(Inner|Outer|Scan)Var */
2028 static pg_attribute_always_inline Datum
ExecJustVarImpl(ExprState * state,TupleTableSlot * slot,bool * isnull)2029 ExecJustVarImpl(ExprState *state, TupleTableSlot *slot, bool *isnull)
2030 {
2031 	ExprEvalStep *op = &state->steps[1];
2032 	int			attnum = op->d.var.attnum + 1;
2033 
2034 	CheckOpSlotCompatibility(&state->steps[0], slot);
2035 
2036 	/*
2037 	 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
2038 	 * step explicitly, and we also needn't Assert that the attnum is in range
2039 	 * --- slot_getattr() will take care of any problems.
2040 	 */
2041 	return slot_getattr(slot, attnum, isnull);
2042 }
2043 
2044 /* Simple reference to inner Var */
2045 static Datum
ExecJustInnerVar(ExprState * state,ExprContext * econtext,bool * isnull)2046 ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
2047 {
2048 	return ExecJustVarImpl(state, econtext->ecxt_innertuple, isnull);
2049 }
2050 
2051 /* Simple reference to outer Var */
2052 static Datum
ExecJustOuterVar(ExprState * state,ExprContext * econtext,bool * isnull)2053 ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
2054 {
2055 	return ExecJustVarImpl(state, econtext->ecxt_outertuple, isnull);
2056 }
2057 
2058 /* Simple reference to scan Var */
2059 static Datum
ExecJustScanVar(ExprState * state,ExprContext * econtext,bool * isnull)2060 ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
2061 {
2062 	return ExecJustVarImpl(state, econtext->ecxt_scantuple, isnull);
2063 }
2064 
2065 /* implementation of ExecJustAssign(Inner|Outer|Scan)Var */
2066 static pg_attribute_always_inline Datum
ExecJustAssignVarImpl(ExprState * state,TupleTableSlot * inslot,bool * isnull)2067 ExecJustAssignVarImpl(ExprState *state, TupleTableSlot *inslot, bool *isnull)
2068 {
2069 	ExprEvalStep *op = &state->steps[1];
2070 	int			attnum = op->d.assign_var.attnum + 1;
2071 	int			resultnum = op->d.assign_var.resultnum;
2072 	TupleTableSlot *outslot = state->resultslot;
2073 
2074 	CheckOpSlotCompatibility(&state->steps[0], inslot);
2075 
2076 	/*
2077 	 * We do not need CheckVarSlotCompatibility here; that was taken care of
2078 	 * at compilation time.
2079 	 *
2080 	 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
2081 	 * step explicitly, and we also needn't Assert that the attnum is in range
2082 	 * --- slot_getattr() will take care of any problems.  Nonetheless, check
2083 	 * that resultnum is in range.
2084 	 */
2085 	Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
2086 	outslot->tts_values[resultnum] =
2087 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
2088 	return 0;
2089 }
2090 
2091 /* Evaluate inner Var and assign to appropriate column of result tuple */
2092 static Datum
ExecJustAssignInnerVar(ExprState * state,ExprContext * econtext,bool * isnull)2093 ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
2094 {
2095 	return ExecJustAssignVarImpl(state, econtext->ecxt_innertuple, isnull);
2096 }
2097 
2098 /* Evaluate outer Var and assign to appropriate column of result tuple */
2099 static Datum
ExecJustAssignOuterVar(ExprState * state,ExprContext * econtext,bool * isnull)2100 ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
2101 {
2102 	return ExecJustAssignVarImpl(state, econtext->ecxt_outertuple, isnull);
2103 }
2104 
2105 /* Evaluate scan Var and assign to appropriate column of result tuple */
2106 static Datum
ExecJustAssignScanVar(ExprState * state,ExprContext * econtext,bool * isnull)2107 ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
2108 {
2109 	return ExecJustAssignVarImpl(state, econtext->ecxt_scantuple, isnull);
2110 }
2111 
2112 /* Evaluate CASE_TESTVAL and apply a strict function to it */
2113 static Datum
ExecJustApplyFuncToCase(ExprState * state,ExprContext * econtext,bool * isnull)2114 ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
2115 {
2116 	ExprEvalStep *op = &state->steps[0];
2117 	FunctionCallInfo fcinfo;
2118 	NullableDatum *args;
2119 	int			nargs;
2120 	Datum		d;
2121 
2122 	/*
2123 	 * XXX with some redesign of the CaseTestExpr mechanism, maybe we could
2124 	 * get rid of this data shuffling?
2125 	 */
2126 	*op->resvalue = *op->d.casetest.value;
2127 	*op->resnull = *op->d.casetest.isnull;
2128 
2129 	op++;
2130 
2131 	nargs = op->d.func.nargs;
2132 	fcinfo = op->d.func.fcinfo_data;
2133 	args = fcinfo->args;
2134 
2135 	/* strict function, so check for NULL args */
2136 	for (int argno = 0; argno < nargs; argno++)
2137 	{
2138 		if (args[argno].isnull)
2139 		{
2140 			*isnull = true;
2141 			return (Datum) 0;
2142 		}
2143 	}
2144 	fcinfo->isnull = false;
2145 	d = op->d.func.fn_addr(fcinfo);
2146 	*isnull = fcinfo->isnull;
2147 	return d;
2148 }
2149 
2150 /* Simple Const expression */
2151 static Datum
ExecJustConst(ExprState * state,ExprContext * econtext,bool * isnull)2152 ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull)
2153 {
2154 	ExprEvalStep *op = &state->steps[0];
2155 
2156 	*isnull = op->d.constval.isnull;
2157 	return op->d.constval.value;
2158 }
2159 
2160 /* implementation of ExecJust(Inner|Outer|Scan)VarVirt */
2161 static pg_attribute_always_inline Datum
ExecJustVarVirtImpl(ExprState * state,TupleTableSlot * slot,bool * isnull)2162 ExecJustVarVirtImpl(ExprState *state, TupleTableSlot *slot, bool *isnull)
2163 {
2164 	ExprEvalStep *op = &state->steps[0];
2165 	int			attnum = op->d.var.attnum;
2166 
2167 	/*
2168 	 * As it is guaranteed that a virtual slot is used, there never is a need
2169 	 * to perform tuple deforming (nor would it be possible). Therefore
2170 	 * execExpr.c has not emitted an EEOP_*_FETCHSOME step. Verify, as much as
2171 	 * possible, that that determination was accurate.
2172 	 */
2173 	Assert(TTS_IS_VIRTUAL(slot));
2174 	Assert(TTS_FIXED(slot));
2175 	Assert(attnum >= 0 && attnum < slot->tts_nvalid);
2176 
2177 	*isnull = slot->tts_isnull[attnum];
2178 
2179 	return slot->tts_values[attnum];
2180 }
2181 
2182 /* Like ExecJustInnerVar, optimized for virtual slots */
2183 static Datum
ExecJustInnerVarVirt(ExprState * state,ExprContext * econtext,bool * isnull)2184 ExecJustInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
2185 {
2186 	return ExecJustVarVirtImpl(state, econtext->ecxt_innertuple, isnull);
2187 }
2188 
2189 /* Like ExecJustOuterVar, optimized for virtual slots */
2190 static Datum
ExecJustOuterVarVirt(ExprState * state,ExprContext * econtext,bool * isnull)2191 ExecJustOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
2192 {
2193 	return ExecJustVarVirtImpl(state, econtext->ecxt_outertuple, isnull);
2194 }
2195 
2196 /* Like ExecJustScanVar, optimized for virtual slots */
2197 static Datum
ExecJustScanVarVirt(ExprState * state,ExprContext * econtext,bool * isnull)2198 ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
2199 {
2200 	return ExecJustVarVirtImpl(state, econtext->ecxt_scantuple, isnull);
2201 }
2202 
2203 /* implementation of ExecJustAssign(Inner|Outer|Scan)VarVirt */
2204 static pg_attribute_always_inline Datum
ExecJustAssignVarVirtImpl(ExprState * state,TupleTableSlot * inslot,bool * isnull)2205 ExecJustAssignVarVirtImpl(ExprState *state, TupleTableSlot *inslot, bool *isnull)
2206 {
2207 	ExprEvalStep *op = &state->steps[0];
2208 	int			attnum = op->d.assign_var.attnum;
2209 	int			resultnum = op->d.assign_var.resultnum;
2210 	TupleTableSlot *outslot = state->resultslot;
2211 
2212 	/* see ExecJustVarVirtImpl for comments */
2213 
2214 	Assert(TTS_IS_VIRTUAL(inslot));
2215 	Assert(TTS_FIXED(inslot));
2216 	Assert(attnum >= 0 && attnum < inslot->tts_nvalid);
2217 	Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
2218 
2219 	outslot->tts_values[resultnum] = inslot->tts_values[attnum];
2220 	outslot->tts_isnull[resultnum] = inslot->tts_isnull[attnum];
2221 
2222 	return 0;
2223 }
2224 
2225 /* Like ExecJustAssignInnerVar, optimized for virtual slots */
2226 static Datum
ExecJustAssignInnerVarVirt(ExprState * state,ExprContext * econtext,bool * isnull)2227 ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
2228 {
2229 	return ExecJustAssignVarVirtImpl(state, econtext->ecxt_innertuple, isnull);
2230 }
2231 
2232 /* Like ExecJustAssignOuterVar, optimized for virtual slots */
2233 static Datum
ExecJustAssignOuterVarVirt(ExprState * state,ExprContext * econtext,bool * isnull)2234 ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
2235 {
2236 	return ExecJustAssignVarVirtImpl(state, econtext->ecxt_outertuple, isnull);
2237 }
2238 
2239 /* Like ExecJustAssignScanVar, optimized for virtual slots */
2240 static Datum
ExecJustAssignScanVarVirt(ExprState * state,ExprContext * econtext,bool * isnull)2241 ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
2242 {
2243 	return ExecJustAssignVarVirtImpl(state, econtext->ecxt_scantuple, isnull);
2244 }
2245 
2246 #if defined(EEO_USE_COMPUTED_GOTO)
2247 /*
2248  * Comparator used when building address->opcode lookup table for
2249  * ExecEvalStepOp() in the threaded dispatch case.
2250  */
2251 static int
dispatch_compare_ptr(const void * a,const void * b)2252 dispatch_compare_ptr(const void *a, const void *b)
2253 {
2254 	const ExprEvalOpLookup *la = (const ExprEvalOpLookup *) a;
2255 	const ExprEvalOpLookup *lb = (const ExprEvalOpLookup *) b;
2256 
2257 	if (la->opcode < lb->opcode)
2258 		return -1;
2259 	else if (la->opcode > lb->opcode)
2260 		return 1;
2261 	return 0;
2262 }
2263 #endif
2264 
2265 /*
2266  * Do one-time initialization of interpretation machinery.
2267  */
2268 static void
ExecInitInterpreter(void)2269 ExecInitInterpreter(void)
2270 {
2271 #if defined(EEO_USE_COMPUTED_GOTO)
2272 	/* Set up externally-visible pointer to dispatch table */
2273 	if (dispatch_table == NULL)
2274 	{
2275 		dispatch_table = (const void **)
2276 			DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
2277 
2278 		/* build reverse lookup table */
2279 		for (int i = 0; i < EEOP_LAST; i++)
2280 		{
2281 			reverse_dispatch_table[i].opcode = dispatch_table[i];
2282 			reverse_dispatch_table[i].op = (ExprEvalOp) i;
2283 		}
2284 
2285 		/* make it bsearch()able */
2286 		qsort(reverse_dispatch_table,
2287 			  EEOP_LAST /* nmembers */ ,
2288 			  sizeof(ExprEvalOpLookup),
2289 			  dispatch_compare_ptr);
2290 	}
2291 #endif
2292 }
2293 
2294 /*
2295  * Function to return the opcode of an expression step.
2296  *
2297  * When direct-threading is in use, ExprState->opcode isn't easily
2298  * decipherable. This function returns the appropriate enum member.
2299  */
2300 ExprEvalOp
ExecEvalStepOp(ExprState * state,ExprEvalStep * op)2301 ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
2302 {
2303 #if defined(EEO_USE_COMPUTED_GOTO)
2304 	if (state->flags & EEO_FLAG_DIRECT_THREADED)
2305 	{
2306 		ExprEvalOpLookup key;
2307 		ExprEvalOpLookup *res;
2308 
2309 		key.opcode = (void *) op->opcode;
2310 		res = bsearch(&key,
2311 					  reverse_dispatch_table,
2312 					  EEOP_LAST /* nmembers */ ,
2313 					  sizeof(ExprEvalOpLookup),
2314 					  dispatch_compare_ptr);
2315 		Assert(res);			/* unknown ops shouldn't get looked up */
2316 		return res->op;
2317 	}
2318 #endif
2319 	return (ExprEvalOp) op->opcode;
2320 }
2321 
2322 
2323 /*
2324  * Out-of-line helper functions for complex instructions.
2325  */
2326 
2327 /*
2328  * Evaluate EEOP_FUNCEXPR_FUSAGE
2329  */
2330 void
ExecEvalFuncExprFusage(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2331 ExecEvalFuncExprFusage(ExprState *state, ExprEvalStep *op,
2332 					   ExprContext *econtext)
2333 {
2334 	FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2335 	PgStat_FunctionCallUsage fcusage;
2336 	Datum		d;
2337 
2338 	pgstat_init_function_usage(fcinfo, &fcusage);
2339 
2340 	fcinfo->isnull = false;
2341 	d = op->d.func.fn_addr(fcinfo);
2342 	*op->resvalue = d;
2343 	*op->resnull = fcinfo->isnull;
2344 
2345 	pgstat_end_function_usage(&fcusage, true);
2346 }
2347 
2348 /*
2349  * Evaluate EEOP_FUNCEXPR_STRICT_FUSAGE
2350  */
2351 void
ExecEvalFuncExprStrictFusage(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2352 ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
2353 							 ExprContext *econtext)
2354 {
2355 
2356 	FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2357 	PgStat_FunctionCallUsage fcusage;
2358 	NullableDatum *args = fcinfo->args;
2359 	int			nargs = op->d.func.nargs;
2360 	Datum		d;
2361 
2362 	/* strict function, so check for NULL args */
2363 	for (int argno = 0; argno < nargs; argno++)
2364 	{
2365 		if (args[argno].isnull)
2366 		{
2367 			*op->resnull = true;
2368 			return;
2369 		}
2370 	}
2371 
2372 	pgstat_init_function_usage(fcinfo, &fcusage);
2373 
2374 	fcinfo->isnull = false;
2375 	d = op->d.func.fn_addr(fcinfo);
2376 	*op->resvalue = d;
2377 	*op->resnull = fcinfo->isnull;
2378 
2379 	pgstat_end_function_usage(&fcusage, true);
2380 }
2381 
2382 /*
2383  * Evaluate a PARAM_EXEC parameter.
2384  *
2385  * PARAM_EXEC params (internal executor parameters) are stored in the
2386  * ecxt_param_exec_vals array, and can be accessed by array index.
2387  */
2388 void
ExecEvalParamExec(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2389 ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2390 {
2391 	ParamExecData *prm;
2392 
2393 	prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2394 	if (unlikely(prm->execPlan != NULL))
2395 	{
2396 		/* Parameter not evaluated yet, so go do it */
2397 		ExecSetParamPlan(prm->execPlan, econtext);
2398 		/* ExecSetParamPlan should have processed this param... */
2399 		Assert(prm->execPlan == NULL);
2400 	}
2401 	*op->resvalue = prm->value;
2402 	*op->resnull = prm->isnull;
2403 }
2404 
2405 /*
2406  * Evaluate a PARAM_EXTERN parameter.
2407  *
2408  * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
2409  */
2410 void
ExecEvalParamExtern(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2411 ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2412 {
2413 	ParamListInfo paramInfo = econtext->ecxt_param_list_info;
2414 	int			paramId = op->d.param.paramid;
2415 
2416 	if (likely(paramInfo &&
2417 			   paramId > 0 && paramId <= paramInfo->numParams))
2418 	{
2419 		ParamExternData *prm;
2420 		ParamExternData prmdata;
2421 
2422 		/* give hook a chance in case parameter is dynamic */
2423 		if (paramInfo->paramFetch != NULL)
2424 			prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
2425 		else
2426 			prm = &paramInfo->params[paramId - 1];
2427 
2428 		if (likely(OidIsValid(prm->ptype)))
2429 		{
2430 			/* safety check in case hook did something unexpected */
2431 			if (unlikely(prm->ptype != op->d.param.paramtype))
2432 				ereport(ERROR,
2433 						(errcode(ERRCODE_DATATYPE_MISMATCH),
2434 						 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
2435 								paramId,
2436 								format_type_be(prm->ptype),
2437 								format_type_be(op->d.param.paramtype))));
2438 			*op->resvalue = prm->value;
2439 			*op->resnull = prm->isnull;
2440 			return;
2441 		}
2442 	}
2443 
2444 	ereport(ERROR,
2445 			(errcode(ERRCODE_UNDEFINED_OBJECT),
2446 			 errmsg("no value found for parameter %d", paramId)));
2447 }
2448 
2449 /*
2450  * Evaluate a SQLValueFunction expression.
2451  */
2452 void
ExecEvalSQLValueFunction(ExprState * state,ExprEvalStep * op)2453 ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
2454 {
2455 	LOCAL_FCINFO(fcinfo, 0);
2456 	SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
2457 
2458 	*op->resnull = false;
2459 
2460 	/*
2461 	 * Note: current_schema() can return NULL.  current_user() etc currently
2462 	 * cannot, but might as well code those cases the same way for safety.
2463 	 */
2464 	switch (svf->op)
2465 	{
2466 		case SVFOP_CURRENT_DATE:
2467 			*op->resvalue = DateADTGetDatum(GetSQLCurrentDate());
2468 			break;
2469 		case SVFOP_CURRENT_TIME:
2470 		case SVFOP_CURRENT_TIME_N:
2471 			*op->resvalue = TimeTzADTPGetDatum(GetSQLCurrentTime(svf->typmod));
2472 			break;
2473 		case SVFOP_CURRENT_TIMESTAMP:
2474 		case SVFOP_CURRENT_TIMESTAMP_N:
2475 			*op->resvalue = TimestampTzGetDatum(GetSQLCurrentTimestamp(svf->typmod));
2476 			break;
2477 		case SVFOP_LOCALTIME:
2478 		case SVFOP_LOCALTIME_N:
2479 			*op->resvalue = TimeADTGetDatum(GetSQLLocalTime(svf->typmod));
2480 			break;
2481 		case SVFOP_LOCALTIMESTAMP:
2482 		case SVFOP_LOCALTIMESTAMP_N:
2483 			*op->resvalue = TimestampGetDatum(GetSQLLocalTimestamp(svf->typmod));
2484 			break;
2485 		case SVFOP_CURRENT_ROLE:
2486 		case SVFOP_CURRENT_USER:
2487 		case SVFOP_USER:
2488 			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2489 			*op->resvalue = current_user(fcinfo);
2490 			*op->resnull = fcinfo->isnull;
2491 			break;
2492 		case SVFOP_SESSION_USER:
2493 			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2494 			*op->resvalue = session_user(fcinfo);
2495 			*op->resnull = fcinfo->isnull;
2496 			break;
2497 		case SVFOP_CURRENT_CATALOG:
2498 			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2499 			*op->resvalue = current_database(fcinfo);
2500 			*op->resnull = fcinfo->isnull;
2501 			break;
2502 		case SVFOP_CURRENT_SCHEMA:
2503 			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2504 			*op->resvalue = current_schema(fcinfo);
2505 			*op->resnull = fcinfo->isnull;
2506 			break;
2507 	}
2508 }
2509 
2510 /*
2511  * Raise error if a CURRENT OF expression is evaluated.
2512  *
2513  * The planner should convert CURRENT OF into a TidScan qualification, or some
2514  * other special handling in a ForeignScan node.  So we have to be able to do
2515  * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
2516  * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
2517  * table whose FDW doesn't handle it, and complain accordingly.
2518  */
2519 void
ExecEvalCurrentOfExpr(ExprState * state,ExprEvalStep * op)2520 ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op)
2521 {
2522 	ereport(ERROR,
2523 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2524 			 errmsg("WHERE CURRENT OF is not supported for this table type")));
2525 }
2526 
2527 /*
2528  * Evaluate NextValueExpr.
2529  */
2530 void
ExecEvalNextValueExpr(ExprState * state,ExprEvalStep * op)2531 ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op)
2532 {
2533 	int64		newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
2534 
2535 	switch (op->d.nextvalueexpr.seqtypid)
2536 	{
2537 		case INT2OID:
2538 			*op->resvalue = Int16GetDatum((int16) newval);
2539 			break;
2540 		case INT4OID:
2541 			*op->resvalue = Int32GetDatum((int32) newval);
2542 			break;
2543 		case INT8OID:
2544 			*op->resvalue = Int64GetDatum((int64) newval);
2545 			break;
2546 		default:
2547 			elog(ERROR, "unsupported sequence type %u",
2548 				 op->d.nextvalueexpr.seqtypid);
2549 	}
2550 	*op->resnull = false;
2551 }
2552 
2553 /*
2554  * Evaluate NullTest / IS NULL for rows.
2555  */
2556 void
ExecEvalRowNull(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2557 ExecEvalRowNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2558 {
2559 	ExecEvalRowNullInt(state, op, econtext, true);
2560 }
2561 
2562 /*
2563  * Evaluate NullTest / IS NOT NULL for rows.
2564  */
2565 void
ExecEvalRowNotNull(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2566 ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2567 {
2568 	ExecEvalRowNullInt(state, op, econtext, false);
2569 }
2570 
2571 /* Common code for IS [NOT] NULL on a row value */
2572 static void
ExecEvalRowNullInt(ExprState * state,ExprEvalStep * op,ExprContext * econtext,bool checkisnull)2573 ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op,
2574 				   ExprContext *econtext, bool checkisnull)
2575 {
2576 	Datum		value = *op->resvalue;
2577 	bool		isnull = *op->resnull;
2578 	HeapTupleHeader tuple;
2579 	Oid			tupType;
2580 	int32		tupTypmod;
2581 	TupleDesc	tupDesc;
2582 	HeapTupleData tmptup;
2583 
2584 	*op->resnull = false;
2585 
2586 	/* NULL row variables are treated just as NULL scalar columns */
2587 	if (isnull)
2588 	{
2589 		*op->resvalue = BoolGetDatum(checkisnull);
2590 		return;
2591 	}
2592 
2593 	/*
2594 	 * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
2595 	 * as:
2596 	 *
2597 	 * "R IS NULL" is true if every field is the null value.
2598 	 *
2599 	 * "R IS NOT NULL" is true if no field is the null value.
2600 	 *
2601 	 * This definition is (apparently intentionally) not recursive; so our
2602 	 * tests on the fields are primitive attisnull tests, not recursive checks
2603 	 * to see if they are all-nulls or no-nulls rowtypes.
2604 	 *
2605 	 * The standard does not consider the possibility of zero-field rows, but
2606 	 * here we consider them to vacuously satisfy both predicates.
2607 	 */
2608 
2609 	tuple = DatumGetHeapTupleHeader(value);
2610 
2611 	tupType = HeapTupleHeaderGetTypeId(tuple);
2612 	tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2613 
2614 	/* Lookup tupdesc if first time through or if type changes */
2615 	tupDesc = get_cached_rowtype(tupType, tupTypmod,
2616 								 &op->d.nulltest_row.rowcache, NULL);
2617 
2618 	/*
2619 	 * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
2620 	 */
2621 	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2622 	tmptup.t_data = tuple;
2623 
2624 	for (int att = 1; att <= tupDesc->natts; att++)
2625 	{
2626 		/* ignore dropped columns */
2627 		if (TupleDescAttr(tupDesc, att - 1)->attisdropped)
2628 			continue;
2629 		if (heap_attisnull(&tmptup, att, tupDesc))
2630 		{
2631 			/* null field disproves IS NOT NULL */
2632 			if (!checkisnull)
2633 			{
2634 				*op->resvalue = BoolGetDatum(false);
2635 				return;
2636 			}
2637 		}
2638 		else
2639 		{
2640 			/* non-null field disproves IS NULL */
2641 			if (checkisnull)
2642 			{
2643 				*op->resvalue = BoolGetDatum(false);
2644 				return;
2645 			}
2646 		}
2647 	}
2648 
2649 	*op->resvalue = BoolGetDatum(true);
2650 }
2651 
2652 /*
2653  * Evaluate an ARRAY[] expression.
2654  *
2655  * The individual array elements (or subarrays) have already been evaluated
2656  * into op->d.arrayexpr.elemvalues[]/elemnulls[].
2657  */
2658 void
ExecEvalArrayExpr(ExprState * state,ExprEvalStep * op)2659 ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
2660 {
2661 	ArrayType  *result;
2662 	Oid			element_type = op->d.arrayexpr.elemtype;
2663 	int			nelems = op->d.arrayexpr.nelems;
2664 	int			ndims = 0;
2665 	int			dims[MAXDIM];
2666 	int			lbs[MAXDIM];
2667 
2668 	/* Set non-null as default */
2669 	*op->resnull = false;
2670 
2671 	if (!op->d.arrayexpr.multidims)
2672 	{
2673 		/* Elements are presumably of scalar type */
2674 		Datum	   *dvalues = op->d.arrayexpr.elemvalues;
2675 		bool	   *dnulls = op->d.arrayexpr.elemnulls;
2676 
2677 		/* setup for 1-D array of the given length */
2678 		ndims = 1;
2679 		dims[0] = nelems;
2680 		lbs[0] = 1;
2681 
2682 		result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2683 									element_type,
2684 									op->d.arrayexpr.elemlength,
2685 									op->d.arrayexpr.elembyval,
2686 									op->d.arrayexpr.elemalign);
2687 	}
2688 	else
2689 	{
2690 		/* Must be nested array expressions */
2691 		int			nbytes = 0;
2692 		int			nitems = 0;
2693 		int			outer_nelems = 0;
2694 		int			elem_ndims = 0;
2695 		int		   *elem_dims = NULL;
2696 		int		   *elem_lbs = NULL;
2697 		bool		firstone = true;
2698 		bool		havenulls = false;
2699 		bool		haveempty = false;
2700 		char	  **subdata;
2701 		bits8	  **subbitmaps;
2702 		int		   *subbytes;
2703 		int		   *subnitems;
2704 		int32		dataoffset;
2705 		char	   *dat;
2706 		int			iitem;
2707 
2708 		subdata = (char **) palloc(nelems * sizeof(char *));
2709 		subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
2710 		subbytes = (int *) palloc(nelems * sizeof(int));
2711 		subnitems = (int *) palloc(nelems * sizeof(int));
2712 
2713 		/* loop through and get data area from each element */
2714 		for (int elemoff = 0; elemoff < nelems; elemoff++)
2715 		{
2716 			Datum		arraydatum;
2717 			bool		eisnull;
2718 			ArrayType  *array;
2719 			int			this_ndims;
2720 
2721 			arraydatum = op->d.arrayexpr.elemvalues[elemoff];
2722 			eisnull = op->d.arrayexpr.elemnulls[elemoff];
2723 
2724 			/* temporarily ignore null subarrays */
2725 			if (eisnull)
2726 			{
2727 				haveempty = true;
2728 				continue;
2729 			}
2730 
2731 			array = DatumGetArrayTypeP(arraydatum);
2732 
2733 			/* run-time double-check on element type */
2734 			if (element_type != ARR_ELEMTYPE(array))
2735 				ereport(ERROR,
2736 						(errcode(ERRCODE_DATATYPE_MISMATCH),
2737 						 errmsg("cannot merge incompatible arrays"),
2738 						 errdetail("Array with element type %s cannot be "
2739 								   "included in ARRAY construct with element type %s.",
2740 								   format_type_be(ARR_ELEMTYPE(array)),
2741 								   format_type_be(element_type))));
2742 
2743 			this_ndims = ARR_NDIM(array);
2744 			/* temporarily ignore zero-dimensional subarrays */
2745 			if (this_ndims <= 0)
2746 			{
2747 				haveempty = true;
2748 				continue;
2749 			}
2750 
2751 			if (firstone)
2752 			{
2753 				/* Get sub-array details from first member */
2754 				elem_ndims = this_ndims;
2755 				ndims = elem_ndims + 1;
2756 				if (ndims <= 0 || ndims > MAXDIM)
2757 					ereport(ERROR,
2758 							(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2759 							 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2760 									ndims, MAXDIM)));
2761 
2762 				elem_dims = (int *) palloc(elem_ndims * sizeof(int));
2763 				memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
2764 				elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
2765 				memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
2766 
2767 				firstone = false;
2768 			}
2769 			else
2770 			{
2771 				/* Check other sub-arrays are compatible */
2772 				if (elem_ndims != this_ndims ||
2773 					memcmp(elem_dims, ARR_DIMS(array),
2774 						   elem_ndims * sizeof(int)) != 0 ||
2775 					memcmp(elem_lbs, ARR_LBOUND(array),
2776 						   elem_ndims * sizeof(int)) != 0)
2777 					ereport(ERROR,
2778 							(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2779 							 errmsg("multidimensional arrays must have array "
2780 									"expressions with matching dimensions")));
2781 			}
2782 
2783 			subdata[outer_nelems] = ARR_DATA_PTR(array);
2784 			subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
2785 			subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
2786 			nbytes += subbytes[outer_nelems];
2787 			subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
2788 													 ARR_DIMS(array));
2789 			nitems += subnitems[outer_nelems];
2790 			havenulls |= ARR_HASNULL(array);
2791 			outer_nelems++;
2792 		}
2793 
2794 		/*
2795 		 * If all items were null or empty arrays, return an empty array;
2796 		 * otherwise, if some were and some weren't, raise error.  (Note: we
2797 		 * must special-case this somehow to avoid trying to generate a 1-D
2798 		 * array formed from empty arrays.  It's not ideal...)
2799 		 */
2800 		if (haveempty)
2801 		{
2802 			if (ndims == 0)		/* didn't find any nonempty array */
2803 			{
2804 				*op->resvalue = PointerGetDatum(construct_empty_array(element_type));
2805 				return;
2806 			}
2807 			ereport(ERROR,
2808 					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2809 					 errmsg("multidimensional arrays must have array "
2810 							"expressions with matching dimensions")));
2811 		}
2812 
2813 		/* setup for multi-D array */
2814 		dims[0] = outer_nelems;
2815 		lbs[0] = 1;
2816 		for (int i = 1; i < ndims; i++)
2817 		{
2818 			dims[i] = elem_dims[i - 1];
2819 			lbs[i] = elem_lbs[i - 1];
2820 		}
2821 
2822 		/* check for subscript overflow */
2823 		(void) ArrayGetNItems(ndims, dims);
2824 		ArrayCheckBounds(ndims, dims, lbs);
2825 
2826 		if (havenulls)
2827 		{
2828 			dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
2829 			nbytes += dataoffset;
2830 		}
2831 		else
2832 		{
2833 			dataoffset = 0;		/* marker for no null bitmap */
2834 			nbytes += ARR_OVERHEAD_NONULLS(ndims);
2835 		}
2836 
2837 		result = (ArrayType *) palloc(nbytes);
2838 		SET_VARSIZE(result, nbytes);
2839 		result->ndim = ndims;
2840 		result->dataoffset = dataoffset;
2841 		result->elemtype = element_type;
2842 		memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
2843 		memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
2844 
2845 		dat = ARR_DATA_PTR(result);
2846 		iitem = 0;
2847 		for (int i = 0; i < outer_nelems; i++)
2848 		{
2849 			memcpy(dat, subdata[i], subbytes[i]);
2850 			dat += subbytes[i];
2851 			if (havenulls)
2852 				array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
2853 								  subbitmaps[i], 0,
2854 								  subnitems[i]);
2855 			iitem += subnitems[i];
2856 		}
2857 	}
2858 
2859 	*op->resvalue = PointerGetDatum(result);
2860 }
2861 
2862 /*
2863  * Evaluate an ArrayCoerceExpr expression.
2864  *
2865  * Source array is in step's result variable.
2866  */
2867 void
ExecEvalArrayCoerce(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2868 ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2869 {
2870 	Datum		arraydatum;
2871 
2872 	/* NULL array -> NULL result */
2873 	if (*op->resnull)
2874 		return;
2875 
2876 	arraydatum = *op->resvalue;
2877 
2878 	/*
2879 	 * If it's binary-compatible, modify the element type in the array header,
2880 	 * but otherwise leave the array as we received it.
2881 	 */
2882 	if (op->d.arraycoerce.elemexprstate == NULL)
2883 	{
2884 		/* Detoast input array if necessary, and copy in any case */
2885 		ArrayType  *array = DatumGetArrayTypePCopy(arraydatum);
2886 
2887 		ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
2888 		*op->resvalue = PointerGetDatum(array);
2889 		return;
2890 	}
2891 
2892 	/*
2893 	 * Use array_map to apply the sub-expression to each array element.
2894 	 */
2895 	*op->resvalue = array_map(arraydatum,
2896 							  op->d.arraycoerce.elemexprstate,
2897 							  econtext,
2898 							  op->d.arraycoerce.resultelemtype,
2899 							  op->d.arraycoerce.amstate);
2900 }
2901 
2902 /*
2903  * Evaluate a ROW() expression.
2904  *
2905  * The individual columns have already been evaluated into
2906  * op->d.row.elemvalues[]/elemnulls[].
2907  */
2908 void
ExecEvalRow(ExprState * state,ExprEvalStep * op)2909 ExecEvalRow(ExprState *state, ExprEvalStep *op)
2910 {
2911 	HeapTuple	tuple;
2912 
2913 	/* build tuple from evaluated field values */
2914 	tuple = heap_form_tuple(op->d.row.tupdesc,
2915 							op->d.row.elemvalues,
2916 							op->d.row.elemnulls);
2917 
2918 	*op->resvalue = HeapTupleGetDatum(tuple);
2919 	*op->resnull = false;
2920 }
2921 
2922 /*
2923  * Evaluate GREATEST() or LEAST() expression (note this is *not* MIN()/MAX()).
2924  *
2925  * All of the to-be-compared expressions have already been evaluated into
2926  * op->d.minmax.values[]/nulls[].
2927  */
2928 void
ExecEvalMinMax(ExprState * state,ExprEvalStep * op)2929 ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
2930 {
2931 	Datum	   *values = op->d.minmax.values;
2932 	bool	   *nulls = op->d.minmax.nulls;
2933 	FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
2934 	MinMaxOp	operator = op->d.minmax.op;
2935 
2936 	/* set at initialization */
2937 	Assert(fcinfo->args[0].isnull == false);
2938 	Assert(fcinfo->args[1].isnull == false);
2939 
2940 	/* default to null result */
2941 	*op->resnull = true;
2942 
2943 	for (int off = 0; off < op->d.minmax.nelems; off++)
2944 	{
2945 		/* ignore NULL inputs */
2946 		if (nulls[off])
2947 			continue;
2948 
2949 		if (*op->resnull)
2950 		{
2951 			/* first nonnull input, adopt value */
2952 			*op->resvalue = values[off];
2953 			*op->resnull = false;
2954 		}
2955 		else
2956 		{
2957 			int			cmpresult;
2958 
2959 			/* apply comparison function */
2960 			fcinfo->args[0].value = *op->resvalue;
2961 			fcinfo->args[1].value = values[off];
2962 
2963 			fcinfo->isnull = false;
2964 			cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
2965 			if (fcinfo->isnull) /* probably should not happen */
2966 				continue;
2967 
2968 			if (cmpresult > 0 && operator == IS_LEAST)
2969 				*op->resvalue = values[off];
2970 			else if (cmpresult < 0 && operator == IS_GREATEST)
2971 				*op->resvalue = values[off];
2972 		}
2973 	}
2974 }
2975 
2976 /*
2977  * Evaluate a FieldSelect node.
2978  *
2979  * Source record is in step's result variable.
2980  */
2981 void
ExecEvalFieldSelect(ExprState * state,ExprEvalStep * op,ExprContext * econtext)2982 ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
2983 {
2984 	AttrNumber	fieldnum = op->d.fieldselect.fieldnum;
2985 	Datum		tupDatum;
2986 	HeapTupleHeader tuple;
2987 	Oid			tupType;
2988 	int32		tupTypmod;
2989 	TupleDesc	tupDesc;
2990 	Form_pg_attribute attr;
2991 	HeapTupleData tmptup;
2992 
2993 	/* NULL record -> NULL result */
2994 	if (*op->resnull)
2995 		return;
2996 
2997 	tupDatum = *op->resvalue;
2998 
2999 	/* We can special-case expanded records for speed */
3000 	if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(tupDatum)))
3001 	{
3002 		ExpandedRecordHeader *erh = (ExpandedRecordHeader *) DatumGetEOHP(tupDatum);
3003 
3004 		Assert(erh->er_magic == ER_MAGIC);
3005 
3006 		/* Extract record's TupleDesc */
3007 		tupDesc = expanded_record_get_tupdesc(erh);
3008 
3009 		/*
3010 		 * Find field's attr record.  Note we don't support system columns
3011 		 * here: a datum tuple doesn't have valid values for most of the
3012 		 * interesting system columns anyway.
3013 		 */
3014 		if (fieldnum <= 0)		/* should never happen */
3015 			elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3016 				 fieldnum);
3017 		if (fieldnum > tupDesc->natts)	/* should never happen */
3018 			elog(ERROR, "attribute number %d exceeds number of columns %d",
3019 				 fieldnum, tupDesc->natts);
3020 		attr = TupleDescAttr(tupDesc, fieldnum - 1);
3021 
3022 		/* Check for dropped column, and force a NULL result if so */
3023 		if (attr->attisdropped)
3024 		{
3025 			*op->resnull = true;
3026 			return;
3027 		}
3028 
3029 		/* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3030 		/* As in CheckVarSlotCompatibility, we should but can't check typmod */
3031 		if (op->d.fieldselect.resulttype != attr->atttypid)
3032 			ereport(ERROR,
3033 					(errcode(ERRCODE_DATATYPE_MISMATCH),
3034 					 errmsg("attribute %d has wrong type", fieldnum),
3035 					 errdetail("Table has type %s, but query expects %s.",
3036 							   format_type_be(attr->atttypid),
3037 							   format_type_be(op->d.fieldselect.resulttype))));
3038 
3039 		/* extract the field */
3040 		*op->resvalue = expanded_record_get_field(erh, fieldnum,
3041 												  op->resnull);
3042 	}
3043 	else
3044 	{
3045 		/* Get the composite datum and extract its type fields */
3046 		tuple = DatumGetHeapTupleHeader(tupDatum);
3047 
3048 		tupType = HeapTupleHeaderGetTypeId(tuple);
3049 		tupTypmod = HeapTupleHeaderGetTypMod(tuple);
3050 
3051 		/* Lookup tupdesc if first time through or if type changes */
3052 		tupDesc = get_cached_rowtype(tupType, tupTypmod,
3053 									 &op->d.fieldselect.rowcache, NULL);
3054 
3055 		/*
3056 		 * Find field's attr record.  Note we don't support system columns
3057 		 * here: a datum tuple doesn't have valid values for most of the
3058 		 * interesting system columns anyway.
3059 		 */
3060 		if (fieldnum <= 0)		/* should never happen */
3061 			elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3062 				 fieldnum);
3063 		if (fieldnum > tupDesc->natts)	/* should never happen */
3064 			elog(ERROR, "attribute number %d exceeds number of columns %d",
3065 				 fieldnum, tupDesc->natts);
3066 		attr = TupleDescAttr(tupDesc, fieldnum - 1);
3067 
3068 		/* Check for dropped column, and force a NULL result if so */
3069 		if (attr->attisdropped)
3070 		{
3071 			*op->resnull = true;
3072 			return;
3073 		}
3074 
3075 		/* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3076 		/* As in CheckVarSlotCompatibility, we should but can't check typmod */
3077 		if (op->d.fieldselect.resulttype != attr->atttypid)
3078 			ereport(ERROR,
3079 					(errcode(ERRCODE_DATATYPE_MISMATCH),
3080 					 errmsg("attribute %d has wrong type", fieldnum),
3081 					 errdetail("Table has type %s, but query expects %s.",
3082 							   format_type_be(attr->atttypid),
3083 							   format_type_be(op->d.fieldselect.resulttype))));
3084 
3085 		/* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
3086 		tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3087 		tmptup.t_data = tuple;
3088 
3089 		/* extract the field */
3090 		*op->resvalue = heap_getattr(&tmptup,
3091 									 fieldnum,
3092 									 tupDesc,
3093 									 op->resnull);
3094 	}
3095 }
3096 
3097 /*
3098  * Deform source tuple, filling in the step's values/nulls arrays, before
3099  * evaluating individual new values as part of a FieldStore expression.
3100  * Subsequent steps will overwrite individual elements of the values/nulls
3101  * arrays with the new field values, and then FIELDSTORE_FORM will build the
3102  * new tuple value.
3103  *
3104  * Source record is in step's result variable.
3105  */
3106 void
ExecEvalFieldStoreDeForm(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3107 ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3108 {
3109 	TupleDesc	tupDesc;
3110 
3111 	/* Lookup tupdesc if first time through or if type changes */
3112 	tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3113 								 op->d.fieldstore.rowcache, NULL);
3114 
3115 	/* Check that current tupdesc doesn't have more fields than we allocated */
3116 	if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
3117 		elog(ERROR, "too many columns in composite type %u",
3118 			 op->d.fieldstore.fstore->resulttype);
3119 
3120 	if (*op->resnull)
3121 	{
3122 		/* Convert null input tuple into an all-nulls row */
3123 		memset(op->d.fieldstore.nulls, true,
3124 			   op->d.fieldstore.ncolumns * sizeof(bool));
3125 	}
3126 	else
3127 	{
3128 		/*
3129 		 * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
3130 		 * set all the fields in the struct just in case.
3131 		 */
3132 		Datum		tupDatum = *op->resvalue;
3133 		HeapTupleHeader tuphdr;
3134 		HeapTupleData tmptup;
3135 
3136 		tuphdr = DatumGetHeapTupleHeader(tupDatum);
3137 		tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
3138 		ItemPointerSetInvalid(&(tmptup.t_self));
3139 		tmptup.t_tableOid = InvalidOid;
3140 		tmptup.t_data = tuphdr;
3141 
3142 		heap_deform_tuple(&tmptup, tupDesc,
3143 						  op->d.fieldstore.values,
3144 						  op->d.fieldstore.nulls);
3145 	}
3146 }
3147 
3148 /*
3149  * Compute the new composite datum after each individual field value of a
3150  * FieldStore expression has been evaluated.
3151  */
3152 void
ExecEvalFieldStoreForm(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3153 ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3154 {
3155 	TupleDesc	tupDesc;
3156 	HeapTuple	tuple;
3157 
3158 	/* Lookup tupdesc (should be valid already) */
3159 	tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3160 								 op->d.fieldstore.rowcache, NULL);
3161 
3162 	tuple = heap_form_tuple(tupDesc,
3163 							op->d.fieldstore.values,
3164 							op->d.fieldstore.nulls);
3165 
3166 	*op->resvalue = HeapTupleGetDatum(tuple);
3167 	*op->resnull = false;
3168 }
3169 
3170 /*
3171  * Process a subscript in a SubscriptingRef expression.
3172  *
3173  * If subscript is NULL, throw error in assignment case, or in fetch case
3174  * set result to NULL and return false (instructing caller to skip the rest
3175  * of the SubscriptingRef sequence).
3176  *
3177  * Subscript expression result is in subscriptvalue/subscriptnull.
3178  * On success, integer subscript value has been saved in upperindex[] or
3179  * lowerindex[] for use later.
3180  */
3181 bool
ExecEvalSubscriptingRef(ExprState * state,ExprEvalStep * op)3182 ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op)
3183 {
3184 	SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
3185 	int		   *indexes;
3186 	int			off;
3187 
3188 	/* If any index expr yields NULL, result is NULL or error */
3189 	if (sbsrefstate->subscriptnull)
3190 	{
3191 		if (sbsrefstate->isassignment)
3192 			ereport(ERROR,
3193 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3194 					 errmsg("array subscript in assignment must not be null")));
3195 		*op->resnull = true;
3196 		return false;
3197 	}
3198 
3199 	/* Convert datum to int, save in appropriate place */
3200 	if (op->d.sbsref_subscript.isupper)
3201 		indexes = sbsrefstate->upperindex;
3202 	else
3203 		indexes = sbsrefstate->lowerindex;
3204 	off = op->d.sbsref_subscript.off;
3205 
3206 	indexes[off] = DatumGetInt32(sbsrefstate->subscriptvalue);
3207 
3208 	return true;
3209 }
3210 
3211 /*
3212  * Evaluate SubscriptingRef fetch.
3213  *
3214  * Source container is in step's result variable.
3215  */
3216 void
ExecEvalSubscriptingRefFetch(ExprState * state,ExprEvalStep * op)3217 ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op)
3218 {
3219 	SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
3220 
3221 	/* Should not get here if source container (or any subscript) is null */
3222 	Assert(!(*op->resnull));
3223 
3224 	if (sbsrefstate->numlower == 0)
3225 	{
3226 		/* Scalar case */
3227 		*op->resvalue = array_get_element(*op->resvalue,
3228 										  sbsrefstate->numupper,
3229 										  sbsrefstate->upperindex,
3230 										  sbsrefstate->refattrlength,
3231 										  sbsrefstate->refelemlength,
3232 										  sbsrefstate->refelembyval,
3233 										  sbsrefstate->refelemalign,
3234 										  op->resnull);
3235 	}
3236 	else
3237 	{
3238 		/* Slice case */
3239 		*op->resvalue = array_get_slice(*op->resvalue,
3240 										sbsrefstate->numupper,
3241 										sbsrefstate->upperindex,
3242 										sbsrefstate->lowerindex,
3243 										sbsrefstate->upperprovided,
3244 										sbsrefstate->lowerprovided,
3245 										sbsrefstate->refattrlength,
3246 										sbsrefstate->refelemlength,
3247 										sbsrefstate->refelembyval,
3248 										sbsrefstate->refelemalign);
3249 	}
3250 }
3251 
3252 /*
3253  * Compute old container element/slice value for a SubscriptingRef assignment
3254  * expression. Will only be generated if the new-value subexpression
3255  * contains SubscriptingRef or FieldStore. The value is stored into the
3256  * SubscriptingRefState's prevvalue/prevnull fields.
3257  */
3258 void
ExecEvalSubscriptingRefOld(ExprState * state,ExprEvalStep * op)3259 ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op)
3260 {
3261 	SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
3262 
3263 	if (*op->resnull)
3264 	{
3265 		/* whole array is null, so any element or slice is too */
3266 		sbsrefstate->prevvalue = (Datum) 0;
3267 		sbsrefstate->prevnull = true;
3268 	}
3269 	else if (sbsrefstate->numlower == 0)
3270 	{
3271 		/* Scalar case */
3272 		sbsrefstate->prevvalue = array_get_element(*op->resvalue,
3273 												   sbsrefstate->numupper,
3274 												   sbsrefstate->upperindex,
3275 												   sbsrefstate->refattrlength,
3276 												   sbsrefstate->refelemlength,
3277 												   sbsrefstate->refelembyval,
3278 												   sbsrefstate->refelemalign,
3279 												   &sbsrefstate->prevnull);
3280 	}
3281 	else
3282 	{
3283 		/* Slice case */
3284 		/* this is currently unreachable */
3285 		sbsrefstate->prevvalue = array_get_slice(*op->resvalue,
3286 												 sbsrefstate->numupper,
3287 												 sbsrefstate->upperindex,
3288 												 sbsrefstate->lowerindex,
3289 												 sbsrefstate->upperprovided,
3290 												 sbsrefstate->lowerprovided,
3291 												 sbsrefstate->refattrlength,
3292 												 sbsrefstate->refelemlength,
3293 												 sbsrefstate->refelembyval,
3294 												 sbsrefstate->refelemalign);
3295 		sbsrefstate->prevnull = false;
3296 	}
3297 }
3298 
3299 /*
3300  * Evaluate SubscriptingRef assignment.
3301  *
3302  * Input container (possibly null) is in result area, replacement value is in
3303  * SubscriptingRefState's replacevalue/replacenull.
3304  */
3305 void
ExecEvalSubscriptingRefAssign(ExprState * state,ExprEvalStep * op)3306 ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op)
3307 {
3308 	SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
3309 
3310 	/*
3311 	 * For an assignment to a fixed-length container type, both the original
3312 	 * container and the value to be assigned into it must be non-NULL, else
3313 	 * we punt and return the original container.
3314 	 */
3315 	if (sbsrefstate->refattrlength > 0)
3316 	{
3317 		if (*op->resnull || sbsrefstate->replacenull)
3318 			return;
3319 	}
3320 
3321 	/*
3322 	 * For assignment to varlena arrays, we handle a NULL original array by
3323 	 * substituting an empty (zero-dimensional) array; insertion of the new
3324 	 * element will result in a singleton array value.  It does not matter
3325 	 * whether the new element is NULL.
3326 	 */
3327 	if (*op->resnull)
3328 	{
3329 		*op->resvalue = PointerGetDatum(construct_empty_array(sbsrefstate->refelemtype));
3330 		*op->resnull = false;
3331 	}
3332 
3333 	if (sbsrefstate->numlower == 0)
3334 	{
3335 		/* Scalar case */
3336 		*op->resvalue = array_set_element(*op->resvalue,
3337 										  sbsrefstate->numupper,
3338 										  sbsrefstate->upperindex,
3339 										  sbsrefstate->replacevalue,
3340 										  sbsrefstate->replacenull,
3341 										  sbsrefstate->refattrlength,
3342 										  sbsrefstate->refelemlength,
3343 										  sbsrefstate->refelembyval,
3344 										  sbsrefstate->refelemalign);
3345 	}
3346 	else
3347 	{
3348 		/* Slice case */
3349 		*op->resvalue = array_set_slice(*op->resvalue,
3350 										sbsrefstate->numupper,
3351 										sbsrefstate->upperindex,
3352 										sbsrefstate->lowerindex,
3353 										sbsrefstate->upperprovided,
3354 										sbsrefstate->lowerprovided,
3355 										sbsrefstate->replacevalue,
3356 										sbsrefstate->replacenull,
3357 										sbsrefstate->refattrlength,
3358 										sbsrefstate->refelemlength,
3359 										sbsrefstate->refelembyval,
3360 										sbsrefstate->refelemalign);
3361 	}
3362 }
3363 
3364 /*
3365  * Evaluate a rowtype coercion operation.
3366  * This may require rearranging field positions.
3367  *
3368  * Source record is in step's result variable.
3369  */
3370 void
ExecEvalConvertRowtype(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3371 ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3372 {
3373 	HeapTuple	result;
3374 	Datum		tupDatum;
3375 	HeapTupleHeader tuple;
3376 	HeapTupleData tmptup;
3377 	TupleDesc	indesc,
3378 				outdesc;
3379 	bool		changed = false;
3380 
3381 	/* NULL in -> NULL out */
3382 	if (*op->resnull)
3383 		return;
3384 
3385 	tupDatum = *op->resvalue;
3386 	tuple = DatumGetHeapTupleHeader(tupDatum);
3387 
3388 	/*
3389 	 * Lookup tupdescs if first time through or if type changes.  We'd better
3390 	 * pin them since type conversion functions could do catalog lookups and
3391 	 * hence cause cache invalidation.
3392 	 */
3393 	indesc = get_cached_rowtype(op->d.convert_rowtype.inputtype, -1,
3394 								op->d.convert_rowtype.incache,
3395 								&changed);
3396 	IncrTupleDescRefCount(indesc);
3397 	outdesc = get_cached_rowtype(op->d.convert_rowtype.outputtype, -1,
3398 								 op->d.convert_rowtype.outcache,
3399 								 &changed);
3400 	IncrTupleDescRefCount(outdesc);
3401 
3402 	/*
3403 	 * We used to be able to assert that incoming tuples are marked with
3404 	 * exactly the rowtype of indesc.  However, now that ExecEvalWholeRowVar
3405 	 * might change the tuples' marking to plain RECORD due to inserting
3406 	 * aliases, we can only make this weak test:
3407 	 */
3408 	Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
3409 		   HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
3410 
3411 	/* if first time through, or after change, initialize conversion map */
3412 	if (changed)
3413 	{
3414 		MemoryContext old_cxt;
3415 
3416 		/* allocate map in long-lived memory context */
3417 		old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3418 
3419 		/* prepare map from old to new attribute numbers */
3420 		op->d.convert_rowtype.map = convert_tuples_by_name(indesc, outdesc);
3421 
3422 		MemoryContextSwitchTo(old_cxt);
3423 	}
3424 
3425 	/* Following steps need a HeapTuple not a bare HeapTupleHeader */
3426 	tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3427 	tmptup.t_data = tuple;
3428 
3429 	if (op->d.convert_rowtype.map != NULL)
3430 	{
3431 		/* Full conversion with attribute rearrangement needed */
3432 		result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map);
3433 		/* Result already has appropriate composite-datum header fields */
3434 		*op->resvalue = HeapTupleGetDatum(result);
3435 	}
3436 	else
3437 	{
3438 		/*
3439 		 * The tuple is physically compatible as-is, but we need to insert the
3440 		 * destination rowtype OID in its composite-datum header field, so we
3441 		 * have to copy it anyway.  heap_copy_tuple_as_datum() is convenient
3442 		 * for this since it will both make the physical copy and insert the
3443 		 * correct composite header fields.  Note that we aren't expecting to
3444 		 * have to flatten any toasted fields: the input was a composite
3445 		 * datum, so it shouldn't contain any.  So heap_copy_tuple_as_datum()
3446 		 * is overkill here, but its check for external fields is cheap.
3447 		 */
3448 		*op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
3449 	}
3450 
3451 	DecrTupleDescRefCount(indesc);
3452 	DecrTupleDescRefCount(outdesc);
3453 }
3454 
3455 /*
3456  * Evaluate "scalar op ANY/ALL (array)".
3457  *
3458  * Source array is in our result area, scalar arg is already evaluated into
3459  * fcinfo->args[0].
3460  *
3461  * The operator always yields boolean, and we combine the results across all
3462  * array elements using OR and AND (for ANY and ALL respectively).  Of course
3463  * we short-circuit as soon as the result is known.
3464  */
3465 void
ExecEvalScalarArrayOp(ExprState * state,ExprEvalStep * op)3466 ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
3467 {
3468 	FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
3469 	bool		useOr = op->d.scalararrayop.useOr;
3470 	bool		strictfunc = op->d.scalararrayop.finfo->fn_strict;
3471 	ArrayType  *arr;
3472 	int			nitems;
3473 	Datum		result;
3474 	bool		resultnull;
3475 	int16		typlen;
3476 	bool		typbyval;
3477 	char		typalign;
3478 	char	   *s;
3479 	bits8	   *bitmap;
3480 	int			bitmask;
3481 
3482 	/*
3483 	 * If the array is NULL then we return NULL --- it's not very meaningful
3484 	 * to do anything else, even if the operator isn't strict.
3485 	 */
3486 	if (*op->resnull)
3487 		return;
3488 
3489 	/* Else okay to fetch and detoast the array */
3490 	arr = DatumGetArrayTypeP(*op->resvalue);
3491 
3492 	/*
3493 	 * If the array is empty, we return either FALSE or TRUE per the useOr
3494 	 * flag.  This is correct even if the scalar is NULL; since we would
3495 	 * evaluate the operator zero times, it matters not whether it would want
3496 	 * to return NULL.
3497 	 */
3498 	nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3499 	if (nitems <= 0)
3500 	{
3501 		*op->resvalue = BoolGetDatum(!useOr);
3502 		*op->resnull = false;
3503 		return;
3504 	}
3505 
3506 	/*
3507 	 * If the scalar is NULL, and the function is strict, return NULL; no
3508 	 * point in iterating the loop.
3509 	 */
3510 	if (fcinfo->args[0].isnull && strictfunc)
3511 	{
3512 		*op->resnull = true;
3513 		return;
3514 	}
3515 
3516 	/*
3517 	 * We arrange to look up info about the element type only once per series
3518 	 * of calls, assuming the element type doesn't change underneath us.
3519 	 */
3520 	if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
3521 	{
3522 		get_typlenbyvalalign(ARR_ELEMTYPE(arr),
3523 							 &op->d.scalararrayop.typlen,
3524 							 &op->d.scalararrayop.typbyval,
3525 							 &op->d.scalararrayop.typalign);
3526 		op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
3527 	}
3528 
3529 	typlen = op->d.scalararrayop.typlen;
3530 	typbyval = op->d.scalararrayop.typbyval;
3531 	typalign = op->d.scalararrayop.typalign;
3532 
3533 	/* Initialize result appropriately depending on useOr */
3534 	result = BoolGetDatum(!useOr);
3535 	resultnull = false;
3536 
3537 	/* Loop over the array elements */
3538 	s = (char *) ARR_DATA_PTR(arr);
3539 	bitmap = ARR_NULLBITMAP(arr);
3540 	bitmask = 1;
3541 
3542 	for (int i = 0; i < nitems; i++)
3543 	{
3544 		Datum		elt;
3545 		Datum		thisresult;
3546 
3547 		/* Get array element, checking for NULL */
3548 		if (bitmap && (*bitmap & bitmask) == 0)
3549 		{
3550 			fcinfo->args[1].value = (Datum) 0;
3551 			fcinfo->args[1].isnull = true;
3552 		}
3553 		else
3554 		{
3555 			elt = fetch_att(s, typbyval, typlen);
3556 			s = att_addlength_pointer(s, typlen, s);
3557 			s = (char *) att_align_nominal(s, typalign);
3558 			fcinfo->args[1].value = elt;
3559 			fcinfo->args[1].isnull = false;
3560 		}
3561 
3562 		/* Call comparison function */
3563 		if (fcinfo->args[1].isnull && strictfunc)
3564 		{
3565 			fcinfo->isnull = true;
3566 			thisresult = (Datum) 0;
3567 		}
3568 		else
3569 		{
3570 			fcinfo->isnull = false;
3571 			thisresult = op->d.scalararrayop.fn_addr(fcinfo);
3572 		}
3573 
3574 		/* Combine results per OR or AND semantics */
3575 		if (fcinfo->isnull)
3576 			resultnull = true;
3577 		else if (useOr)
3578 		{
3579 			if (DatumGetBool(thisresult))
3580 			{
3581 				result = BoolGetDatum(true);
3582 				resultnull = false;
3583 				break;			/* needn't look at any more elements */
3584 			}
3585 		}
3586 		else
3587 		{
3588 			if (!DatumGetBool(thisresult))
3589 			{
3590 				result = BoolGetDatum(false);
3591 				resultnull = false;
3592 				break;			/* needn't look at any more elements */
3593 			}
3594 		}
3595 
3596 		/* advance bitmap pointer if any */
3597 		if (bitmap)
3598 		{
3599 			bitmask <<= 1;
3600 			if (bitmask == 0x100)
3601 			{
3602 				bitmap++;
3603 				bitmask = 1;
3604 			}
3605 		}
3606 	}
3607 
3608 	*op->resvalue = result;
3609 	*op->resnull = resultnull;
3610 }
3611 
3612 /*
3613  * Evaluate a NOT NULL domain constraint.
3614  */
3615 void
ExecEvalConstraintNotNull(ExprState * state,ExprEvalStep * op)3616 ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op)
3617 {
3618 	if (*op->resnull)
3619 		ereport(ERROR,
3620 				(errcode(ERRCODE_NOT_NULL_VIOLATION),
3621 				 errmsg("domain %s does not allow null values",
3622 						format_type_be(op->d.domaincheck.resulttype)),
3623 				 errdatatype(op->d.domaincheck.resulttype)));
3624 }
3625 
3626 /*
3627  * Evaluate a CHECK domain constraint.
3628  */
3629 void
ExecEvalConstraintCheck(ExprState * state,ExprEvalStep * op)3630 ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
3631 {
3632 	if (!*op->d.domaincheck.checknull &&
3633 		!DatumGetBool(*op->d.domaincheck.checkvalue))
3634 		ereport(ERROR,
3635 				(errcode(ERRCODE_CHECK_VIOLATION),
3636 				 errmsg("value for domain %s violates check constraint \"%s\"",
3637 						format_type_be(op->d.domaincheck.resulttype),
3638 						op->d.domaincheck.constraintname),
3639 				 errdomainconstraint(op->d.domaincheck.resulttype,
3640 									 op->d.domaincheck.constraintname)));
3641 }
3642 
3643 /*
3644  * Evaluate the various forms of XmlExpr.
3645  *
3646  * Arguments have been evaluated into named_argvalue/named_argnull
3647  * and/or argvalue/argnull arrays.
3648  */
3649 void
ExecEvalXmlExpr(ExprState * state,ExprEvalStep * op)3650 ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
3651 {
3652 	XmlExpr    *xexpr = op->d.xmlexpr.xexpr;
3653 	Datum		value;
3654 
3655 	*op->resnull = true;		/* until we get a result */
3656 	*op->resvalue = (Datum) 0;
3657 
3658 	switch (xexpr->op)
3659 	{
3660 		case IS_XMLCONCAT:
3661 			{
3662 				Datum	   *argvalue = op->d.xmlexpr.argvalue;
3663 				bool	   *argnull = op->d.xmlexpr.argnull;
3664 				List	   *values = NIL;
3665 
3666 				for (int i = 0; i < list_length(xexpr->args); i++)
3667 				{
3668 					if (!argnull[i])
3669 						values = lappend(values, DatumGetPointer(argvalue[i]));
3670 				}
3671 
3672 				if (values != NIL)
3673 				{
3674 					*op->resvalue = PointerGetDatum(xmlconcat(values));
3675 					*op->resnull = false;
3676 				}
3677 			}
3678 			break;
3679 
3680 		case IS_XMLFOREST:
3681 			{
3682 				Datum	   *argvalue = op->d.xmlexpr.named_argvalue;
3683 				bool	   *argnull = op->d.xmlexpr.named_argnull;
3684 				StringInfoData buf;
3685 				ListCell   *lc;
3686 				ListCell   *lc2;
3687 				int			i;
3688 
3689 				initStringInfo(&buf);
3690 
3691 				i = 0;
3692 				forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
3693 				{
3694 					Expr	   *e = (Expr *) lfirst(lc);
3695 					char	   *argname = strVal(lfirst(lc2));
3696 
3697 					if (!argnull[i])
3698 					{
3699 						value = argvalue[i];
3700 						appendStringInfo(&buf, "<%s>%s</%s>",
3701 										 argname,
3702 										 map_sql_value_to_xml_value(value,
3703 																	exprType((Node *) e), true),
3704 										 argname);
3705 						*op->resnull = false;
3706 					}
3707 					i++;
3708 				}
3709 
3710 				if (!*op->resnull)
3711 				{
3712 					text	   *result;
3713 
3714 					result = cstring_to_text_with_len(buf.data, buf.len);
3715 					*op->resvalue = PointerGetDatum(result);
3716 				}
3717 
3718 				pfree(buf.data);
3719 			}
3720 			break;
3721 
3722 		case IS_XMLELEMENT:
3723 			*op->resvalue = PointerGetDatum(xmlelement(xexpr,
3724 													   op->d.xmlexpr.named_argvalue,
3725 													   op->d.xmlexpr.named_argnull,
3726 													   op->d.xmlexpr.argvalue,
3727 													   op->d.xmlexpr.argnull));
3728 			*op->resnull = false;
3729 			break;
3730 
3731 		case IS_XMLPARSE:
3732 			{
3733 				Datum	   *argvalue = op->d.xmlexpr.argvalue;
3734 				bool	   *argnull = op->d.xmlexpr.argnull;
3735 				text	   *data;
3736 				bool		preserve_whitespace;
3737 
3738 				/* arguments are known to be text, bool */
3739 				Assert(list_length(xexpr->args) == 2);
3740 
3741 				if (argnull[0])
3742 					return;
3743 				value = argvalue[0];
3744 				data = DatumGetTextPP(value);
3745 
3746 				if (argnull[1]) /* probably can't happen */
3747 					return;
3748 				value = argvalue[1];
3749 				preserve_whitespace = DatumGetBool(value);
3750 
3751 				*op->resvalue = PointerGetDatum(xmlparse(data,
3752 														 xexpr->xmloption,
3753 														 preserve_whitespace));
3754 				*op->resnull = false;
3755 			}
3756 			break;
3757 
3758 		case IS_XMLPI:
3759 			{
3760 				text	   *arg;
3761 				bool		isnull;
3762 
3763 				/* optional argument is known to be text */
3764 				Assert(list_length(xexpr->args) <= 1);
3765 
3766 				if (xexpr->args)
3767 				{
3768 					isnull = op->d.xmlexpr.argnull[0];
3769 					if (isnull)
3770 						arg = NULL;
3771 					else
3772 						arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
3773 				}
3774 				else
3775 				{
3776 					arg = NULL;
3777 					isnull = false;
3778 				}
3779 
3780 				*op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
3781 													  arg,
3782 													  isnull,
3783 													  op->resnull));
3784 			}
3785 			break;
3786 
3787 		case IS_XMLROOT:
3788 			{
3789 				Datum	   *argvalue = op->d.xmlexpr.argvalue;
3790 				bool	   *argnull = op->d.xmlexpr.argnull;
3791 				xmltype    *data;
3792 				text	   *version;
3793 				int			standalone;
3794 
3795 				/* arguments are known to be xml, text, int */
3796 				Assert(list_length(xexpr->args) == 3);
3797 
3798 				if (argnull[0])
3799 					return;
3800 				data = DatumGetXmlP(argvalue[0]);
3801 
3802 				if (argnull[1])
3803 					version = NULL;
3804 				else
3805 					version = DatumGetTextPP(argvalue[1]);
3806 
3807 				Assert(!argnull[2]);	/* always present */
3808 				standalone = DatumGetInt32(argvalue[2]);
3809 
3810 				*op->resvalue = PointerGetDatum(xmlroot(data,
3811 														version,
3812 														standalone));
3813 				*op->resnull = false;
3814 			}
3815 			break;
3816 
3817 		case IS_XMLSERIALIZE:
3818 			{
3819 				Datum	   *argvalue = op->d.xmlexpr.argvalue;
3820 				bool	   *argnull = op->d.xmlexpr.argnull;
3821 
3822 				/* argument type is known to be xml */
3823 				Assert(list_length(xexpr->args) == 1);
3824 
3825 				if (argnull[0])
3826 					return;
3827 				value = argvalue[0];
3828 
3829 				*op->resvalue = PointerGetDatum(xmltotext_with_xmloption(DatumGetXmlP(value),
3830 																		 xexpr->xmloption));
3831 				*op->resnull = false;
3832 			}
3833 			break;
3834 
3835 		case IS_DOCUMENT:
3836 			{
3837 				Datum	   *argvalue = op->d.xmlexpr.argvalue;
3838 				bool	   *argnull = op->d.xmlexpr.argnull;
3839 
3840 				/* optional argument is known to be xml */
3841 				Assert(list_length(xexpr->args) == 1);
3842 
3843 				if (argnull[0])
3844 					return;
3845 				value = argvalue[0];
3846 
3847 				*op->resvalue =
3848 					BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
3849 				*op->resnull = false;
3850 			}
3851 			break;
3852 
3853 		default:
3854 			elog(ERROR, "unrecognized XML operation");
3855 			break;
3856 	}
3857 }
3858 
3859 /*
3860  * ExecEvalGroupingFunc
3861  *
3862  * Computes a bitmask with a bit for each (unevaluated) argument expression
3863  * (rightmost arg is least significant bit).
3864  *
3865  * A bit is set if the corresponding expression is NOT part of the set of
3866  * grouping expressions in the current grouping set.
3867  */
3868 void
ExecEvalGroupingFunc(ExprState * state,ExprEvalStep * op)3869 ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op)
3870 {
3871 	AggState   *aggstate = castNode(AggState, state->parent);
3872 	int			result = 0;
3873 	Bitmapset  *grouped_cols = aggstate->grouped_cols;
3874 	ListCell   *lc;
3875 
3876 	foreach(lc, op->d.grouping_func.clauses)
3877 	{
3878 		int			attnum = lfirst_int(lc);
3879 
3880 		result <<= 1;
3881 
3882 		if (!bms_is_member(attnum, grouped_cols))
3883 			result |= 1;
3884 	}
3885 
3886 	*op->resvalue = Int32GetDatum(result);
3887 	*op->resnull = false;
3888 }
3889 
3890 /*
3891  * Hand off evaluation of a subplan to nodeSubplan.c
3892  */
3893 void
ExecEvalSubPlan(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3894 ExecEvalSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3895 {
3896 	SubPlanState *sstate = op->d.subplan.sstate;
3897 
3898 	/* could potentially be nested, so make sure there's enough stack */
3899 	check_stack_depth();
3900 
3901 	*op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
3902 }
3903 
3904 /*
3905  * Hand off evaluation of an alternative subplan to nodeSubplan.c
3906  */
3907 void
ExecEvalAlternativeSubPlan(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3908 ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3909 {
3910 	AlternativeSubPlanState *asstate = op->d.alternative_subplan.asstate;
3911 
3912 	/* could potentially be nested, so make sure there's enough stack */
3913 	check_stack_depth();
3914 
3915 	*op->resvalue = ExecAlternativeSubPlan(asstate, econtext, op->resnull);
3916 }
3917 
3918 /*
3919  * Evaluate a wholerow Var expression.
3920  *
3921  * Returns a Datum whose value is the value of a whole-row range variable
3922  * with respect to given expression context.
3923  */
3924 void
ExecEvalWholeRowVar(ExprState * state,ExprEvalStep * op,ExprContext * econtext)3925 ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
3926 {
3927 	Var		   *variable = op->d.wholerow.var;
3928 	TupleTableSlot *slot;
3929 	TupleDesc	output_tupdesc;
3930 	MemoryContext oldcontext;
3931 	HeapTupleHeader dtuple;
3932 	HeapTuple	tuple;
3933 
3934 	/* This was checked by ExecInitExpr */
3935 	Assert(variable->varattno == InvalidAttrNumber);
3936 
3937 	/* Get the input slot we want */
3938 	switch (variable->varno)
3939 	{
3940 		case INNER_VAR:
3941 			/* get the tuple from the inner node */
3942 			slot = econtext->ecxt_innertuple;
3943 			break;
3944 
3945 		case OUTER_VAR:
3946 			/* get the tuple from the outer node */
3947 			slot = econtext->ecxt_outertuple;
3948 			break;
3949 
3950 			/* INDEX_VAR is handled by default case */
3951 
3952 		default:
3953 			/* get the tuple from the relation being scanned */
3954 			slot = econtext->ecxt_scantuple;
3955 			break;
3956 	}
3957 
3958 	/* Apply the junkfilter if any */
3959 	if (op->d.wholerow.junkFilter != NULL)
3960 		slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
3961 
3962 	/*
3963 	 * If first time through, obtain tuple descriptor and check compatibility.
3964 	 *
3965 	 * XXX: It'd be great if this could be moved to the expression
3966 	 * initialization phase, but due to using slots that's currently not
3967 	 * feasible.
3968 	 */
3969 	if (op->d.wholerow.first)
3970 	{
3971 		/* optimistically assume we don't need slow path */
3972 		op->d.wholerow.slow = false;
3973 
3974 		/*
3975 		 * If the Var identifies a named composite type, we must check that
3976 		 * the actual tuple type is compatible with it.
3977 		 */
3978 		if (variable->vartype != RECORDOID)
3979 		{
3980 			TupleDesc	var_tupdesc;
3981 			TupleDesc	slot_tupdesc;
3982 
3983 			/*
3984 			 * We really only care about numbers of attributes and data types.
3985 			 * Also, we can ignore type mismatch on columns that are dropped
3986 			 * in the destination type, so long as (1) the physical storage
3987 			 * matches or (2) the actual column value is NULL.  Case (1) is
3988 			 * helpful in some cases involving out-of-date cached plans, while
3989 			 * case (2) is expected behavior in situations such as an INSERT
3990 			 * into a table with dropped columns (the planner typically
3991 			 * generates an INT4 NULL regardless of the dropped column type).
3992 			 * If we find a dropped column and cannot verify that case (1)
3993 			 * holds, we have to use the slow path to check (2) for each row.
3994 			 *
3995 			 * If vartype is a domain over composite, just look through that
3996 			 * to the base composite type.
3997 			 */
3998 			var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
3999 														-1, false);
4000 
4001 			slot_tupdesc = slot->tts_tupleDescriptor;
4002 
4003 			if (var_tupdesc->natts != slot_tupdesc->natts)
4004 				ereport(ERROR,
4005 						(errcode(ERRCODE_DATATYPE_MISMATCH),
4006 						 errmsg("table row type and query-specified row type do not match"),
4007 						 errdetail_plural("Table row contains %d attribute, but query expects %d.",
4008 										  "Table row contains %d attributes, but query expects %d.",
4009 										  slot_tupdesc->natts,
4010 										  slot_tupdesc->natts,
4011 										  var_tupdesc->natts)));
4012 
4013 			for (int i = 0; i < var_tupdesc->natts; i++)
4014 			{
4015 				Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4016 				Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i);
4017 
4018 				if (vattr->atttypid == sattr->atttypid)
4019 					continue;	/* no worries */
4020 				if (!vattr->attisdropped)
4021 					ereport(ERROR,
4022 							(errcode(ERRCODE_DATATYPE_MISMATCH),
4023 							 errmsg("table row type and query-specified row type do not match"),
4024 							 errdetail("Table has type %s at ordinal position %d, but query expects %s.",
4025 									   format_type_be(sattr->atttypid),
4026 									   i + 1,
4027 									   format_type_be(vattr->atttypid))));
4028 
4029 				if (vattr->attlen != sattr->attlen ||
4030 					vattr->attalign != sattr->attalign)
4031 					op->d.wholerow.slow = true; /* need to check for nulls */
4032 			}
4033 
4034 			/*
4035 			 * Use the variable's declared rowtype as the descriptor for the
4036 			 * output values, modulo possibly assigning new column names
4037 			 * below. In particular, we *must* absorb any attisdropped
4038 			 * markings.
4039 			 */
4040 			oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
4041 			output_tupdesc = CreateTupleDescCopy(var_tupdesc);
4042 			MemoryContextSwitchTo(oldcontext);
4043 
4044 			ReleaseTupleDesc(var_tupdesc);
4045 		}
4046 		else
4047 		{
4048 			/*
4049 			 * In the RECORD case, we use the input slot's rowtype as the
4050 			 * descriptor for the output values, modulo possibly assigning new
4051 			 * column names below.
4052 			 */
4053 			oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
4054 			output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
4055 			MemoryContextSwitchTo(oldcontext);
4056 		}
4057 
4058 		/*
4059 		 * Construct a tuple descriptor for the composite values we'll
4060 		 * produce, and make sure its record type is "blessed".  The main
4061 		 * reason to do this is to be sure that operations such as
4062 		 * row_to_json() will see the desired column names when they look up
4063 		 * the descriptor from the type information embedded in the composite
4064 		 * values.
4065 		 *
4066 		 * We already got the correct physical datatype info above, but now we
4067 		 * should try to find the source RTE and adopt its column aliases, in
4068 		 * case they are different from the original rowtype's names.  For
4069 		 * example, in "SELECT foo(t) FROM tab t(x,y)", the first two columns
4070 		 * in the composite output should be named "x" and "y" regardless of
4071 		 * tab's column names.
4072 		 *
4073 		 * If we can't locate the RTE, assume the column names we've got are
4074 		 * OK.  (As of this writing, the only cases where we can't locate the
4075 		 * RTE are in execution of trigger WHEN clauses, and then the Var will
4076 		 * have the trigger's relation's rowtype, so its names are fine.)
4077 		 * Also, if the creator of the RTE didn't bother to fill in an eref
4078 		 * field, assume our column names are OK.  (This happens in COPY, and
4079 		 * perhaps other places.)
4080 		 */
4081 		if (econtext->ecxt_estate &&
4082 			variable->varno <= econtext->ecxt_estate->es_range_table_size)
4083 		{
4084 			RangeTblEntry *rte = exec_rt_fetch(variable->varno,
4085 											   econtext->ecxt_estate);
4086 
4087 			if (rte->eref)
4088 				ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
4089 		}
4090 
4091 		/* Bless the tupdesc if needed, and save it in the execution state */
4092 		op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
4093 
4094 		op->d.wholerow.first = false;
4095 	}
4096 
4097 	/*
4098 	 * Make sure all columns of the slot are accessible in the slot's
4099 	 * Datum/isnull arrays.
4100 	 */
4101 	slot_getallattrs(slot);
4102 
4103 	if (op->d.wholerow.slow)
4104 	{
4105 		/* Check to see if any dropped attributes are non-null */
4106 		TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
4107 		TupleDesc	var_tupdesc = op->d.wholerow.tupdesc;
4108 
4109 		Assert(var_tupdesc->natts == tupleDesc->natts);
4110 
4111 		for (int i = 0; i < var_tupdesc->natts; i++)
4112 		{
4113 			Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4114 			Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i);
4115 
4116 			if (!vattr->attisdropped)
4117 				continue;		/* already checked non-dropped cols */
4118 			if (slot->tts_isnull[i])
4119 				continue;		/* null is always okay */
4120 			if (vattr->attlen != sattr->attlen ||
4121 				vattr->attalign != sattr->attalign)
4122 				ereport(ERROR,
4123 						(errcode(ERRCODE_DATATYPE_MISMATCH),
4124 						 errmsg("table row type and query-specified row type do not match"),
4125 						 errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
4126 								   i + 1)));
4127 		}
4128 	}
4129 
4130 	/*
4131 	 * Build a composite datum, making sure any toasted fields get detoasted.
4132 	 *
4133 	 * (Note: it is critical that we not change the slot's state here.)
4134 	 */
4135 	tuple = toast_build_flattened_tuple(slot->tts_tupleDescriptor,
4136 										slot->tts_values,
4137 										slot->tts_isnull);
4138 	dtuple = tuple->t_data;
4139 
4140 	/*
4141 	 * Label the datum with the composite type info we identified before.
4142 	 *
4143 	 * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
4144 	 * the tuple build step; but that seems a tad risky so let's not.)
4145 	 */
4146 	HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
4147 	HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
4148 
4149 	*op->resvalue = PointerGetDatum(dtuple);
4150 	*op->resnull = false;
4151 }
4152 
4153 void
ExecEvalSysVar(ExprState * state,ExprEvalStep * op,ExprContext * econtext,TupleTableSlot * slot)4154 ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4155 			   TupleTableSlot *slot)
4156 {
4157 	Datum		d;
4158 
4159 	/* slot_getsysattr has sufficient defenses against bad attnums */
4160 	d = slot_getsysattr(slot,
4161 						op->d.var.attnum,
4162 						op->resnull);
4163 	*op->resvalue = d;
4164 	/* this ought to be unreachable, but it's cheap enough to check */
4165 	if (unlikely(*op->resnull))
4166 		elog(ERROR, "failed to fetch attribute from slot");
4167 }
4168 
4169 /*
4170  * Transition value has not been initialized. This is the first non-NULL input
4171  * value for a group. We use it as the initial value for transValue.
4172  */
4173 void
ExecAggInitGroup(AggState * aggstate,AggStatePerTrans pertrans,AggStatePerGroup pergroup,ExprContext * aggcontext)4174 ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup,
4175 				 ExprContext *aggcontext)
4176 {
4177 	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4178 	MemoryContext oldContext;
4179 
4180 	/*
4181 	 * We must copy the datum into aggcontext if it is pass-by-ref. We do not
4182 	 * need to pfree the old transValue, since it's NULL.  (We already checked
4183 	 * that the agg's input type is binary-compatible with its transtype, so
4184 	 * straight copy here is OK.)
4185 	 */
4186 	oldContext = MemoryContextSwitchTo(aggcontext->ecxt_per_tuple_memory);
4187 	pergroup->transValue = datumCopy(fcinfo->args[1].value,
4188 									 pertrans->transtypeByVal,
4189 									 pertrans->transtypeLen);
4190 	pergroup->transValueIsNull = false;
4191 	pergroup->noTransValue = false;
4192 	MemoryContextSwitchTo(oldContext);
4193 }
4194 
4195 /*
4196  * Ensure that the current transition value is a child of the aggcontext,
4197  * rather than the per-tuple context.
4198  *
4199  * NB: This can change the current memory context.
4200  */
4201 Datum
ExecAggTransReparent(AggState * aggstate,AggStatePerTrans pertrans,Datum newValue,bool newValueIsNull,Datum oldValue,bool oldValueIsNull)4202 ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
4203 					 Datum newValue, bool newValueIsNull,
4204 					 Datum oldValue, bool oldValueIsNull)
4205 {
4206 	Assert(newValue != oldValue);
4207 
4208 	if (!newValueIsNull)
4209 	{
4210 		MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory);
4211 		if (DatumIsReadWriteExpandedObject(newValue,
4212 										   false,
4213 										   pertrans->transtypeLen) &&
4214 			MemoryContextGetParent(DatumGetEOHP(newValue)->eoh_context) == CurrentMemoryContext)
4215 			 /* do nothing */ ;
4216 		else
4217 			newValue = datumCopy(newValue,
4218 								 pertrans->transtypeByVal,
4219 								 pertrans->transtypeLen);
4220 	}
4221 	else
4222 	{
4223 		/*
4224 		 * Ensure that AggStatePerGroup->transValue ends up being 0, so
4225 		 * callers can safely compare newValue/oldValue without having to
4226 		 * check their respective nullness.
4227 		 */
4228 		newValue = (Datum) 0;
4229 	}
4230 
4231 	if (!oldValueIsNull)
4232 	{
4233 		if (DatumIsReadWriteExpandedObject(oldValue,
4234 										   false,
4235 										   pertrans->transtypeLen))
4236 			DeleteExpandedObject(oldValue);
4237 		else
4238 			pfree(DatumGetPointer(oldValue));
4239 	}
4240 
4241 	return newValue;
4242 }
4243 
4244 /*
4245  * Invoke ordered transition function, with a datum argument.
4246  */
4247 void
ExecEvalAggOrderedTransDatum(ExprState * state,ExprEvalStep * op,ExprContext * econtext)4248 ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op,
4249 							 ExprContext *econtext)
4250 {
4251 	AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
4252 	int			setno = op->d.agg_trans.setno;
4253 
4254 	tuplesort_putdatum(pertrans->sortstates[setno],
4255 					   *op->resvalue, *op->resnull);
4256 }
4257 
4258 /*
4259  * Invoke ordered transition function, with a tuple argument.
4260  */
4261 void
ExecEvalAggOrderedTransTuple(ExprState * state,ExprEvalStep * op,ExprContext * econtext)4262 ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
4263 							 ExprContext *econtext)
4264 {
4265 	AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
4266 	int			setno = op->d.agg_trans.setno;
4267 
4268 	ExecClearTuple(pertrans->sortslot);
4269 	pertrans->sortslot->tts_nvalid = pertrans->numInputs;
4270 	ExecStoreVirtualTuple(pertrans->sortslot);
4271 	tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
4272 }
4273 
4274 /* implementation of transition function invocation for byval types */
4275 static pg_attribute_always_inline void
ExecAggPlainTransByVal(AggState * aggstate,AggStatePerTrans pertrans,AggStatePerGroup pergroup,ExprContext * aggcontext,int setno)4276 ExecAggPlainTransByVal(AggState *aggstate, AggStatePerTrans pertrans,
4277 					   AggStatePerGroup pergroup,
4278 					   ExprContext *aggcontext, int setno)
4279 {
4280 	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4281 	MemoryContext oldContext;
4282 	Datum		newVal;
4283 
4284 	/* cf. select_current_set() */
4285 	aggstate->curaggcontext = aggcontext;
4286 	aggstate->current_set = setno;
4287 
4288 	/* set up aggstate->curpertrans for AggGetAggref() */
4289 	aggstate->curpertrans = pertrans;
4290 
4291 	/* invoke transition function in per-tuple context */
4292 	oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
4293 
4294 	fcinfo->args[0].value = pergroup->transValue;
4295 	fcinfo->args[0].isnull = pergroup->transValueIsNull;
4296 	fcinfo->isnull = false;		/* just in case transfn doesn't set it */
4297 
4298 	newVal = FunctionCallInvoke(fcinfo);
4299 
4300 	pergroup->transValue = newVal;
4301 	pergroup->transValueIsNull = fcinfo->isnull;
4302 
4303 	MemoryContextSwitchTo(oldContext);
4304 }
4305 
4306 /* implementation of transition function invocation for byref types */
4307 static pg_attribute_always_inline void
ExecAggPlainTransByRef(AggState * aggstate,AggStatePerTrans pertrans,AggStatePerGroup pergroup,ExprContext * aggcontext,int setno)4308 ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans,
4309 					   AggStatePerGroup pergroup,
4310 					   ExprContext *aggcontext, int setno)
4311 {
4312 	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4313 	MemoryContext oldContext;
4314 	Datum		newVal;
4315 
4316 	/* cf. select_current_set() */
4317 	aggstate->curaggcontext = aggcontext;
4318 	aggstate->current_set = setno;
4319 
4320 	/* set up aggstate->curpertrans for AggGetAggref() */
4321 	aggstate->curpertrans = pertrans;
4322 
4323 	/* invoke transition function in per-tuple context */
4324 	oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
4325 
4326 	fcinfo->args[0].value = pergroup->transValue;
4327 	fcinfo->args[0].isnull = pergroup->transValueIsNull;
4328 	fcinfo->isnull = false;		/* just in case transfn doesn't set it */
4329 
4330 	newVal = FunctionCallInvoke(fcinfo);
4331 
4332 	/*
4333 	 * For pass-by-ref datatype, must copy the new value into aggcontext and
4334 	 * free the prior transValue.  But if transfn returned a pointer to its
4335 	 * first input, we don't need to do anything.  Also, if transfn returned a
4336 	 * pointer to a R/W expanded object that is already a child of the
4337 	 * aggcontext, assume we can adopt that value without copying it.
4338 	 *
4339 	 * It's safe to compare newVal with pergroup->transValue without regard
4340 	 * for either being NULL, because ExecAggTransReparent() takes care to set
4341 	 * transValue to 0 when NULL. Otherwise we could end up accidentally not
4342 	 * reparenting, when the transValue has the same numerical value as
4343 	 * newValue, despite being NULL.  This is a somewhat hot path, making it
4344 	 * undesirable to instead solve this with another branch for the common
4345 	 * case of the transition function returning its (modified) input
4346 	 * argument.
4347 	 */
4348 	if (DatumGetPointer(newVal) != DatumGetPointer(pergroup->transValue))
4349 		newVal = ExecAggTransReparent(aggstate, pertrans,
4350 									  newVal, fcinfo->isnull,
4351 									  pergroup->transValue,
4352 									  pergroup->transValueIsNull);
4353 
4354 	pergroup->transValue = newVal;
4355 	pergroup->transValueIsNull = fcinfo->isnull;
4356 
4357 	MemoryContextSwitchTo(oldContext);
4358 }
4359