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