PostgreSQL Source Code  git master
execExprInterp.c
Go to the documentation of this file.
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-2024, PostgreSQL Global Development Group
50  * Portions Copyright (c) 1994, Regents of the University of California
51  *
52  * IDENTIFICATION
53  * src/backend/executor/execExprInterp.c
54  *
55  *-------------------------------------------------------------------------
56  */
57 #include "postgres.h"
58 
59 #include "access/heaptoast.h"
60 #include "catalog/pg_type.h"
61 #include "commands/sequence.h"
62 #include "executor/execExpr.h"
63 #include "executor/nodeSubplan.h"
64 #include "funcapi.h"
65 #include "miscadmin.h"
66 #include "nodes/miscnodes.h"
67 #include "nodes/nodeFuncs.h"
68 #include "pgstat.h"
69 #include "utils/array.h"
70 #include "utils/builtins.h"
71 #include "utils/date.h"
72 #include "utils/datum.h"
73 #include "utils/expandedrecord.h"
74 #include "utils/json.h"
75 #include "utils/jsonfuncs.h"
76 #include "utils/jsonpath.h"
77 #include "utils/lsyscache.h"
78 #include "utils/memutils.h"
79 #include "utils/timestamp.h"
80 #include "utils/typcache.h"
81 #include "utils/xml.h"
82 
83 /*
84  * Use computed-goto-based opcode dispatch when computed gotos are available.
85  * But use a separate symbol so that it's easy to adjust locally in this file
86  * for development and testing.
87  */
88 #ifdef HAVE_COMPUTED_GOTO
89 #define EEO_USE_COMPUTED_GOTO
90 #endif /* HAVE_COMPUTED_GOTO */
91 
92 /*
93  * Macros for opcode dispatch.
94  *
95  * EEO_SWITCH - just hides the switch if not in use.
96  * EEO_CASE - labels the implementation of named expression step type.
97  * EEO_DISPATCH - jump to the implementation of the step type for 'op'.
98  * EEO_OPCODE - compute opcode required by used expression evaluation method.
99  * EEO_NEXT - increment 'op' and jump to correct next step type.
100  * EEO_JUMP - jump to the specified step number within the current expression.
101  */
102 #if defined(EEO_USE_COMPUTED_GOTO)
103 
104 /* struct for jump target -> opcode lookup table */
105 typedef struct ExprEvalOpLookup
106 {
107  const void *opcode;
108  ExprEvalOp op;
109 } ExprEvalOpLookup;
110 
111 /* to make dispatch_table accessible outside ExecInterpExpr() */
112 static const void **dispatch_table = NULL;
113 
114 /* jump target -> opcode lookup table */
115 static ExprEvalOpLookup reverse_dispatch_table[EEOP_LAST];
116 
117 #define EEO_SWITCH()
118 #define EEO_CASE(name) CASE_##name:
119 #define EEO_DISPATCH() goto *((void *) op->opcode)
120 #define EEO_OPCODE(opcode) ((intptr_t) dispatch_table[opcode])
121 
122 #else /* !EEO_USE_COMPUTED_GOTO */
123 
124 #define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode)
125 #define EEO_CASE(name) case name:
126 #define EEO_DISPATCH() goto starteval
127 #define EEO_OPCODE(opcode) (opcode)
128 
129 #endif /* EEO_USE_COMPUTED_GOTO */
130 
131 #define EEO_NEXT() \
132  do { \
133  op++; \
134  EEO_DISPATCH(); \
135  } while (0)
136 
137 #define EEO_JUMP(stepno) \
138  do { \
139  op = &state->steps[stepno]; \
140  EEO_DISPATCH(); \
141  } while (0)
142 
143 
144 static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull);
145 static void ExecInitInterpreter(void);
146 
147 /* support functions */
148 static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype);
150 static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
151  ExprEvalRowtypeCache *rowcache,
152  bool *changed);
154  ExprContext *econtext, bool checkisnull);
155 
156 /* fast-path evaluation functions */
157 static Datum ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
158 static Datum ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
159 static Datum ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
160 static Datum ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull);
161 static Datum ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull);
162 static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull);
163 static Datum ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull);
164 static Datum ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull);
165 static Datum ExecJustInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
166 static Datum ExecJustOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
167 static Datum ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
168 static Datum ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
169 static Datum ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
170 static Datum ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull);
171 
172 /* execution helper functions */
174  AggStatePerTrans pertrans,
175  AggStatePerGroup pergroup,
176  ExprContext *aggcontext,
177  int setno);
179  AggStatePerTrans pertrans,
180  AggStatePerGroup pergroup,
181  ExprContext *aggcontext,
182  int setno);
183 static char *ExecGetJsonValueItemString(JsonbValue *item, bool *resnull);
184 
185 /*
186  * ScalarArrayOpExprHashEntry
187  * Hash table entry type used during EEOP_HASHED_SCALARARRAYOP
188  */
190 {
192  uint32 status; /* hash status */
193  uint32 hash; /* hash value (cached) */
195 
196 #define SH_PREFIX saophash
197 #define SH_ELEMENT_TYPE ScalarArrayOpExprHashEntry
198 #define SH_KEY_TYPE Datum
199 #define SH_SCOPE static inline
200 #define SH_DECLARE
201 #include "lib/simplehash.h"
202 
203 static bool saop_hash_element_match(struct saophash_hash *tb, Datum key1,
204  Datum key2);
205 static uint32 saop_element_hash(struct saophash_hash *tb, Datum key);
206 
207 /*
208  * ScalarArrayOpExprHashTable
209  * Hash table for EEOP_HASHED_SCALARARRAYOP
210  */
212 {
213  saophash_hash *hashtab; /* underlying hash table */
214  struct ExprEvalStep *op;
215  FmgrInfo hash_finfo; /* function's lookup data */
218 
219 /* Define parameters for ScalarArrayOpExpr hash table code generation. */
220 #define SH_PREFIX saophash
221 #define SH_ELEMENT_TYPE ScalarArrayOpExprHashEntry
222 #define SH_KEY_TYPE Datum
223 #define SH_KEY key
224 #define SH_HASH_KEY(tb, key) saop_element_hash(tb, key)
225 #define SH_EQUAL(tb, a, b) saop_hash_element_match(tb, a, b)
226 #define SH_SCOPE static inline
227 #define SH_STORE_HASH
228 #define SH_GET_HASH(tb, a) a->hash
229 #define SH_DEFINE
230 #include "lib/simplehash.h"
231 
232 /*
233  * Prepare ExprState for interpreted execution.
234  */
235 void
237 {
238  /* Ensure one-time interpreter setup has been done */
240 
241  /* Simple validity checks on expression */
242  Assert(state->steps_len >= 1);
243  Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE);
244 
245  /*
246  * Don't perform redundant initialization. This is unreachable in current
247  * cases, but might be hit if there's additional expression evaluation
248  * methods that rely on interpreted execution to work.
249  */
251  return;
252 
253  /*
254  * First time through, check whether attribute matches Var. Might not be
255  * ok anymore, due to schema changes. We do that by setting up a callback
256  * that does checking on the first call, which then sets the evalfunc
257  * callback to the actual method of execution.
258  */
259  state->evalfunc = ExecInterpExprStillValid;
260 
261  /* DIRECT_THREADED should not already be set */
262  Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0);
263 
264  /*
265  * There shouldn't be any errors before the expression is fully
266  * initialized, and even if so, it'd lead to the expression being
267  * abandoned. So we can set the flag now and save some code.
268  */
270 
271  /*
272  * Select fast-path evalfuncs for very simple expressions. "Starting up"
273  * the full interpreter is a measurable overhead for these, and these
274  * patterns occur often enough to be worth optimizing.
275  */
276  if (state->steps_len == 3)
277  {
278  ExprEvalOp step0 = state->steps[0].opcode;
279  ExprEvalOp step1 = state->steps[1].opcode;
280 
281  if (step0 == EEOP_INNER_FETCHSOME &&
282  step1 == EEOP_INNER_VAR)
283  {
284  state->evalfunc_private = (void *) ExecJustInnerVar;
285  return;
286  }
287  else if (step0 == EEOP_OUTER_FETCHSOME &&
288  step1 == EEOP_OUTER_VAR)
289  {
290  state->evalfunc_private = (void *) ExecJustOuterVar;
291  return;
292  }
293  else if (step0 == EEOP_SCAN_FETCHSOME &&
294  step1 == EEOP_SCAN_VAR)
295  {
296  state->evalfunc_private = (void *) ExecJustScanVar;
297  return;
298  }
299  else if (step0 == EEOP_INNER_FETCHSOME &&
300  step1 == EEOP_ASSIGN_INNER_VAR)
301  {
302  state->evalfunc_private = (void *) ExecJustAssignInnerVar;
303  return;
304  }
305  else if (step0 == EEOP_OUTER_FETCHSOME &&
306  step1 == EEOP_ASSIGN_OUTER_VAR)
307  {
308  state->evalfunc_private = (void *) ExecJustAssignOuterVar;
309  return;
310  }
311  else if (step0 == EEOP_SCAN_FETCHSOME &&
312  step1 == EEOP_ASSIGN_SCAN_VAR)
313  {
314  state->evalfunc_private = (void *) ExecJustAssignScanVar;
315  return;
316  }
317  else if (step0 == EEOP_CASE_TESTVAL &&
318  step1 == EEOP_FUNCEXPR_STRICT &&
319  state->steps[0].d.casetest.value)
320  {
321  state->evalfunc_private = (void *) ExecJustApplyFuncToCase;
322  return;
323  }
324  }
325  else if (state->steps_len == 2)
326  {
327  ExprEvalOp step0 = state->steps[0].opcode;
328 
329  if (step0 == EEOP_CONST)
330  {
331  state->evalfunc_private = (void *) ExecJustConst;
332  return;
333  }
334  else if (step0 == EEOP_INNER_VAR)
335  {
336  state->evalfunc_private = (void *) ExecJustInnerVarVirt;
337  return;
338  }
339  else if (step0 == EEOP_OUTER_VAR)
340  {
341  state->evalfunc_private = (void *) ExecJustOuterVarVirt;
342  return;
343  }
344  else if (step0 == EEOP_SCAN_VAR)
345  {
346  state->evalfunc_private = (void *) ExecJustScanVarVirt;
347  return;
348  }
349  else if (step0 == EEOP_ASSIGN_INNER_VAR)
350  {
351  state->evalfunc_private = (void *) ExecJustAssignInnerVarVirt;
352  return;
353  }
354  else if (step0 == EEOP_ASSIGN_OUTER_VAR)
355  {
356  state->evalfunc_private = (void *) ExecJustAssignOuterVarVirt;
357  return;
358  }
359  else if (step0 == EEOP_ASSIGN_SCAN_VAR)
360  {
361  state->evalfunc_private = (void *) ExecJustAssignScanVarVirt;
362  return;
363  }
364  }
365 
366 #if defined(EEO_USE_COMPUTED_GOTO)
367 
368  /*
369  * In the direct-threaded implementation, replace each opcode with the
370  * address to jump to. (Use ExecEvalStepOp() to get back the opcode.)
371  */
372  for (int off = 0; off < state->steps_len; off++)
373  {
374  ExprEvalStep *op = &state->steps[off];
375 
376  op->opcode = EEO_OPCODE(op->opcode);
377  }
378 
380 #endif /* EEO_USE_COMPUTED_GOTO */
381 
382  state->evalfunc_private = (void *) ExecInterpExpr;
383 }
384 
385 
386 /*
387  * Evaluate expression identified by "state" in the execution context
388  * given by "econtext". *isnull is set to the is-null flag for the result,
389  * and the Datum value is the function result.
390  *
391  * As a special case, return the dispatch table's address if state is NULL.
392  * This is used by ExecInitInterpreter to set up the dispatch_table global.
393  * (Only applies when EEO_USE_COMPUTED_GOTO is defined.)
394  */
395 static Datum
397 {
398  ExprEvalStep *op;
399  TupleTableSlot *resultslot;
400  TupleTableSlot *innerslot;
401  TupleTableSlot *outerslot;
402  TupleTableSlot *scanslot;
403 
404  /*
405  * This array has to be in the same order as enum ExprEvalOp.
406  */
407 #if defined(EEO_USE_COMPUTED_GOTO)
408  static const void *const dispatch_table[] = {
409  &&CASE_EEOP_DONE,
410  &&CASE_EEOP_INNER_FETCHSOME,
411  &&CASE_EEOP_OUTER_FETCHSOME,
412  &&CASE_EEOP_SCAN_FETCHSOME,
413  &&CASE_EEOP_INNER_VAR,
414  &&CASE_EEOP_OUTER_VAR,
415  &&CASE_EEOP_SCAN_VAR,
416  &&CASE_EEOP_INNER_SYSVAR,
417  &&CASE_EEOP_OUTER_SYSVAR,
418  &&CASE_EEOP_SCAN_SYSVAR,
419  &&CASE_EEOP_WHOLEROW,
420  &&CASE_EEOP_ASSIGN_INNER_VAR,
421  &&CASE_EEOP_ASSIGN_OUTER_VAR,
422  &&CASE_EEOP_ASSIGN_SCAN_VAR,
423  &&CASE_EEOP_ASSIGN_TMP,
424  &&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
425  &&CASE_EEOP_CONST,
426  &&CASE_EEOP_FUNCEXPR,
427  &&CASE_EEOP_FUNCEXPR_STRICT,
428  &&CASE_EEOP_FUNCEXPR_FUSAGE,
429  &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
430  &&CASE_EEOP_BOOL_AND_STEP_FIRST,
431  &&CASE_EEOP_BOOL_AND_STEP,
432  &&CASE_EEOP_BOOL_AND_STEP_LAST,
433  &&CASE_EEOP_BOOL_OR_STEP_FIRST,
434  &&CASE_EEOP_BOOL_OR_STEP,
435  &&CASE_EEOP_BOOL_OR_STEP_LAST,
436  &&CASE_EEOP_BOOL_NOT_STEP,
437  &&CASE_EEOP_QUAL,
438  &&CASE_EEOP_JUMP,
439  &&CASE_EEOP_JUMP_IF_NULL,
440  &&CASE_EEOP_JUMP_IF_NOT_NULL,
441  &&CASE_EEOP_JUMP_IF_NOT_TRUE,
442  &&CASE_EEOP_NULLTEST_ISNULL,
443  &&CASE_EEOP_NULLTEST_ISNOTNULL,
444  &&CASE_EEOP_NULLTEST_ROWISNULL,
445  &&CASE_EEOP_NULLTEST_ROWISNOTNULL,
446  &&CASE_EEOP_BOOLTEST_IS_TRUE,
447  &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
448  &&CASE_EEOP_BOOLTEST_IS_FALSE,
449  &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
450  &&CASE_EEOP_PARAM_EXEC,
451  &&CASE_EEOP_PARAM_EXTERN,
452  &&CASE_EEOP_PARAM_CALLBACK,
453  &&CASE_EEOP_PARAM_SET,
454  &&CASE_EEOP_CASE_TESTVAL,
455  &&CASE_EEOP_MAKE_READONLY,
456  &&CASE_EEOP_IOCOERCE,
457  &&CASE_EEOP_IOCOERCE_SAFE,
458  &&CASE_EEOP_DISTINCT,
459  &&CASE_EEOP_NOT_DISTINCT,
460  &&CASE_EEOP_NULLIF,
461  &&CASE_EEOP_SQLVALUEFUNCTION,
462  &&CASE_EEOP_CURRENTOFEXPR,
463  &&CASE_EEOP_NEXTVALUEEXPR,
464  &&CASE_EEOP_ARRAYEXPR,
465  &&CASE_EEOP_ARRAYCOERCE,
466  &&CASE_EEOP_ROW,
467  &&CASE_EEOP_ROWCOMPARE_STEP,
468  &&CASE_EEOP_ROWCOMPARE_FINAL,
469  &&CASE_EEOP_MINMAX,
470  &&CASE_EEOP_FIELDSELECT,
471  &&CASE_EEOP_FIELDSTORE_DEFORM,
472  &&CASE_EEOP_FIELDSTORE_FORM,
473  &&CASE_EEOP_SBSREF_SUBSCRIPTS,
474  &&CASE_EEOP_SBSREF_OLD,
475  &&CASE_EEOP_SBSREF_ASSIGN,
476  &&CASE_EEOP_SBSREF_FETCH,
477  &&CASE_EEOP_DOMAIN_TESTVAL,
478  &&CASE_EEOP_DOMAIN_NOTNULL,
479  &&CASE_EEOP_DOMAIN_CHECK,
480  &&CASE_EEOP_HASHDATUM_SET_INITVAL,
481  &&CASE_EEOP_HASHDATUM_FIRST,
482  &&CASE_EEOP_HASHDATUM_FIRST_STRICT,
483  &&CASE_EEOP_HASHDATUM_NEXT32,
484  &&CASE_EEOP_HASHDATUM_NEXT32_STRICT,
485  &&CASE_EEOP_CONVERT_ROWTYPE,
486  &&CASE_EEOP_SCALARARRAYOP,
487  &&CASE_EEOP_HASHED_SCALARARRAYOP,
488  &&CASE_EEOP_XMLEXPR,
489  &&CASE_EEOP_JSON_CONSTRUCTOR,
490  &&CASE_EEOP_IS_JSON,
491  &&CASE_EEOP_JSONEXPR_PATH,
492  &&CASE_EEOP_JSONEXPR_COERCION,
493  &&CASE_EEOP_JSONEXPR_COERCION_FINISH,
494  &&CASE_EEOP_AGGREF,
495  &&CASE_EEOP_GROUPING_FUNC,
496  &&CASE_EEOP_WINDOW_FUNC,
497  &&CASE_EEOP_MERGE_SUPPORT_FUNC,
498  &&CASE_EEOP_SUBPLAN,
499  &&CASE_EEOP_AGG_STRICT_DESERIALIZE,
500  &&CASE_EEOP_AGG_DESERIALIZE,
501  &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
502  &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
503  &&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
504  &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
505  &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL,
506  &&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
507  &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
508  &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
509  &&CASE_EEOP_AGG_PLAIN_TRANS_BYREF,
510  &&CASE_EEOP_AGG_PRESORTED_DISTINCT_SINGLE,
511  &&CASE_EEOP_AGG_PRESORTED_DISTINCT_MULTI,
512  &&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,
513  &&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,
514  &&CASE_EEOP_LAST
515  };
516 
517  StaticAssertDecl(lengthof(dispatch_table) == EEOP_LAST + 1,
518  "dispatch_table out of whack with ExprEvalOp");
519 
520  if (unlikely(state == NULL))
521  return PointerGetDatum(dispatch_table);
522 #else
523  Assert(state != NULL);
524 #endif /* EEO_USE_COMPUTED_GOTO */
525 
526  /* setup state */
527  op = state->steps;
528  resultslot = state->resultslot;
529  innerslot = econtext->ecxt_innertuple;
530  outerslot = econtext->ecxt_outertuple;
531  scanslot = econtext->ecxt_scantuple;
532 
533 #if defined(EEO_USE_COMPUTED_GOTO)
534  EEO_DISPATCH();
535 #endif
536 
537  EEO_SWITCH()
538  {
540  {
541  goto out;
542  }
543 
545  {
546  CheckOpSlotCompatibility(op, innerslot);
547 
548  slot_getsomeattrs(innerslot, op->d.fetch.last_var);
549 
550  EEO_NEXT();
551  }
552 
554  {
555  CheckOpSlotCompatibility(op, outerslot);
556 
557  slot_getsomeattrs(outerslot, op->d.fetch.last_var);
558 
559  EEO_NEXT();
560  }
561 
563  {
564  CheckOpSlotCompatibility(op, scanslot);
565 
566  slot_getsomeattrs(scanslot, op->d.fetch.last_var);
567 
568  EEO_NEXT();
569  }
570 
572  {
573  int attnum = op->d.var.attnum;
574 
575  /*
576  * Since we already extracted all referenced columns from the
577  * tuple with a FETCHSOME step, we can just grab the value
578  * directly out of the slot's decomposed-data arrays. But let's
579  * have an Assert to check that that did happen.
580  */
581  Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
582  *op->resvalue = innerslot->tts_values[attnum];
583  *op->resnull = innerslot->tts_isnull[attnum];
584 
585  EEO_NEXT();
586  }
587 
589  {
590  int attnum = op->d.var.attnum;
591 
592  /* See EEOP_INNER_VAR comments */
593 
594  Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
595  *op->resvalue = outerslot->tts_values[attnum];
596  *op->resnull = outerslot->tts_isnull[attnum];
597 
598  EEO_NEXT();
599  }
600 
602  {
603  int attnum = op->d.var.attnum;
604 
605  /* See EEOP_INNER_VAR comments */
606 
607  Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
608  *op->resvalue = scanslot->tts_values[attnum];
609  *op->resnull = scanslot->tts_isnull[attnum];
610 
611  EEO_NEXT();
612  }
613 
615  {
616  ExecEvalSysVar(state, op, econtext, innerslot);
617  EEO_NEXT();
618  }
619 
621  {
622  ExecEvalSysVar(state, op, econtext, outerslot);
623  EEO_NEXT();
624  }
625 
627  {
628  ExecEvalSysVar(state, op, econtext, scanslot);
629  EEO_NEXT();
630  }
631 
633  {
634  /* too complex for an inline implementation */
635  ExecEvalWholeRowVar(state, op, econtext);
636 
637  EEO_NEXT();
638  }
639 
641  {
642  int resultnum = op->d.assign_var.resultnum;
643  int attnum = op->d.assign_var.attnum;
644 
645  /*
646  * We do not need CheckVarSlotCompatibility here; that was taken
647  * care of at compilation time. But see EEOP_INNER_VAR comments.
648  */
649  Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
650  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
651  resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
652  resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
653 
654  EEO_NEXT();
655  }
656 
658  {
659  int resultnum = op->d.assign_var.resultnum;
660  int attnum = op->d.assign_var.attnum;
661 
662  /*
663  * We do not need CheckVarSlotCompatibility here; that was taken
664  * care of at compilation time. But see EEOP_INNER_VAR comments.
665  */
666  Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
667  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
668  resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
669  resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
670 
671  EEO_NEXT();
672  }
673 
675  {
676  int resultnum = op->d.assign_var.resultnum;
677  int attnum = op->d.assign_var.attnum;
678 
679  /*
680  * We do not need CheckVarSlotCompatibility here; that was taken
681  * care of at compilation time. But see EEOP_INNER_VAR comments.
682  */
683  Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
684  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
685  resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
686  resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
687 
688  EEO_NEXT();
689  }
690 
692  {
693  int resultnum = op->d.assign_tmp.resultnum;
694 
695  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
696  resultslot->tts_values[resultnum] = state->resvalue;
697  resultslot->tts_isnull[resultnum] = state->resnull;
698 
699  EEO_NEXT();
700  }
701 
703  {
704  int resultnum = op->d.assign_tmp.resultnum;
705 
706  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
707  resultslot->tts_isnull[resultnum] = state->resnull;
708  if (!resultslot->tts_isnull[resultnum])
709  resultslot->tts_values[resultnum] =
711  else
712  resultslot->tts_values[resultnum] = state->resvalue;
713 
714  EEO_NEXT();
715  }
716 
718  {
719  *op->resnull = op->d.constval.isnull;
720  *op->resvalue = op->d.constval.value;
721 
722  EEO_NEXT();
723  }
724 
725  /*
726  * Function-call implementations. Arguments have previously been
727  * evaluated directly into fcinfo->args.
728  *
729  * As both STRICT checks and function-usage are noticeable performance
730  * wise, and function calls are a very hot-path (they also back
731  * operators!), it's worth having so many separate opcodes.
732  *
733  * Note: the reason for using a temporary variable "d", here and in
734  * other places, is that some compilers think "*op->resvalue = f();"
735  * requires them to evaluate op->resvalue into a register before
736  * calling f(), just in case f() is able to modify op->resvalue
737  * somehow. The extra line of code can save a useless register spill
738  * and reload across the function call.
739  */
741  {
742  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
743  Datum d;
744 
745  fcinfo->isnull = false;
746  d = op->d.func.fn_addr(fcinfo);
747  *op->resvalue = d;
748  *op->resnull = fcinfo->isnull;
749 
750  EEO_NEXT();
751  }
752 
754  {
755  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
756  NullableDatum *args = fcinfo->args;
757  int nargs = op->d.func.nargs;
758  Datum d;
759 
760  /* strict function, so check for NULL args */
761  for (int argno = 0; argno < nargs; argno++)
762  {
763  if (args[argno].isnull)
764  {
765  *op->resnull = true;
766  goto strictfail;
767  }
768  }
769  fcinfo->isnull = false;
770  d = op->d.func.fn_addr(fcinfo);
771  *op->resvalue = d;
772  *op->resnull = fcinfo->isnull;
773 
774  strictfail:
775  EEO_NEXT();
776  }
777 
779  {
780  /* not common enough to inline */
781  ExecEvalFuncExprFusage(state, op, econtext);
782 
783  EEO_NEXT();
784  }
785 
787  {
788  /* not common enough to inline */
790 
791  EEO_NEXT();
792  }
793 
794  /*
795  * If any of its clauses is FALSE, an AND's result is FALSE regardless
796  * of the states of the rest of the clauses, so we can stop evaluating
797  * and return FALSE immediately. If none are FALSE and one or more is
798  * NULL, we return NULL; otherwise we return TRUE. This makes sense
799  * when you interpret NULL as "don't know": perhaps one of the "don't
800  * knows" would have been FALSE if we'd known its value. Only when
801  * all the inputs are known to be TRUE can we state confidently that
802  * the AND's result is TRUE.
803  */
805  {
806  *op->d.boolexpr.anynull = false;
807 
808  /*
809  * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
810  * same as EEOP_BOOL_AND_STEP - so fall through to that.
811  */
812 
813  /* FALL THROUGH */
814  }
815 
817  {
818  if (*op->resnull)
819  {
820  *op->d.boolexpr.anynull = true;
821  }
822  else if (!DatumGetBool(*op->resvalue))
823  {
824  /* result is already set to FALSE, need not change it */
825  /* bail out early */
826  EEO_JUMP(op->d.boolexpr.jumpdone);
827  }
828 
829  EEO_NEXT();
830  }
831 
833  {
834  if (*op->resnull)
835  {
836  /* result is already set to NULL, need not change it */
837  }
838  else if (!DatumGetBool(*op->resvalue))
839  {
840  /* result is already set to FALSE, need not change it */
841 
842  /*
843  * No point jumping early to jumpdone - would be same target
844  * (as this is the last argument to the AND expression),
845  * except more expensive.
846  */
847  }
848  else if (*op->d.boolexpr.anynull)
849  {
850  *op->resvalue = (Datum) 0;
851  *op->resnull = true;
852  }
853  else
854  {
855  /* result is already set to TRUE, need not change it */
856  }
857 
858  EEO_NEXT();
859  }
860 
861  /*
862  * If any of its clauses is TRUE, an OR's result is TRUE regardless of
863  * the states of the rest of the clauses, so we can stop evaluating
864  * and return TRUE immediately. If none are TRUE and one or more is
865  * NULL, we return NULL; otherwise we return FALSE. This makes sense
866  * when you interpret NULL as "don't know": perhaps one of the "don't
867  * knows" would have been TRUE if we'd known its value. Only when all
868  * the inputs are known to be FALSE can we state confidently that the
869  * OR's result is FALSE.
870  */
872  {
873  *op->d.boolexpr.anynull = false;
874 
875  /*
876  * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
877  * as EEOP_BOOL_OR_STEP - so fall through to that.
878  */
879 
880  /* FALL THROUGH */
881  }
882 
884  {
885  if (*op->resnull)
886  {
887  *op->d.boolexpr.anynull = true;
888  }
889  else if (DatumGetBool(*op->resvalue))
890  {
891  /* result is already set to TRUE, need not change it */
892  /* bail out early */
893  EEO_JUMP(op->d.boolexpr.jumpdone);
894  }
895 
896  EEO_NEXT();
897  }
898 
900  {
901  if (*op->resnull)
902  {
903  /* result is already set to NULL, need not change it */
904  }
905  else if (DatumGetBool(*op->resvalue))
906  {
907  /* result is already set to TRUE, need not change it */
908 
909  /*
910  * No point jumping to jumpdone - would be same target (as
911  * this is the last argument to the AND expression), except
912  * more expensive.
913  */
914  }
915  else if (*op->d.boolexpr.anynull)
916  {
917  *op->resvalue = (Datum) 0;
918  *op->resnull = true;
919  }
920  else
921  {
922  /* result is already set to FALSE, need not change it */
923  }
924 
925  EEO_NEXT();
926  }
927 
929  {
930  /*
931  * Evaluation of 'not' is simple... if expr is false, then return
932  * 'true' and vice versa. It's safe to do this even on a
933  * nominally null value, so we ignore resnull; that means that
934  * NULL in produces NULL out, which is what we want.
935  */
936  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
937 
938  EEO_NEXT();
939  }
940 
942  {
943  /* simplified version of BOOL_AND_STEP for use by ExecQual() */
944 
945  /* If argument (also result) is false or null ... */
946  if (*op->resnull ||
947  !DatumGetBool(*op->resvalue))
948  {
949  /* ... bail out early, returning FALSE */
950  *op->resnull = false;
951  *op->resvalue = BoolGetDatum(false);
952  EEO_JUMP(op->d.qualexpr.jumpdone);
953  }
954 
955  /*
956  * Otherwise, leave the TRUE value in place, in case this is the
957  * last qual. Then, TRUE is the correct answer.
958  */
959 
960  EEO_NEXT();
961  }
962 
964  {
965  /* Unconditionally jump to target step */
966  EEO_JUMP(op->d.jump.jumpdone);
967  }
968 
970  {
971  /* Transfer control if current result is null */
972  if (*op->resnull)
973  EEO_JUMP(op->d.jump.jumpdone);
974 
975  EEO_NEXT();
976  }
977 
979  {
980  /* Transfer control if current result is non-null */
981  if (!*op->resnull)
982  EEO_JUMP(op->d.jump.jumpdone);
983 
984  EEO_NEXT();
985  }
986 
988  {
989  /* Transfer control if current result is null or false */
990  if (*op->resnull || !DatumGetBool(*op->resvalue))
991  EEO_JUMP(op->d.jump.jumpdone);
992 
993  EEO_NEXT();
994  }
995 
997  {
998  *op->resvalue = BoolGetDatum(*op->resnull);
999  *op->resnull = false;
1000 
1001  EEO_NEXT();
1002  }
1003 
1005  {
1006  *op->resvalue = BoolGetDatum(!*op->resnull);
1007  *op->resnull = false;
1008 
1009  EEO_NEXT();
1010  }
1011 
1013  {
1014  /* out of line implementation: too large */
1015  ExecEvalRowNull(state, op, econtext);
1016 
1017  EEO_NEXT();
1018  }
1019 
1021  {
1022  /* out of line implementation: too large */
1023  ExecEvalRowNotNull(state, op, econtext);
1024 
1025  EEO_NEXT();
1026  }
1027 
1028  /* BooleanTest implementations for all booltesttypes */
1029 
1031  {
1032  if (*op->resnull)
1033  {
1034  *op->resvalue = BoolGetDatum(false);
1035  *op->resnull = false;
1036  }
1037  /* else, input value is the correct output as well */
1038 
1039  EEO_NEXT();
1040  }
1041 
1043  {
1044  if (*op->resnull)
1045  {
1046  *op->resvalue = BoolGetDatum(true);
1047  *op->resnull = false;
1048  }
1049  else
1050  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
1051 
1052  EEO_NEXT();
1053  }
1054 
1056  {
1057  if (*op->resnull)
1058  {
1059  *op->resvalue = BoolGetDatum(false);
1060  *op->resnull = false;
1061  }
1062  else
1063  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
1064 
1065  EEO_NEXT();
1066  }
1067 
1069  {
1070  if (*op->resnull)
1071  {
1072  *op->resvalue = BoolGetDatum(true);
1073  *op->resnull = false;
1074  }
1075  /* else, input value is the correct output as well */
1076 
1077  EEO_NEXT();
1078  }
1079 
1081  {
1082  /* out of line implementation: too large */
1083  ExecEvalParamExec(state, op, econtext);
1084 
1085  EEO_NEXT();
1086  }
1087 
1089  {
1090  /* out of line implementation: too large */
1091  ExecEvalParamExtern(state, op, econtext);
1092  EEO_NEXT();
1093  }
1094 
1096  {
1097  /* allow an extension module to supply a PARAM_EXTERN value */
1098  op->d.cparam.paramfunc(state, op, econtext);
1099  EEO_NEXT();
1100  }
1101 
1103  {
1104  /* out of line, unlikely to matter performance-wise */
1105  ExecEvalParamSet(state, op, econtext);
1106  EEO_NEXT();
1107  }
1108 
1110  {
1111  /*
1112  * Normally upper parts of the expression tree have setup the
1113  * values to be returned here, but some parts of the system
1114  * currently misuse {caseValue,domainValue}_{datum,isNull} to set
1115  * run-time data. So if no values have been set-up, use
1116  * ExprContext's. This isn't pretty, but also not *that* ugly,
1117  * and this is unlikely to be performance sensitive enough to
1118  * worry about an extra branch.
1119  */
1120  if (op->d.casetest.value)
1121  {
1122  *op->resvalue = *op->d.casetest.value;
1123  *op->resnull = *op->d.casetest.isnull;
1124  }
1125  else
1126  {
1127  *op->resvalue = econtext->caseValue_datum;
1128  *op->resnull = econtext->caseValue_isNull;
1129  }
1130 
1131  EEO_NEXT();
1132  }
1133 
1135  {
1136  /*
1137  * See EEOP_CASE_TESTVAL comment.
1138  */
1139  if (op->d.casetest.value)
1140  {
1141  *op->resvalue = *op->d.casetest.value;
1142  *op->resnull = *op->d.casetest.isnull;
1143  }
1144  else
1145  {
1146  *op->resvalue = econtext->domainValue_datum;
1147  *op->resnull = econtext->domainValue_isNull;
1148  }
1149 
1150  EEO_NEXT();
1151  }
1152 
1154  {
1155  /*
1156  * Force a varlena value that might be read multiple times to R/O
1157  */
1158  if (!*op->d.make_readonly.isnull)
1159  *op->resvalue =
1160  MakeExpandedObjectReadOnlyInternal(*op->d.make_readonly.value);
1161  *op->resnull = *op->d.make_readonly.isnull;
1162 
1163  EEO_NEXT();
1164  }
1165 
1167  {
1168  /*
1169  * Evaluate a CoerceViaIO node. This can be quite a hot path, so
1170  * inline as much work as possible. The source value is in our
1171  * result variable.
1172  *
1173  * Also look at ExecEvalCoerceViaIOSafe() if you change anything
1174  * here.
1175  */
1176  char *str;
1177 
1178  /* call output function (similar to OutputFunctionCall) */
1179  if (*op->resnull)
1180  {
1181  /* output functions are not called on nulls */
1182  str = NULL;
1183  }
1184  else
1185  {
1186  FunctionCallInfo fcinfo_out;
1187 
1188  fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1189  fcinfo_out->args[0].value = *op->resvalue;
1190  fcinfo_out->args[0].isnull = false;
1191 
1192  fcinfo_out->isnull = false;
1193  str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
1194 
1195  /* OutputFunctionCall assumes result isn't null */
1196  Assert(!fcinfo_out->isnull);
1197  }
1198 
1199  /* call input function (similar to InputFunctionCall) */
1200  if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
1201  {
1202  FunctionCallInfo fcinfo_in;
1203  Datum d;
1204 
1205  fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1206  fcinfo_in->args[0].value = PointerGetDatum(str);
1207  fcinfo_in->args[0].isnull = *op->resnull;
1208  /* second and third arguments are already set up */
1209 
1210  fcinfo_in->isnull = false;
1211  d = FunctionCallInvoke(fcinfo_in);
1212  *op->resvalue = d;
1213 
1214  /* Should get null result if and only if str is NULL */
1215  if (str == NULL)
1216  {
1217  Assert(*op->resnull);
1218  Assert(fcinfo_in->isnull);
1219  }
1220  else
1221  {
1222  Assert(!*op->resnull);
1223  Assert(!fcinfo_in->isnull);
1224  }
1225  }
1226 
1227  EEO_NEXT();
1228  }
1229 
1231  {
1233  EEO_NEXT();
1234  }
1235 
1237  {
1238  /*
1239  * IS DISTINCT FROM must evaluate arguments (already done into
1240  * fcinfo->args) to determine whether they are NULL; if either is
1241  * NULL then the result is determined. If neither is NULL, then
1242  * proceed to evaluate the comparison function, which is just the
1243  * type's standard equality operator. We need not care whether
1244  * that function is strict. Because the handling of nulls is
1245  * different, we can't just reuse EEOP_FUNCEXPR.
1246  */
1247  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1248 
1249  /* check function arguments for NULLness */
1250  if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
1251  {
1252  /* Both NULL? Then is not distinct... */
1253  *op->resvalue = BoolGetDatum(false);
1254  *op->resnull = false;
1255  }
1256  else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
1257  {
1258  /* Only one is NULL? Then is distinct... */
1259  *op->resvalue = BoolGetDatum(true);
1260  *op->resnull = false;
1261  }
1262  else
1263  {
1264  /* Neither null, so apply the equality function */
1265  Datum eqresult;
1266 
1267  fcinfo->isnull = false;
1268  eqresult = op->d.func.fn_addr(fcinfo);
1269  /* Must invert result of "="; safe to do even if null */
1270  *op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
1271  *op->resnull = fcinfo->isnull;
1272  }
1273 
1274  EEO_NEXT();
1275  }
1276 
1277  /* see EEOP_DISTINCT for comments, this is just inverted */
1279  {
1280  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1281 
1282  if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
1283  {
1284  *op->resvalue = BoolGetDatum(true);
1285  *op->resnull = false;
1286  }
1287  else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
1288  {
1289  *op->resvalue = BoolGetDatum(false);
1290  *op->resnull = false;
1291  }
1292  else
1293  {
1294  Datum eqresult;
1295 
1296  fcinfo->isnull = false;
1297  eqresult = op->d.func.fn_addr(fcinfo);
1298  *op->resvalue = eqresult;
1299  *op->resnull = fcinfo->isnull;
1300  }
1301 
1302  EEO_NEXT();
1303  }
1304 
1306  {
1307  /*
1308  * The arguments are already evaluated into fcinfo->args.
1309  */
1310  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1311 
1312  /* if either argument is NULL they can't be equal */
1313  if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
1314  {
1315  Datum result;
1316 
1317  fcinfo->isnull = false;
1318  result = op->d.func.fn_addr(fcinfo);
1319 
1320  /* if the arguments are equal return null */
1321  if (!fcinfo->isnull && DatumGetBool(result))
1322  {
1323  *op->resvalue = (Datum) 0;
1324  *op->resnull = true;
1325 
1326  EEO_NEXT();
1327  }
1328  }
1329 
1330  /* Arguments aren't equal, so return the first one */
1331  *op->resvalue = fcinfo->args[0].value;
1332  *op->resnull = fcinfo->args[0].isnull;
1333 
1334  EEO_NEXT();
1335  }
1336 
1338  {
1339  /*
1340  * Doesn't seem worthwhile to have an inline implementation
1341  * efficiency-wise.
1342  */
1344 
1345  EEO_NEXT();
1346  }
1347 
1349  {
1350  /* error invocation uses space, and shouldn't ever occur */
1352 
1353  EEO_NEXT();
1354  }
1355 
1357  {
1358  /*
1359  * Doesn't seem worthwhile to have an inline implementation
1360  * efficiency-wise.
1361  */
1363 
1364  EEO_NEXT();
1365  }
1366 
1368  {
1369  /* too complex for an inline implementation */
1371 
1372  EEO_NEXT();
1373  }
1374 
1376  {
1377  /* too complex for an inline implementation */
1378  ExecEvalArrayCoerce(state, op, econtext);
1379 
1380  EEO_NEXT();
1381  }
1382 
1384  {
1385  /* too complex for an inline implementation */
1386  ExecEvalRow(state, op);
1387 
1388  EEO_NEXT();
1389  }
1390 
1392  {
1393  FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1394  Datum d;
1395 
1396  /* force NULL result if strict fn and NULL input */
1397  if (op->d.rowcompare_step.finfo->fn_strict &&
1398  (fcinfo->args[0].isnull || fcinfo->args[1].isnull))
1399  {
1400  *op->resnull = true;
1401  EEO_JUMP(op->d.rowcompare_step.jumpnull);
1402  }
1403 
1404  /* Apply comparison function */
1405  fcinfo->isnull = false;
1406  d = op->d.rowcompare_step.fn_addr(fcinfo);
1407  *op->resvalue = d;
1408 
1409  /* force NULL result if NULL function result */
1410  if (fcinfo->isnull)
1411  {
1412  *op->resnull = true;
1413  EEO_JUMP(op->d.rowcompare_step.jumpnull);
1414  }
1415  *op->resnull = false;
1416 
1417  /* If unequal, no need to compare remaining columns */
1418  if (DatumGetInt32(*op->resvalue) != 0)
1419  {
1420  EEO_JUMP(op->d.rowcompare_step.jumpdone);
1421  }
1422 
1423  EEO_NEXT();
1424  }
1425 
1427  {
1428  int32 cmpresult = DatumGetInt32(*op->resvalue);
1429  RowCompareType rctype = op->d.rowcompare_final.rctype;
1430 
1431  *op->resnull = false;
1432  switch (rctype)
1433  {
1434  /* EQ and NE cases aren't allowed here */
1435  case ROWCOMPARE_LT:
1436  *op->resvalue = BoolGetDatum(cmpresult < 0);
1437  break;
1438  case ROWCOMPARE_LE:
1439  *op->resvalue = BoolGetDatum(cmpresult <= 0);
1440  break;
1441  case ROWCOMPARE_GE:
1442  *op->resvalue = BoolGetDatum(cmpresult >= 0);
1443  break;
1444  case ROWCOMPARE_GT:
1445  *op->resvalue = BoolGetDatum(cmpresult > 0);
1446  break;
1447  default:
1448  Assert(false);
1449  break;
1450  }
1451 
1452  EEO_NEXT();
1453  }
1454 
1456  {
1457  /* too complex for an inline implementation */
1459 
1460  EEO_NEXT();
1461  }
1462 
1464  {
1465  /* too complex for an inline implementation */
1466  ExecEvalFieldSelect(state, op, econtext);
1467 
1468  EEO_NEXT();
1469  }
1470 
1472  {
1473  /* too complex for an inline implementation */
1474  ExecEvalFieldStoreDeForm(state, op, econtext);
1475 
1476  EEO_NEXT();
1477  }
1478 
1480  {
1481  /* too complex for an inline implementation */
1482  ExecEvalFieldStoreForm(state, op, econtext);
1483 
1484  EEO_NEXT();
1485  }
1486 
1488  {
1489  /* Precheck SubscriptingRef subscript(s) */
1490  if (op->d.sbsref_subscript.subscriptfunc(state, op, econtext))
1491  {
1492  EEO_NEXT();
1493  }
1494  else
1495  {
1496  /* Subscript is null, short-circuit SubscriptingRef to NULL */
1497  EEO_JUMP(op->d.sbsref_subscript.jumpdone);
1498  }
1499  }
1500 
1504  {
1505  /* Perform a SubscriptingRef fetch or assignment */
1506  op->d.sbsref.subscriptfunc(state, op, econtext);
1507 
1508  EEO_NEXT();
1509  }
1510 
1512  {
1513  /* too complex for an inline implementation */
1514  ExecEvalConvertRowtype(state, op, econtext);
1515 
1516  EEO_NEXT();
1517  }
1518 
1520  {
1521  /* too complex for an inline implementation */
1523 
1524  EEO_NEXT();
1525  }
1526 
1528  {
1529  /* too complex for an inline implementation */
1530  ExecEvalHashedScalarArrayOp(state, op, econtext);
1531 
1532  EEO_NEXT();
1533  }
1534 
1536  {
1537  /* too complex for an inline implementation */
1539 
1540  EEO_NEXT();
1541  }
1542 
1544  {
1545  /* too complex for an inline implementation */
1547 
1548  EEO_NEXT();
1549  }
1550 
1552  {
1553  *op->resvalue = op->d.hashdatum_initvalue.init_value;
1554  *op->resnull = false;
1555 
1556  EEO_NEXT();
1557  }
1558 
1560  {
1561  FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data;
1562 
1563  /*
1564  * Save the Datum on non-null inputs, otherwise store 0 so that
1565  * subsequent NEXT32 operations combine with an initialized value.
1566  */
1567  if (!fcinfo->args[0].isnull)
1568  *op->resvalue = op->d.hashdatum.fn_addr(fcinfo);
1569  else
1570  *op->resvalue = (Datum) 0;
1571 
1572  *op->resnull = false;
1573 
1574  EEO_NEXT();
1575  }
1576 
1578  {
1579  FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data;
1580 
1581  if (fcinfo->args[0].isnull)
1582  {
1583  /*
1584  * With strict we have the expression return NULL instead of
1585  * ignoring NULL input values. We've nothing more to do after
1586  * finding a NULL.
1587  */
1588  *op->resnull = true;
1589  *op->resvalue = (Datum) 0;
1590  EEO_JUMP(op->d.hashdatum.jumpdone);
1591  }
1592 
1593  /* execute the hash function and save the resulting value */
1594  *op->resvalue = op->d.hashdatum.fn_addr(fcinfo);
1595  *op->resnull = false;
1596 
1597  EEO_NEXT();
1598  }
1599 
1601  {
1602  FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data;
1603  uint32 existing_hash = DatumGetUInt32(*op->resvalue);
1604 
1605  /* combine successive hash values by rotating */
1606  existing_hash = pg_rotate_left32(existing_hash, 1);
1607 
1608  /* leave the hash value alone on NULL inputs */
1609  if (!fcinfo->args[0].isnull)
1610  {
1611  uint32 hashvalue;
1612 
1613  /* execute hash func and combine with previous hash value */
1614  hashvalue = DatumGetUInt32(op->d.hashdatum.fn_addr(fcinfo));
1615  existing_hash = existing_hash ^ hashvalue;
1616  }
1617 
1618  *op->resvalue = UInt32GetDatum(existing_hash);
1619  *op->resnull = false;
1620 
1621  EEO_NEXT();
1622  }
1623 
1625  {
1626  FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data;
1627 
1628  if (fcinfo->args[0].isnull)
1629  {
1630  /*
1631  * With strict we have the expression return NULL instead of
1632  * ignoring NULL input values. We've nothing more to do after
1633  * finding a NULL.
1634  */
1635  *op->resnull = true;
1636  *op->resvalue = (Datum) 0;
1637  EEO_JUMP(op->d.hashdatum.jumpdone);
1638  }
1639  else
1640  {
1641  uint32 existing_hash = DatumGetUInt32(*op->resvalue);
1642  uint32 hashvalue;
1643 
1644  /* combine successive hash values by rotating */
1645  existing_hash = pg_rotate_left32(existing_hash, 1);
1646 
1647  /* execute hash func and combine with previous hash value */
1648  hashvalue = DatumGetUInt32(op->d.hashdatum.fn_addr(fcinfo));
1649  *op->resvalue = UInt32GetDatum(existing_hash ^ hashvalue);
1650  *op->resnull = false;
1651  }
1652 
1653  EEO_NEXT();
1654  }
1655 
1657  {
1658  /* too complex for an inline implementation */
1660 
1661  EEO_NEXT();
1662  }
1663 
1665  {
1666  /* too complex for an inline implementation */
1667  ExecEvalJsonConstructor(state, op, econtext);
1668  EEO_NEXT();
1669  }
1670 
1672  {
1673  /* too complex for an inline implementation */
1675 
1676  EEO_NEXT();
1677  }
1678 
1680  {
1681  /* too complex for an inline implementation */
1682  EEO_JUMP(ExecEvalJsonExprPath(state, op, econtext));
1683  }
1684 
1686  {
1687  /* too complex for an inline implementation */
1688  ExecEvalJsonCoercion(state, op, econtext);
1689 
1690  EEO_NEXT();
1691  }
1692 
1694  {
1695  /* too complex for an inline implementation */
1697 
1698  EEO_NEXT();
1699  }
1700 
1702  {
1703  /*
1704  * Returns a Datum whose value is the precomputed aggregate value
1705  * found in the given expression context.
1706  */
1707  int aggno = op->d.aggref.aggno;
1708 
1709  Assert(econtext->ecxt_aggvalues != NULL);
1710 
1711  *op->resvalue = econtext->ecxt_aggvalues[aggno];
1712  *op->resnull = econtext->ecxt_aggnulls[aggno];
1713 
1714  EEO_NEXT();
1715  }
1716 
1718  {
1719  /* too complex/uncommon for an inline implementation */
1721 
1722  EEO_NEXT();
1723  }
1724 
1726  {
1727  /*
1728  * Like Aggref, just return a precomputed value from the econtext.
1729  */
1730  WindowFuncExprState *wfunc = op->d.window_func.wfstate;
1731 
1732  Assert(econtext->ecxt_aggvalues != NULL);
1733 
1734  *op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
1735  *op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
1736 
1737  EEO_NEXT();
1738  }
1739 
1741  {
1742  /* too complex/uncommon for an inline implementation */
1743  ExecEvalMergeSupportFunc(state, op, econtext);
1744 
1745  EEO_NEXT();
1746  }
1747 
1749  {
1750  /* too complex for an inline implementation */
1751  ExecEvalSubPlan(state, op, econtext);
1752 
1753  EEO_NEXT();
1754  }
1755 
1756  /* evaluate a strict aggregate deserialization function */
1758  {
1759  /* Don't call a strict deserialization function with NULL input */
1760  if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
1761  EEO_JUMP(op->d.agg_deserialize.jumpnull);
1762 
1763  /* fallthrough */
1764  }
1765 
1766  /* evaluate aggregate deserialization function (non-strict portion) */
1768  {
1769  FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
1770  AggState *aggstate = castNode(AggState, state->parent);
1771  MemoryContext oldContext;
1772 
1773  /*
1774  * We run the deserialization functions in per-input-tuple memory
1775  * context.
1776  */
1777  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
1778  fcinfo->isnull = false;
1779  *op->resvalue = FunctionCallInvoke(fcinfo);
1780  *op->resnull = fcinfo->isnull;
1781  MemoryContextSwitchTo(oldContext);
1782 
1783  EEO_NEXT();
1784  }
1785 
1786  /*
1787  * Check that a strict aggregate transition / combination function's
1788  * input is not NULL.
1789  */
1790 
1792  {
1793  NullableDatum *args = op->d.agg_strict_input_check.args;
1794  int nargs = op->d.agg_strict_input_check.nargs;
1795 
1796  for (int argno = 0; argno < nargs; argno++)
1797  {
1798  if (args[argno].isnull)
1799  EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
1800  }
1801  EEO_NEXT();
1802  }
1803 
1805  {
1806  bool *nulls = op->d.agg_strict_input_check.nulls;
1807  int nargs = op->d.agg_strict_input_check.nargs;
1808 
1809  for (int argno = 0; argno < nargs; argno++)
1810  {
1811  if (nulls[argno])
1812  EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
1813  }
1814  EEO_NEXT();
1815  }
1816 
1817  /*
1818  * Check for a NULL pointer to the per-group states.
1819  */
1820 
1822  {
1823  AggState *aggstate = castNode(AggState, state->parent);
1824  AggStatePerGroup pergroup_allaggs =
1825  aggstate->all_pergroups[op->d.agg_plain_pergroup_nullcheck.setoff];
1826 
1827  if (pergroup_allaggs == NULL)
1828  EEO_JUMP(op->d.agg_plain_pergroup_nullcheck.jumpnull);
1829 
1830  EEO_NEXT();
1831  }
1832 
1833  /*
1834  * Different types of aggregate transition functions are implemented
1835  * as different types of steps, to avoid incurring unnecessary
1836  * overhead. There's a step type for each valid combination of having
1837  * a by value / by reference transition type, [not] needing to the
1838  * initialize the transition value for the first row in a group from
1839  * input, and [not] strict transition function.
1840  *
1841  * Could optimize further by splitting off by-reference for
1842  * fixed-length types, but currently that doesn't seem worth it.
1843  */
1844 
1846  {
1847  AggState *aggstate = castNode(AggState, state->parent);
1848  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1849  AggStatePerGroup pergroup =
1850  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1851 
1853 
1854  if (pergroup->noTransValue)
1855  {
1856  /* If transValue has not yet been initialized, do so now. */
1857  ExecAggInitGroup(aggstate, pertrans, pergroup,
1858  op->d.agg_trans.aggcontext);
1859  /* copied trans value from input, done this round */
1860  }
1861  else if (likely(!pergroup->transValueIsNull))
1862  {
1863  /* invoke transition function, unless prevented by strictness */
1864  ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1865  op->d.agg_trans.aggcontext,
1866  op->d.agg_trans.setno);
1867  }
1868 
1869  EEO_NEXT();
1870  }
1871 
1872  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1874  {
1875  AggState *aggstate = castNode(AggState, state->parent);
1876  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1877  AggStatePerGroup pergroup =
1878  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1879 
1881 
1882  if (likely(!pergroup->transValueIsNull))
1883  ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1884  op->d.agg_trans.aggcontext,
1885  op->d.agg_trans.setno);
1886 
1887  EEO_NEXT();
1888  }
1889 
1890  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1892  {
1893  AggState *aggstate = castNode(AggState, state->parent);
1894  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1895  AggStatePerGroup pergroup =
1896  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1897 
1899 
1900  ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1901  op->d.agg_trans.aggcontext,
1902  op->d.agg_trans.setno);
1903 
1904  EEO_NEXT();
1905  }
1906 
1907  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1909  {
1910  AggState *aggstate = castNode(AggState, state->parent);
1911  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1912  AggStatePerGroup pergroup =
1913  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1914 
1916 
1917  if (pergroup->noTransValue)
1918  ExecAggInitGroup(aggstate, pertrans, pergroup,
1919  op->d.agg_trans.aggcontext);
1920  else if (likely(!pergroup->transValueIsNull))
1921  ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1922  op->d.agg_trans.aggcontext,
1923  op->d.agg_trans.setno);
1924 
1925  EEO_NEXT();
1926  }
1927 
1928  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1930  {
1931  AggState *aggstate = castNode(AggState, state->parent);
1932  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1933  AggStatePerGroup pergroup =
1934  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1935 
1937 
1938  if (likely(!pergroup->transValueIsNull))
1939  ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1940  op->d.agg_trans.aggcontext,
1941  op->d.agg_trans.setno);
1942  EEO_NEXT();
1943  }
1944 
1945  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1947  {
1948  AggState *aggstate = castNode(AggState, state->parent);
1949  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1950  AggStatePerGroup pergroup =
1951  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1952 
1954 
1955  ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1956  op->d.agg_trans.aggcontext,
1957  op->d.agg_trans.setno);
1958 
1959  EEO_NEXT();
1960  }
1961 
1963  {
1964  AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
1965  AggState *aggstate = castNode(AggState, state->parent);
1966 
1968  EEO_NEXT();
1969  else
1970  EEO_JUMP(op->d.agg_presorted_distinctcheck.jumpdistinct);
1971  }
1972 
1974  {
1975  AggState *aggstate = castNode(AggState, state->parent);
1976  AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
1977 
1979  EEO_NEXT();
1980  else
1981  EEO_JUMP(op->d.agg_presorted_distinctcheck.jumpdistinct);
1982  }
1983 
1984  /* process single-column ordered aggregate datum */
1986  {
1987  /* too complex for an inline implementation */
1989 
1990  EEO_NEXT();
1991  }
1992 
1993  /* process multi-column ordered aggregate tuple */
1995  {
1996  /* too complex for an inline implementation */
1998 
1999  EEO_NEXT();
2000  }
2001 
2003  {
2004  /* unreachable */
2005  Assert(false);
2006  goto out;
2007  }
2008  }
2009 
2010 out:
2011  *isnull = state->resnull;
2012  return state->resvalue;
2013 }
2014 
2015 /*
2016  * Expression evaluation callback that performs extra checks before executing
2017  * the expression. Declared extern so other methods of execution can use it
2018  * too.
2019  */
2020 Datum
2022 {
2023  /*
2024  * First time through, check whether attribute matches Var. Might not be
2025  * ok anymore, due to schema changes.
2026  */
2027  CheckExprStillValid(state, econtext);
2028 
2029  /* skip the check during further executions */
2030  state->evalfunc = (ExprStateEvalFunc) state->evalfunc_private;
2031 
2032  /* and actually execute */
2033  return state->evalfunc(state, econtext, isNull);
2034 }
2035 
2036 /*
2037  * Check that an expression is still valid in the face of potential schema
2038  * changes since the plan has been created.
2039  */
2040 void
2042 {
2043  TupleTableSlot *innerslot;
2044  TupleTableSlot *outerslot;
2045  TupleTableSlot *scanslot;
2046 
2047  innerslot = econtext->ecxt_innertuple;
2048  outerslot = econtext->ecxt_outertuple;
2049  scanslot = econtext->ecxt_scantuple;
2050 
2051  for (int i = 0; i < state->steps_len; i++)
2052  {
2053  ExprEvalStep *op = &state->steps[i];
2054 
2055  switch (ExecEvalStepOp(state, op))
2056  {
2057  case EEOP_INNER_VAR:
2058  {
2059  int attnum = op->d.var.attnum;
2060 
2061  CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
2062  break;
2063  }
2064 
2065  case EEOP_OUTER_VAR:
2066  {
2067  int attnum = op->d.var.attnum;
2068 
2069  CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
2070  break;
2071  }
2072 
2073  case EEOP_SCAN_VAR:
2074  {
2075  int attnum = op->d.var.attnum;
2076 
2077  CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
2078  break;
2079  }
2080  default:
2081  break;
2082  }
2083  }
2084 }
2085 
2086 /*
2087  * Check whether a user attribute in a slot can be referenced by a Var
2088  * expression. This should succeed unless there have been schema changes
2089  * since the expression tree has been created.
2090  */
2091 static void
2093 {
2094  /*
2095  * What we have to check for here is the possibility of an attribute
2096  * having been dropped or changed in type since the plan tree was created.
2097  * Ideally the plan will get invalidated and not re-used, but just in
2098  * case, we keep these defenses. Fortunately it's sufficient to check
2099  * once on the first time through.
2100  *
2101  * Note: ideally we'd check typmod as well as typid, but that seems
2102  * impractical at the moment: in many cases the tupdesc will have been
2103  * generated by ExecTypeFromTL(), and that can't guarantee to generate an
2104  * accurate typmod in all cases, because some expression node types don't
2105  * carry typmod. Fortunately, for precisely that reason, there should be
2106  * no places with a critical dependency on the typmod of a value.
2107  *
2108  * System attributes don't require checking since their types never
2109  * change.
2110  */
2111  if (attnum > 0)
2112  {
2113  TupleDesc slot_tupdesc = slot->tts_tupleDescriptor;
2114  Form_pg_attribute attr;
2115 
2116  if (attnum > slot_tupdesc->natts) /* should never happen */
2117  elog(ERROR, "attribute number %d exceeds number of columns %d",
2118  attnum, slot_tupdesc->natts);
2119 
2120  attr = TupleDescAttr(slot_tupdesc, attnum - 1);
2121 
2122  if (attr->attisdropped)
2123  ereport(ERROR,
2124  (errcode(ERRCODE_UNDEFINED_COLUMN),
2125  errmsg("attribute %d of type %s has been dropped",
2126  attnum, format_type_be(slot_tupdesc->tdtypeid))));
2127 
2128  if (vartype != attr->atttypid)
2129  ereport(ERROR,
2130  (errcode(ERRCODE_DATATYPE_MISMATCH),
2131  errmsg("attribute %d of type %s has wrong type",
2132  attnum, format_type_be(slot_tupdesc->tdtypeid)),
2133  errdetail("Table has type %s, but query expects %s.",
2134  format_type_be(attr->atttypid),
2135  format_type_be(vartype))));
2136  }
2137 }
2138 
2139 /*
2140  * Verify that the slot is compatible with a EEOP_*_FETCHSOME operation.
2141  */
2142 static void
2144 {
2145 #ifdef USE_ASSERT_CHECKING
2146  /* there's nothing to check */
2147  if (!op->d.fetch.fixed)
2148  return;
2149 
2150  /*
2151  * Should probably fixed at some point, but for now it's easier to allow
2152  * buffer and heap tuples to be used interchangeably.
2153  */
2154  if (slot->tts_ops == &TTSOpsBufferHeapTuple &&
2155  op->d.fetch.kind == &TTSOpsHeapTuple)
2156  return;
2157  if (slot->tts_ops == &TTSOpsHeapTuple &&
2158  op->d.fetch.kind == &TTSOpsBufferHeapTuple)
2159  return;
2160 
2161  /*
2162  * At the moment we consider it OK if a virtual slot is used instead of a
2163  * specific type of slot, as a virtual slot never needs to be deformed.
2164  */
2165  if (slot->tts_ops == &TTSOpsVirtual)
2166  return;
2167 
2168  Assert(op->d.fetch.kind == slot->tts_ops);
2169 #endif
2170 }
2171 
2172 /*
2173  * get_cached_rowtype: utility function to lookup a rowtype tupdesc
2174  *
2175  * type_id, typmod: identity of the rowtype
2176  * rowcache: space for caching identity info
2177  * (rowcache->cacheptr must be initialized to NULL)
2178  * changed: if not NULL, *changed is set to true on any update
2179  *
2180  * The returned TupleDesc is not guaranteed pinned; caller must pin it
2181  * to use it across any operation that might incur cache invalidation,
2182  * including for example detoasting of input tuples.
2183  * (The TupleDesc is always refcounted, so just use IncrTupleDescRefCount.)
2184  *
2185  * NOTE: because composite types can change contents, we must be prepared
2186  * to re-do this during any node execution; cannot call just once during
2187  * expression initialization.
2188  */
2189 static TupleDesc
2190 get_cached_rowtype(Oid type_id, int32 typmod,
2192  bool *changed)
2193 {
2194  if (type_id != RECORDOID)
2195  {
2196  /*
2197  * It's a named composite type, so use the regular typcache. Do a
2198  * lookup first time through, or if the composite type changed. Note:
2199  * "tupdesc_id == 0" may look redundant, but it protects against the
2200  * admittedly-theoretical possibility that type_id was RECORDOID the
2201  * last time through, so that the cacheptr isn't TypeCacheEntry *.
2202  */
2204 
2205  if (unlikely(typentry == NULL ||
2206  rowcache->tupdesc_id == 0 ||
2207  typentry->tupDesc_identifier != rowcache->tupdesc_id))
2208  {
2209  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
2210  if (typentry->tupDesc == NULL)
2211  ereport(ERROR,
2212  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2213  errmsg("type %s is not composite",
2214  format_type_be(type_id))));
2215  rowcache->cacheptr = (void *) typentry;
2216  rowcache->tupdesc_id = typentry->tupDesc_identifier;
2217  if (changed)
2218  *changed = true;
2219  }
2220  return typentry->tupDesc;
2221  }
2222  else
2223  {
2224  /*
2225  * A RECORD type, once registered, doesn't change for the life of the
2226  * backend. So we don't need a typcache entry as such, which is good
2227  * because there isn't one. It's possible that the caller is asking
2228  * about a different type than before, though.
2229  */
2230  TupleDesc tupDesc = (TupleDesc) rowcache->cacheptr;
2231 
2232  if (unlikely(tupDesc == NULL ||
2233  rowcache->tupdesc_id != 0 ||
2234  type_id != tupDesc->tdtypeid ||
2235  typmod != tupDesc->tdtypmod))
2236  {
2237  tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
2238  /* Drop pin acquired by lookup_rowtype_tupdesc */
2239  ReleaseTupleDesc(tupDesc);
2240  rowcache->cacheptr = (void *) tupDesc;
2241  rowcache->tupdesc_id = 0; /* not a valid value for non-RECORD */
2242  if (changed)
2243  *changed = true;
2244  }
2245  return tupDesc;
2246  }
2247 }
2248 
2249 
2250 /*
2251  * Fast-path functions, for very simple expressions
2252  */
2253 
2254 /* implementation of ExecJust(Inner|Outer|Scan)Var */
2257 {
2258  ExprEvalStep *op = &state->steps[1];
2259  int attnum = op->d.var.attnum + 1;
2260 
2261  CheckOpSlotCompatibility(&state->steps[0], slot);
2262 
2263  /*
2264  * Since we use slot_getattr(), we don't need to implement the FETCHSOME
2265  * step explicitly, and we also needn't Assert that the attnum is in range
2266  * --- slot_getattr() will take care of any problems.
2267  */
2268  return slot_getattr(slot, attnum, isnull);
2269 }
2270 
2271 /* Simple reference to inner Var */
2272 static Datum
2274 {
2275  return ExecJustVarImpl(state, econtext->ecxt_innertuple, isnull);
2276 }
2277 
2278 /* Simple reference to outer Var */
2279 static Datum
2281 {
2282  return ExecJustVarImpl(state, econtext->ecxt_outertuple, isnull);
2283 }
2284 
2285 /* Simple reference to scan Var */
2286 static Datum
2288 {
2289  return ExecJustVarImpl(state, econtext->ecxt_scantuple, isnull);
2290 }
2291 
2292 /* implementation of ExecJustAssign(Inner|Outer|Scan)Var */
2295 {
2296  ExprEvalStep *op = &state->steps[1];
2297  int attnum = op->d.assign_var.attnum + 1;
2298  int resultnum = op->d.assign_var.resultnum;
2299  TupleTableSlot *outslot = state->resultslot;
2300 
2301  CheckOpSlotCompatibility(&state->steps[0], inslot);
2302 
2303  /*
2304  * We do not need CheckVarSlotCompatibility here; that was taken care of
2305  * at compilation time.
2306  *
2307  * Since we use slot_getattr(), we don't need to implement the FETCHSOME
2308  * step explicitly, and we also needn't Assert that the attnum is in range
2309  * --- slot_getattr() will take care of any problems. Nonetheless, check
2310  * that resultnum is in range.
2311  */
2312  Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
2313  outslot->tts_values[resultnum] =
2314  slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
2315  return 0;
2316 }
2317 
2318 /* Evaluate inner Var and assign to appropriate column of result tuple */
2319 static Datum
2321 {
2322  return ExecJustAssignVarImpl(state, econtext->ecxt_innertuple, isnull);
2323 }
2324 
2325 /* Evaluate outer Var and assign to appropriate column of result tuple */
2326 static Datum
2328 {
2329  return ExecJustAssignVarImpl(state, econtext->ecxt_outertuple, isnull);
2330 }
2331 
2332 /* Evaluate scan Var and assign to appropriate column of result tuple */
2333 static Datum
2335 {
2336  return ExecJustAssignVarImpl(state, econtext->ecxt_scantuple, isnull);
2337 }
2338 
2339 /* Evaluate CASE_TESTVAL and apply a strict function to it */
2340 static Datum
2342 {
2343  ExprEvalStep *op = &state->steps[0];
2344  FunctionCallInfo fcinfo;
2346  int nargs;
2347  Datum d;
2348 
2349  /*
2350  * XXX with some redesign of the CaseTestExpr mechanism, maybe we could
2351  * get rid of this data shuffling?
2352  */
2353  *op->resvalue = *op->d.casetest.value;
2354  *op->resnull = *op->d.casetest.isnull;
2355 
2356  op++;
2357 
2358  nargs = op->d.func.nargs;
2359  fcinfo = op->d.func.fcinfo_data;
2360  args = fcinfo->args;
2361 
2362  /* strict function, so check for NULL args */
2363  for (int argno = 0; argno < nargs; argno++)
2364  {
2365  if (args[argno].isnull)
2366  {
2367  *isnull = true;
2368  return (Datum) 0;
2369  }
2370  }
2371  fcinfo->isnull = false;
2372  d = op->d.func.fn_addr(fcinfo);
2373  *isnull = fcinfo->isnull;
2374  return d;
2375 }
2376 
2377 /* Simple Const expression */
2378 static Datum
2380 {
2381  ExprEvalStep *op = &state->steps[0];
2382 
2383  *isnull = op->d.constval.isnull;
2384  return op->d.constval.value;
2385 }
2386 
2387 /* implementation of ExecJust(Inner|Outer|Scan)VarVirt */
2390 {
2391  ExprEvalStep *op = &state->steps[0];
2392  int attnum = op->d.var.attnum;
2393 
2394  /*
2395  * As it is guaranteed that a virtual slot is used, there never is a need
2396  * to perform tuple deforming (nor would it be possible). Therefore
2397  * execExpr.c has not emitted an EEOP_*_FETCHSOME step. Verify, as much as
2398  * possible, that that determination was accurate.
2399  */
2400  Assert(TTS_IS_VIRTUAL(slot));
2401  Assert(TTS_FIXED(slot));
2402  Assert(attnum >= 0 && attnum < slot->tts_nvalid);
2403 
2404  *isnull = slot->tts_isnull[attnum];
2405 
2406  return slot->tts_values[attnum];
2407 }
2408 
2409 /* Like ExecJustInnerVar, optimized for virtual slots */
2410 static Datum
2412 {
2413  return ExecJustVarVirtImpl(state, econtext->ecxt_innertuple, isnull);
2414 }
2415 
2416 /* Like ExecJustOuterVar, optimized for virtual slots */
2417 static Datum
2419 {
2420  return ExecJustVarVirtImpl(state, econtext->ecxt_outertuple, isnull);
2421 }
2422 
2423 /* Like ExecJustScanVar, optimized for virtual slots */
2424 static Datum
2426 {
2427  return ExecJustVarVirtImpl(state, econtext->ecxt_scantuple, isnull);
2428 }
2429 
2430 /* implementation of ExecJustAssign(Inner|Outer|Scan)VarVirt */
2433 {
2434  ExprEvalStep *op = &state->steps[0];
2435  int attnum = op->d.assign_var.attnum;
2436  int resultnum = op->d.assign_var.resultnum;
2437  TupleTableSlot *outslot = state->resultslot;
2438 
2439  /* see ExecJustVarVirtImpl for comments */
2440 
2441  Assert(TTS_IS_VIRTUAL(inslot));
2442  Assert(TTS_FIXED(inslot));
2443  Assert(attnum >= 0 && attnum < inslot->tts_nvalid);
2444  Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
2445 
2446  outslot->tts_values[resultnum] = inslot->tts_values[attnum];
2447  outslot->tts_isnull[resultnum] = inslot->tts_isnull[attnum];
2448 
2449  return 0;
2450 }
2451 
2452 /* Like ExecJustAssignInnerVar, optimized for virtual slots */
2453 static Datum
2455 {
2457 }
2458 
2459 /* Like ExecJustAssignOuterVar, optimized for virtual slots */
2460 static Datum
2462 {
2464 }
2465 
2466 /* Like ExecJustAssignScanVar, optimized for virtual slots */
2467 static Datum
2469 {
2471 }
2472 
2473 #if defined(EEO_USE_COMPUTED_GOTO)
2474 /*
2475  * Comparator used when building address->opcode lookup table for
2476  * ExecEvalStepOp() in the threaded dispatch case.
2477  */
2478 static int
2479 dispatch_compare_ptr(const void *a, const void *b)
2480 {
2481  const ExprEvalOpLookup *la = (const ExprEvalOpLookup *) a;
2482  const ExprEvalOpLookup *lb = (const ExprEvalOpLookup *) b;
2483 
2484  if (la->opcode < lb->opcode)
2485  return -1;
2486  else if (la->opcode > lb->opcode)
2487  return 1;
2488  return 0;
2489 }
2490 #endif
2491 
2492 /*
2493  * Do one-time initialization of interpretation machinery.
2494  */
2495 static void
2497 {
2498 #if defined(EEO_USE_COMPUTED_GOTO)
2499  /* Set up externally-visible pointer to dispatch table */
2500  if (dispatch_table == NULL)
2501  {
2502  dispatch_table = (const void **)
2503  DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
2504 
2505  /* build reverse lookup table */
2506  for (int i = 0; i < EEOP_LAST; i++)
2507  {
2508  reverse_dispatch_table[i].opcode = dispatch_table[i];
2509  reverse_dispatch_table[i].op = (ExprEvalOp) i;
2510  }
2511 
2512  /* make it bsearch()able */
2513  qsort(reverse_dispatch_table,
2514  EEOP_LAST /* nmembers */ ,
2515  sizeof(ExprEvalOpLookup),
2516  dispatch_compare_ptr);
2517  }
2518 #endif
2519 }
2520 
2521 /*
2522  * Function to return the opcode of an expression step.
2523  *
2524  * When direct-threading is in use, ExprState->opcode isn't easily
2525  * decipherable. This function returns the appropriate enum member.
2526  */
2527 ExprEvalOp
2529 {
2530 #if defined(EEO_USE_COMPUTED_GOTO)
2531  if (state->flags & EEO_FLAG_DIRECT_THREADED)
2532  {
2533  ExprEvalOpLookup key;
2534  ExprEvalOpLookup *res;
2535 
2536  key.opcode = (void *) op->opcode;
2537  res = bsearch(&key,
2538  reverse_dispatch_table,
2539  EEOP_LAST /* nmembers */ ,
2540  sizeof(ExprEvalOpLookup),
2541  dispatch_compare_ptr);
2542  Assert(res); /* unknown ops shouldn't get looked up */
2543  return res->op;
2544  }
2545 #endif
2546  return (ExprEvalOp) op->opcode;
2547 }
2548 
2549 
2550 /*
2551  * Out-of-line helper functions for complex instructions.
2552  */
2553 
2554 /*
2555  * Evaluate EEOP_FUNCEXPR_FUSAGE
2556  */
2557 void
2559  ExprContext *econtext)
2560 {
2561  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2562  PgStat_FunctionCallUsage fcusage;
2563  Datum d;
2564 
2565  pgstat_init_function_usage(fcinfo, &fcusage);
2566 
2567  fcinfo->isnull = false;
2568  d = op->d.func.fn_addr(fcinfo);
2569  *op->resvalue = d;
2570  *op->resnull = fcinfo->isnull;
2571 
2572  pgstat_end_function_usage(&fcusage, true);
2573 }
2574 
2575 /*
2576  * Evaluate EEOP_FUNCEXPR_STRICT_FUSAGE
2577  */
2578 void
2580  ExprContext *econtext)
2581 {
2582 
2583  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2584  PgStat_FunctionCallUsage fcusage;
2585  NullableDatum *args = fcinfo->args;
2586  int nargs = op->d.func.nargs;
2587  Datum d;
2588 
2589  /* strict function, so check for NULL args */
2590  for (int argno = 0; argno < nargs; argno++)
2591  {
2592  if (args[argno].isnull)
2593  {
2594  *op->resnull = true;
2595  return;
2596  }
2597  }
2598 
2599  pgstat_init_function_usage(fcinfo, &fcusage);
2600 
2601  fcinfo->isnull = false;
2602  d = op->d.func.fn_addr(fcinfo);
2603  *op->resvalue = d;
2604  *op->resnull = fcinfo->isnull;
2605 
2606  pgstat_end_function_usage(&fcusage, true);
2607 }
2608 
2609 /*
2610  * Evaluate a PARAM_EXEC parameter.
2611  *
2612  * PARAM_EXEC params (internal executor parameters) are stored in the
2613  * ecxt_param_exec_vals array, and can be accessed by array index.
2614  */
2615 void
2617 {
2618  ParamExecData *prm;
2619 
2620  prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2621  if (unlikely(prm->execPlan != NULL))
2622  {
2623  /* Parameter not evaluated yet, so go do it */
2624  ExecSetParamPlan(prm->execPlan, econtext);
2625  /* ExecSetParamPlan should have processed this param... */
2626  Assert(prm->execPlan == NULL);
2627  }
2628  *op->resvalue = prm->value;
2629  *op->resnull = prm->isnull;
2630 }
2631 
2632 /*
2633  * Evaluate a PARAM_EXTERN parameter.
2634  *
2635  * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
2636  */
2637 void
2639 {
2640  ParamListInfo paramInfo = econtext->ecxt_param_list_info;
2641  int paramId = op->d.param.paramid;
2642 
2643  if (likely(paramInfo &&
2644  paramId > 0 && paramId <= paramInfo->numParams))
2645  {
2646  ParamExternData *prm;
2647  ParamExternData prmdata;
2648 
2649  /* give hook a chance in case parameter is dynamic */
2650  if (paramInfo->paramFetch != NULL)
2651  prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
2652  else
2653  prm = &paramInfo->params[paramId - 1];
2654 
2655  if (likely(OidIsValid(prm->ptype)))
2656  {
2657  /* safety check in case hook did something unexpected */
2658  if (unlikely(prm->ptype != op->d.param.paramtype))
2659  ereport(ERROR,
2660  (errcode(ERRCODE_DATATYPE_MISMATCH),
2661  errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
2662  paramId,
2663  format_type_be(prm->ptype),
2664  format_type_be(op->d.param.paramtype))));
2665  *op->resvalue = prm->value;
2666  *op->resnull = prm->isnull;
2667  return;
2668  }
2669  }
2670 
2671  ereport(ERROR,
2672  (errcode(ERRCODE_UNDEFINED_OBJECT),
2673  errmsg("no value found for parameter %d", paramId)));
2674 }
2675 
2676 /*
2677  * Set value of a param (currently always PARAM_EXEC) from
2678  * state->res{value,null}.
2679  */
2680 void
2682 {
2683  ParamExecData *prm;
2684 
2685  prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2686 
2687  /* Shouldn't have a pending evaluation anymore */
2688  Assert(prm->execPlan == NULL);
2689 
2690  prm->value = state->resvalue;
2691  prm->isnull = state->resnull;
2692 }
2693 
2694 /*
2695  * Evaluate a CoerceViaIO node in soft-error mode.
2696  *
2697  * The source value is in op's result variable.
2698  *
2699  * Note: This implements EEOP_IOCOERCE_SAFE. If you change anything here,
2700  * also look at the inline code for EEOP_IOCOERCE.
2701  */
2702 void
2704 {
2705  char *str;
2706 
2707  /* call output function (similar to OutputFunctionCall) */
2708  if (*op->resnull)
2709  {
2710  /* output functions are not called on nulls */
2711  str = NULL;
2712  }
2713  else
2714  {
2715  FunctionCallInfo fcinfo_out;
2716 
2717  fcinfo_out = op->d.iocoerce.fcinfo_data_out;
2718  fcinfo_out->args[0].value = *op->resvalue;
2719  fcinfo_out->args[0].isnull = false;
2720 
2721  fcinfo_out->isnull = false;
2722  str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
2723 
2724  /* OutputFunctionCall assumes result isn't null */
2725  Assert(!fcinfo_out->isnull);
2726  }
2727 
2728  /* call input function (similar to InputFunctionCallSafe) */
2729  if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
2730  {
2731  FunctionCallInfo fcinfo_in;
2732 
2733  fcinfo_in = op->d.iocoerce.fcinfo_data_in;
2734  fcinfo_in->args[0].value = PointerGetDatum(str);
2735  fcinfo_in->args[0].isnull = *op->resnull;
2736  /* second and third arguments are already set up */
2737 
2738  /* ErrorSaveContext must be present. */
2739  Assert(IsA(fcinfo_in->context, ErrorSaveContext));
2740 
2741  fcinfo_in->isnull = false;
2742  *op->resvalue = FunctionCallInvoke(fcinfo_in);
2743 
2744  if (SOFT_ERROR_OCCURRED(fcinfo_in->context))
2745  {
2746  *op->resnull = true;
2747  *op->resvalue = (Datum) 0;
2748  return;
2749  }
2750 
2751  /* Should get null result if and only if str is NULL */
2752  if (str == NULL)
2753  Assert(*op->resnull);
2754  else
2755  Assert(!*op->resnull);
2756  }
2757 }
2758 
2759 /*
2760  * Evaluate a SQLValueFunction expression.
2761  */
2762 void
2764 {
2765  LOCAL_FCINFO(fcinfo, 0);
2766  SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
2767 
2768  *op->resnull = false;
2769 
2770  /*
2771  * Note: current_schema() can return NULL. current_user() etc currently
2772  * cannot, but might as well code those cases the same way for safety.
2773  */
2774  switch (svf->op)
2775  {
2776  case SVFOP_CURRENT_DATE:
2777  *op->resvalue = DateADTGetDatum(GetSQLCurrentDate());
2778  break;
2779  case SVFOP_CURRENT_TIME:
2780  case SVFOP_CURRENT_TIME_N:
2782  break;
2786  break;
2787  case SVFOP_LOCALTIME:
2788  case SVFOP_LOCALTIME_N:
2789  *op->resvalue = TimeADTGetDatum(GetSQLLocalTime(svf->typmod));
2790  break;
2791  case SVFOP_LOCALTIMESTAMP:
2794  break;
2795  case SVFOP_CURRENT_ROLE:
2796  case SVFOP_CURRENT_USER:
2797  case SVFOP_USER:
2798  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2799  *op->resvalue = current_user(fcinfo);
2800  *op->resnull = fcinfo->isnull;
2801  break;
2802  case SVFOP_SESSION_USER:
2803  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2804  *op->resvalue = session_user(fcinfo);
2805  *op->resnull = fcinfo->isnull;
2806  break;
2807  case SVFOP_CURRENT_CATALOG:
2808  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2809  *op->resvalue = current_database(fcinfo);
2810  *op->resnull = fcinfo->isnull;
2811  break;
2812  case SVFOP_CURRENT_SCHEMA:
2813  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2814  *op->resvalue = current_schema(fcinfo);
2815  *op->resnull = fcinfo->isnull;
2816  break;
2817  }
2818 }
2819 
2820 /*
2821  * Raise error if a CURRENT OF expression is evaluated.
2822  *
2823  * The planner should convert CURRENT OF into a TidScan qualification, or some
2824  * other special handling in a ForeignScan node. So we have to be able to do
2825  * ExecInitExpr on a CurrentOfExpr, but we shouldn't ever actually execute it.
2826  * If we get here, we suppose we must be dealing with CURRENT OF on a foreign
2827  * table whose FDW doesn't handle it, and complain accordingly.
2828  */
2829 void
2831 {
2832  ereport(ERROR,
2833  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2834  errmsg("WHERE CURRENT OF is not supported for this table type")));
2835 }
2836 
2837 /*
2838  * Evaluate NextValueExpr.
2839  */
2840 void
2842 {
2843  int64 newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
2844 
2845  switch (op->d.nextvalueexpr.seqtypid)
2846  {
2847  case INT2OID:
2848  *op->resvalue = Int16GetDatum((int16) newval);
2849  break;
2850  case INT4OID:
2851  *op->resvalue = Int32GetDatum((int32) newval);
2852  break;
2853  case INT8OID:
2854  *op->resvalue = Int64GetDatum((int64) newval);
2855  break;
2856  default:
2857  elog(ERROR, "unsupported sequence type %u",
2858  op->d.nextvalueexpr.seqtypid);
2859  }
2860  *op->resnull = false;
2861 }
2862 
2863 /*
2864  * Evaluate NullTest / IS NULL for rows.
2865  */
2866 void
2868 {
2869  ExecEvalRowNullInt(state, op, econtext, true);
2870 }
2871 
2872 /*
2873  * Evaluate NullTest / IS NOT NULL for rows.
2874  */
2875 void
2877 {
2878  ExecEvalRowNullInt(state, op, econtext, false);
2879 }
2880 
2881 /* Common code for IS [NOT] NULL on a row value */
2882 static void
2884  ExprContext *econtext, bool checkisnull)
2885 {
2886  Datum value = *op->resvalue;
2887  bool isnull = *op->resnull;
2888  HeapTupleHeader tuple;
2889  Oid tupType;
2890  int32 tupTypmod;
2891  TupleDesc tupDesc;
2892  HeapTupleData tmptup;
2893 
2894  *op->resnull = false;
2895 
2896  /* NULL row variables are treated just as NULL scalar columns */
2897  if (isnull)
2898  {
2899  *op->resvalue = BoolGetDatum(checkisnull);
2900  return;
2901  }
2902 
2903  /*
2904  * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
2905  * as:
2906  *
2907  * "R IS NULL" is true if every field is the null value.
2908  *
2909  * "R IS NOT NULL" is true if no field is the null value.
2910  *
2911  * This definition is (apparently intentionally) not recursive; so our
2912  * tests on the fields are primitive attisnull tests, not recursive checks
2913  * to see if they are all-nulls or no-nulls rowtypes.
2914  *
2915  * The standard does not consider the possibility of zero-field rows, but
2916  * here we consider them to vacuously satisfy both predicates.
2917  */
2918 
2919  tuple = DatumGetHeapTupleHeader(value);
2920 
2921  tupType = HeapTupleHeaderGetTypeId(tuple);
2922  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2923 
2924  /* Lookup tupdesc if first time through or if type changes */
2925  tupDesc = get_cached_rowtype(tupType, tupTypmod,
2926  &op->d.nulltest_row.rowcache, NULL);
2927 
2928  /*
2929  * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
2930  */
2931  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2932  tmptup.t_data = tuple;
2933 
2934  for (int att = 1; att <= tupDesc->natts; att++)
2935  {
2936  /* ignore dropped columns */
2937  if (TupleDescAttr(tupDesc, att - 1)->attisdropped)
2938  continue;
2939  if (heap_attisnull(&tmptup, att, tupDesc))
2940  {
2941  /* null field disproves IS NOT NULL */
2942  if (!checkisnull)
2943  {
2944  *op->resvalue = BoolGetDatum(false);
2945  return;
2946  }
2947  }
2948  else
2949  {
2950  /* non-null field disproves IS NULL */
2951  if (checkisnull)
2952  {
2953  *op->resvalue = BoolGetDatum(false);
2954  return;
2955  }
2956  }
2957  }
2958 
2959  *op->resvalue = BoolGetDatum(true);
2960 }
2961 
2962 /*
2963  * Evaluate an ARRAY[] expression.
2964  *
2965  * The individual array elements (or subarrays) have already been evaluated
2966  * into op->d.arrayexpr.elemvalues[]/elemnulls[].
2967  */
2968 void
2970 {
2971  ArrayType *result;
2972  Oid element_type = op->d.arrayexpr.elemtype;
2973  int nelems = op->d.arrayexpr.nelems;
2974  int ndims = 0;
2975  int dims[MAXDIM];
2976  int lbs[MAXDIM];
2977 
2978  /* Set non-null as default */
2979  *op->resnull = false;
2980 
2981  if (!op->d.arrayexpr.multidims)
2982  {
2983  /* Elements are presumably of scalar type */
2984  Datum *dvalues = op->d.arrayexpr.elemvalues;
2985  bool *dnulls = op->d.arrayexpr.elemnulls;
2986 
2987  /* setup for 1-D array of the given length */
2988  ndims = 1;
2989  dims[0] = nelems;
2990  lbs[0] = 1;
2991 
2992  result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2993  element_type,
2994  op->d.arrayexpr.elemlength,
2995  op->d.arrayexpr.elembyval,
2996  op->d.arrayexpr.elemalign);
2997  }
2998  else
2999  {
3000  /* Must be nested array expressions */
3001  int nbytes = 0;
3002  int nitems;
3003  int outer_nelems = 0;
3004  int elem_ndims = 0;
3005  int *elem_dims = NULL;
3006  int *elem_lbs = NULL;
3007  bool firstone = true;
3008  bool havenulls = false;
3009  bool haveempty = false;
3010  char **subdata;
3011  bits8 **subbitmaps;
3012  int *subbytes;
3013  int *subnitems;
3014  int32 dataoffset;
3015  char *dat;
3016  int iitem;
3017 
3018  subdata = (char **) palloc(nelems * sizeof(char *));
3019  subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
3020  subbytes = (int *) palloc(nelems * sizeof(int));
3021  subnitems = (int *) palloc(nelems * sizeof(int));
3022 
3023  /* loop through and get data area from each element */
3024  for (int elemoff = 0; elemoff < nelems; elemoff++)
3025  {
3026  Datum arraydatum;
3027  bool eisnull;
3028  ArrayType *array;
3029  int this_ndims;
3030 
3031  arraydatum = op->d.arrayexpr.elemvalues[elemoff];
3032  eisnull = op->d.arrayexpr.elemnulls[elemoff];
3033 
3034  /* temporarily ignore null subarrays */
3035  if (eisnull)
3036  {
3037  haveempty = true;
3038  continue;
3039  }
3040 
3041  array = DatumGetArrayTypeP(arraydatum);
3042 
3043  /* run-time double-check on element type */
3044  if (element_type != ARR_ELEMTYPE(array))
3045  ereport(ERROR,
3046  (errcode(ERRCODE_DATATYPE_MISMATCH),
3047  errmsg("cannot merge incompatible arrays"),
3048  errdetail("Array with element type %s cannot be "
3049  "included in ARRAY construct with element type %s.",
3050  format_type_be(ARR_ELEMTYPE(array)),
3052 
3053  this_ndims = ARR_NDIM(array);
3054  /* temporarily ignore zero-dimensional subarrays */
3055  if (this_ndims <= 0)
3056  {
3057  haveempty = true;
3058  continue;
3059  }
3060 
3061  if (firstone)
3062  {
3063  /* Get sub-array details from first member */
3064  elem_ndims = this_ndims;
3065  ndims = elem_ndims + 1;
3066  if (ndims <= 0 || ndims > MAXDIM)
3067  ereport(ERROR,
3068  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3069  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3070  ndims, MAXDIM)));
3071 
3072  elem_dims = (int *) palloc(elem_ndims * sizeof(int));
3073  memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
3074  elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
3075  memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
3076 
3077  firstone = false;
3078  }
3079  else
3080  {
3081  /* Check other sub-arrays are compatible */
3082  if (elem_ndims != this_ndims ||
3083  memcmp(elem_dims, ARR_DIMS(array),
3084  elem_ndims * sizeof(int)) != 0 ||
3085  memcmp(elem_lbs, ARR_LBOUND(array),
3086  elem_ndims * sizeof(int)) != 0)
3087  ereport(ERROR,
3088  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3089  errmsg("multidimensional arrays must have array "
3090  "expressions with matching dimensions")));
3091  }
3092 
3093  subdata[outer_nelems] = ARR_DATA_PTR(array);
3094  subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
3095  subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
3096  nbytes += subbytes[outer_nelems];
3097  /* check for overflow of total request */
3098  if (!AllocSizeIsValid(nbytes))
3099  ereport(ERROR,
3100  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3101  errmsg("array size exceeds the maximum allowed (%d)",
3102  (int) MaxAllocSize)));
3103  subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
3104  ARR_DIMS(array));
3105  havenulls |= ARR_HASNULL(array);
3106  outer_nelems++;
3107  }
3108 
3109  /*
3110  * If all items were null or empty arrays, return an empty array;
3111  * otherwise, if some were and some weren't, raise error. (Note: we
3112  * must special-case this somehow to avoid trying to generate a 1-D
3113  * array formed from empty arrays. It's not ideal...)
3114  */
3115  if (haveempty)
3116  {
3117  if (ndims == 0) /* didn't find any nonempty array */
3118  {
3120  return;
3121  }
3122  ereport(ERROR,
3123  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3124  errmsg("multidimensional arrays must have array "
3125  "expressions with matching dimensions")));
3126  }
3127 
3128  /* setup for multi-D array */
3129  dims[0] = outer_nelems;
3130  lbs[0] = 1;
3131  for (int i = 1; i < ndims; i++)
3132  {
3133  dims[i] = elem_dims[i - 1];
3134  lbs[i] = elem_lbs[i - 1];
3135  }
3136 
3137  /* check for subscript overflow */
3138  nitems = ArrayGetNItems(ndims, dims);
3139  ArrayCheckBounds(ndims, dims, lbs);
3140 
3141  if (havenulls)
3142  {
3143  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
3144  nbytes += dataoffset;
3145  }
3146  else
3147  {
3148  dataoffset = 0; /* marker for no null bitmap */
3149  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3150  }
3151 
3152  result = (ArrayType *) palloc0(nbytes);
3153  SET_VARSIZE(result, nbytes);
3154  result->ndim = ndims;
3155  result->dataoffset = dataoffset;
3156  result->elemtype = element_type;
3157  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3158  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3159 
3160  dat = ARR_DATA_PTR(result);
3161  iitem = 0;
3162  for (int i = 0; i < outer_nelems; i++)
3163  {
3164  memcpy(dat, subdata[i], subbytes[i]);
3165  dat += subbytes[i];
3166  if (havenulls)
3167  array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
3168  subbitmaps[i], 0,
3169  subnitems[i]);
3170  iitem += subnitems[i];
3171  }
3172  }
3173 
3174  *op->resvalue = PointerGetDatum(result);
3175 }
3176 
3177 /*
3178  * Evaluate an ArrayCoerceExpr expression.
3179  *
3180  * Source array is in step's result variable.
3181  */
3182 void
3184 {
3185  Datum arraydatum;
3186 
3187  /* NULL array -> NULL result */
3188  if (*op->resnull)
3189  return;
3190 
3191  arraydatum = *op->resvalue;
3192 
3193  /*
3194  * If it's binary-compatible, modify the element type in the array header,
3195  * but otherwise leave the array as we received it.
3196  */
3197  if (op->d.arraycoerce.elemexprstate == NULL)
3198  {
3199  /* Detoast input array if necessary, and copy in any case */
3200  ArrayType *array = DatumGetArrayTypePCopy(arraydatum);
3201 
3202  ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
3203  *op->resvalue = PointerGetDatum(array);
3204  return;
3205  }
3206 
3207  /*
3208  * Use array_map to apply the sub-expression to each array element.
3209  */
3210  *op->resvalue = array_map(arraydatum,
3211  op->d.arraycoerce.elemexprstate,
3212  econtext,
3213  op->d.arraycoerce.resultelemtype,
3214  op->d.arraycoerce.amstate);
3215 }
3216 
3217 /*
3218  * Evaluate a ROW() expression.
3219  *
3220  * The individual columns have already been evaluated into
3221  * op->d.row.elemvalues[]/elemnulls[].
3222  */
3223 void
3225 {
3226  HeapTuple tuple;
3227 
3228  /* build tuple from evaluated field values */
3229  tuple = heap_form_tuple(op->d.row.tupdesc,
3230  op->d.row.elemvalues,
3231  op->d.row.elemnulls);
3232 
3233  *op->resvalue = HeapTupleGetDatum(tuple);
3234  *op->resnull = false;
3235 }
3236 
3237 /*
3238  * Evaluate GREATEST() or LEAST() expression (note this is *not* MIN()/MAX()).
3239  *
3240  * All of the to-be-compared expressions have already been evaluated into
3241  * op->d.minmax.values[]/nulls[].
3242  */
3243 void
3245 {
3246  Datum *values = op->d.minmax.values;
3247  bool *nulls = op->d.minmax.nulls;
3248  FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
3249  MinMaxOp operator = op->d.minmax.op;
3250 
3251  /* set at initialization */
3252  Assert(fcinfo->args[0].isnull == false);
3253  Assert(fcinfo->args[1].isnull == false);
3254 
3255  /* default to null result */
3256  *op->resnull = true;
3257 
3258  for (int off = 0; off < op->d.minmax.nelems; off++)
3259  {
3260  /* ignore NULL inputs */
3261  if (nulls[off])
3262  continue;
3263 
3264  if (*op->resnull)
3265  {
3266  /* first nonnull input, adopt value */
3267  *op->resvalue = values[off];
3268  *op->resnull = false;
3269  }
3270  else
3271  {
3272  int cmpresult;
3273 
3274  /* apply comparison function */
3275  fcinfo->args[0].value = *op->resvalue;
3276  fcinfo->args[1].value = values[off];
3277 
3278  fcinfo->isnull = false;
3279  cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
3280  if (fcinfo->isnull) /* probably should not happen */
3281  continue;
3282 
3283  if (cmpresult > 0 && operator == IS_LEAST)
3284  *op->resvalue = values[off];
3285  else if (cmpresult < 0 && operator == IS_GREATEST)
3286  *op->resvalue = values[off];
3287  }
3288  }
3289 }
3290 
3291 /*
3292  * Evaluate a FieldSelect node.
3293  *
3294  * Source record is in step's result variable.
3295  */
3296 void
3298 {
3299  AttrNumber fieldnum = op->d.fieldselect.fieldnum;
3300  Datum tupDatum;
3301  HeapTupleHeader tuple;
3302  Oid tupType;
3303  int32 tupTypmod;
3304  TupleDesc tupDesc;
3305  Form_pg_attribute attr;
3306  HeapTupleData tmptup;
3307 
3308  /* NULL record -> NULL result */
3309  if (*op->resnull)
3310  return;
3311 
3312  tupDatum = *op->resvalue;
3313 
3314  /* We can special-case expanded records for speed */
3316  {
3318 
3319  Assert(erh->er_magic == ER_MAGIC);
3320 
3321  /* Extract record's TupleDesc */
3322  tupDesc = expanded_record_get_tupdesc(erh);
3323 
3324  /*
3325  * Find field's attr record. Note we don't support system columns
3326  * here: a datum tuple doesn't have valid values for most of the
3327  * interesting system columns anyway.
3328  */
3329  if (fieldnum <= 0) /* should never happen */
3330  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3331  fieldnum);
3332  if (fieldnum > tupDesc->natts) /* should never happen */
3333  elog(ERROR, "attribute number %d exceeds number of columns %d",
3334  fieldnum, tupDesc->natts);
3335  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3336 
3337  /* Check for dropped column, and force a NULL result if so */
3338  if (attr->attisdropped)
3339  {
3340  *op->resnull = true;
3341  return;
3342  }
3343 
3344  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3345  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3346  if (op->d.fieldselect.resulttype != attr->atttypid)
3347  ereport(ERROR,
3348  (errcode(ERRCODE_DATATYPE_MISMATCH),
3349  errmsg("attribute %d has wrong type", fieldnum),
3350  errdetail("Table has type %s, but query expects %s.",
3351  format_type_be(attr->atttypid),
3352  format_type_be(op->d.fieldselect.resulttype))));
3353 
3354  /* extract the field */
3355  *op->resvalue = expanded_record_get_field(erh, fieldnum,
3356  op->resnull);
3357  }
3358  else
3359  {
3360  /* Get the composite datum and extract its type fields */
3361  tuple = DatumGetHeapTupleHeader(tupDatum);
3362 
3363  tupType = HeapTupleHeaderGetTypeId(tuple);
3364  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
3365 
3366  /* Lookup tupdesc if first time through or if type changes */
3367  tupDesc = get_cached_rowtype(tupType, tupTypmod,
3368  &op->d.fieldselect.rowcache, NULL);
3369 
3370  /*
3371  * Find field's attr record. Note we don't support system columns
3372  * here: a datum tuple doesn't have valid values for most of the
3373  * interesting system columns anyway.
3374  */
3375  if (fieldnum <= 0) /* should never happen */
3376  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3377  fieldnum);
3378  if (fieldnum > tupDesc->natts) /* should never happen */
3379  elog(ERROR, "attribute number %d exceeds number of columns %d",
3380  fieldnum, tupDesc->natts);
3381  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3382 
3383  /* Check for dropped column, and force a NULL result if so */
3384  if (attr->attisdropped)
3385  {
3386  *op->resnull = true;
3387  return;
3388  }
3389 
3390  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3391  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3392  if (op->d.fieldselect.resulttype != attr->atttypid)
3393  ereport(ERROR,
3394  (errcode(ERRCODE_DATATYPE_MISMATCH),
3395  errmsg("attribute %d has wrong type", fieldnum),
3396  errdetail("Table has type %s, but query expects %s.",
3397  format_type_be(attr->atttypid),
3398  format_type_be(op->d.fieldselect.resulttype))));
3399 
3400  /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
3401  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3402  tmptup.t_data = tuple;
3403 
3404  /* extract the field */
3405  *op->resvalue = heap_getattr(&tmptup,
3406  fieldnum,
3407  tupDesc,
3408  op->resnull);
3409  }
3410 }
3411 
3412 /*
3413  * Deform source tuple, filling in the step's values/nulls arrays, before
3414  * evaluating individual new values as part of a FieldStore expression.
3415  * Subsequent steps will overwrite individual elements of the values/nulls
3416  * arrays with the new field values, and then FIELDSTORE_FORM will build the
3417  * new tuple value.
3418  *
3419  * Source record is in step's result variable.
3420  */
3421 void
3423 {
3424  if (*op->resnull)
3425  {
3426  /* Convert null input tuple into an all-nulls row */
3427  memset(op->d.fieldstore.nulls, true,
3428  op->d.fieldstore.ncolumns * sizeof(bool));
3429  }
3430  else
3431  {
3432  /*
3433  * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
3434  * set all the fields in the struct just in case.
3435  */
3436  Datum tupDatum = *op->resvalue;
3437  HeapTupleHeader tuphdr;
3438  HeapTupleData tmptup;
3439  TupleDesc tupDesc;
3440 
3441  tuphdr = DatumGetHeapTupleHeader(tupDatum);
3442  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
3443  ItemPointerSetInvalid(&(tmptup.t_self));
3444  tmptup.t_tableOid = InvalidOid;
3445  tmptup.t_data = tuphdr;
3446 
3447  /*
3448  * Lookup tupdesc if first time through or if type changes. Because
3449  * we don't pin the tupdesc, we must not do this lookup until after
3450  * doing DatumGetHeapTupleHeader: that could do database access while
3451  * detoasting the datum.
3452  */
3453  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3454  op->d.fieldstore.rowcache, NULL);
3455 
3456  /* Check that current tupdesc doesn't have more fields than allocated */
3457  if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
3458  elog(ERROR, "too many columns in composite type %u",
3459  op->d.fieldstore.fstore->resulttype);
3460 
3461  heap_deform_tuple(&tmptup, tupDesc,
3462  op->d.fieldstore.values,
3463  op->d.fieldstore.nulls);
3464  }
3465 }
3466 
3467 /*
3468  * Compute the new composite datum after each individual field value of a
3469  * FieldStore expression has been evaluated.
3470  */
3471 void
3473 {
3474  TupleDesc tupDesc;
3475  HeapTuple tuple;
3476 
3477  /* Lookup tupdesc (should be valid already) */
3478  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3479  op->d.fieldstore.rowcache, NULL);
3480 
3481  tuple = heap_form_tuple(tupDesc,
3482  op->d.fieldstore.values,
3483  op->d.fieldstore.nulls);
3484 
3485  *op->resvalue = HeapTupleGetDatum(tuple);
3486  *op->resnull = false;
3487 }
3488 
3489 /*
3490  * Evaluate a rowtype coercion operation.
3491  * This may require rearranging field positions.
3492  *
3493  * Source record is in step's result variable.
3494  */
3495 void
3497 {
3498  HeapTuple result;
3499  Datum tupDatum;
3500  HeapTupleHeader tuple;
3501  HeapTupleData tmptup;
3502  TupleDesc indesc,
3503  outdesc;
3504  bool changed = false;
3505 
3506  /* NULL in -> NULL out */
3507  if (*op->resnull)
3508  return;
3509 
3510  tupDatum = *op->resvalue;
3511  tuple = DatumGetHeapTupleHeader(tupDatum);
3512 
3513  /*
3514  * Lookup tupdescs if first time through or if type changes. We'd better
3515  * pin them since type conversion functions could do catalog lookups and
3516  * hence cause cache invalidation.
3517  */
3518  indesc = get_cached_rowtype(op->d.convert_rowtype.inputtype, -1,
3519  op->d.convert_rowtype.incache,
3520  &changed);
3521  IncrTupleDescRefCount(indesc);
3522  outdesc = get_cached_rowtype(op->d.convert_rowtype.outputtype, -1,
3523  op->d.convert_rowtype.outcache,
3524  &changed);
3525  IncrTupleDescRefCount(outdesc);
3526 
3527  /*
3528  * We used to be able to assert that incoming tuples are marked with
3529  * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
3530  * might change the tuples' marking to plain RECORD due to inserting
3531  * aliases, we can only make this weak test:
3532  */
3533  Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
3534  HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
3535 
3536  /* if first time through, or after change, initialize conversion map */
3537  if (changed)
3538  {
3539  MemoryContext old_cxt;
3540 
3541  /* allocate map in long-lived memory context */
3542  old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3543 
3544  /* prepare map from old to new attribute numbers */
3545  op->d.convert_rowtype.map = convert_tuples_by_name(indesc, outdesc);
3546 
3547  MemoryContextSwitchTo(old_cxt);
3548  }
3549 
3550  /* Following steps need a HeapTuple not a bare HeapTupleHeader */
3551  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3552  tmptup.t_data = tuple;
3553 
3554  if (op->d.convert_rowtype.map != NULL)
3555  {
3556  /* Full conversion with attribute rearrangement needed */
3557  result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map);
3558  /* Result already has appropriate composite-datum header fields */
3559  *op->resvalue = HeapTupleGetDatum(result);
3560  }
3561  else
3562  {
3563  /*
3564  * The tuple is physically compatible as-is, but we need to insert the
3565  * destination rowtype OID in its composite-datum header field, so we
3566  * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
3567  * for this since it will both make the physical copy and insert the
3568  * correct composite header fields. Note that we aren't expecting to
3569  * have to flatten any toasted fields: the input was a composite
3570  * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
3571  * is overkill here, but its check for external fields is cheap.
3572  */
3573  *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
3574  }
3575 
3576  DecrTupleDescRefCount(indesc);
3577  DecrTupleDescRefCount(outdesc);
3578 }
3579 
3580 /*
3581  * Evaluate "scalar op ANY/ALL (array)".
3582  *
3583  * Source array is in our result area, scalar arg is already evaluated into
3584  * fcinfo->args[0].
3585  *
3586  * The operator always yields boolean, and we combine the results across all
3587  * array elements using OR and AND (for ANY and ALL respectively). Of course
3588  * we short-circuit as soon as the result is known.
3589  */
3590 void
3592 {
3593  FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
3594  bool useOr = op->d.scalararrayop.useOr;
3595  bool strictfunc = op->d.scalararrayop.finfo->fn_strict;
3596  ArrayType *arr;
3597  int nitems;
3598  Datum result;
3599  bool resultnull;
3600  int16 typlen;
3601  bool typbyval;
3602  char typalign;
3603  char *s;
3604  bits8 *bitmap;
3605  int bitmask;
3606 
3607  /*
3608  * If the array is NULL then we return NULL --- it's not very meaningful
3609  * to do anything else, even if the operator isn't strict.
3610  */
3611  if (*op->resnull)
3612  return;
3613 
3614  /* Else okay to fetch and detoast the array */
3615  arr = DatumGetArrayTypeP(*op->resvalue);
3616 
3617  /*
3618  * If the array is empty, we return either FALSE or TRUE per the useOr
3619  * flag. This is correct even if the scalar is NULL; since we would
3620  * evaluate the operator zero times, it matters not whether it would want
3621  * to return NULL.
3622  */
3623  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3624  if (nitems <= 0)
3625  {
3626  *op->resvalue = BoolGetDatum(!useOr);
3627  *op->resnull = false;
3628  return;
3629  }
3630 
3631  /*
3632  * If the scalar is NULL, and the function is strict, return NULL; no
3633  * point in iterating the loop.
3634  */
3635  if (fcinfo->args[0].isnull && strictfunc)
3636  {
3637  *op->resnull = true;
3638  return;
3639  }
3640 
3641  /*
3642  * We arrange to look up info about the element type only once per series
3643  * of calls, assuming the element type doesn't change underneath us.
3644  */
3645  if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
3646  {
3648  &op->d.scalararrayop.typlen,
3649  &op->d.scalararrayop.typbyval,
3650  &op->d.scalararrayop.typalign);
3651  op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
3652  }
3653 
3654  typlen = op->d.scalararrayop.typlen;
3655  typbyval = op->d.scalararrayop.typbyval;
3656  typalign = op->d.scalararrayop.typalign;
3657 
3658  /* Initialize result appropriately depending on useOr */
3659  result = BoolGetDatum(!useOr);
3660  resultnull = false;
3661 
3662  /* Loop over the array elements */
3663  s = (char *) ARR_DATA_PTR(arr);
3664  bitmap = ARR_NULLBITMAP(arr);
3665  bitmask = 1;
3666 
3667  for (int i = 0; i < nitems; i++)
3668  {
3669  Datum elt;
3670  Datum thisresult;
3671 
3672  /* Get array element, checking for NULL */
3673  if (bitmap && (*bitmap & bitmask) == 0)
3674  {
3675  fcinfo->args[1].value = (Datum) 0;
3676  fcinfo->args[1].isnull = true;
3677  }
3678  else
3679  {
3680  elt = fetch_att(s, typbyval, typlen);
3681  s = att_addlength_pointer(s, typlen, s);
3682  s = (char *) att_align_nominal(s, typalign);
3683  fcinfo->args[1].value = elt;
3684  fcinfo->args[1].isnull = false;
3685  }
3686 
3687  /* Call comparison function */
3688  if (fcinfo->args[1].isnull && strictfunc)
3689  {
3690  fcinfo->isnull = true;
3691  thisresult = (Datum) 0;
3692  }
3693  else
3694  {
3695  fcinfo->isnull = false;
3696  thisresult = op->d.scalararrayop.fn_addr(fcinfo);
3697  }
3698 
3699  /* Combine results per OR or AND semantics */
3700  if (fcinfo->isnull)
3701  resultnull = true;
3702  else if (useOr)
3703  {
3704  if (DatumGetBool(thisresult))
3705  {
3706  result = BoolGetDatum(true);
3707  resultnull = false;
3708  break; /* needn't look at any more elements */
3709  }
3710  }
3711  else
3712  {
3713  if (!DatumGetBool(thisresult))
3714  {
3715  result = BoolGetDatum(false);
3716  resultnull = false;
3717  break; /* needn't look at any more elements */
3718  }
3719  }
3720 
3721  /* advance bitmap pointer if any */
3722  if (bitmap)
3723  {
3724  bitmask <<= 1;
3725  if (bitmask == 0x100)
3726  {
3727  bitmap++;
3728  bitmask = 1;
3729  }
3730  }
3731  }
3732 
3733  *op->resvalue = result;
3734  *op->resnull = resultnull;
3735 }
3736 
3737 /*
3738  * Hash function for scalar array hash op elements.
3739  *
3740  * We use the element type's default hash opclass, and the column collation
3741  * if the type is collation-sensitive.
3742  */
3743 static uint32
3744 saop_element_hash(struct saophash_hash *tb, Datum key)
3745 {
3748  Datum hash;
3749 
3750  fcinfo->args[0].value = key;
3751  fcinfo->args[0].isnull = false;
3752 
3753  hash = elements_tab->hash_finfo.fn_addr(fcinfo);
3754 
3755  return DatumGetUInt32(hash);
3756 }
3757 
3758 /*
3759  * Matching function for scalar array hash op elements, to be used in hashtable
3760  * lookups.
3761  */
3762 static bool
3763 saop_hash_element_match(struct saophash_hash *tb, Datum key1, Datum key2)
3764 {
3765  Datum result;
3766 
3768  FunctionCallInfo fcinfo = elements_tab->op->d.hashedscalararrayop.fcinfo_data;
3769 
3770  fcinfo->args[0].value = key1;
3771  fcinfo->args[0].isnull = false;
3772  fcinfo->args[1].value = key2;
3773  fcinfo->args[1].isnull = false;
3774 
3775  result = elements_tab->op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
3776 
3777  return DatumGetBool(result);
3778 }
3779 
3780 /*
3781  * Evaluate "scalar op ANY (const array)".
3782  *
3783  * Similar to ExecEvalScalarArrayOp, but optimized for faster repeat lookups
3784  * by building a hashtable on the first lookup. This hashtable will be reused
3785  * by subsequent lookups. Unlike ExecEvalScalarArrayOp, this version only
3786  * supports OR semantics.
3787  *
3788  * Source array is in our result area, scalar arg is already evaluated into
3789  * fcinfo->args[0].
3790  *
3791  * The operator always yields boolean.
3792  */
3793 void
3795 {
3796  ScalarArrayOpExprHashTable *elements_tab = op->d.hashedscalararrayop.elements_tab;
3797  FunctionCallInfo fcinfo = op->d.hashedscalararrayop.fcinfo_data;
3798  bool inclause = op->d.hashedscalararrayop.inclause;
3799  bool strictfunc = op->d.hashedscalararrayop.finfo->fn_strict;
3800  Datum scalar = fcinfo->args[0].value;
3801  bool scalar_isnull = fcinfo->args[0].isnull;
3802  Datum result;
3803  bool resultnull;
3804  bool hashfound;
3805 
3806  /* We don't setup a hashed scalar array op if the array const is null. */
3807  Assert(!*op->resnull);
3808 
3809  /*
3810  * If the scalar is NULL, and the function is strict, return NULL; no
3811  * point in executing the search.
3812  */
3813  if (fcinfo->args[0].isnull && strictfunc)
3814  {
3815  *op->resnull = true;
3816  return;
3817  }
3818 
3819  /* Build the hash table on first evaluation */
3820  if (elements_tab == NULL)
3821  {
3823  int16 typlen;
3824  bool typbyval;
3825  char typalign;
3826  int nitems;
3827  bool has_nulls = false;
3828  char *s;
3829  bits8 *bitmap;
3830  int bitmask;
3831  MemoryContext oldcontext;
3832  ArrayType *arr;
3833 
3834  saop = op->d.hashedscalararrayop.saop;
3835 
3836  arr = DatumGetArrayTypeP(*op->resvalue);
3837  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3838 
3840  &typlen,
3841  &typbyval,
3842  &typalign);
3843 
3844  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3845 
3847  palloc0(offsetof(ScalarArrayOpExprHashTable, hash_fcinfo_data) +
3849  op->d.hashedscalararrayop.elements_tab = elements_tab;
3850  elements_tab->op = op;
3851 
3852  fmgr_info(saop->hashfuncid, &elements_tab->hash_finfo);
3854 
3857  1,
3858  saop->inputcollid,
3859  NULL,
3860  NULL);
3861 
3862  /*
3863  * Create the hash table sizing it according to the number of elements
3864  * in the array. This does assume that the array has no duplicates.
3865  * If the array happens to contain many duplicate values then it'll
3866  * just mean that we sized the table a bit on the large side.
3867  */
3868  elements_tab->hashtab = saophash_create(CurrentMemoryContext, nitems,
3869  elements_tab);
3870 
3871  MemoryContextSwitchTo(oldcontext);
3872 
3873  s = (char *) ARR_DATA_PTR(arr);
3874  bitmap = ARR_NULLBITMAP(arr);
3875  bitmask = 1;
3876  for (int i = 0; i < nitems; i++)
3877  {
3878  /* Get array element, checking for NULL. */
3879  if (bitmap && (*bitmap & bitmask) == 0)
3880  {
3881  has_nulls = true;
3882  }
3883  else
3884  {
3885  Datum element;
3886 
3888  s = att_addlength_pointer(s, typlen, s);
3889  s = (char *) att_align_nominal(s, typalign);
3890 
3891  saophash_insert(elements_tab->hashtab, element, &hashfound);
3892  }
3893 
3894  /* Advance bitmap pointer if any. */
3895  if (bitmap)
3896  {
3897  bitmask <<= 1;
3898  if (bitmask == 0x100)
3899  {
3900  bitmap++;
3901  bitmask = 1;
3902  }
3903  }
3904  }
3905 
3906  /*
3907  * Remember if we had any nulls so that we know if we need to execute
3908  * non-strict functions with a null lhs value if no match is found.
3909  */
3910  op->d.hashedscalararrayop.has_nulls = has_nulls;
3911  }
3912 
3913  /* Check the hash to see if we have a match. */
3914  hashfound = NULL != saophash_lookup(elements_tab->hashtab, scalar);
3915 
3916  /* the result depends on if the clause is an IN or NOT IN clause */
3917  if (inclause)
3918  result = BoolGetDatum(hashfound); /* IN */
3919  else
3920  result = BoolGetDatum(!hashfound); /* NOT IN */
3921 
3922  resultnull = false;
3923 
3924  /*
3925  * If we didn't find a match in the array, we still might need to handle
3926  * the possibility of null values. We didn't put any NULLs into the
3927  * hashtable, but instead marked if we found any when building the table
3928  * in has_nulls.
3929  */
3930  if (!hashfound && op->d.hashedscalararrayop.has_nulls)
3931  {
3932  if (strictfunc)
3933  {
3934 
3935  /*
3936  * We have nulls in the array so a non-null lhs and no match must
3937  * yield NULL.
3938  */
3939  result = (Datum) 0;
3940  resultnull = true;
3941  }
3942  else
3943  {
3944  /*
3945  * Execute function will null rhs just once.
3946  *
3947  * The hash lookup path will have scribbled on the lhs argument so
3948  * we need to set it up also (even though we entered this function
3949  * with it already set).
3950  */
3951  fcinfo->args[0].value = scalar;
3952  fcinfo->args[0].isnull = scalar_isnull;
3953  fcinfo->args[1].value = (Datum) 0;
3954  fcinfo->args[1].isnull = true;
3955 
3956  result = op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
3957  resultnull = fcinfo->isnull;
3958 
3959  /*
3960  * Reverse the result for NOT IN clauses since the above function
3961  * is the equality function and we need not-equals.
3962  */
3963  if (!inclause)
3964  result = !result;
3965  }
3966  }
3967 
3968  *op->resvalue = result;
3969  *op->resnull = resultnull;
3970 }
3971 
3972 /*
3973  * Evaluate a NOT NULL domain constraint.
3974  */
3975 void
3977 {
3978  if (*op->resnull)
3979  errsave((Node *) op->d.domaincheck.escontext,
3980  (errcode(ERRCODE_NOT_NULL_VIOLATION),
3981  errmsg("domain %s does not allow null values",
3982  format_type_be(op->d.domaincheck.resulttype)),
3983  errdatatype(op->d.domaincheck.resulttype)));
3984 }
3985 
3986 /*
3987  * Evaluate a CHECK domain constraint.
3988  */
3989 void
3991 {
3992  if (!*op->d.domaincheck.checknull &&
3993  !DatumGetBool(*op->d.domaincheck.checkvalue))
3994  errsave((Node *) op->d.domaincheck.escontext,
3995  (errcode(ERRCODE_CHECK_VIOLATION),
3996  errmsg("value for domain %s violates check constraint \"%s\"",
3997  format_type_be(op->d.domaincheck.resulttype),
3998  op->d.domaincheck.constraintname),
3999  errdomainconstraint(op->d.domaincheck.resulttype,
4000  op->d.domaincheck.constraintname)));
4001 }
4002 
4003 /*
4004  * Evaluate the various forms of XmlExpr.
4005  *
4006  * Arguments have been evaluated into named_argvalue/named_argnull
4007  * and/or argvalue/argnull arrays.
4008  */
4009 void
4011 {
4012  XmlExpr *xexpr = op->d.xmlexpr.xexpr;
4013  Datum value;
4014 
4015  *op->resnull = true; /* until we get a result */
4016  *op->resvalue = (Datum) 0;
4017 
4018  switch (xexpr->op)
4019  {
4020  case IS_XMLCONCAT:
4021  {
4022  Datum *argvalue = op->d.xmlexpr.argvalue;
4023  bool *argnull = op->d.xmlexpr.argnull;
4024  List *values = NIL;
4025 
4026  for (int i = 0; i < list_length(xexpr->args); i++)
4027  {
4028  if (!argnull[i])
4030  }
4031 
4032  if (values != NIL)
4033  {
4034  *op->resvalue = PointerGetDatum(xmlconcat(values));
4035  *op->resnull = false;
4036  }
4037  }
4038  break;
4039 
4040  case IS_XMLFOREST:
4041  {
4042  Datum *argvalue = op->d.xmlexpr.named_argvalue;
4043  bool *argnull = op->d.xmlexpr.named_argnull;
4045  ListCell *lc;
4046  ListCell *lc2;
4047  int i;
4048 
4049  initStringInfo(&buf);
4050 
4051  i = 0;
4052  forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
4053  {
4054  Expr *e = (Expr *) lfirst(lc);
4055  char *argname = strVal(lfirst(lc2));
4056 
4057  if (!argnull[i])
4058  {
4059  value = argvalue[i];
4060  appendStringInfo(&buf, "<%s>%s</%s>",
4061  argname,
4063  exprType((Node *) e), true),
4064  argname);
4065  *op->resnull = false;
4066  }
4067  i++;
4068  }
4069 
4070  if (!*op->resnull)
4071  {
4072  text *result;
4073 
4074  result = cstring_to_text_with_len(buf.data, buf.len);
4075  *op->resvalue = PointerGetDatum(result);
4076  }
4077 
4078  pfree(buf.data);
4079  }
4080  break;
4081 
4082  case IS_XMLELEMENT:
4083  *op->resvalue = PointerGetDatum(xmlelement(xexpr,
4084  op->d.xmlexpr.named_argvalue,
4085  op->d.xmlexpr.named_argnull,
4086  op->d.xmlexpr.argvalue,
4087  op->d.xmlexpr.argnull));
4088  *op->resnull = false;
4089  break;
4090 
4091  case IS_XMLPARSE:
4092  {
4093  Datum *argvalue = op->d.xmlexpr.argvalue;
4094  bool *argnull = op->d.xmlexpr.argnull;
4095  text *data;
4096  bool preserve_whitespace;
4097 
4098  /* arguments are known to be text, bool */
4099  Assert(list_length(xexpr->args) == 2);
4100 
4101  if (argnull[0])
4102  return;
4103  value = argvalue[0];
4105 
4106  if (argnull[1]) /* probably can't happen */
4107  return;
4108  value = argvalue[1];
4109  preserve_whitespace = DatumGetBool(value);
4110 
4111  *op->resvalue = PointerGetDatum(xmlparse(data,
4112  xexpr->xmloption,
4113  preserve_whitespace));
4114  *op->resnull = false;
4115  }
4116  break;
4117 
4118  case IS_XMLPI:
4119  {
4120  text *arg;
4121  bool isnull;
4122 
4123  /* optional argument is known to be text */
4124  Assert(list_length(xexpr->args) <= 1);
4125 
4126  if (xexpr->args)
4127  {
4128  isnull = op->d.xmlexpr.argnull[0];
4129  if (isnull)
4130  arg = NULL;
4131  else
4132  arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
4133  }
4134  else
4135  {
4136  arg = NULL;
4137  isnull = false;
4138  }
4139 
4140  *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
4141  arg,
4142  isnull,
4143  op->resnull));
4144  }
4145  break;
4146 
4147  case IS_XMLROOT:
4148  {
4149  Datum *argvalue = op->d.xmlexpr.argvalue;
4150  bool *argnull = op->d.xmlexpr.argnull;
4151  xmltype *data;
4152  text *version;
4153  int standalone;
4154 
4155  /* arguments are known to be xml, text, int */
4156  Assert(list_length(xexpr->args) == 3);
4157 
4158  if (argnull[0])
4159  return;
4160  data = DatumGetXmlP(argvalue[0]);
4161 
4162  if (argnull[1])
4163  version = NULL;
4164  else
4165  version = DatumGetTextPP(argvalue[1]);
4166 
4167  Assert(!argnull[2]); /* always present */
4168  standalone = DatumGetInt32(argvalue[2]);
4169 
4170  *op->resvalue = PointerGetDatum(xmlroot(data,
4171  version,
4172  standalone));
4173  *op->resnull = false;
4174  }
4175  break;
4176 
4177  case IS_XMLSERIALIZE:
4178  {
4179  Datum *argvalue = op->d.xmlexpr.argvalue;
4180  bool *argnull = op->d.xmlexpr.argnull;
4181 
4182  /* argument type is known to be xml */
4183  Assert(list_length(xexpr->args) == 1);
4184 
4185  if (argnull[0])
4186  return;
4187  value = argvalue[0];
4188 
4189  *op->resvalue =
4191  xexpr->xmloption,
4192  xexpr->indent));
4193  *op->resnull = false;
4194  }
4195  break;
4196 
4197  case IS_DOCUMENT:
4198  {
4199  Datum *argvalue = op->d.xmlexpr.argvalue;
4200  bool *argnull = op->d.xmlexpr.argnull;
4201 
4202  /* optional argument is known to be xml */
4203  Assert(list_length(xexpr->args) == 1);
4204 
4205  if (argnull[0])
4206  return;
4207  value = argvalue[0];
4208 
4209  *op->resvalue =
4211  *op->resnull = false;
4212  }
4213  break;
4214 
4215  default:
4216  elog(ERROR, "unrecognized XML operation");
4217  break;
4218  }
4219 }
4220 
4221 /*
4222  * Evaluate a JSON constructor expression.
4223  */
4224 void
4226  ExprContext *econtext)
4227 {
4228  Datum res;
4229  JsonConstructorExprState *jcstate = op->d.json_constructor.jcstate;
4231  bool is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
4232  bool isnull = false;
4233 
4234  if (ctor->type == JSCTOR_JSON_ARRAY)
4235  res = (is_jsonb ?
4239  jcstate->arg_nulls,
4240  jcstate->arg_types,
4242  else if (ctor->type == JSCTOR_JSON_OBJECT)
4243  res = (is_jsonb ?
4247  jcstate->arg_nulls,
4248  jcstate->arg_types,
4251  else if (ctor->type == JSCTOR_JSON_SCALAR)
4252  {
4253  if (jcstate->arg_nulls[0])
4254  {
4255  res = (Datum) 0;
4256  isnull = true;
4257  }
4258  else
4259  {
4260  Datum value = jcstate->arg_values[0];
4261  Oid outfuncid = jcstate->arg_type_cache[0].outfuncid;
4262  JsonTypeCategory category = (JsonTypeCategory)
4264 
4265  if (is_jsonb)
4266  res = datum_to_jsonb(value, category, outfuncid);
4267  else
4268  res = datum_to_json(value, category, outfuncid);
4269  }
4270  }
4271  else if (ctor->type == JSCTOR_JSON_PARSE)
4272  {
4273  if (jcstate->arg_nulls[0])
4274  {
4275  res = (Datum) 0;
4276  isnull = true;
4277  }
4278  else
4279  {
4280  Datum value = jcstate->arg_values[0];
4281  text *js = DatumGetTextP(value);
4282 
4283  if (is_jsonb)
4284  res = jsonb_from_text(js, true);
4285  else
4286  {
4287  (void) json_validate(js, true, true);
4288  res = value;
4289  }
4290  }
4291  }
4292  else
4293  elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type);
4294 
4295  *op->resvalue = res;
4296  *op->resnull = isnull;
4297 }
4298 
4299 /*
4300  * Evaluate a IS JSON predicate.
4301  */
4302 void
4304 {
4305  JsonIsPredicate *pred = op->d.is_json.pred;
4306  Datum js = *op->resvalue;
4307  Oid exprtype;
4308  bool res;
4309 
4310  if (*op->resnull)
4311  {
4312  *op->resvalue = BoolGetDatum(false);
4313  return;
4314  }
4315 
4316  exprtype = exprType(pred->expr);
4317 
4318  if (exprtype == TEXTOID || exprtype == JSONOID)
4319  {
4320  text *json = DatumGetTextP(js);
4321 
4322  if (pred->item_type == JS_TYPE_ANY)
4323  res = true;
4324  else
4325  {
4326  switch (json_get_first_token(json, false))
4327  {
4330  break;
4333  break;
4334  case JSON_TOKEN_STRING:
4335  case JSON_TOKEN_NUMBER:
4336  case JSON_TOKEN_TRUE:
4337  case JSON_TOKEN_FALSE:
4338  case JSON_TOKEN_NULL:
4340  break;
4341  default:
4342  res = false;
4343  break;
4344  }
4345  }
4346 
4347  /*
4348  * Do full parsing pass only for uniqueness check or for JSON text
4349  * validation.
4350  */
4351  if (res && (pred->unique_keys || exprtype == TEXTOID))
4352  res = json_validate(json, pred->unique_keys, false);
4353  }
4354  else if (exprtype == JSONBOID)
4355  {
4356  if (pred->item_type == JS_TYPE_ANY)
4357  res = true;
4358  else
4359  {
4360  Jsonb *jb = DatumGetJsonbP(js);
4361 
4362  switch (pred->item_type)
4363  {
4364  case JS_TYPE_OBJECT:
4365  res = JB_ROOT_IS_OBJECT(jb);
4366  break;
4367  case JS_TYPE_ARRAY:
4368  res = JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb);
4369  break;
4370  case JS_TYPE_SCALAR:
4371  res = JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb);
4372  break;
4373  default:
4374  res = false;
4375  break;
4376  }
4377  }
4378 
4379  /* Key uniqueness check is redundant for jsonb */
4380  }
4381  else
4382  res = false;
4383 
4384  *op->resvalue = BoolGetDatum(res);
4385 }
4386 
4387 /*
4388  * Evaluate a jsonpath against a document, both of which must have been
4389  * evaluated and their values saved in op->d.jsonexpr.jsestate.
4390  *
4391  * If an error occurs during JsonPath* evaluation or when coercing its result
4392  * to the RETURNING type, JsonExprState.error is set to true, provided the
4393  * ON ERROR behavior is not ERROR. Similarly, if JsonPath{Query|Value}() found
4394  * no matching items, JsonExprState.empty is set to true, provided the ON EMPTY
4395  * behavior is not ERROR. That is to signal to the subsequent steps that check
4396  * those flags to return the ON ERROR / ON EMPTY expression.
4397  *
4398  * Return value is the step address to be performed next. It will be one of
4399  * jump_error, jump_empty, jump_eval_coercion, or jump_end, all given in
4400  * op->d.jsonexpr.jsestate.
4401  */
4402 int
4404  ExprContext *econtext)
4405 {
4406  JsonExprState *jsestate = op->d.jsonexpr.jsestate;
4407  JsonExpr *jsexpr = jsestate->jsexpr;
4408  Datum item;
4409  JsonPath *path;
4410  bool throw_error = jsexpr->on_error->btype == JSON_BEHAVIOR_ERROR;
4411  bool error = false,
4412  empty = false;
4413  int jump_eval_coercion = jsestate->jump_eval_coercion;
4414  char *val_string = NULL;
4415 
4416  item = jsestate->formatted_expr.value;
4418 
4419  /* Set error/empty to false. */
4420  memset(&jsestate->error, 0, sizeof(NullableDatum));
4421  memset(&jsestate->empty, 0, sizeof(NullableDatum));
4422 
4423  /* Also reset ErrorSaveContext contents for the next row. */
4425  {
4426  jsestate->escontext.error_data = NULL;
4428  }
4430 
4431  switch (jsexpr->op)
4432  {
4433  case JSON_EXISTS_OP:
4434  {
4435  bool exists = JsonPathExists(item, path,
4436  !throw_error ? &error : NULL,
4437  jsestate->args);
4438 
4439  if (!error)
4440  {
4441  *op->resnull = false;
4442  *op->resvalue = BoolGetDatum(exists);
4443  }
4444  }
4445  break;
4446 
4447  case JSON_QUERY_OP:
4448  *op->resvalue = JsonPathQuery(item, path, jsexpr->wrapper, &empty,
4449  !throw_error ? &error : NULL,
4450  jsestate->args,
4451  jsexpr->column_name);
4452 
4453  *op->resnull = (DatumGetPointer(*op->resvalue) == NULL);
4454  break;
4455 
4456  case JSON_VALUE_OP:
4457  {
4458  JsonbValue *jbv = JsonPathValue(item, path, &empty,
4459  !throw_error ? &error : NULL,
4460  jsestate->args,
4461  jsexpr->column_name);
4462 
4463  if (jbv == NULL)
4464  {
4465  /* Will be coerced with json_populate_type(), if needed. */
4466  *op->resvalue = (Datum) 0;
4467  *op->resnull = true;
4468  }
4469  else if (!error && !empty)
4470  {
4471  if (jsexpr->returning->typid == JSONOID ||
4472  jsexpr->returning->typid == JSONBOID)
4473  {
4476  }
4477  else if (jsexpr->use_json_coercion)
4478  {
4479  *op->resvalue = JsonbPGetDatum(JsonbValueToJsonb(jbv));
4480  *op->resnull = false;
4481  }
4482  else
4483  {
4484  val_string = ExecGetJsonValueItemString(jbv, op->resnull);
4485 
4486  /*
4487  * Simply convert to the default RETURNING type (text)
4488  * if no coercion needed.
4489  */
4490  if (!jsexpr->use_io_coercion)
4491  *op->resvalue = DirectFunctionCall1(textin,
4493  }
4494  }
4495  break;
4496  }
4497 
4498  /* JSON_TABLE_OP can't happen here */
4499 
4500  default:
4501  elog(ERROR, "unrecognized SQL/JSON expression op %d",
4502  (int) jsexpr->op);
4503  return false;
4504  }
4505 
4506  /*
4507  * Coerce the result value to the RETURNING type by calling its input
4508  * function.
4509  */
4510  if (!*op->resnull && jsexpr->use_io_coercion)
4511  {
4512  FunctionCallInfo fcinfo;
4513 
4514  Assert(jump_eval_coercion == -1);
4515  fcinfo = jsestate->input_fcinfo;
4516  Assert(fcinfo != NULL);
4517  Assert(val_string != NULL);
4518  fcinfo->args[0].value = PointerGetDatum(val_string);
4519  fcinfo->args[0].isnull = *op->resnull;
4520 
4521  /*
4522  * Second and third arguments are already set up in
4523  * ExecInitJsonExpr().
4524  */
4525 
4526  fcinfo->isnull = false;
4527  *op->resvalue = FunctionCallInvoke(fcinfo);
4529  error = true;
4530  }
4531 
4532  /*
4533  * When setting up the ErrorSaveContext (if needed) for capturing the
4534  * errors that occur when coercing the JsonBehavior expression, set
4535  * details_wanted to be able to show the actual error message as the
4536  * DETAIL of the error message that tells that it is the JsonBehavior
4537  * expression that caused the error; see ExecEvalJsonCoercionFinish().
4538  */
4539 
4540  /* Handle ON EMPTY. */
4541  if (empty)
4542  {
4543  *op->resvalue = (Datum) 0;
4544  *op->resnull = true;
4545  if (jsexpr->on_empty)
4546  {
4547  if (jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR)
4548  {
4549  jsestate->empty.value = BoolGetDatum(true);
4550  /* Set up to catch coercion errors of the ON EMPTY value. */
4553  /* Jump to end if the ON EMPTY behavior is to return NULL */
4555  }
4556  }
4557  else if (jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR)
4558  {
4559  jsestate->error.value = BoolGetDatum(true);
4560  /* Set up to catch coercion errors of the ON ERROR value. */
4563  Assert(!throw_error);
4564  /* Jump to end if the ON ERROR behavior is to return NULL */
4566  }
4567 
4568  if (jsexpr->column_name)
4569  ereport(ERROR,
4570  errcode(ERRCODE_NO_SQL_JSON_ITEM),
4571  errmsg("no SQL/JSON item found for specified path of column \"%s\"",
4572  jsexpr->column_name));
4573  else
4574  ereport(ERROR,
4575  errcode(ERRCODE_NO_SQL_JSON_ITEM),
4576  errmsg("no SQL/JSON item found for specified path"));
4577  }
4578 
4579  /*
4580  * ON ERROR. Wouldn't get here if the behavior is ERROR, because they
4581  * would have already been thrown.
4582  */
4583  if (error)
4584  {
4585  Assert(!throw_error);
4586  *op->resvalue = (Datum) 0;
4587  *op->resnull = true;
4588  jsestate->error.value = BoolGetDatum(true);
4589  /* Set up to catch coercion errors of the ON ERROR value. */
4592  /* Jump to end if the ON ERROR behavior is to return NULL */
4594  }
4595 
4596  return jump_eval_coercion >= 0 ? jump_eval_coercion : jsestate->jump_end;
4597 }
4598 
4599 /*
4600  * Convert the given JsonbValue to its C string representation
4601  *
4602  * *resnull is set if the JsonbValue is a jbvNull.
4603  */
4604 static char *
4606 {
4607  *resnull = false;
4608 
4609  /* get coercion state reference and datum of the corresponding SQL type */
4610  switch (item->type)
4611  {
4612  case jbvNull:
4613  *resnull = true;
4614  return NULL;
4615 
4616  case jbvString:
4617  {
4618  char *str = palloc(item->val.string.len + 1);
4619 
4620  memcpy(str, item->val.string.val, item->val.string.len);
4621  str[item->val.string.len] = '\0';
4622  return str;
4623  }
4624 
4625  case jbvNumeric:
4627  NumericGetDatum(item->val.numeric)));
4628 
4629  case jbvBool:
4631  BoolGetDatum(item->val.boolean)));
4632 
4633  case jbvDatetime:
4634  switch (item->val.datetime.typid)
4635  {
4636  case DATEOID:
4638  item->val.datetime.value));
4639  case TIMEOID:
4641  item->val.datetime.value));
4642  case TIMETZOID:
4644  item->val.datetime.value));
4645  case TIMESTAMPOID:
4647  item->val.datetime.value));
4648  case TIMESTAMPTZOID:
4650  item->val.datetime.value));
4651  default:
4652  elog(ERROR, "unexpected jsonb datetime type oid %u",
4653  item->val.datetime.typid);
4654  }
4655  break;
4656 
4657  case jbvArray:
4658  case jbvObject:
4659  case jbvBinary:
4662 
4663  default:
4664  elog(ERROR, "unexpected jsonb value type %d", item->type);
4665  }
4666 
4667  Assert(false);
4668  *resnull = true;
4669  return NULL;
4670 }
4671 
4672 /*
4673  * Coerce a jsonb value produced by ExecEvalJsonExprPath() or an ON ERROR /
4674  * ON EMPTY behavior expression to the target type.
4675  *
4676  * Any soft errors that occur here will be checked by
4677  * EEOP_JSONEXPR_COERCION_FINISH that will run after this.
4678  */
4679 void
4681  ExprContext *econtext)
4682 {
4683  ErrorSaveContext *escontext = op->d.jsonexpr_coercion.escontext;
4684 
4685  /*
4686  * Prepare to call json_populate_type() to coerce the boolean result of
4687  * JSON_EXISTS_OP to the target type. If the the target type is integer
4688  * or a domain over integer, call the boolean-to-integer cast function
4689  * instead, because the integer's input function (which is what
4690  * json_populate_type() calls to coerce to scalar target types) doesn't
4691  * accept boolean literals as valid input. We only have a special case
4692  * for integer and domains thereof as it seems common to use those types
4693  * for EXISTS columns in JSON_TABLE().
4694  */
4695  if (op->d.jsonexpr_coercion.exists_coerce)
4696  {
4697  if (op->d.jsonexpr_coercion.exists_cast_to_int)
4698  {
4699  /* Check domain constraints if any. */
4700  if (op->d.jsonexpr_coercion.exists_check_domain &&
4701  !domain_check_safe(*op->resvalue, *op->resnull,
4702  op->d.jsonexpr_coercion.targettype,
4703  &op->d.jsonexpr_coercion.json_coercion_cache,
4704  econtext->ecxt_per_query_memory,
4705  (Node *) escontext))
4706  {
4707  *op->resnull = true;
4708  *op->resvalue = (Datum) 0;
4709  }
4710  else
4711  *op->resvalue = DirectFunctionCall1(bool_int4, *op->resvalue);
4712  return;
4713  }
4714 
4715  *op->resvalue = DirectFunctionCall1(jsonb_in,
4716  DatumGetBool(*op->resvalue) ?
4717  CStringGetDatum("true") :
4718  CStringGetDatum("false"));
4719  }
4720 
4721  *op->resvalue = json_populate_type(*op->resvalue, JSONBOID,
4722  op->d.jsonexpr_coercion.targettype,
4723  op->d.jsonexpr_coercion.targettypmod,
4724  &op->d.jsonexpr_coercion.json_coercion_cache,
4725  econtext->ecxt_per_query_memory,
4726  op->resnull,
4727  op->d.jsonexpr_coercion.omit_quotes,
4728  (Node *) escontext);
4729 }
4730 
4731 static char *
4733 {
4734  /*
4735  * The order of array elements must correspond to the order of
4736  * JsonBehaviorType members.
4737  */
4738  const char *behavior_names[] =
4739  {
4740  "NULL",
4741  "ERROR",
4742  "EMPTY",
4743  "TRUE",
4744  "FALSE",
4745  "UNKNOWN",
4746  "EMPTY ARRAY",
4747  "EMPTY OBJECT",
4748  "DEFAULT"
4749  };
4750 
4751  return pstrdup(behavior_names[behavior->btype]);
4752 }
4753 
4754 /*
4755  * Checks if an error occurred in ExecEvalJsonCoercion(). If so, this sets
4756  * JsonExprState.error to trigger the ON ERROR handling steps, unless the
4757  * error is thrown when coercing a JsonBehavior value.
4758  */
4759 void
4761 {
4762  JsonExprState *jsestate = op->d.jsonexpr.jsestate;
4763 
4765  {
4766  /*
4767  * jsestate->error or jsestate->empty being set means that the error
4768  * occurred when coercing the JsonBehavior value. Throw the error in
4769  * that case with the actual coercion error message shown in the
4770  * DETAIL part.
4771  */
4773  ereport(ERROR,
4774  (errcode(ERRCODE_DATATYPE_MISMATCH),
4775  /*- translator: first %s is a SQL/JSON clause (e.g. ON ERROR) */
4776  errmsg("could not coerce %s expression (%s) to the RETURNING type",
4777  "ON ERROR",
4780  else if (DatumGetBool(jsestate->empty.value))
4781  ereport(ERROR,
4782  (errcode(ERRCODE_DATATYPE_MISMATCH),
4783  /*- translator: first %s is a SQL/JSON clause (e.g. ON ERROR) */
4784  errmsg("could not coerce %s expression (%s) to the RETURNING type",
4785  "ON EMPTY",
4788 
4789  *op->resvalue = (Datum) 0;
4790  *op->resnull = true;
4791 
4792  jsestate->error.value = BoolGetDatum(true);
4793 
4794  /*
4795  * Reset for next use such as for catching errors when coercing a
4796  * JsonBehavior expression.
4797  */
4801  }
4802 }
4803 
4804 /*
4805  * ExecEvalGroupingFunc
4806  *
4807  * Computes a bitmask with a bit for each (unevaluated) argument expression
4808  * (rightmost arg is least significant bit).
4809  *
4810  * A bit is set if the corresponding expression is NOT part of the set of
4811  * grouping expressions in the current grouping set.
4812  */
4813 void
4815 {
4816  AggState *aggstate = castNode(AggState, state->parent);
4817  int result = 0;
4818  Bitmapset *grouped_cols = aggstate->grouped_cols;
4819  ListCell *lc;
4820 
4821  foreach(lc, op->d.grouping_func.clauses)
4822  {
4823  int attnum = lfirst_int(lc);
4824 
4825  result <<= 1;
4826 
4827  if (!bms_is_member(attnum, grouped_cols))
4828  result |= 1;
4829  }
4830 
4831  *op->resvalue = Int32GetDatum(result);
4832  *op->resnull = false;
4833 }
4834 
4835 /*
4836  * ExecEvalMergeSupportFunc
4837  *
4838  * Returns information about the current MERGE action for its RETURNING list.
4839  */
4840 void
4842  ExprContext *econtext)
4843 {
4844  ModifyTableState *mtstate = castNode(ModifyTableState, state->parent);
4845  MergeActionState *relaction = mtstate->mt_merge_action;
4846 
4847  if (!relaction)
4848  elog(ERROR, "no merge action in progress");
4849 
4850  /* Return the MERGE action ("INSERT", "UPDATE", or "DELETE") */
4851  switch (relaction->mas_action->commandType)
4852  {
4853  case CMD_INSERT:
4854  *op->resvalue = PointerGetDatum(cstring_to_text_with_len("INSERT", 6));
4855  *op->resnull = false;
4856  break;
4857  case CMD_UPDATE:
4858  *op->resvalue = PointerGetDatum(cstring_to_text_with_len("UPDATE", 6));
4859  *op->resnull = false;
4860  break;
4861  case CMD_DELETE:
4862  *op->resvalue = PointerGetDatum(cstring_to_text_with_len("DELETE", 6));
4863  *op->resnull = false;
4864  break;
4865  case CMD_NOTHING:
4866  elog(ERROR, "unexpected merge action: DO NOTHING");
4867  break;
4868  default:
4869  elog(ERROR, "unrecognized commandType: %d",
4870  (int) relaction->mas_action->commandType);
4871  }
4872 }
4873 
4874 /*
4875  * Hand off evaluation of a subplan to nodeSubplan.c
4876  */
4877 void
4879 {
4880  SubPlanState *sstate = op->d.subplan.sstate;
4881 
4882  /* could potentially be nested, so make sure there's enough stack */
4884 
4885  *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
4886 }
4887 
4888 /*
4889  * Evaluate a wholerow Var expression.
4890  *
4891  * Returns a Datum whose value is the value of a whole-row range variable
4892  * with respect to given expression context.
4893  */
4894 void
4896 {
4897  Var *variable = op->d.wholerow.var;
4898  TupleTableSlot *slot;
4899  TupleDesc output_tupdesc;
4900  MemoryContext oldcontext;
4901  HeapTupleHeader dtuple;
4902  HeapTuple tuple;
4903 
4904  /* This was checked by ExecInitExpr */
4905  Assert(variable->varattno == InvalidAttrNumber);
4906 
4907  /* Get the input slot we want */
4908  switch (variable->varno)
4909  {
4910  case INNER_VAR:
4911  /* get the tuple from the inner node */
4912  slot = econtext->ecxt_innertuple;
4913  break;
4914 
4915  case OUTER_VAR:
4916  /* get the tuple from the outer node */
4917  slot = econtext->ecxt_outertuple;
4918  break;
4919 
4920  /* INDEX_VAR is handled by default case */
4921 
4922  default:
4923  /* get the tuple from the relation being scanned */
4924  slot = econtext->ecxt_scantuple;
4925  break;
4926  }
4927 
4928  /* Apply the junkfilter if any */
4929  if (op->d.wholerow.junkFilter != NULL)
4930  slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
4931 
4932  /*
4933  * If first time through, obtain tuple descriptor and check compatibility.
4934  *
4935  * XXX: It'd be great if this could be moved to the expression
4936  * initialization phase, but due to using slots that's currently not
4937  * feasible.
4938  */
4939  if (op->d.wholerow.first)
4940  {
4941  /* optimistically assume we don't need slow path */
4942  op->d.wholerow.slow = false;
4943 
4944  /*
4945  * If the Var identifies a named composite type, we must check that
4946  * the actual tuple type is compatible with it.
4947  */
4948  if (variable->vartype != RECORDOID)
4949  {
4950  TupleDesc var_tupdesc;
4951  TupleDesc slot_tupdesc;
4952 
4953  /*
4954  * We really only care about numbers of attributes and data types.
4955  * Also, we can ignore type mismatch on columns that are dropped
4956  * in the destination type, so long as (1) the physical storage
4957  * matches or (2) the actual column value is NULL. Case (1) is
4958  * helpful in some cases involving out-of-date cached plans, while
4959  * case (2) is expected behavior in situations such as an INSERT
4960  * into a table with dropped columns (the planner typically
4961  * generates an INT4 NULL regardless of the dropped column type).
4962  * If we find a dropped column and cannot verify that case (1)
4963  * holds, we have to use the slow path to check (2) for each row.
4964  *
4965  * If vartype is a domain over composite, just look through that
4966  * to the base composite type.
4967  */
4968  var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
4969  -1, false);
4970 
4971  slot_tupdesc = slot->tts_tupleDescriptor;
4972 
4973  if (var_tupdesc->natts != slot_tupdesc->natts)
4974  ereport(ERROR,
4975  (errcode(ERRCODE_DATATYPE_MISMATCH),
4976  errmsg("table row type and query-specified row type do not match"),
4977  errdetail_plural("Table row contains %d attribute, but query expects %d.",
4978  "Table row contains %d attributes, but query expects %d.",
4979  slot_tupdesc->natts,
4980  slot_tupdesc->natts,
4981  var_tupdesc->natts)));
4982 
4983  for (int i = 0; i < var_tupdesc->natts; i++)
4984  {
4985  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4986  Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i);
4987 
4988  if (vattr->atttypid == sattr->atttypid)
4989  continue; /* no worries */
4990  if (!vattr->attisdropped)
4991  ereport(ERROR,
4992  (errcode(ERRCODE_DATATYPE_MISMATCH),
4993  errmsg("table row type and query-specified row type do not match"),
4994  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
4995  format_type_be(sattr->atttypid),
4996  i + 1,
4997  format_type_be(vattr->atttypid))));
4998 
4999  if (vattr->attlen != sattr->attlen ||
5000  vattr->attalign != sattr->attalign)
5001  op->d.wholerow.slow = true; /* need to check for nulls */
5002  }
5003 
5004  /*
5005  * Use the variable's declared rowtype as the descriptor for the
5006  * output values. In particular, we *must* absorb any
5007  * attisdropped markings.
5008  */
5009  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
5010  output_tupdesc = CreateTupleDescCopy(var_tupdesc);
5011  MemoryContextSwitchTo(oldcontext);
5012 
5013  ReleaseTupleDesc(var_tupdesc);
5014  }
5015  else
5016  {
5017  /*
5018  * In the RECORD case, we use the input slot's rowtype as the
5019  * descriptor for the output values, modulo possibly assigning new
5020  * column names below.
5021  */
5022  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
5023  output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
5024  MemoryContextSwitchTo(oldcontext);
5025 
5026  /*
5027  * It's possible that the input slot is a relation scan slot and
5028  * so is marked with that relation's rowtype. But we're supposed
5029  * to be returning RECORD, so reset to that.
5030  */
5031  output_tupdesc->tdtypeid = RECORDOID;
5032  output_tupdesc->tdtypmod = -1;
5033 
5034  /*
5035  * We already got the correct physical datatype info above, but
5036  * now we should try to find the source RTE and adopt its column
5037  * aliases, since it's unlikely that the input slot has the
5038  * desired names.
5039  *
5040  * If we can't locate the RTE, assume the column names we've got
5041  * are OK. (As of this writing, the only cases where we can't
5042  * locate the RTE are in execution of trigger WHEN clauses, and
5043  * then the Var will have the trigger's relation's rowtype, so its
5044  * names are fine.) Also, if the creator of the RTE didn't bother
5045  * to fill in an eref field, assume our column names are OK. (This
5046  * happens in COPY, and perhaps other places.)
5047  */
5048  if (econtext->ecxt_estate &&
5049  variable->varno <= econtext->ecxt_estate->es_range_table_size)
5050  {
5051  RangeTblEntry *rte = exec_rt_fetch(variable->varno,
5052  econtext->ecxt_estate);
5053 
5054  if (rte->eref)
5055  ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
5056  }
5057  }
5058 
5059  /* Bless the tupdesc if needed, and save it in the execution state */
5060  op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
5061 
5062  op->d.wholerow.first = false;
5063  }
5064 
5065  /*
5066  * Make sure all columns of the slot are accessible in the slot's
5067  * Datum/isnull arrays.
5068  */
5069  slot_getallattrs(slot);
5070 
5071  if (op->d.wholerow.slow)
5072  {
5073  /* Check to see if any dropped attributes are non-null */
5074  TupleDesc tupleDesc = slot->tts_tupleDescriptor;
5075  TupleDesc var_tupdesc = op->d.wholerow.tupdesc;
5076 
5077  Assert(var_tupdesc->natts == tupleDesc->natts);
5078 
5079  for (int i = 0; i < var_tupdesc->natts; i++)
5080  {
5081  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
5082  Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i);
5083 
5084  if (!vattr->attisdropped)
5085  continue; /* already checked non-dropped cols */
5086  if (slot->tts_isnull[i])
5087  continue; /* null is always okay */
5088  if (vattr->attlen != sattr->attlen ||
5089  vattr->attalign != sattr->attalign)
5090  ereport(ERROR,
5091  (errcode(ERRCODE_DATATYPE_MISMATCH),
5092  errmsg("table row type and query-specified row type do not match"),
5093  errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
5094  i + 1)));
5095  }
5096  }
5097 
5098  /*
5099  * Build a composite datum, making sure any toasted fields get detoasted.
5100  *
5101  * (Note: it is critical that we not change the slot's state here.)
5102  */
5104  slot->tts_values,
5105  slot->tts_isnull);
5106  dtuple = tuple->t_data;
5107 
5108  /*
5109  * Label the datum with the composite type info we identified before.
5110  *
5111  * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
5112  * the tuple build step; but that seems a tad risky so let's not.)
5113  */
5114  HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
5115  HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
5116 
5117  *op->resvalue = PointerGetDatum(dtuple);
5118  *op->resnull = false;
5119 }
5120 
5121 void
5123  TupleTableSlot *slot)
5124 {
5125  Datum d;
5126 
5127  /* slot_getsysattr has sufficient defenses against bad attnums */
5128  d = slot_getsysattr(slot,
5129  op->d.var.attnum,
5130  op->resnull);
5131  *op->resvalue = d;
5132  /* this ought to be unreachable, but it's cheap enough to check */
5133  if (unlikely(*op->resnull))
5134  elog(ERROR, "failed to fetch attribute from slot");
5135 }
5136 
5137 /*
5138  * Transition value has not been initialized. This is the first non-NULL input
5139  * value for a group. We use it as the initial value for transValue.
5140  */
5141 void
5144 {
5146  MemoryContext oldContext;
5147 
5148  /*
5149  * We must copy the datum into aggcontext if it is pass-by-ref. We do not
5150  * need to pfree the old transValue, since it's NULL. (We already checked
5151  * that the agg's input type is binary-compatible with its transtype, so
5152  * straight copy here is OK.)
5153  */
5155  pergroup->transValue = datumCopy(fcinfo->args[1].value,
5158  pergroup->transValueIsNull = false;
5159  pergroup->noTransValue = false;
5160  MemoryContextSwitchTo(oldContext);
5161 }
5162 
5163 /*
5164  * Ensure that the new transition value is stored in the aggcontext,
5165  * rather than the per-tuple context. This should be invoked only when
5166  * we know (a) the transition data type is pass-by-reference, and (b)
5167  * the newValue is distinct from the oldValue.
5168  *
5169  * NB: This can change the current memory context.
5170  *
5171  * We copy the presented newValue into the aggcontext, except when the datum
5172  * points to a R/W expanded object that is already a child of the aggcontext,
5173  * in which case we need not copy. We then delete the oldValue, if not null.
5174  *
5175  * If the presented datum points to a R/W expanded object that is a child of
5176  * some other context, ideally we would just reparent it under the aggcontext.
5177  * Unfortunately, that doesn't work easily, and it wouldn't help anyway for
5178  * aggregate-aware transfns. We expect that a transfn that deals in expanded
5179  * objects and is aware of the memory management conventions for aggregate
5180  * transition values will (1) on first call, return a R/W expanded object that
5181  * is already in the right context, allowing us to do nothing here, and (2) on
5182  * subsequent calls, modify and return that same object, so that control
5183  * doesn't even reach here. However, if we have a generic transfn that
5184  * returns a new R/W expanded object (probably in the per-tuple context),
5185  * reparenting that result would cause problems. We'd pass that R/W object to
5186  * the next invocation of the transfn, and then it would be at liberty to
5187  * change or delete that object, and if it deletes it then our own attempt to
5188  * delete the now-old transvalue afterwards would be a double free. We avoid
5189  * this problem by forcing the stored transvalue to always be a flat
5190  * non-expanded object unless the transfn is visibly doing aggregate-aware
5191  * memory management. This is somewhat inefficient, but the best answer to
5192  * that is to write a smarter transfn.
5193  */
5194 Datum
5196  Datum newValue, bool newValueIsNull,
5197  Datum oldValue, bool oldValueIsNull)
5198 {
5199  Assert(newValue != oldValue);
5200 
5201  if (!newValueIsNull)
5202  {
5204  if (DatumIsReadWriteExpandedObject(newValue,
5205  false,
5206  pertrans->transtypeLen) &&
5207  MemoryContextGetParent(DatumGetEOHP(newValue)->eoh_context) == CurrentMemoryContext)
5208  /* do nothing */ ;
5209  else
5210  newValue = datumCopy(newValue,
5213  }
5214  else
5215  {
5216  /*
5217  * Ensure that AggStatePerGroup->transValue ends up being 0, so
5218  * callers can safely compare newValue/oldValue without having to
5219  * check their respective nullness.
5220  */
5221  newValue = (Datum) 0;
5222  }
5223 
5224  if (!oldValueIsNull)
5225  {
5226  if (DatumIsReadWriteExpandedObject(oldValue,
5227  false,
5229  DeleteExpandedObject(oldValue);
5230  else
5231  pfree(DatumGetPointer(oldValue));
5232  }
5233 
5234  return newValue;
5235 }
5236 
5237 /*
5238  * ExecEvalPreOrderedDistinctSingle
5239  * Returns true when the aggregate transition value Datum is distinct
5240  * from the previous input Datum and returns false when the input Datum
5241  * matches the previous input Datum.
5242  */
5243 bool
5245 {
5248 
5249  if (!pertrans->haslast ||
5250  pertrans->lastisnull != isnull ||
5253  pertrans->lastdatum, value))))
5254  {
5256  !pertrans->lastisnull)
5258 
5259  pertrans->haslast = true;
5260  if (!isnull)
5261  {
5262  MemoryContext oldContext;
5263 
5265 
5268 
5269  MemoryContextSwitchTo(oldContext);
5270  }
5271  else
5272  pertrans->lastdatum = (Datum) 0;
5274  return true;
5275  }
5276 
5277  return false;
5278 }
5279 
5280 /*
5281  * ExecEvalPreOrderedDistinctMulti
5282  * Returns true when the aggregate input is distinct from the previous
5283  * input and returns false when the input matches the previous input, or
5284  * when there was no previous input.
5285  */
5286 bool
5288 {
5289  ExprContext *tmpcontext = aggstate->tmpcontext;
5290  bool isdistinct = false; /* for now */
5291  TupleTableSlot *save_outer;
5292  TupleTableSlot *save_inner;
5293 
5294  for (int i = 0; i < pertrans->numTransInputs; i++)
5295  {
5298  }
5299 
5303 
5304  /* save the previous slots before we overwrite them */
5305  save_outer = tmpcontext->ecxt_outertuple;
5306  save_inner = tmpcontext->ecxt_innertuple;
5307 
5308  tmpcontext->ecxt_outertuple = pertrans->sortslot;
5309  tmpcontext->ecxt_innertuple = pertrans->uniqslot;
5310 
5311  if (!pertrans->haslast ||
5312  !ExecQual(pertrans->equalfnMulti, tmpcontext))
5313  {
5314  if (pertrans->haslast)
5316 
5317  pertrans->haslast = true;
5319 
5320  isdistinct = true;
5321  }
5322 
5323  /* restore the original slots */
5324  tmpcontext->ecxt_outertuple = save_outer;
5325  tmpcontext->ecxt_innertuple = save_inner;
5326 
5327  return isdistinct;
5328 }
5329 
5330 /*
5331  * Invoke ordered transition function, with a datum argument.
5332  */
5333 void
5335  ExprContext *econtext)
5336 {
5337  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
5338  int setno = op->d.agg_trans.setno;
5339 
5341  *op->resvalue, *op->resnull);
5342 }
5343 
5344 /*
5345  * Invoke ordered transition function, with a tuple argument.
5346  */
5347 void