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