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