PostgreSQL Source Code  git master
execExpr.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * execExpr.c
4  * Expression evaluation infrastructure.
5  *
6  * During executor startup, we compile each expression tree (which has
7  * previously been processed by the parser and planner) into an ExprState,
8  * using ExecInitExpr() et al. This converts the tree into a flat array
9  * of ExprEvalSteps, which may be thought of as instructions in a program.
10  * At runtime, we'll execute steps, starting with the first, until we reach
11  * an EEOP_DONE opcode.
12  *
13  * This file contains the "compilation" logic. It is independent of the
14  * specific execution technology we use (switch statement, computed goto,
15  * JIT compilation, etc).
16  *
17  * See src/backend/executor/README for some background, specifically the
18  * "Expression Trees and ExprState nodes", "Expression Initialization",
19  * and "Expression Evaluation" sections.
20  *
21  *
22  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
23  * Portions Copyright (c) 1994, Regents of the University of California
24  *
25  *
26  * IDENTIFICATION
27  * src/backend/executor/execExpr.c
28  *
29  *-------------------------------------------------------------------------
30  */
31 #include "postgres.h"
32 
33 #include "access/nbtree.h"
34 #include "catalog/objectaccess.h"
35 #include "catalog/pg_proc.h"
36 #include "catalog/pg_type.h"
37 #include "executor/execExpr.h"
38 #include "executor/nodeSubplan.h"
39 #include "funcapi.h"
40 #include "jit/jit.h"
41 #include "miscadmin.h"
42 #include "nodes/makefuncs.h"
43 #include "nodes/nodeFuncs.h"
44 #include "nodes/subscripting.h"
45 #include "optimizer/optimizer.h"
46 #include "pgstat.h"
47 #include "utils/acl.h"
48 #include "utils/array.h"
49 #include "utils/builtins.h"
50 #include "utils/jsonfuncs.h"
51 #include "utils/jsonpath.h"
52 #include "utils/lsyscache.h"
53 #include "utils/typcache.h"
54 
55 
56 typedef struct ExprSetupInfo
57 {
58  /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */
62  /* MULTIEXPR SubPlan nodes appearing in the expression: */
65 
66 static void ExecReadyExpr(ExprState *state);
67 static void ExecInitExprRec(Expr *node, ExprState *state,
68  Datum *resv, bool *resnull);
69 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
70  Oid funcid, Oid inputcollid,
71  ExprState *state);
72 static void ExecInitSubPlanExpr(SubPlan *subplan,
74  Datum *resv, bool *resnull);
75 static void ExecCreateExprSetupSteps(ExprState *state, Node *node);
77 static bool expr_setup_walker(Node *node, ExprSetupInfo *info);
79 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
80  ExprState *state);
81 static void ExecInitSubscriptingRef(ExprEvalStep *scratch,
82  SubscriptingRef *sbsref,
84  Datum *resv, bool *resnull);
85 static bool isAssignmentIndirectionExpr(Expr *expr);
86 static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
88  Datum *resv, bool *resnull);
89 static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
90  ExprEvalStep *scratch,
91  FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
92  int transno, int setno, int setoff, bool ishash,
93  bool nullcheck);
94 static void ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
95  Datum *resv, bool *resnull,
96  ExprEvalStep *scratch);
97 static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning,
98  ErrorSaveContext *escontext, bool omit_quotes,
99  bool exists_coerce,
100  Datum *resv, bool *resnull);
101 
102 
103 /*
104  * ExecInitExpr: prepare an expression tree for execution
105  *
106  * This function builds and returns an ExprState implementing the given
107  * Expr node tree. The return ExprState can then be handed to ExecEvalExpr
108  * for execution. Because the Expr tree itself is read-only as far as
109  * ExecInitExpr and ExecEvalExpr are concerned, several different executions
110  * of the same plan tree can occur concurrently. (But note that an ExprState
111  * does mutate at runtime, so it can't be re-used concurrently.)
112  *
113  * This must be called in a memory context that will last as long as repeated
114  * executions of the expression are needed. Typically the context will be
115  * the same as the per-query context of the associated ExprContext.
116  *
117  * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
118  * the lists of such nodes held by the parent PlanState.
119  *
120  * Note: there is no ExecEndExpr function; we assume that any resource
121  * cleanup needed will be handled by just releasing the memory context
122  * in which the state tree is built. Functions that require additional
123  * cleanup work can register a shutdown callback in the ExprContext.
124  *
125  * 'node' is the root of the expression tree to compile.
126  * 'parent' is the PlanState node that owns the expression.
127  *
128  * 'parent' may be NULL if we are preparing an expression that is not
129  * associated with a plan tree. (If so, it can't have aggs or subplans.)
130  * Such cases should usually come through ExecPrepareExpr, not directly here.
131  *
132  * Also, if 'node' is NULL, we just return NULL. This is convenient for some
133  * callers that may or may not have an expression that needs to be compiled.
134  * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
135  * although ExecQual and ExecCheck will accept one (and treat it as "true").
136  */
137 ExprState *
138 ExecInitExpr(Expr *node, PlanState *parent)
139 {
140  ExprState *state;
141  ExprEvalStep scratch = {0};
142 
143  /* Special case: NULL expression produces a NULL ExprState pointer */
144  if (node == NULL)
145  return NULL;
146 
147  /* Initialize ExprState with empty step list */
149  state->expr = node;
150  state->parent = parent;
151  state->ext_params = NULL;
152 
153  /* Insert setup steps as needed */
155 
156  /* Compile the expression proper */
157  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
158 
159  /* Finally, append a DONE step */
160  scratch.opcode = EEOP_DONE;
161  ExprEvalPushStep(state, &scratch);
162 
164 
165  return state;
166 }
167 
168 /*
169  * ExecInitExprWithParams: prepare a standalone expression tree for execution
170  *
171  * This is the same as ExecInitExpr, except that there is no parent PlanState,
172  * and instead we may have a ParamListInfo describing PARAM_EXTERN Params.
173  */
174 ExprState *
176 {
177  ExprState *state;
178  ExprEvalStep scratch = {0};
179 
180  /* Special case: NULL expression produces a NULL ExprState pointer */
181  if (node == NULL)
182  return NULL;
183 
184  /* Initialize ExprState with empty step list */
186  state->expr = node;
187  state->parent = NULL;
188  state->ext_params = ext_params;
189 
190  /* Insert setup steps as needed */
192 
193  /* Compile the expression proper */
194  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
195 
196  /* Finally, append a DONE step */
197  scratch.opcode = EEOP_DONE;
198  ExprEvalPushStep(state, &scratch);
199 
201 
202  return state;
203 }
204 
205 /*
206  * ExecInitQual: prepare a qual for execution by ExecQual
207  *
208  * Prepares for the evaluation of a conjunctive boolean expression (qual list
209  * with implicit AND semantics) that returns true if none of the
210  * subexpressions are false.
211  *
212  * We must return true if the list is empty. Since that's a very common case,
213  * we optimize it a bit further by translating to a NULL ExprState pointer
214  * rather than setting up an ExprState that computes constant TRUE. (Some
215  * especially hot-spot callers of ExecQual detect this and avoid calling
216  * ExecQual at all.)
217  *
218  * If any of the subexpressions yield NULL, then the result of the conjunction
219  * is false. This makes ExecQual primarily useful for evaluating WHERE
220  * clauses, since SQL specifies that tuples with null WHERE results do not
221  * get selected.
222  */
223 ExprState *
224 ExecInitQual(List *qual, PlanState *parent)
225 {
226  ExprState *state;
227  ExprEvalStep scratch = {0};
228  List *adjust_jumps = NIL;
229 
230  /* short-circuit (here and in ExecQual) for empty restriction list */
231  if (qual == NIL)
232  return NULL;
233 
234  Assert(IsA(qual, List));
235 
237  state->expr = (Expr *) qual;
238  state->parent = parent;
239  state->ext_params = NULL;
240 
241  /* mark expression as to be used with ExecQual() */
242  state->flags = EEO_FLAG_IS_QUAL;
243 
244  /* Insert setup steps as needed */
246 
247  /*
248  * ExecQual() needs to return false for an expression returning NULL. That
249  * allows us to short-circuit the evaluation the first time a NULL is
250  * encountered. As qual evaluation is a hot-path this warrants using a
251  * special opcode for qual evaluation that's simpler than BOOL_AND (which
252  * has more complex NULL handling).
253  */
254  scratch.opcode = EEOP_QUAL;
255 
256  /*
257  * We can use ExprState's resvalue/resnull as target for each qual expr.
258  */
259  scratch.resvalue = &state->resvalue;
260  scratch.resnull = &state->resnull;
261 
262  foreach_ptr(Expr, node, qual)
263  {
264  /* first evaluate expression */
265  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
266 
267  /* then emit EEOP_QUAL to detect if it's false (or null) */
268  scratch.d.qualexpr.jumpdone = -1;
269  ExprEvalPushStep(state, &scratch);
270  adjust_jumps = lappend_int(adjust_jumps,
271  state->steps_len - 1);
272  }
273 
274  /* adjust jump targets */
275  foreach_int(jump, adjust_jumps)
276  {
277  ExprEvalStep *as = &state->steps[jump];
278 
279  Assert(as->opcode == EEOP_QUAL);
280  Assert(as->d.qualexpr.jumpdone == -1);
281  as->d.qualexpr.jumpdone = state->steps_len;
282  }
283 
284  /*
285  * At the end, we don't need to do anything more. The last qual expr must
286  * have yielded TRUE, and since its result is stored in the desired output
287  * location, we're done.
288  */
289  scratch.opcode = EEOP_DONE;
290  ExprEvalPushStep(state, &scratch);
291 
293 
294  return state;
295 }
296 
297 /*
298  * ExecInitCheck: prepare a check constraint for execution by ExecCheck
299  *
300  * This is much like ExecInitQual/ExecQual, except that a null result from
301  * the conjunction is treated as TRUE. This behavior is appropriate for
302  * evaluating CHECK constraints, since SQL specifies that NULL constraint
303  * conditions are not failures.
304  *
305  * Note that like ExecInitQual, this expects input in implicit-AND format.
306  * Users of ExecCheck that have expressions in normal explicit-AND format
307  * can just apply ExecInitExpr to produce suitable input for ExecCheck.
308  */
309 ExprState *
310 ExecInitCheck(List *qual, PlanState *parent)
311 {
312  /* short-circuit (here and in ExecCheck) for empty restriction list */
313  if (qual == NIL)
314  return NULL;
315 
316  Assert(IsA(qual, List));
317 
318  /*
319  * Just convert the implicit-AND list to an explicit AND (if there's more
320  * than one entry), and compile normally. Unlike ExecQual, we can't
321  * short-circuit on NULL results, so the regular AND behavior is needed.
322  */
323  return ExecInitExpr(make_ands_explicit(qual), parent);
324 }
325 
326 /*
327  * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
328  */
329 List *
331 {
332  List *result = NIL;
333  ListCell *lc;
334 
335  foreach(lc, nodes)
336  {
337  Expr *e = lfirst(lc);
338 
339  result = lappend(result, ExecInitExpr(e, parent));
340  }
341 
342  return result;
343 }
344 
345 /*
346  * ExecBuildProjectionInfo
347  *
348  * Build a ProjectionInfo node for evaluating the given tlist in the given
349  * econtext, and storing the result into the tuple slot. (Caller must have
350  * ensured that tuple slot has a descriptor matching the tlist!)
351  *
352  * inputDesc can be NULL, but if it is not, we check to see whether simple
353  * Vars in the tlist match the descriptor. It is important to provide
354  * inputDesc for relation-scan plan nodes, as a cross check that the relation
355  * hasn't been changed since the plan was made. At higher levels of a plan,
356  * there is no need to recheck.
357  *
358  * This is implemented by internally building an ExprState that performs the
359  * whole projection in one go.
360  *
361  * Caution: before PG v10, the targetList was a list of ExprStates; now it
362  * should be the planner-created targetlist, since we do the compilation here.
363  */
366  ExprContext *econtext,
367  TupleTableSlot *slot,
368  PlanState *parent,
369  TupleDesc inputDesc)
370 {
372  ExprState *state;
373  ExprEvalStep scratch = {0};
374  ListCell *lc;
375 
376  projInfo->pi_exprContext = econtext;
377  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
378  projInfo->pi_state.type = T_ExprState;
379  state = &projInfo->pi_state;
380  state->expr = (Expr *) targetList;
381  state->parent = parent;
382  state->ext_params = NULL;
383 
384  state->resultslot = slot;
385 
386  /* Insert setup steps as needed */
387  ExecCreateExprSetupSteps(state, (Node *) targetList);
388 
389  /* Now compile each tlist column */
390  foreach(lc, targetList)
391  {
392  TargetEntry *tle = lfirst_node(TargetEntry, lc);
393  Var *variable = NULL;
394  AttrNumber attnum = 0;
395  bool isSafeVar = false;
396 
397  /*
398  * If tlist expression is a safe non-system Var, use the fast-path
399  * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
400  * CheckVarSlotCompatibility() during plan startup. If a source slot
401  * was provided, we make the equivalent tests here; if a slot was not
402  * provided, we assume that no check is needed because we're dealing
403  * with a non-relation-scan-level expression.
404  */
405  if (tle->expr != NULL &&
406  IsA(tle->expr, Var) &&
407  ((Var *) tle->expr)->varattno > 0)
408  {
409  /* Non-system Var, but how safe is it? */
410  variable = (Var *) tle->expr;
411  attnum = variable->varattno;
412 
413  if (inputDesc == NULL)
414  isSafeVar = true; /* can't check, just assume OK */
415  else if (attnum <= inputDesc->natts)
416  {
417  Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
418 
419  /*
420  * If user attribute is dropped or has a type mismatch, don't
421  * use ASSIGN_*_VAR. Instead let the normal expression
422  * machinery handle it (which'll possibly error out).
423  */
424  if (!attr->attisdropped && variable->vartype == attr->atttypid)
425  {
426  isSafeVar = true;
427  }
428  }
429  }
430 
431  if (isSafeVar)
432  {
433  /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
434  switch (variable->varno)
435  {
436  case INNER_VAR:
437  /* get the tuple from the inner node */
438  scratch.opcode = EEOP_ASSIGN_INNER_VAR;
439  break;
440 
441  case OUTER_VAR:
442  /* get the tuple from the outer node */
443  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
444  break;
445 
446  /* INDEX_VAR is handled by default case */
447 
448  default:
449  /* get the tuple from the relation being scanned */
450  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
451  break;
452  }
453 
454  scratch.d.assign_var.attnum = attnum - 1;
455  scratch.d.assign_var.resultnum = tle->resno - 1;
456  ExprEvalPushStep(state, &scratch);
457  }
458  else
459  {
460  /*
461  * Otherwise, compile the column expression normally.
462  *
463  * We can't tell the expression to evaluate directly into the
464  * result slot, as the result slot (and the exprstate for that
465  * matter) can change between executions. We instead evaluate
466  * into the ExprState's resvalue/resnull and then move.
467  */
468  ExecInitExprRec(tle->expr, state,
469  &state->resvalue, &state->resnull);
470 
471  /*
472  * Column might be referenced multiple times in upper nodes, so
473  * force value to R/O - but only if it could be an expanded datum.
474  */
475  if (get_typlen(exprType((Node *) tle->expr)) == -1)
477  else
478  scratch.opcode = EEOP_ASSIGN_TMP;
479  scratch.d.assign_tmp.resultnum = tle->resno - 1;
480  ExprEvalPushStep(state, &scratch);
481  }
482  }
483 
484  scratch.opcode = EEOP_DONE;
485  ExprEvalPushStep(state, &scratch);
486 
488 
489  return projInfo;
490 }
491 
492 /*
493  * ExecBuildUpdateProjection
494  *
495  * Build a ProjectionInfo node for constructing a new tuple during UPDATE.
496  * The projection will be executed in the given econtext and the result will
497  * be stored into the given tuple slot. (Caller must have ensured that tuple
498  * slot has a descriptor matching the target rel!)
499  *
500  * When evalTargetList is false, targetList contains the UPDATE ... SET
501  * expressions that have already been computed by a subplan node; the values
502  * from this tlist are assumed to be available in the "outer" tuple slot.
503  * When evalTargetList is true, targetList contains the UPDATE ... SET
504  * expressions that must be computed (which could contain references to
505  * the outer, inner, or scan tuple slots).
506  *
507  * In either case, targetColnos contains a list of the target column numbers
508  * corresponding to the non-resjunk entries of targetList. The tlist values
509  * are assigned into these columns of the result tuple slot. Target columns
510  * not listed in targetColnos are filled from the UPDATE's old tuple, which
511  * is assumed to be available in the "scan" tuple slot.
512  *
513  * targetList can also contain resjunk columns. These must be evaluated
514  * if evalTargetList is true, but their values are discarded.
515  *
516  * relDesc must describe the relation we intend to update.
517  *
518  * This is basically a specialized variant of ExecBuildProjectionInfo.
519  * However, it also performs sanity checks equivalent to ExecCheckPlanOutput.
520  * Since we never make a normal tlist equivalent to the whole
521  * tuple-to-be-assigned, there is no convenient way to apply
522  * ExecCheckPlanOutput, so we must do our safety checks here.
523  */
526  bool evalTargetList,
527  List *targetColnos,
528  TupleDesc relDesc,
529  ExprContext *econtext,
530  TupleTableSlot *slot,
531  PlanState *parent)
532 {
534  ExprState *state;
535  int nAssignableCols;
536  bool sawJunk;
537  Bitmapset *assignedCols;
538  ExprSetupInfo deform = {0, 0, 0, NIL};
539  ExprEvalStep scratch = {0};
540  int outerattnum;
541  ListCell *lc,
542  *lc2;
543 
544  projInfo->pi_exprContext = econtext;
545  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
546  projInfo->pi_state.type = T_ExprState;
547  state = &projInfo->pi_state;
548  if (evalTargetList)
549  state->expr = (Expr *) targetList;
550  else
551  state->expr = NULL; /* not used */
552  state->parent = parent;
553  state->ext_params = NULL;
554 
555  state->resultslot = slot;
556 
557  /*
558  * Examine the targetList to see how many non-junk columns there are, and
559  * to verify that the non-junk columns come before the junk ones.
560  */
561  nAssignableCols = 0;
562  sawJunk = false;
563  foreach(lc, targetList)
564  {
565  TargetEntry *tle = lfirst_node(TargetEntry, lc);
566 
567  if (tle->resjunk)
568  sawJunk = true;
569  else
570  {
571  if (sawJunk)
572  elog(ERROR, "subplan target list is out of order");
573  nAssignableCols++;
574  }
575  }
576 
577  /* We should have one targetColnos entry per non-junk column */
578  if (nAssignableCols != list_length(targetColnos))
579  elog(ERROR, "targetColnos does not match subplan target list");
580 
581  /*
582  * Build a bitmapset of the columns in targetColnos. (We could just use
583  * list_member_int() tests, but that risks O(N^2) behavior with many
584  * columns.)
585  */
586  assignedCols = NULL;
587  foreach(lc, targetColnos)
588  {
589  AttrNumber targetattnum = lfirst_int(lc);
590 
591  assignedCols = bms_add_member(assignedCols, targetattnum);
592  }
593 
594  /*
595  * We need to insert EEOP_*_FETCHSOME steps to ensure the input tuples are
596  * sufficiently deconstructed. The scan tuple must be deconstructed at
597  * least as far as the last old column we need.
598  */
599  for (int attnum = relDesc->natts; attnum > 0; attnum--)
600  {
601  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
602 
603  if (attr->attisdropped)
604  continue;
605  if (bms_is_member(attnum, assignedCols))
606  continue;
607  deform.last_scan = attnum;
608  break;
609  }
610 
611  /*
612  * If we're actually evaluating the tlist, incorporate its input
613  * requirements too; otherwise, we'll just need to fetch the appropriate
614  * number of columns of the "outer" tuple.
615  */
616  if (evalTargetList)
617  expr_setup_walker((Node *) targetList, &deform);
618  else
619  deform.last_outer = nAssignableCols;
620 
621  ExecPushExprSetupSteps(state, &deform);
622 
623  /*
624  * Now generate code to evaluate the tlist's assignable expressions or
625  * fetch them from the outer tuple, incidentally validating that they'll
626  * be of the right data type. The checks above ensure that the forboth()
627  * will iterate over exactly the non-junk columns. Note that we don't
628  * bother evaluating any remaining resjunk columns.
629  */
630  outerattnum = 0;
631  forboth(lc, targetList, lc2, targetColnos)
632  {
633  TargetEntry *tle = lfirst_node(TargetEntry, lc);
634  AttrNumber targetattnum = lfirst_int(lc2);
635  Form_pg_attribute attr;
636 
637  Assert(!tle->resjunk);
638 
639  /*
640  * Apply sanity checks comparable to ExecCheckPlanOutput().
641  */
642  if (targetattnum <= 0 || targetattnum > relDesc->natts)
643  ereport(ERROR,
644  (errcode(ERRCODE_DATATYPE_MISMATCH),
645  errmsg("table row type and query-specified row type do not match"),
646  errdetail("Query has too many columns.")));
647  attr = TupleDescAttr(relDesc, targetattnum - 1);
648 
649  if (attr->attisdropped)
650  ereport(ERROR,
651  (errcode(ERRCODE_DATATYPE_MISMATCH),
652  errmsg("table row type and query-specified row type do not match"),
653  errdetail("Query provides a value for a dropped column at ordinal position %d.",
654  targetattnum)));
655  if (exprType((Node *) tle->expr) != attr->atttypid)
656  ereport(ERROR,
657  (errcode(ERRCODE_DATATYPE_MISMATCH),
658  errmsg("table row type and query-specified row type do not match"),
659  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
660  format_type_be(attr->atttypid),
661  targetattnum,
662  format_type_be(exprType((Node *) tle->expr)))));
663 
664  /* OK, generate code to perform the assignment. */
665  if (evalTargetList)
666  {
667  /*
668  * We must evaluate the TLE's expression and assign it. We do not
669  * bother jumping through hoops for "safe" Vars like
670  * ExecBuildProjectionInfo does; this is a relatively less-used
671  * path and it doesn't seem worth expending code for that.
672  */
673  ExecInitExprRec(tle->expr, state,
674  &state->resvalue, &state->resnull);
675  /* Needn't worry about read-only-ness here, either. */
676  scratch.opcode = EEOP_ASSIGN_TMP;
677  scratch.d.assign_tmp.resultnum = targetattnum - 1;
678  ExprEvalPushStep(state, &scratch);
679  }
680  else
681  {
682  /* Just assign from the outer tuple. */
683  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
684  scratch.d.assign_var.attnum = outerattnum;
685  scratch.d.assign_var.resultnum = targetattnum - 1;
686  ExprEvalPushStep(state, &scratch);
687  }
688  outerattnum++;
689  }
690 
691  /*
692  * Now generate code to copy over any old columns that were not assigned
693  * to, and to ensure that dropped columns are set to NULL.
694  */
695  for (int attnum = 1; attnum <= relDesc->natts; attnum++)
696  {
697  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
698 
699  if (attr->attisdropped)
700  {
701  /* Put a null into the ExprState's resvalue/resnull ... */
702  scratch.opcode = EEOP_CONST;
703  scratch.resvalue = &state->resvalue;
704  scratch.resnull = &state->resnull;
705  scratch.d.constval.value = (Datum) 0;
706  scratch.d.constval.isnull = true;
707  ExprEvalPushStep(state, &scratch);
708  /* ... then assign it to the result slot */
709  scratch.opcode = EEOP_ASSIGN_TMP;
710  scratch.d.assign_tmp.resultnum = attnum - 1;
711  ExprEvalPushStep(state, &scratch);
712  }
713  else if (!bms_is_member(attnum, assignedCols))
714  {
715  /* Certainly the right type, so needn't check */
716  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
717  scratch.d.assign_var.attnum = attnum - 1;
718  scratch.d.assign_var.resultnum = attnum - 1;
719  ExprEvalPushStep(state, &scratch);
720  }
721  }
722 
723  scratch.opcode = EEOP_DONE;
724  ExprEvalPushStep(state, &scratch);
725 
727 
728  return projInfo;
729 }
730 
731 /*
732  * ExecPrepareExpr --- initialize for expression execution outside a normal
733  * Plan tree context.
734  *
735  * This differs from ExecInitExpr in that we don't assume the caller is
736  * already running in the EState's per-query context. Also, we run the
737  * passed expression tree through expression_planner() to prepare it for
738  * execution. (In ordinary Plan trees the regular planning process will have
739  * made the appropriate transformations on expressions, but for standalone
740  * expressions this won't have happened.)
741  */
742 ExprState *
743 ExecPrepareExpr(Expr *node, EState *estate)
744 {
745  ExprState *result;
746  MemoryContext oldcontext;
747 
748  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
749 
750  node = expression_planner(node);
751 
752  result = ExecInitExpr(node, NULL);
753 
754  MemoryContextSwitchTo(oldcontext);
755 
756  return result;
757 }
758 
759 /*
760  * ExecPrepareQual --- initialize for qual execution outside a normal
761  * Plan tree context.
762  *
763  * This differs from ExecInitQual in that we don't assume the caller is
764  * already running in the EState's per-query context. Also, we run the
765  * passed expression tree through expression_planner() to prepare it for
766  * execution. (In ordinary Plan trees the regular planning process will have
767  * made the appropriate transformations on expressions, but for standalone
768  * expressions this won't have happened.)
769  */
770 ExprState *
771 ExecPrepareQual(List *qual, EState *estate)
772 {
773  ExprState *result;
774  MemoryContext oldcontext;
775 
776  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
777 
778  qual = (List *) expression_planner((Expr *) qual);
779 
780  result = ExecInitQual(qual, NULL);
781 
782  MemoryContextSwitchTo(oldcontext);
783 
784  return result;
785 }
786 
787 /*
788  * ExecPrepareCheck -- initialize check constraint for execution outside a
789  * normal Plan tree context.
790  *
791  * See ExecPrepareExpr() and ExecInitCheck() for details.
792  */
793 ExprState *
794 ExecPrepareCheck(List *qual, EState *estate)
795 {
796  ExprState *result;
797  MemoryContext oldcontext;
798 
799  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
800 
801  qual = (List *) expression_planner((Expr *) qual);
802 
803  result = ExecInitCheck(qual, NULL);
804 
805  MemoryContextSwitchTo(oldcontext);
806 
807  return result;
808 }
809 
810 /*
811  * Call ExecPrepareExpr() on each member of a list of Exprs, and return
812  * a list of ExprStates.
813  *
814  * See ExecPrepareExpr() for details.
815  */
816 List *
818 {
819  List *result = NIL;
820  MemoryContext oldcontext;
821  ListCell *lc;
822 
823  /* Ensure that the list cell nodes are in the right context too */
824  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
825 
826  foreach(lc, nodes)
827  {
828  Expr *e = (Expr *) lfirst(lc);
829 
830  result = lappend(result, ExecPrepareExpr(e, estate));
831  }
832 
833  MemoryContextSwitchTo(oldcontext);
834 
835  return result;
836 }
837 
838 /*
839  * ExecCheck - evaluate a check constraint
840  *
841  * For check constraints, a null result is taken as TRUE, ie the constraint
842  * passes.
843  *
844  * The check constraint may have been prepared with ExecInitCheck
845  * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
846  * format, but a regular boolean expression prepared with ExecInitExpr or
847  * ExecPrepareExpr works too.
848  */
849 bool
851 {
852  Datum ret;
853  bool isnull;
854 
855  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
856  if (state == NULL)
857  return true;
858 
859  /* verify that expression was not compiled using ExecInitQual */
860  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
861 
862  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
863 
864  if (isnull)
865  return true;
866 
867  return DatumGetBool(ret);
868 }
869 
870 /*
871  * Prepare a compiled expression for execution. This has to be called for
872  * every ExprState before it can be executed.
873  *
874  * NB: While this currently only calls ExecReadyInterpretedExpr(),
875  * this will likely get extended to further expression evaluation methods.
876  * Therefore this should be used instead of directly calling
877  * ExecReadyInterpretedExpr().
878  */
879 static void
881 {
882  if (jit_compile_expr(state))
883  return;
884 
886 }
887 
888 /*
889  * Append the steps necessary for the evaluation of node to ExprState->steps,
890  * possibly recursing into sub-expressions of node.
891  *
892  * node - expression to evaluate
893  * state - ExprState to whose ->steps to append the necessary operations
894  * resv / resnull - where to store the result of the node into
895  */
896 static void
898  Datum *resv, bool *resnull)
899 {
900  ExprEvalStep scratch = {0};
901 
902  /* Guard against stack overflow due to overly complex expressions */
904 
905  /* Step's output location is always what the caller gave us */
906  Assert(resv != NULL && resnull != NULL);
907  scratch.resvalue = resv;
908  scratch.resnull = resnull;
909 
910  /* cases should be ordered as they are in enum NodeTag */
911  switch (nodeTag(node))
912  {
913  case T_Var:
914  {
915  Var *variable = (Var *) node;
916 
917  if (variable->varattno == InvalidAttrNumber)
918  {
919  /* whole-row Var */
920  ExecInitWholeRowVar(&scratch, variable, state);
921  }
922  else if (variable->varattno <= 0)
923  {
924  /* system column */
925  scratch.d.var.attnum = variable->varattno;
926  scratch.d.var.vartype = variable->vartype;
927  switch (variable->varno)
928  {
929  case INNER_VAR:
930  scratch.opcode = EEOP_INNER_SYSVAR;
931  break;
932  case OUTER_VAR:
933  scratch.opcode = EEOP_OUTER_SYSVAR;
934  break;
935 
936  /* INDEX_VAR is handled by default case */
937 
938  default:
939  scratch.opcode = EEOP_SCAN_SYSVAR;
940  break;
941  }
942  }
943  else
944  {
945  /* regular user column */
946  scratch.d.var.attnum = variable->varattno - 1;
947  scratch.d.var.vartype = variable->vartype;
948  switch (variable->varno)
949  {
950  case INNER_VAR:
951  scratch.opcode = EEOP_INNER_VAR;
952  break;
953  case OUTER_VAR:
954  scratch.opcode = EEOP_OUTER_VAR;
955  break;
956 
957  /* INDEX_VAR is handled by default case */
958 
959  default:
960  scratch.opcode = EEOP_SCAN_VAR;
961  break;
962  }
963  }
964 
965  ExprEvalPushStep(state, &scratch);
966  break;
967  }
968 
969  case T_Const:
970  {
971  Const *con = (Const *) node;
972 
973  scratch.opcode = EEOP_CONST;
974  scratch.d.constval.value = con->constvalue;
975  scratch.d.constval.isnull = con->constisnull;
976 
977  ExprEvalPushStep(state, &scratch);
978  break;
979  }
980 
981  case T_Param:
982  {
983  Param *param = (Param *) node;
984  ParamListInfo params;
985 
986  switch (param->paramkind)
987  {
988  case PARAM_EXEC:
989  scratch.opcode = EEOP_PARAM_EXEC;
990  scratch.d.param.paramid = param->paramid;
991  scratch.d.param.paramtype = param->paramtype;
992  ExprEvalPushStep(state, &scratch);
993  break;
994  case PARAM_EXTERN:
995 
996  /*
997  * If we have a relevant ParamCompileHook, use it;
998  * otherwise compile a standard EEOP_PARAM_EXTERN
999  * step. ext_params, if supplied, takes precedence
1000  * over info from the parent node's EState (if any).
1001  */
1002  if (state->ext_params)
1003  params = state->ext_params;
1004  else if (state->parent &&
1005  state->parent->state)
1006  params = state->parent->state->es_param_list_info;
1007  else
1008  params = NULL;
1009  if (params && params->paramCompile)
1010  {
1011  params->paramCompile(params, param, state,
1012  resv, resnull);
1013  }
1014  else
1015  {
1016  scratch.opcode = EEOP_PARAM_EXTERN;
1017  scratch.d.param.paramid = param->paramid;
1018  scratch.d.param.paramtype = param->paramtype;
1019  ExprEvalPushStep(state, &scratch);
1020  }
1021  break;
1022  default:
1023  elog(ERROR, "unrecognized paramkind: %d",
1024  (int) param->paramkind);
1025  break;
1026  }
1027  break;
1028  }
1029 
1030  case T_Aggref:
1031  {
1032  Aggref *aggref = (Aggref *) node;
1033 
1034  scratch.opcode = EEOP_AGGREF;
1035  scratch.d.aggref.aggno = aggref->aggno;
1036 
1037  if (state->parent && IsA(state->parent, AggState))
1038  {
1039  AggState *aggstate = (AggState *) state->parent;
1040 
1041  aggstate->aggs = lappend(aggstate->aggs, aggref);
1042  }
1043  else
1044  {
1045  /* planner messed up */
1046  elog(ERROR, "Aggref found in non-Agg plan node");
1047  }
1048 
1049  ExprEvalPushStep(state, &scratch);
1050  break;
1051  }
1052 
1053  case T_GroupingFunc:
1054  {
1055  GroupingFunc *grp_node = (GroupingFunc *) node;
1056  Agg *agg;
1057 
1058  if (!state->parent || !IsA(state->parent, AggState) ||
1059  !IsA(state->parent->plan, Agg))
1060  elog(ERROR, "GroupingFunc found in non-Agg plan node");
1061 
1062  scratch.opcode = EEOP_GROUPING_FUNC;
1063 
1064  agg = (Agg *) (state->parent->plan);
1065 
1066  if (agg->groupingSets)
1067  scratch.d.grouping_func.clauses = grp_node->cols;
1068  else
1069  scratch.d.grouping_func.clauses = NIL;
1070 
1071  ExprEvalPushStep(state, &scratch);
1072  break;
1073  }
1074 
1075  case T_WindowFunc:
1076  {
1077  WindowFunc *wfunc = (WindowFunc *) node;
1079 
1080  wfstate->wfunc = wfunc;
1081 
1082  if (state->parent && IsA(state->parent, WindowAggState))
1083  {
1084  WindowAggState *winstate = (WindowAggState *) state->parent;
1085  int nfuncs;
1086 
1087  winstate->funcs = lappend(winstate->funcs, wfstate);
1088  nfuncs = ++winstate->numfuncs;
1089  if (wfunc->winagg)
1090  winstate->numaggs++;
1091 
1092  /* for now initialize agg using old style expressions */
1093  wfstate->args = ExecInitExprList(wfunc->args,
1094  state->parent);
1095  wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
1096  state->parent);
1097 
1098  /*
1099  * Complain if the windowfunc's arguments contain any
1100  * windowfuncs; nested window functions are semantically
1101  * nonsensical. (This should have been caught earlier,
1102  * but we defend against it here anyway.)
1103  */
1104  if (nfuncs != winstate->numfuncs)
1105  ereport(ERROR,
1106  (errcode(ERRCODE_WINDOWING_ERROR),
1107  errmsg("window function calls cannot be nested")));
1108  }
1109  else
1110  {
1111  /* planner messed up */
1112  elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
1113  }
1114 
1115  scratch.opcode = EEOP_WINDOW_FUNC;
1116  scratch.d.window_func.wfstate = wfstate;
1117  ExprEvalPushStep(state, &scratch);
1118  break;
1119  }
1120 
1121  case T_MergeSupportFunc:
1122  {
1123  /* must be in a MERGE, else something messed up */
1124  if (!state->parent ||
1125  !IsA(state->parent, ModifyTableState) ||
1126  ((ModifyTableState *) state->parent)->operation != CMD_MERGE)
1127  elog(ERROR, "MergeSupportFunc found in non-merge plan node");
1128 
1129  scratch.opcode = EEOP_MERGE_SUPPORT_FUNC;
1130  ExprEvalPushStep(state, &scratch);
1131  break;
1132  }
1133 
1134  case T_SubscriptingRef:
1135  {
1136  SubscriptingRef *sbsref = (SubscriptingRef *) node;
1137 
1138  ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull);
1139  break;
1140  }
1141 
1142  case T_FuncExpr:
1143  {
1144  FuncExpr *func = (FuncExpr *) node;
1145 
1146  ExecInitFunc(&scratch, node,
1147  func->args, func->funcid, func->inputcollid,
1148  state);
1149  ExprEvalPushStep(state, &scratch);
1150  break;
1151  }
1152 
1153  case T_OpExpr:
1154  {
1155  OpExpr *op = (OpExpr *) node;
1156 
1157  ExecInitFunc(&scratch, node,
1158  op->args, op->opfuncid, op->inputcollid,
1159  state);
1160  ExprEvalPushStep(state, &scratch);
1161  break;
1162  }
1163 
1164  case T_DistinctExpr:
1165  {
1166  DistinctExpr *op = (DistinctExpr *) node;
1167 
1168  ExecInitFunc(&scratch, node,
1169  op->args, op->opfuncid, op->inputcollid,
1170  state);
1171 
1172  /*
1173  * Change opcode of call instruction to EEOP_DISTINCT.
1174  *
1175  * XXX: historically we've not called the function usage
1176  * pgstat infrastructure - that seems inconsistent given that
1177  * we do so for normal function *and* operator evaluation. If
1178  * we decided to do that here, we'd probably want separate
1179  * opcodes for FUSAGE or not.
1180  */
1181  scratch.opcode = EEOP_DISTINCT;
1182  ExprEvalPushStep(state, &scratch);
1183  break;
1184  }
1185 
1186  case T_NullIfExpr:
1187  {
1188  NullIfExpr *op = (NullIfExpr *) node;
1189 
1190  ExecInitFunc(&scratch, node,
1191  op->args, op->opfuncid, op->inputcollid,
1192  state);
1193 
1194  /*
1195  * Change opcode of call instruction to EEOP_NULLIF.
1196  *
1197  * XXX: historically we've not called the function usage
1198  * pgstat infrastructure - that seems inconsistent given that
1199  * we do so for normal function *and* operator evaluation. If
1200  * we decided to do that here, we'd probably want separate
1201  * opcodes for FUSAGE or not.
1202  */
1203  scratch.opcode = EEOP_NULLIF;
1204  ExprEvalPushStep(state, &scratch);
1205  break;
1206  }
1207 
1208  case T_ScalarArrayOpExpr:
1209  {
1210  ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1211  Expr *scalararg;
1212  Expr *arrayarg;
1213  FmgrInfo *finfo;
1214  FunctionCallInfo fcinfo;
1215  AclResult aclresult;
1216  Oid cmpfuncid;
1217 
1218  /*
1219  * Select the correct comparison function. When we do hashed
1220  * NOT IN clauses, the opfuncid will be the inequality
1221  * comparison function and negfuncid will be set to equality.
1222  * We need to use the equality function for hash probes.
1223  */
1224  if (OidIsValid(opexpr->negfuncid))
1225  {
1226  Assert(OidIsValid(opexpr->hashfuncid));
1227  cmpfuncid = opexpr->negfuncid;
1228  }
1229  else
1230  cmpfuncid = opexpr->opfuncid;
1231 
1232  Assert(list_length(opexpr->args) == 2);
1233  scalararg = (Expr *) linitial(opexpr->args);
1234  arrayarg = (Expr *) lsecond(opexpr->args);
1235 
1236  /* Check permission to call function */
1237  aclresult = object_aclcheck(ProcedureRelationId, cmpfuncid,
1238  GetUserId(),
1239  ACL_EXECUTE);
1240  if (aclresult != ACLCHECK_OK)
1241  aclcheck_error(aclresult, OBJECT_FUNCTION,
1242  get_func_name(cmpfuncid));
1243  InvokeFunctionExecuteHook(cmpfuncid);
1244 
1245  if (OidIsValid(opexpr->hashfuncid))
1246  {
1247  aclresult = object_aclcheck(ProcedureRelationId, opexpr->hashfuncid,
1248  GetUserId(),
1249  ACL_EXECUTE);
1250  if (aclresult != ACLCHECK_OK)
1251  aclcheck_error(aclresult, OBJECT_FUNCTION,
1252  get_func_name(opexpr->hashfuncid));
1253  InvokeFunctionExecuteHook(opexpr->hashfuncid);
1254  }
1255 
1256  /* Set up the primary fmgr lookup information */
1257  finfo = palloc0(sizeof(FmgrInfo));
1258  fcinfo = palloc0(SizeForFunctionCallInfo(2));
1259  fmgr_info(cmpfuncid, finfo);
1260  fmgr_info_set_expr((Node *) node, finfo);
1261  InitFunctionCallInfoData(*fcinfo, finfo, 2,
1262  opexpr->inputcollid, NULL, NULL);
1263 
1264  /*
1265  * If hashfuncid is set, we create a EEOP_HASHED_SCALARARRAYOP
1266  * step instead of a EEOP_SCALARARRAYOP. This provides much
1267  * faster lookup performance than the normal linear search
1268  * when the number of items in the array is anything but very
1269  * small.
1270  */
1271  if (OidIsValid(opexpr->hashfuncid))
1272  {
1273  /* Evaluate scalar directly into left function argument */
1274  ExecInitExprRec(scalararg, state,
1275  &fcinfo->args[0].value, &fcinfo->args[0].isnull);
1276 
1277  /*
1278  * Evaluate array argument into our return value. There's
1279  * no danger in that, because the return value is
1280  * guaranteed to be overwritten by
1281  * EEOP_HASHED_SCALARARRAYOP, and will not be passed to
1282  * any other expression.
1283  */
1284  ExecInitExprRec(arrayarg, state, resv, resnull);
1285 
1286  /* And perform the operation */
1288  scratch.d.hashedscalararrayop.inclause = opexpr->useOr;
1289  scratch.d.hashedscalararrayop.finfo = finfo;
1290  scratch.d.hashedscalararrayop.fcinfo_data = fcinfo;
1291  scratch.d.hashedscalararrayop.saop = opexpr;
1292 
1293 
1294  ExprEvalPushStep(state, &scratch);
1295  }
1296  else
1297  {
1298  /* Evaluate scalar directly into left function argument */
1299  ExecInitExprRec(scalararg, state,
1300  &fcinfo->args[0].value,
1301  &fcinfo->args[0].isnull);
1302 
1303  /*
1304  * Evaluate array argument into our return value. There's
1305  * no danger in that, because the return value is
1306  * guaranteed to be overwritten by EEOP_SCALARARRAYOP, and
1307  * will not be passed to any other expression.
1308  */
1309  ExecInitExprRec(arrayarg, state, resv, resnull);
1310 
1311  /* And perform the operation */
1312  scratch.opcode = EEOP_SCALARARRAYOP;
1313  scratch.d.scalararrayop.element_type = InvalidOid;
1314  scratch.d.scalararrayop.useOr = opexpr->useOr;
1315  scratch.d.scalararrayop.finfo = finfo;
1316  scratch.d.scalararrayop.fcinfo_data = fcinfo;
1317  scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
1318  ExprEvalPushStep(state, &scratch);
1319  }
1320  break;
1321  }
1322 
1323  case T_BoolExpr:
1324  {
1325  BoolExpr *boolexpr = (BoolExpr *) node;
1326  int nargs = list_length(boolexpr->args);
1327  List *adjust_jumps = NIL;
1328  int off;
1329  ListCell *lc;
1330 
1331  /* allocate scratch memory used by all steps of AND/OR */
1332  if (boolexpr->boolop != NOT_EXPR)
1333  scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
1334 
1335  /*
1336  * For each argument evaluate the argument itself, then
1337  * perform the bool operation's appropriate handling.
1338  *
1339  * We can evaluate each argument into our result area, since
1340  * the short-circuiting logic means we only need to remember
1341  * previous NULL values.
1342  *
1343  * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
1344  * or more) / STEP_LAST (one) steps, as each of those has to
1345  * perform different work. The FIRST/LAST split is valid
1346  * because AND/OR have at least two arguments.
1347  */
1348  off = 0;
1349  foreach(lc, boolexpr->args)
1350  {
1351  Expr *arg = (Expr *) lfirst(lc);
1352 
1353  /* Evaluate argument into our output variable */
1354  ExecInitExprRec(arg, state, resv, resnull);
1355 
1356  /* Perform the appropriate step type */
1357  switch (boolexpr->boolop)
1358  {
1359  case AND_EXPR:
1360  Assert(nargs >= 2);
1361 
1362  if (off == 0)
1363  scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
1364  else if (off + 1 == nargs)
1365  scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
1366  else
1367  scratch.opcode = EEOP_BOOL_AND_STEP;
1368  break;
1369  case OR_EXPR:
1370  Assert(nargs >= 2);
1371 
1372  if (off == 0)
1373  scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1374  else if (off + 1 == nargs)
1375  scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1376  else
1377  scratch.opcode = EEOP_BOOL_OR_STEP;
1378  break;
1379  case NOT_EXPR:
1380  Assert(nargs == 1);
1381 
1382  scratch.opcode = EEOP_BOOL_NOT_STEP;
1383  break;
1384  default:
1385  elog(ERROR, "unrecognized boolop: %d",
1386  (int) boolexpr->boolop);
1387  break;
1388  }
1389 
1390  scratch.d.boolexpr.jumpdone = -1;
1391  ExprEvalPushStep(state, &scratch);
1392  adjust_jumps = lappend_int(adjust_jumps,
1393  state->steps_len - 1);
1394  off++;
1395  }
1396 
1397  /* adjust jump targets */
1398  foreach(lc, adjust_jumps)
1399  {
1400  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1401 
1402  Assert(as->d.boolexpr.jumpdone == -1);
1403  as->d.boolexpr.jumpdone = state->steps_len;
1404  }
1405 
1406  break;
1407  }
1408 
1409  case T_SubPlan:
1410  {
1411  SubPlan *subplan = (SubPlan *) node;
1412 
1413  /*
1414  * Real execution of a MULTIEXPR SubPlan has already been
1415  * done. What we have to do here is return a dummy NULL record
1416  * value in case this targetlist element is assigned
1417  * someplace.
1418  */
1419  if (subplan->subLinkType == MULTIEXPR_SUBLINK)
1420  {
1421  scratch.opcode = EEOP_CONST;
1422  scratch.d.constval.value = (Datum) 0;
1423  scratch.d.constval.isnull = true;
1424  ExprEvalPushStep(state, &scratch);
1425  break;
1426  }
1427 
1428  ExecInitSubPlanExpr(subplan, state, resv, resnull);
1429  break;
1430  }
1431 
1432  case T_FieldSelect:
1433  {
1434  FieldSelect *fselect = (FieldSelect *) node;
1435 
1436  /* evaluate row/record argument into result area */
1437  ExecInitExprRec(fselect->arg, state, resv, resnull);
1438 
1439  /* and extract field */
1440  scratch.opcode = EEOP_FIELDSELECT;
1441  scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1442  scratch.d.fieldselect.resulttype = fselect->resulttype;
1443  scratch.d.fieldselect.rowcache.cacheptr = NULL;
1444 
1445  ExprEvalPushStep(state, &scratch);
1446  break;
1447  }
1448 
1449  case T_FieldStore:
1450  {
1451  FieldStore *fstore = (FieldStore *) node;
1452  TupleDesc tupDesc;
1453  ExprEvalRowtypeCache *rowcachep;
1454  Datum *values;
1455  bool *nulls;
1456  int ncolumns;
1457  ListCell *l1,
1458  *l2;
1459 
1460  /* find out the number of columns in the composite type */
1461  tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1462  ncolumns = tupDesc->natts;
1463  ReleaseTupleDesc(tupDesc);
1464 
1465  /* create workspace for column values */
1466  values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1467  nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1468 
1469  /* create shared composite-type-lookup cache struct */
1470  rowcachep = palloc(sizeof(ExprEvalRowtypeCache));
1471  rowcachep->cacheptr = NULL;
1472 
1473  /* emit code to evaluate the composite input value */
1474  ExecInitExprRec(fstore->arg, state, resv, resnull);
1475 
1476  /* next, deform the input tuple into our workspace */
1477  scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1478  scratch.d.fieldstore.fstore = fstore;
1479  scratch.d.fieldstore.rowcache = rowcachep;
1480  scratch.d.fieldstore.values = values;
1481  scratch.d.fieldstore.nulls = nulls;
1482  scratch.d.fieldstore.ncolumns = ncolumns;
1483  ExprEvalPushStep(state, &scratch);
1484 
1485  /* evaluate new field values, store in workspace columns */
1486  forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1487  {
1488  Expr *e = (Expr *) lfirst(l1);
1489  AttrNumber fieldnum = lfirst_int(l2);
1490  Datum *save_innermost_caseval;
1491  bool *save_innermost_casenull;
1492 
1493  if (fieldnum <= 0 || fieldnum > ncolumns)
1494  elog(ERROR, "field number %d is out of range in FieldStore",
1495  fieldnum);
1496 
1497  /*
1498  * Use the CaseTestExpr mechanism to pass down the old
1499  * value of the field being replaced; this is needed in
1500  * case the newval is itself a FieldStore or
1501  * SubscriptingRef that has to obtain and modify the old
1502  * value. It's safe to reuse the CASE mechanism because
1503  * there cannot be a CASE between here and where the value
1504  * would be needed, and a field assignment can't be within
1505  * a CASE either. (So saving and restoring
1506  * innermost_caseval is just paranoia, but let's do it
1507  * anyway.)
1508  *
1509  * Another non-obvious point is that it's safe to use the
1510  * field's values[]/nulls[] entries as both the caseval
1511  * source and the result address for this subexpression.
1512  * That's okay only because (1) both FieldStore and
1513  * SubscriptingRef evaluate their arg or refexpr inputs
1514  * first, and (2) any such CaseTestExpr is directly the
1515  * arg or refexpr input. So any read of the caseval will
1516  * occur before there's a chance to overwrite it. Also,
1517  * if multiple entries in the newvals/fieldnums lists
1518  * target the same field, they'll effectively be applied
1519  * left-to-right which is what we want.
1520  */
1521  save_innermost_caseval = state->innermost_caseval;
1522  save_innermost_casenull = state->innermost_casenull;
1523  state->innermost_caseval = &values[fieldnum - 1];
1524  state->innermost_casenull = &nulls[fieldnum - 1];
1525 
1527  &values[fieldnum - 1],
1528  &nulls[fieldnum - 1]);
1529 
1530  state->innermost_caseval = save_innermost_caseval;
1531  state->innermost_casenull = save_innermost_casenull;
1532  }
1533 
1534  /* finally, form result tuple */
1535  scratch.opcode = EEOP_FIELDSTORE_FORM;
1536  scratch.d.fieldstore.fstore = fstore;
1537  scratch.d.fieldstore.rowcache = rowcachep;
1538  scratch.d.fieldstore.values = values;
1539  scratch.d.fieldstore.nulls = nulls;
1540  scratch.d.fieldstore.ncolumns = ncolumns;
1541  ExprEvalPushStep(state, &scratch);
1542  break;
1543  }
1544 
1545  case T_RelabelType:
1546  {
1547  /* relabel doesn't need to do anything at runtime */
1548  RelabelType *relabel = (RelabelType *) node;
1549 
1550  ExecInitExprRec(relabel->arg, state, resv, resnull);
1551  break;
1552  }
1553 
1554  case T_CoerceViaIO:
1555  {
1556  CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1557  Oid iofunc;
1558  bool typisvarlena;
1559  Oid typioparam;
1560  FunctionCallInfo fcinfo_in;
1561 
1562  /* evaluate argument into step's result area */
1563  ExecInitExprRec(iocoerce->arg, state, resv, resnull);
1564 
1565  /*
1566  * Prepare both output and input function calls, to be
1567  * evaluated inside a single evaluation step for speed - this
1568  * can be a very common operation.
1569  *
1570  * We don't check permissions here as a type's input/output
1571  * function are assumed to be executable by everyone.
1572  */
1573  if (state->escontext == NULL)
1574  scratch.opcode = EEOP_IOCOERCE;
1575  else
1576  scratch.opcode = EEOP_IOCOERCE_SAFE;
1577 
1578  /* lookup the source type's output function */
1579  scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1580  scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
1581 
1582  getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1583  &iofunc, &typisvarlena);
1584  fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1585  fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1586  InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1587  scratch.d.iocoerce.finfo_out,
1588  1, InvalidOid, NULL, NULL);
1589 
1590  /* lookup the result type's input function */
1591  scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1592  scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
1593 
1594  getTypeInputInfo(iocoerce->resulttype,
1595  &iofunc, &typioparam);
1596  fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1597  fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1598  InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1599  scratch.d.iocoerce.finfo_in,
1600  3, InvalidOid, NULL, NULL);
1601 
1602  /*
1603  * We can preload the second and third arguments for the input
1604  * function, since they're constants.
1605  */
1606  fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1607  fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam);
1608  fcinfo_in->args[1].isnull = false;
1609  fcinfo_in->args[2].value = Int32GetDatum(-1);
1610  fcinfo_in->args[2].isnull = false;
1611 
1612  fcinfo_in->context = (Node *) state->escontext;
1613 
1614  ExprEvalPushStep(state, &scratch);
1615  break;
1616  }
1617 
1618  case T_ArrayCoerceExpr:
1619  {
1620  ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1621  Oid resultelemtype;
1622  ExprState *elemstate;
1623 
1624  /* evaluate argument into step's result area */
1625  ExecInitExprRec(acoerce->arg, state, resv, resnull);
1626 
1627  resultelemtype = get_element_type(acoerce->resulttype);
1628  if (!OidIsValid(resultelemtype))
1629  ereport(ERROR,
1630  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1631  errmsg("target type is not an array")));
1632 
1633  /*
1634  * Construct a sub-expression for the per-element expression;
1635  * but don't ready it until after we check it for triviality.
1636  * We assume it hasn't any Var references, but does have a
1637  * CaseTestExpr representing the source array element values.
1638  */
1639  elemstate = makeNode(ExprState);
1640  elemstate->expr = acoerce->elemexpr;
1641  elemstate->parent = state->parent;
1642  elemstate->ext_params = state->ext_params;
1643 
1644  elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
1645  elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
1646 
1647  ExecInitExprRec(acoerce->elemexpr, elemstate,
1648  &elemstate->resvalue, &elemstate->resnull);
1649 
1650  if (elemstate->steps_len == 1 &&
1651  elemstate->steps[0].opcode == EEOP_CASE_TESTVAL)
1652  {
1653  /* Trivial, so we need no per-element work at runtime */
1654  elemstate = NULL;
1655  }
1656  else
1657  {
1658  /* Not trivial, so append a DONE step */
1659  scratch.opcode = EEOP_DONE;
1660  ExprEvalPushStep(elemstate, &scratch);
1661  /* and ready the subexpression */
1662  ExecReadyExpr(elemstate);
1663  }
1664 
1665  scratch.opcode = EEOP_ARRAYCOERCE;
1666  scratch.d.arraycoerce.elemexprstate = elemstate;
1667  scratch.d.arraycoerce.resultelemtype = resultelemtype;
1668 
1669  if (elemstate)
1670  {
1671  /* Set up workspace for array_map */
1672  scratch.d.arraycoerce.amstate =
1673  (ArrayMapState *) palloc0(sizeof(ArrayMapState));
1674  }
1675  else
1676  {
1677  /* Don't need workspace if there's no subexpression */
1678  scratch.d.arraycoerce.amstate = NULL;
1679  }
1680 
1681  ExprEvalPushStep(state, &scratch);
1682  break;
1683  }
1684 
1685  case T_ConvertRowtypeExpr:
1686  {
1688  ExprEvalRowtypeCache *rowcachep;
1689 
1690  /* cache structs must be out-of-line for space reasons */
1691  rowcachep = palloc(2 * sizeof(ExprEvalRowtypeCache));
1692  rowcachep[0].cacheptr = NULL;
1693  rowcachep[1].cacheptr = NULL;
1694 
1695  /* evaluate argument into step's result area */
1696  ExecInitExprRec(convert->arg, state, resv, resnull);
1697 
1698  /* and push conversion step */
1699  scratch.opcode = EEOP_CONVERT_ROWTYPE;
1700  scratch.d.convert_rowtype.inputtype =
1701  exprType((Node *) convert->arg);
1702  scratch.d.convert_rowtype.outputtype = convert->resulttype;
1703  scratch.d.convert_rowtype.incache = &rowcachep[0];
1704  scratch.d.convert_rowtype.outcache = &rowcachep[1];
1705  scratch.d.convert_rowtype.map = NULL;
1706 
1707  ExprEvalPushStep(state, &scratch);
1708  break;
1709  }
1710 
1711  /* note that CaseWhen expressions are handled within this block */
1712  case T_CaseExpr:
1713  {
1714  CaseExpr *caseExpr = (CaseExpr *) node;
1715  List *adjust_jumps = NIL;
1716  Datum *caseval = NULL;
1717  bool *casenull = NULL;
1718  ListCell *lc;
1719 
1720  /*
1721  * If there's a test expression, we have to evaluate it and
1722  * save the value where the CaseTestExpr placeholders can find
1723  * it.
1724  */
1725  if (caseExpr->arg != NULL)
1726  {
1727  /* Evaluate testexpr into caseval/casenull workspace */
1728  caseval = palloc(sizeof(Datum));
1729  casenull = palloc(sizeof(bool));
1730 
1731  ExecInitExprRec(caseExpr->arg, state,
1732  caseval, casenull);
1733 
1734  /*
1735  * Since value might be read multiple times, force to R/O
1736  * - but only if it could be an expanded datum.
1737  */
1738  if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
1739  {
1740  /* change caseval in-place */
1741  scratch.opcode = EEOP_MAKE_READONLY;
1742  scratch.resvalue = caseval;
1743  scratch.resnull = casenull;
1744  scratch.d.make_readonly.value = caseval;
1745  scratch.d.make_readonly.isnull = casenull;
1746  ExprEvalPushStep(state, &scratch);
1747  /* restore normal settings of scratch fields */
1748  scratch.resvalue = resv;
1749  scratch.resnull = resnull;
1750  }
1751  }
1752 
1753  /*
1754  * Prepare to evaluate each of the WHEN clauses in turn; as
1755  * soon as one is true we return the value of the
1756  * corresponding THEN clause. If none are true then we return
1757  * the value of the ELSE clause, or NULL if there is none.
1758  */
1759  foreach(lc, caseExpr->args)
1760  {
1761  CaseWhen *when = (CaseWhen *) lfirst(lc);
1762  Datum *save_innermost_caseval;
1763  bool *save_innermost_casenull;
1764  int whenstep;
1765 
1766  /*
1767  * Make testexpr result available to CaseTestExpr nodes
1768  * within the condition. We must save and restore prior
1769  * setting of innermost_caseval fields, in case this node
1770  * is itself within a larger CASE.
1771  *
1772  * If there's no test expression, we don't actually need
1773  * to save and restore these fields; but it's less code to
1774  * just do so unconditionally.
1775  */
1776  save_innermost_caseval = state->innermost_caseval;
1777  save_innermost_casenull = state->innermost_casenull;
1778  state->innermost_caseval = caseval;
1779  state->innermost_casenull = casenull;
1780 
1781  /* evaluate condition into CASE's result variables */
1782  ExecInitExprRec(when->expr, state, resv, resnull);
1783 
1784  state->innermost_caseval = save_innermost_caseval;
1785  state->innermost_casenull = save_innermost_casenull;
1786 
1787  /* If WHEN result isn't true, jump to next CASE arm */
1788  scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
1789  scratch.d.jump.jumpdone = -1; /* computed later */
1790  ExprEvalPushStep(state, &scratch);
1791  whenstep = state->steps_len - 1;
1792 
1793  /*
1794  * If WHEN result is true, evaluate THEN result, storing
1795  * it into the CASE's result variables.
1796  */
1797  ExecInitExprRec(when->result, state, resv, resnull);
1798 
1799  /* Emit JUMP step to jump to end of CASE's code */
1800  scratch.opcode = EEOP_JUMP;
1801  scratch.d.jump.jumpdone = -1; /* computed later */
1802  ExprEvalPushStep(state, &scratch);
1803 
1804  /*
1805  * Don't know address for that jump yet, compute once the
1806  * whole CASE expression is built.
1807  */
1808  adjust_jumps = lappend_int(adjust_jumps,
1809  state->steps_len - 1);
1810 
1811  /*
1812  * But we can set WHEN test's jump target now, to make it
1813  * jump to the next WHEN subexpression or the ELSE.
1814  */
1815  state->steps[whenstep].d.jump.jumpdone = state->steps_len;
1816  }
1817 
1818  /* transformCaseExpr always adds a default */
1819  Assert(caseExpr->defresult);
1820 
1821  /* evaluate ELSE expr into CASE's result variables */
1822  ExecInitExprRec(caseExpr->defresult, state,
1823  resv, resnull);
1824 
1825  /* adjust jump targets */
1826  foreach(lc, adjust_jumps)
1827  {
1828  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1829 
1830  Assert(as->opcode == EEOP_JUMP);
1831  Assert(as->d.jump.jumpdone == -1);
1832  as->d.jump.jumpdone = state->steps_len;
1833  }
1834 
1835  break;
1836  }
1837 
1838  case T_CaseTestExpr:
1839  {
1840  /*
1841  * Read from location identified by innermost_caseval. Note
1842  * that innermost_caseval could be NULL, if this node isn't
1843  * actually within a CaseExpr, ArrayCoerceExpr, etc structure.
1844  * That can happen because some parts of the system abuse
1845  * CaseTestExpr to cause a read of a value externally supplied
1846  * in econtext->caseValue_datum. We'll take care of that
1847  * scenario at runtime.
1848  */
1849  scratch.opcode = EEOP_CASE_TESTVAL;
1850  scratch.d.casetest.value = state->innermost_caseval;
1851  scratch.d.casetest.isnull = state->innermost_casenull;
1852 
1853  ExprEvalPushStep(state, &scratch);
1854  break;
1855  }
1856 
1857  case T_ArrayExpr:
1858  {
1859  ArrayExpr *arrayexpr = (ArrayExpr *) node;
1860  int nelems = list_length(arrayexpr->elements);
1861  ListCell *lc;
1862  int elemoff;
1863 
1864  /*
1865  * Evaluate by computing each element, and then forming the
1866  * array. Elements are computed into scratch arrays
1867  * associated with the ARRAYEXPR step.
1868  */
1869  scratch.opcode = EEOP_ARRAYEXPR;
1870  scratch.d.arrayexpr.elemvalues =
1871  (Datum *) palloc(sizeof(Datum) * nelems);
1872  scratch.d.arrayexpr.elemnulls =
1873  (bool *) palloc(sizeof(bool) * nelems);
1874  scratch.d.arrayexpr.nelems = nelems;
1875 
1876  /* fill remaining fields of step */
1877  scratch.d.arrayexpr.multidims = arrayexpr->multidims;
1878  scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
1879 
1880  /* do one-time catalog lookup for type info */
1881  get_typlenbyvalalign(arrayexpr->element_typeid,
1882  &scratch.d.arrayexpr.elemlength,
1883  &scratch.d.arrayexpr.elembyval,
1884  &scratch.d.arrayexpr.elemalign);
1885 
1886  /* prepare to evaluate all arguments */
1887  elemoff = 0;
1888  foreach(lc, arrayexpr->elements)
1889  {
1890  Expr *e = (Expr *) lfirst(lc);
1891 
1893  &scratch.d.arrayexpr.elemvalues[elemoff],
1894  &scratch.d.arrayexpr.elemnulls[elemoff]);
1895  elemoff++;
1896  }
1897 
1898  /* and then collect all into an array */
1899  ExprEvalPushStep(state, &scratch);
1900  break;
1901  }
1902 
1903  case T_RowExpr:
1904  {
1905  RowExpr *rowexpr = (RowExpr *) node;
1906  int nelems = list_length(rowexpr->args);
1907  TupleDesc tupdesc;
1908  int i;
1909  ListCell *l;
1910 
1911  /* Build tupdesc to describe result tuples */
1912  if (rowexpr->row_typeid == RECORDOID)
1913  {
1914  /* generic record, use types of given expressions */
1915  tupdesc = ExecTypeFromExprList(rowexpr->args);
1916  /* ... but adopt RowExpr's column aliases */
1917  ExecTypeSetColNames(tupdesc, rowexpr->colnames);
1918  /* Bless the tupdesc so it can be looked up later */
1919  BlessTupleDesc(tupdesc);
1920  }
1921  else
1922  {
1923  /* it's been cast to a named type, use that */
1924  tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
1925  }
1926 
1927  /*
1928  * In the named-type case, the tupdesc could have more columns
1929  * than are in the args list, since the type might have had
1930  * columns added since the ROW() was parsed. We want those
1931  * extra columns to go to nulls, so we make sure that the
1932  * workspace arrays are large enough and then initialize any
1933  * extra columns to read as NULLs.
1934  */
1935  Assert(nelems <= tupdesc->natts);
1936  nelems = Max(nelems, tupdesc->natts);
1937 
1938  /*
1939  * Evaluate by first building datums for each field, and then
1940  * a final step forming the composite datum.
1941  */
1942  scratch.opcode = EEOP_ROW;
1943  scratch.d.row.tupdesc = tupdesc;
1944 
1945  /* space for the individual field datums */
1946  scratch.d.row.elemvalues =
1947  (Datum *) palloc(sizeof(Datum) * nelems);
1948  scratch.d.row.elemnulls =
1949  (bool *) palloc(sizeof(bool) * nelems);
1950  /* as explained above, make sure any extra columns are null */
1951  memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
1952 
1953  /* Set up evaluation, skipping any deleted columns */
1954  i = 0;
1955  foreach(l, rowexpr->args)
1956  {
1957  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1958  Expr *e = (Expr *) lfirst(l);
1959 
1960  if (!att->attisdropped)
1961  {
1962  /*
1963  * Guard against ALTER COLUMN TYPE on rowtype since
1964  * the RowExpr was created. XXX should we check
1965  * typmod too? Not sure we can be sure it'll be the
1966  * same.
1967  */
1968  if (exprType((Node *) e) != att->atttypid)
1969  ereport(ERROR,
1970  (errcode(ERRCODE_DATATYPE_MISMATCH),
1971  errmsg("ROW() column has type %s instead of type %s",
1972  format_type_be(exprType((Node *) e)),
1973  format_type_be(att->atttypid))));
1974  }
1975  else
1976  {
1977  /*
1978  * Ignore original expression and insert a NULL. We
1979  * don't really care what type of NULL it is, so
1980  * always make an int4 NULL.
1981  */
1982  e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
1983  }
1984 
1985  /* Evaluate column expr into appropriate workspace slot */
1987  &scratch.d.row.elemvalues[i],
1988  &scratch.d.row.elemnulls[i]);
1989  i++;
1990  }
1991 
1992  /* And finally build the row value */
1993  ExprEvalPushStep(state, &scratch);
1994  break;
1995  }
1996 
1997  case T_RowCompareExpr:
1998  {
1999  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
2000  int nopers = list_length(rcexpr->opnos);
2001  List *adjust_jumps = NIL;
2002  ListCell *l_left_expr,
2003  *l_right_expr,
2004  *l_opno,
2005  *l_opfamily,
2006  *l_inputcollid;
2007  ListCell *lc;
2008 
2009  /*
2010  * Iterate over each field, prepare comparisons. To handle
2011  * NULL results, prepare jumps to after the expression. If a
2012  * comparison yields a != 0 result, jump to the final step.
2013  */
2014  Assert(list_length(rcexpr->largs) == nopers);
2015  Assert(list_length(rcexpr->rargs) == nopers);
2016  Assert(list_length(rcexpr->opfamilies) == nopers);
2017  Assert(list_length(rcexpr->inputcollids) == nopers);
2018 
2019  forfive(l_left_expr, rcexpr->largs,
2020  l_right_expr, rcexpr->rargs,
2021  l_opno, rcexpr->opnos,
2022  l_opfamily, rcexpr->opfamilies,
2023  l_inputcollid, rcexpr->inputcollids)
2024  {
2025  Expr *left_expr = (Expr *) lfirst(l_left_expr);
2026  Expr *right_expr = (Expr *) lfirst(l_right_expr);
2027  Oid opno = lfirst_oid(l_opno);
2028  Oid opfamily = lfirst_oid(l_opfamily);
2029  Oid inputcollid = lfirst_oid(l_inputcollid);
2030  int strategy;
2031  Oid lefttype;
2032  Oid righttype;
2033  Oid proc;
2034  FmgrInfo *finfo;
2035  FunctionCallInfo fcinfo;
2036 
2037  get_op_opfamily_properties(opno, opfamily, false,
2038  &strategy,
2039  &lefttype,
2040  &righttype);
2041  proc = get_opfamily_proc(opfamily,
2042  lefttype,
2043  righttype,
2044  BTORDER_PROC);
2045  if (!OidIsValid(proc))
2046  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
2047  BTORDER_PROC, lefttype, righttype, opfamily);
2048 
2049  /* Set up the primary fmgr lookup information */
2050  finfo = palloc0(sizeof(FmgrInfo));
2051  fcinfo = palloc0(SizeForFunctionCallInfo(2));
2052  fmgr_info(proc, finfo);
2053  fmgr_info_set_expr((Node *) node, finfo);
2054  InitFunctionCallInfoData(*fcinfo, finfo, 2,
2055  inputcollid, NULL, NULL);
2056 
2057  /*
2058  * If we enforced permissions checks on index support
2059  * functions, we'd need to make a check here. But the
2060  * index support machinery doesn't do that, and thus
2061  * neither does this code.
2062  */
2063 
2064  /* evaluate left and right args directly into fcinfo */
2065  ExecInitExprRec(left_expr, state,
2066  &fcinfo->args[0].value, &fcinfo->args[0].isnull);
2067  ExecInitExprRec(right_expr, state,
2068  &fcinfo->args[1].value, &fcinfo->args[1].isnull);
2069 
2070  scratch.opcode = EEOP_ROWCOMPARE_STEP;
2071  scratch.d.rowcompare_step.finfo = finfo;
2072  scratch.d.rowcompare_step.fcinfo_data = fcinfo;
2073  scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
2074  /* jump targets filled below */
2075  scratch.d.rowcompare_step.jumpnull = -1;
2076  scratch.d.rowcompare_step.jumpdone = -1;
2077 
2078  ExprEvalPushStep(state, &scratch);
2079  adjust_jumps = lappend_int(adjust_jumps,
2080  state->steps_len - 1);
2081  }
2082 
2083  /*
2084  * We could have a zero-column rowtype, in which case the rows
2085  * necessarily compare equal.
2086  */
2087  if (nopers == 0)
2088  {
2089  scratch.opcode = EEOP_CONST;
2090  scratch.d.constval.value = Int32GetDatum(0);
2091  scratch.d.constval.isnull = false;
2092  ExprEvalPushStep(state, &scratch);
2093  }
2094 
2095  /* Finally, examine the last comparison result */
2096  scratch.opcode = EEOP_ROWCOMPARE_FINAL;
2097  scratch.d.rowcompare_final.rctype = rcexpr->rctype;
2098  ExprEvalPushStep(state, &scratch);
2099 
2100  /* adjust jump targets */
2101  foreach(lc, adjust_jumps)
2102  {
2103  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2104 
2106  Assert(as->d.rowcompare_step.jumpdone == -1);
2107  Assert(as->d.rowcompare_step.jumpnull == -1);
2108 
2109  /* jump to comparison evaluation */
2110  as->d.rowcompare_step.jumpdone = state->steps_len - 1;
2111  /* jump to the following expression */
2112  as->d.rowcompare_step.jumpnull = state->steps_len;
2113  }
2114 
2115  break;
2116  }
2117 
2118  case T_CoalesceExpr:
2119  {
2120  CoalesceExpr *coalesce = (CoalesceExpr *) node;
2121  List *adjust_jumps = NIL;
2122  ListCell *lc;
2123 
2124  /* We assume there's at least one arg */
2125  Assert(coalesce->args != NIL);
2126 
2127  /*
2128  * Prepare evaluation of all coalesced arguments, after each
2129  * one push a step that short-circuits if not null.
2130  */
2131  foreach(lc, coalesce->args)
2132  {
2133  Expr *e = (Expr *) lfirst(lc);
2134 
2135  /* evaluate argument, directly into result datum */
2136  ExecInitExprRec(e, state, resv, resnull);
2137 
2138  /* if it's not null, skip to end of COALESCE expr */
2139  scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
2140  scratch.d.jump.jumpdone = -1; /* adjust later */
2141  ExprEvalPushStep(state, &scratch);
2142 
2143  adjust_jumps = lappend_int(adjust_jumps,
2144  state->steps_len - 1);
2145  }
2146 
2147  /*
2148  * No need to add a constant NULL return - we only can get to
2149  * the end of the expression if a NULL already is being
2150  * returned.
2151  */
2152 
2153  /* adjust jump targets */
2154  foreach(lc, adjust_jumps)
2155  {
2156  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2157 
2159  Assert(as->d.jump.jumpdone == -1);
2160  as->d.jump.jumpdone = state->steps_len;
2161  }
2162 
2163  break;
2164  }
2165 
2166  case T_MinMaxExpr:
2167  {
2168  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
2169  int nelems = list_length(minmaxexpr->args);
2170  TypeCacheEntry *typentry;
2171  FmgrInfo *finfo;
2172  FunctionCallInfo fcinfo;
2173  ListCell *lc;
2174  int off;
2175 
2176  /* Look up the btree comparison function for the datatype */
2177  typentry = lookup_type_cache(minmaxexpr->minmaxtype,
2179  if (!OidIsValid(typentry->cmp_proc))
2180  ereport(ERROR,
2181  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2182  errmsg("could not identify a comparison function for type %s",
2183  format_type_be(minmaxexpr->minmaxtype))));
2184 
2185  /*
2186  * If we enforced permissions checks on index support
2187  * functions, we'd need to make a check here. But the index
2188  * support machinery doesn't do that, and thus neither does
2189  * this code.
2190  */
2191 
2192  /* Perform function lookup */
2193  finfo = palloc0(sizeof(FmgrInfo));
2194  fcinfo = palloc0(SizeForFunctionCallInfo(2));
2195  fmgr_info(typentry->cmp_proc, finfo);
2196  fmgr_info_set_expr((Node *) node, finfo);
2197  InitFunctionCallInfoData(*fcinfo, finfo, 2,
2198  minmaxexpr->inputcollid, NULL, NULL);
2199 
2200  scratch.opcode = EEOP_MINMAX;
2201  /* allocate space to store arguments */
2202  scratch.d.minmax.values =
2203  (Datum *) palloc(sizeof(Datum) * nelems);
2204  scratch.d.minmax.nulls =
2205  (bool *) palloc(sizeof(bool) * nelems);
2206  scratch.d.minmax.nelems = nelems;
2207 
2208  scratch.d.minmax.op = minmaxexpr->op;
2209  scratch.d.minmax.finfo = finfo;
2210  scratch.d.minmax.fcinfo_data = fcinfo;
2211 
2212  /* evaluate expressions into minmax->values/nulls */
2213  off = 0;
2214  foreach(lc, minmaxexpr->args)
2215  {
2216  Expr *e = (Expr *) lfirst(lc);
2217 
2219  &scratch.d.minmax.values[off],
2220  &scratch.d.minmax.nulls[off]);
2221  off++;
2222  }
2223 
2224  /* and push the final comparison */
2225  ExprEvalPushStep(state, &scratch);
2226  break;
2227  }
2228 
2229  case T_SQLValueFunction:
2230  {
2231  SQLValueFunction *svf = (SQLValueFunction *) node;
2232 
2233  scratch.opcode = EEOP_SQLVALUEFUNCTION;
2234  scratch.d.sqlvaluefunction.svf = svf;
2235 
2236  ExprEvalPushStep(state, &scratch);
2237  break;
2238  }
2239 
2240  case T_XmlExpr:
2241  {
2242  XmlExpr *xexpr = (XmlExpr *) node;
2243  int nnamed = list_length(xexpr->named_args);
2244  int nargs = list_length(xexpr->args);
2245  int off;
2246  ListCell *arg;
2247 
2248  scratch.opcode = EEOP_XMLEXPR;
2249  scratch.d.xmlexpr.xexpr = xexpr;
2250 
2251  /* allocate space for storing all the arguments */
2252  if (nnamed)
2253  {
2254  scratch.d.xmlexpr.named_argvalue =
2255  (Datum *) palloc(sizeof(Datum) * nnamed);
2256  scratch.d.xmlexpr.named_argnull =
2257  (bool *) palloc(sizeof(bool) * nnamed);
2258  }
2259  else
2260  {
2261  scratch.d.xmlexpr.named_argvalue = NULL;
2262  scratch.d.xmlexpr.named_argnull = NULL;
2263  }
2264 
2265  if (nargs)
2266  {
2267  scratch.d.xmlexpr.argvalue =
2268  (Datum *) palloc(sizeof(Datum) * nargs);
2269  scratch.d.xmlexpr.argnull =
2270  (bool *) palloc(sizeof(bool) * nargs);
2271  }
2272  else
2273  {
2274  scratch.d.xmlexpr.argvalue = NULL;
2275  scratch.d.xmlexpr.argnull = NULL;
2276  }
2277 
2278  /* prepare argument execution */
2279  off = 0;
2280  foreach(arg, xexpr->named_args)
2281  {
2282  Expr *e = (Expr *) lfirst(arg);
2283 
2285  &scratch.d.xmlexpr.named_argvalue[off],
2286  &scratch.d.xmlexpr.named_argnull[off]);
2287  off++;
2288  }
2289 
2290  off = 0;
2291  foreach(arg, xexpr->args)
2292  {
2293  Expr *e = (Expr *) lfirst(arg);
2294 
2296  &scratch.d.xmlexpr.argvalue[off],
2297  &scratch.d.xmlexpr.argnull[off]);
2298  off++;
2299  }
2300 
2301  /* and evaluate the actual XML expression */
2302  ExprEvalPushStep(state, &scratch);
2303  break;
2304  }
2305 
2306  case T_JsonValueExpr:
2307  {
2308  JsonValueExpr *jve = (JsonValueExpr *) node;
2309 
2310  Assert(jve->formatted_expr != NULL);
2311  ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
2312  break;
2313  }
2314 
2315  case T_JsonConstructorExpr:
2316  {
2317  JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
2318  List *args = ctor->args;
2319  ListCell *lc;
2320  int nargs = list_length(args);
2321  int argno = 0;
2322 
2323  if (ctor->func)
2324  {
2325  ExecInitExprRec(ctor->func, state, resv, resnull);
2326  }
2327  else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) ||
2328  ctor->type == JSCTOR_JSON_SERIALIZE)
2329  {
2330  /* Use the value of the first argument as result */
2331  ExecInitExprRec(linitial(args), state, resv, resnull);
2332  }
2333  else
2334  {
2335  JsonConstructorExprState *jcstate;
2336 
2337  jcstate = palloc0(sizeof(JsonConstructorExprState));
2338 
2339  scratch.opcode = EEOP_JSON_CONSTRUCTOR;
2340  scratch.d.json_constructor.jcstate = jcstate;
2341 
2342  jcstate->constructor = ctor;
2343  jcstate->arg_values = (Datum *) palloc(sizeof(Datum) * nargs);
2344  jcstate->arg_nulls = (bool *) palloc(sizeof(bool) * nargs);
2345  jcstate->arg_types = (Oid *) palloc(sizeof(Oid) * nargs);
2346  jcstate->nargs = nargs;
2347 
2348  foreach(lc, args)
2349  {
2350  Expr *arg = (Expr *) lfirst(lc);
2351 
2352  jcstate->arg_types[argno] = exprType((Node *) arg);
2353 
2354  if (IsA(arg, Const))
2355  {
2356  /* Don't evaluate const arguments every round */
2357  Const *con = (Const *) arg;
2358 
2359  jcstate->arg_values[argno] = con->constvalue;
2360  jcstate->arg_nulls[argno] = con->constisnull;
2361  }
2362  else
2363  {
2365  &jcstate->arg_values[argno],
2366  &jcstate->arg_nulls[argno]);
2367  }
2368  argno++;
2369  }
2370 
2371  /* prepare type cache for datum_to_json[b]() */
2372  if (ctor->type == JSCTOR_JSON_SCALAR)
2373  {
2374  bool is_jsonb =
2376 
2377  jcstate->arg_type_cache =
2378  palloc(sizeof(*jcstate->arg_type_cache) * nargs);
2379 
2380  for (int i = 0; i < nargs; i++)
2381  {
2382  JsonTypeCategory category;
2383  Oid outfuncid;
2384  Oid typid = jcstate->arg_types[i];
2385 
2386  json_categorize_type(typid, is_jsonb,
2387  &category, &outfuncid);
2388 
2389  jcstate->arg_type_cache[i].outfuncid = outfuncid;
2390  jcstate->arg_type_cache[i].category = (int) category;
2391  }
2392  }
2393 
2394  ExprEvalPushStep(state, &scratch);
2395  }
2396 
2397  if (ctor->coercion)
2398  {
2399  Datum *innermost_caseval = state->innermost_caseval;
2400  bool *innermost_isnull = state->innermost_casenull;
2401 
2402  state->innermost_caseval = resv;
2403  state->innermost_casenull = resnull;
2404 
2405  ExecInitExprRec(ctor->coercion, state, resv, resnull);
2406 
2407  state->innermost_caseval = innermost_caseval;
2408  state->innermost_casenull = innermost_isnull;
2409  }
2410  }
2411  break;
2412 
2413  case T_JsonIsPredicate:
2414  {
2415  JsonIsPredicate *pred = (JsonIsPredicate *) node;
2416 
2417  ExecInitExprRec((Expr *) pred->expr, state, resv, resnull);
2418 
2419  scratch.opcode = EEOP_IS_JSON;
2420  scratch.d.is_json.pred = pred;
2421 
2422  ExprEvalPushStep(state, &scratch);
2423  break;
2424  }
2425 
2426  case T_JsonExpr:
2427  {
2428  JsonExpr *jsexpr = castNode(JsonExpr, node);
2429 
2430  /*
2431  * No need to initialize a full JsonExprState For
2432  * JSON_TABLE(), because the upstream caller tfuncFetchRows()
2433  * is only interested in the value of formatted_expr.
2434  */
2435  if (jsexpr->op == JSON_TABLE_OP)
2437  resv, resnull);
2438  else
2439  ExecInitJsonExpr(jsexpr, state, resv, resnull, &scratch);
2440  break;
2441  }
2442 
2443  case T_NullTest:
2444  {
2445  NullTest *ntest = (NullTest *) node;
2446 
2447  if (ntest->nulltesttype == IS_NULL)
2448  {
2449  if (ntest->argisrow)
2450  scratch.opcode = EEOP_NULLTEST_ROWISNULL;
2451  else
2452  scratch.opcode = EEOP_NULLTEST_ISNULL;
2453  }
2454  else if (ntest->nulltesttype == IS_NOT_NULL)
2455  {
2456  if (ntest->argisrow)
2458  else
2459  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2460  }
2461  else
2462  {
2463  elog(ERROR, "unrecognized nulltesttype: %d",
2464  (int) ntest->nulltesttype);
2465  }
2466  /* initialize cache in case it's a row test */
2467  scratch.d.nulltest_row.rowcache.cacheptr = NULL;
2468 
2469  /* first evaluate argument into result variable */
2470  ExecInitExprRec(ntest->arg, state,
2471  resv, resnull);
2472 
2473  /* then push the test of that argument */
2474  ExprEvalPushStep(state, &scratch);
2475  break;
2476  }
2477 
2478  case T_BooleanTest:
2479  {
2480  BooleanTest *btest = (BooleanTest *) node;
2481 
2482  /*
2483  * Evaluate argument, directly into result datum. That's ok,
2484  * because resv/resnull is definitely not used anywhere else,
2485  * and will get overwritten by the below EEOP_BOOLTEST_IS_*
2486  * step.
2487  */
2488  ExecInitExprRec(btest->arg, state, resv, resnull);
2489 
2490  switch (btest->booltesttype)
2491  {
2492  case IS_TRUE:
2493  scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
2494  break;
2495  case IS_NOT_TRUE:
2497  break;
2498  case IS_FALSE:
2499  scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
2500  break;
2501  case IS_NOT_FALSE:
2503  break;
2504  case IS_UNKNOWN:
2505  /* Same as scalar IS NULL test */
2506  scratch.opcode = EEOP_NULLTEST_ISNULL;
2507  break;
2508  case IS_NOT_UNKNOWN:
2509  /* Same as scalar IS NOT NULL test */
2510  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2511  break;
2512  default:
2513  elog(ERROR, "unrecognized booltesttype: %d",
2514  (int) btest->booltesttype);
2515  }
2516 
2517  ExprEvalPushStep(state, &scratch);
2518  break;
2519  }
2520 
2521  case T_CoerceToDomain:
2522  {
2523  CoerceToDomain *ctest = (CoerceToDomain *) node;
2524 
2525  ExecInitCoerceToDomain(&scratch, ctest, state,
2526  resv, resnull);
2527  break;
2528  }
2529 
2530  case T_CoerceToDomainValue:
2531  {
2532  /*
2533  * Read from location identified by innermost_domainval. Note
2534  * that innermost_domainval could be NULL, if we're compiling
2535  * a standalone domain check rather than one embedded in a
2536  * larger expression. In that case we must read from
2537  * econtext->domainValue_datum. We'll take care of that
2538  * scenario at runtime.
2539  */
2540  scratch.opcode = EEOP_DOMAIN_TESTVAL;
2541  /* we share instruction union variant with case testval */
2542  scratch.d.casetest.value = state->innermost_domainval;
2543  scratch.d.casetest.isnull = state->innermost_domainnull;
2544 
2545  ExprEvalPushStep(state, &scratch);
2546  break;
2547  }
2548 
2549  case T_CurrentOfExpr:
2550  {
2551  scratch.opcode = EEOP_CURRENTOFEXPR;
2552  ExprEvalPushStep(state, &scratch);
2553  break;
2554  }
2555 
2556  case T_NextValueExpr:
2557  {
2558  NextValueExpr *nve = (NextValueExpr *) node;
2559 
2560  scratch.opcode = EEOP_NEXTVALUEEXPR;
2561  scratch.d.nextvalueexpr.seqid = nve->seqid;
2562  scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2563 
2564  ExprEvalPushStep(state, &scratch);
2565  break;
2566  }
2567 
2568  default:
2569  elog(ERROR, "unrecognized node type: %d",
2570  (int) nodeTag(node));
2571  break;
2572  }
2573 }
2574 
2575 /*
2576  * Add another expression evaluation step to ExprState->steps.
2577  *
2578  * Note that this potentially re-allocates es->steps, therefore no pointer
2579  * into that array may be used while the expression is still being built.
2580  */
2581 void
2583 {
2584  if (es->steps_alloc == 0)
2585  {
2586  es->steps_alloc = 16;
2587  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2588  }
2589  else if (es->steps_alloc == es->steps_len)
2590  {
2591  es->steps_alloc *= 2;
2592  es->steps = repalloc(es->steps,
2593  sizeof(ExprEvalStep) * es->steps_alloc);
2594  }
2595 
2596  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2597 }
2598 
2599 /*
2600  * Perform setup necessary for the evaluation of a function-like expression,
2601  * appending argument evaluation steps to the steps list in *state, and
2602  * setting up *scratch so it is ready to be pushed.
2603  *
2604  * *scratch is not pushed here, so that callers may override the opcode,
2605  * which is useful for function-like cases like DISTINCT.
2606  */
2607 static void
2608 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2609  Oid inputcollid, ExprState *state)
2610 {
2611  int nargs = list_length(args);
2612  AclResult aclresult;
2613  FmgrInfo *flinfo;
2614  FunctionCallInfo fcinfo;
2615  int argno;
2616  ListCell *lc;
2617 
2618  /* Check permission to call function */
2619  aclresult = object_aclcheck(ProcedureRelationId, funcid, GetUserId(), ACL_EXECUTE);
2620  if (aclresult != ACLCHECK_OK)
2621  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2622  InvokeFunctionExecuteHook(funcid);
2623 
2624  /*
2625  * Safety check on nargs. Under normal circumstances this should never
2626  * fail, as parser should check sooner. But possibly it might fail if
2627  * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2628  * declared in pg_proc?
2629  */
2630  if (nargs > FUNC_MAX_ARGS)
2631  ereport(ERROR,
2632  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2633  errmsg_plural("cannot pass more than %d argument to a function",
2634  "cannot pass more than %d arguments to a function",
2635  FUNC_MAX_ARGS,
2636  FUNC_MAX_ARGS)));
2637 
2638  /* Allocate function lookup data and parameter workspace for this call */
2639  scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2640  scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2641  flinfo = scratch->d.func.finfo;
2642  fcinfo = scratch->d.func.fcinfo_data;
2643 
2644  /* Set up the primary fmgr lookup information */
2645  fmgr_info(funcid, flinfo);
2646  fmgr_info_set_expr((Node *) node, flinfo);
2647 
2648  /* Initialize function call parameter structure too */
2649  InitFunctionCallInfoData(*fcinfo, flinfo,
2650  nargs, inputcollid, NULL, NULL);
2651 
2652  /* Keep extra copies of this info to save an indirection at runtime */
2653  scratch->d.func.fn_addr = flinfo->fn_addr;
2654  scratch->d.func.nargs = nargs;
2655 
2656  /* We only support non-set functions here */
2657  if (flinfo->fn_retset)
2658  ereport(ERROR,
2659  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2660  errmsg("set-valued function called in context that cannot accept a set"),
2661  state->parent ?
2662  executor_errposition(state->parent->state,
2663  exprLocation((Node *) node)) : 0));
2664 
2665  /* Build code to evaluate arguments directly into the fcinfo struct */
2666  argno = 0;
2667  foreach(lc, args)
2668  {
2669  Expr *arg = (Expr *) lfirst(lc);
2670 
2671  if (IsA(arg, Const))
2672  {
2673  /*
2674  * Don't evaluate const arguments every round; especially
2675  * interesting for constants in comparisons.
2676  */
2677  Const *con = (Const *) arg;
2678 
2679  fcinfo->args[argno].value = con->constvalue;
2680  fcinfo->args[argno].isnull = con->constisnull;
2681  }
2682  else
2683  {
2685  &fcinfo->args[argno].value,
2686  &fcinfo->args[argno].isnull);
2687  }
2688  argno++;
2689  }
2690 
2691  /* Insert appropriate opcode depending on strictness and stats level */
2692  if (pgstat_track_functions <= flinfo->fn_stats)
2693  {
2694  if (flinfo->fn_strict && nargs > 0)
2695  scratch->opcode = EEOP_FUNCEXPR_STRICT;
2696  else
2697  scratch->opcode = EEOP_FUNCEXPR;
2698  }
2699  else
2700  {
2701  if (flinfo->fn_strict && nargs > 0)
2703  else
2704  scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2705  }
2706 }
2707 
2708 /*
2709  * Append the steps necessary for the evaluation of a SubPlan node to
2710  * ExprState->steps.
2711  *
2712  * subplan - SubPlan expression to evaluate
2713  * state - ExprState to whose ->steps to append the necessary operations
2714  * resv / resnull - where to store the result of the node into
2715  */
2716 static void
2718  ExprState *state,
2719  Datum *resv, bool *resnull)
2720 {
2721  ExprEvalStep scratch = {0};
2722  SubPlanState *sstate;
2723  ListCell *pvar;
2724  ListCell *l;
2725 
2726  if (!state->parent)
2727  elog(ERROR, "SubPlan found with no parent plan");
2728 
2729  /*
2730  * Generate steps to evaluate input arguments for the subplan.
2731  *
2732  * We evaluate the argument expressions into ExprState's resvalue/resnull,
2733  * and then use PARAM_SET to update the parameter. We do that, instead of
2734  * evaluating directly into the param, to avoid depending on the pointer
2735  * value remaining stable / being included in the generated expression. No
2736  * danger of conflicts with other uses of resvalue/resnull as storing and
2737  * using the value always is in subsequent steps.
2738  *
2739  * Any calculation we have to do can be done in the parent econtext, since
2740  * the Param values don't need to have per-query lifetime.
2741  */
2742  Assert(list_length(subplan->parParam) == list_length(subplan->args));
2743  forboth(l, subplan->parParam, pvar, subplan->args)
2744  {
2745  int paramid = lfirst_int(l);
2746  Expr *arg = (Expr *) lfirst(pvar);
2747 
2749  &state->resvalue, &state->resnull);
2750 
2751  scratch.opcode = EEOP_PARAM_SET;
2752  scratch.d.param.paramid = paramid;
2753  /* paramtype's not actually used, but we might as well fill it */
2754  scratch.d.param.paramtype = exprType((Node *) arg);
2755  ExprEvalPushStep(state, &scratch);
2756  }
2757 
2758  sstate = ExecInitSubPlan(subplan, state->parent);
2759 
2760  /* add SubPlanState nodes to state->parent->subPlan */
2761  state->parent->subPlan = lappend(state->parent->subPlan,
2762  sstate);
2763 
2764  scratch.opcode = EEOP_SUBPLAN;
2765  scratch.resvalue = resv;
2766  scratch.resnull = resnull;
2767  scratch.d.subplan.sstate = sstate;
2768 
2769  ExprEvalPushStep(state, &scratch);
2770 }
2771 
2772 /*
2773  * Add expression steps performing setup that's needed before any of the
2774  * main execution of the expression.
2775  */
2776 static void
2778 {
2779  ExprSetupInfo info = {0, 0, 0, NIL};
2780 
2781  /* Prescan to find out what we need. */
2782  expr_setup_walker(node, &info);
2783 
2784  /* And generate those steps. */
2785  ExecPushExprSetupSteps(state, &info);
2786 }
2787 
2788 /*
2789  * Add steps performing expression setup as indicated by "info".
2790  * This is useful when building an ExprState covering more than one expression.
2791  */
2792 static void
2794 {
2795  ExprEvalStep scratch = {0};
2796  ListCell *lc;
2797 
2798  scratch.resvalue = NULL;
2799  scratch.resnull = NULL;
2800 
2801  /*
2802  * Add steps deforming the ExprState's inner/outer/scan slots as much as
2803  * required by any Vars appearing in the expression.
2804  */
2805  if (info->last_inner > 0)
2806  {
2807  scratch.opcode = EEOP_INNER_FETCHSOME;
2808  scratch.d.fetch.last_var = info->last_inner;
2809  scratch.d.fetch.fixed = false;
2810  scratch.d.fetch.kind = NULL;
2811  scratch.d.fetch.known_desc = NULL;
2812  if (ExecComputeSlotInfo(state, &scratch))
2813  ExprEvalPushStep(state, &scratch);
2814  }
2815  if (info->last_outer > 0)
2816  {
2817  scratch.opcode = EEOP_OUTER_FETCHSOME;
2818  scratch.d.fetch.last_var = info->last_outer;
2819  scratch.d.fetch.fixed = false;
2820  scratch.d.fetch.kind = NULL;
2821  scratch.d.fetch.known_desc = NULL;
2822  if (ExecComputeSlotInfo(state, &scratch))
2823  ExprEvalPushStep(state, &scratch);
2824  }
2825  if (info->last_scan > 0)
2826  {
2827  scratch.opcode = EEOP_SCAN_FETCHSOME;
2828  scratch.d.fetch.last_var = info->last_scan;
2829  scratch.d.fetch.fixed = false;
2830  scratch.d.fetch.kind = NULL;
2831  scratch.d.fetch.known_desc = NULL;
2832  if (ExecComputeSlotInfo(state, &scratch))
2833  ExprEvalPushStep(state, &scratch);
2834  }
2835 
2836  /*
2837  * Add steps to execute any MULTIEXPR SubPlans appearing in the
2838  * expression. We need to evaluate these before any of the Params
2839  * referencing their outputs are used, but after we've prepared for any
2840  * Var references they may contain. (There cannot be cross-references
2841  * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2842  */
2843  foreach(lc, info->multiexpr_subplans)
2844  {
2845  SubPlan *subplan = (SubPlan *) lfirst(lc);
2846 
2847  Assert(subplan->subLinkType == MULTIEXPR_SUBLINK);
2848 
2849  /* The result can be ignored, but we better put it somewhere */
2850  ExecInitSubPlanExpr(subplan, state,
2851  &state->resvalue, &state->resnull);
2852  }
2853 }
2854 
2855 /*
2856  * expr_setup_walker: expression walker for ExecCreateExprSetupSteps
2857  */
2858 static bool
2860 {
2861  if (node == NULL)
2862  return false;
2863  if (IsA(node, Var))
2864  {
2865  Var *variable = (Var *) node;
2866  AttrNumber attnum = variable->varattno;
2867 
2868  switch (variable->varno)
2869  {
2870  case INNER_VAR:
2871  info->last_inner = Max(info->last_inner, attnum);
2872  break;
2873 
2874  case OUTER_VAR:
2875  info->last_outer = Max(info->last_outer, attnum);
2876  break;
2877 
2878  /* INDEX_VAR is handled by default case */
2879 
2880  default:
2881  info->last_scan = Max(info->last_scan, attnum);
2882  break;
2883  }
2884  return false;
2885  }
2886 
2887  /* Collect all MULTIEXPR SubPlans, too */
2888  if (IsA(node, SubPlan))
2889  {
2890  SubPlan *subplan = (SubPlan *) node;
2891 
2892  if (subplan->subLinkType == MULTIEXPR_SUBLINK)
2894  subplan);
2895  }
2896 
2897  /*
2898  * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2899  * because those do not represent expressions to be evaluated within the
2900  * calling expression's econtext. GroupingFunc arguments are never
2901  * evaluated at all.
2902  */
2903  if (IsA(node, Aggref))
2904  return false;
2905  if (IsA(node, WindowFunc))
2906  return false;
2907  if (IsA(node, GroupingFunc))
2908  return false;
2910  (void *) info);
2911 }
2912 
2913 /*
2914  * Compute additional information for EEOP_*_FETCHSOME ops.
2915  *
2916  * The goal is to determine whether a slot is 'fixed', that is, every
2917  * evaluation of the expression will have the same type of slot, with an
2918  * equivalent descriptor.
2919  *
2920  * Returns true if the deforming step is required, false otherwise.
2921  */
2922 static bool
2924 {
2925  PlanState *parent = state->parent;
2926  TupleDesc desc = NULL;
2927  const TupleTableSlotOps *tts_ops = NULL;
2928  bool isfixed = false;
2929  ExprEvalOp opcode = op->opcode;
2930 
2931  Assert(opcode == EEOP_INNER_FETCHSOME ||
2932  opcode == EEOP_OUTER_FETCHSOME ||
2933  opcode == EEOP_SCAN_FETCHSOME);
2934 
2935  if (op->d.fetch.known_desc != NULL)
2936  {
2937  desc = op->d.fetch.known_desc;
2938  tts_ops = op->d.fetch.kind;
2939  isfixed = op->d.fetch.kind != NULL;
2940  }
2941  else if (!parent)
2942  {
2943  isfixed = false;
2944  }
2945  else if (opcode == EEOP_INNER_FETCHSOME)
2946  {
2947  PlanState *is = innerPlanState(parent);
2948 
2949  if (parent->inneropsset && !parent->inneropsfixed)
2950  {
2951  isfixed = false;
2952  }
2953  else if (parent->inneropsset && parent->innerops)
2954  {
2955  isfixed = true;
2956  tts_ops = parent->innerops;
2957  desc = ExecGetResultType(is);
2958  }
2959  else if (is)
2960  {
2961  tts_ops = ExecGetResultSlotOps(is, &isfixed);
2962  desc = ExecGetResultType(is);
2963  }
2964  }
2965  else if (opcode == EEOP_OUTER_FETCHSOME)
2966  {
2967  PlanState *os = outerPlanState(parent);
2968 
2969  if (parent->outeropsset && !parent->outeropsfixed)
2970  {
2971  isfixed = false;
2972  }
2973  else if (parent->outeropsset && parent->outerops)
2974  {
2975  isfixed = true;
2976  tts_ops = parent->outerops;
2977  desc = ExecGetResultType(os);
2978  }
2979  else if (os)
2980  {
2981  tts_ops = ExecGetResultSlotOps(os, &isfixed);
2982  desc = ExecGetResultType(os);
2983  }
2984  }
2985  else if (opcode == EEOP_SCAN_FETCHSOME)
2986  {
2987  desc = parent->scandesc;
2988 
2989  if (parent->scanops)
2990  tts_ops = parent->scanops;
2991 
2992  if (parent->scanopsset)
2993  isfixed = parent->scanopsfixed;
2994  }
2995 
2996  if (isfixed && desc != NULL && tts_ops != NULL)
2997  {
2998  op->d.fetch.fixed = true;
2999  op->d.fetch.kind = tts_ops;
3000  op->d.fetch.known_desc = desc;
3001  }
3002  else
3003  {
3004  op->d.fetch.fixed = false;
3005  op->d.fetch.kind = NULL;
3006  op->d.fetch.known_desc = NULL;
3007  }
3008 
3009  /* if the slot is known to always virtual we never need to deform */
3010  if (op->d.fetch.fixed && op->d.fetch.kind == &TTSOpsVirtual)
3011  return false;
3012 
3013  return true;
3014 }
3015 
3016 /*
3017  * Prepare step for the evaluation of a whole-row variable.
3018  * The caller still has to push the step.
3019  */
3020 static void
3022 {
3023  PlanState *parent = state->parent;
3024 
3025  /* fill in all but the target */
3026  scratch->opcode = EEOP_WHOLEROW;
3027  scratch->d.wholerow.var = variable;
3028  scratch->d.wholerow.first = true;
3029  scratch->d.wholerow.slow = false;
3030  scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
3031  scratch->d.wholerow.junkFilter = NULL;
3032 
3033  /*
3034  * If the input tuple came from a subquery, it might contain "resjunk"
3035  * columns (such as GROUP BY or ORDER BY columns), which we don't want to
3036  * keep in the whole-row result. We can get rid of such columns by
3037  * passing the tuple through a JunkFilter --- but to make one, we have to
3038  * lay our hands on the subquery's targetlist. Fortunately, there are not
3039  * very many cases where this can happen, and we can identify all of them
3040  * by examining our parent PlanState. We assume this is not an issue in
3041  * standalone expressions that don't have parent plans. (Whole-row Vars
3042  * can occur in such expressions, but they will always be referencing
3043  * table rows.)
3044  */
3045  if (parent)
3046  {
3047  PlanState *subplan = NULL;
3048 
3049  switch (nodeTag(parent))
3050  {
3051  case T_SubqueryScanState:
3052  subplan = ((SubqueryScanState *) parent)->subplan;
3053  break;
3054  case T_CteScanState:
3055  subplan = ((CteScanState *) parent)->cteplanstate;
3056  break;
3057  default:
3058  break;
3059  }
3060 
3061  if (subplan)
3062  {
3063  bool junk_filter_needed = false;
3064  ListCell *tlist;
3065 
3066  /* Detect whether subplan tlist actually has any junk columns */
3067  foreach(tlist, subplan->plan->targetlist)
3068  {
3069  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
3070 
3071  if (tle->resjunk)
3072  {
3073  junk_filter_needed = true;
3074  break;
3075  }
3076  }
3077 
3078  /* If so, build the junkfilter now */
3079  if (junk_filter_needed)
3080  {
3081  scratch->d.wholerow.junkFilter =
3083  ExecInitExtraTupleSlot(parent->state, NULL,
3084  &TTSOpsVirtual));
3085  }
3086  }
3087  }
3088 }
3089 
3090 /*
3091  * Prepare evaluation of a SubscriptingRef expression.
3092  */
3093 static void
3095  ExprState *state, Datum *resv, bool *resnull)
3096 {
3097  bool isAssignment = (sbsref->refassgnexpr != NULL);
3098  int nupper = list_length(sbsref->refupperindexpr);
3099  int nlower = list_length(sbsref->reflowerindexpr);
3100  const SubscriptRoutines *sbsroutines;
3101  SubscriptingRefState *sbsrefstate;
3102  SubscriptExecSteps methods;
3103  char *ptr;
3104  List *adjust_jumps = NIL;
3105  ListCell *lc;
3106  int i;
3107 
3108  /* Look up the subscripting support methods */
3109  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
3110  if (!sbsroutines)
3111  ereport(ERROR,
3112  (errcode(ERRCODE_DATATYPE_MISMATCH),
3113  errmsg("cannot subscript type %s because it does not support subscripting",
3114  format_type_be(sbsref->refcontainertype)),
3115  state->parent ?
3116  executor_errposition(state->parent->state,
3117  exprLocation((Node *) sbsref)) : 0));
3118 
3119  /* Allocate sbsrefstate, with enough space for per-subscript arrays too */
3120  sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +
3121  (nupper + nlower) * (sizeof(Datum) +
3122  2 * sizeof(bool)));
3123 
3124  /* Fill constant fields of SubscriptingRefState */
3125  sbsrefstate->isassignment = isAssignment;
3126  sbsrefstate->numupper = nupper;
3127  sbsrefstate->numlower = nlower;
3128  /* Set up per-subscript arrays */
3129  ptr = ((char *) sbsrefstate) + MAXALIGN(sizeof(SubscriptingRefState));
3130  sbsrefstate->upperindex = (Datum *) ptr;
3131  ptr += nupper * sizeof(Datum);
3132  sbsrefstate->lowerindex = (Datum *) ptr;
3133  ptr += nlower * sizeof(Datum);
3134  sbsrefstate->upperprovided = (bool *) ptr;
3135  ptr += nupper * sizeof(bool);
3136  sbsrefstate->lowerprovided = (bool *) ptr;
3137  ptr += nlower * sizeof(bool);
3138  sbsrefstate->upperindexnull = (bool *) ptr;
3139  ptr += nupper * sizeof(bool);
3140  sbsrefstate->lowerindexnull = (bool *) ptr;
3141  /* ptr += nlower * sizeof(bool); */
3142 
3143  /*
3144  * Let the container-type-specific code have a chance. It must fill the
3145  * "methods" struct with function pointers for us to possibly use in
3146  * execution steps below; and it can optionally set up some data pointed
3147  * to by the workspace field.
3148  */
3149  memset(&methods, 0, sizeof(methods));
3150  sbsroutines->exec_setup(sbsref, sbsrefstate, &methods);
3151 
3152  /*
3153  * Evaluate array input. It's safe to do so into resv/resnull, because we
3154  * won't use that as target for any of the other subexpressions, and it'll
3155  * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
3156  * pushed last.
3157  */
3158  ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
3159 
3160  /*
3161  * If refexpr yields NULL, and the operation should be strict, then result
3162  * is NULL. We can implement this with just JUMP_IF_NULL, since we
3163  * evaluated the array into the desired target location.
3164  */
3165  if (!isAssignment && sbsroutines->fetch_strict)
3166  {
3167  scratch->opcode = EEOP_JUMP_IF_NULL;
3168  scratch->d.jump.jumpdone = -1; /* adjust later */
3169  ExprEvalPushStep(state, scratch);
3170  adjust_jumps = lappend_int(adjust_jumps,
3171  state->steps_len - 1);
3172  }
3173 
3174  /* Evaluate upper subscripts */
3175  i = 0;
3176  foreach(lc, sbsref->refupperindexpr)
3177  {
3178  Expr *e = (Expr *) lfirst(lc);
3179 
3180  /* When slicing, individual subscript bounds can be omitted */
3181  if (!e)
3182  {
3183  sbsrefstate->upperprovided[i] = false;
3184  sbsrefstate->upperindexnull[i] = true;
3185  }
3186  else
3187  {
3188  sbsrefstate->upperprovided[i] = true;
3189  /* Each subscript is evaluated into appropriate array entry */
3191  &sbsrefstate->upperindex[i],
3192  &sbsrefstate->upperindexnull[i]);
3193  }
3194  i++;
3195  }
3196 
3197  /* Evaluate lower subscripts similarly */
3198  i = 0;
3199  foreach(lc, sbsref->reflowerindexpr)
3200  {
3201  Expr *e = (Expr *) lfirst(lc);
3202 
3203  /* When slicing, individual subscript bounds can be omitted */
3204  if (!e)
3205  {
3206  sbsrefstate->lowerprovided[i] = false;
3207  sbsrefstate->lowerindexnull[i] = true;
3208  }
3209  else
3210  {
3211  sbsrefstate->lowerprovided[i] = true;
3212  /* Each subscript is evaluated into appropriate array entry */
3214  &sbsrefstate->lowerindex[i],
3215  &sbsrefstate->lowerindexnull[i]);
3216  }
3217  i++;
3218  }
3219 
3220  /* SBSREF_SUBSCRIPTS checks and converts all the subscripts at once */
3221  if (methods.sbs_check_subscripts)
3222  {
3223  scratch->opcode = EEOP_SBSREF_SUBSCRIPTS;
3224  scratch->d.sbsref_subscript.subscriptfunc = methods.sbs_check_subscripts;
3225  scratch->d.sbsref_subscript.state = sbsrefstate;
3226  scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
3227  ExprEvalPushStep(state, scratch);
3228  adjust_jumps = lappend_int(adjust_jumps,
3229  state->steps_len - 1);
3230  }
3231 
3232  if (isAssignment)
3233  {
3234  Datum *save_innermost_caseval;
3235  bool *save_innermost_casenull;
3236 
3237  /* Check for unimplemented methods */
3238  if (!methods.sbs_assign)
3239  ereport(ERROR,
3240  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3241  errmsg("type %s does not support subscripted assignment",
3242  format_type_be(sbsref->refcontainertype))));
3243 
3244  /*
3245  * We might have a nested-assignment situation, in which the
3246  * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
3247  * to obtain and modify the previous value of the array element or
3248  * slice being replaced. If so, we have to extract that value from
3249  * the array and pass it down via the CaseTestExpr mechanism. It's
3250  * safe to reuse the CASE mechanism because there cannot be a CASE
3251  * between here and where the value would be needed, and an array
3252  * assignment can't be within a CASE either. (So saving and restoring
3253  * innermost_caseval is just paranoia, but let's do it anyway.)
3254  *
3255  * Since fetching the old element might be a nontrivial expense, do it
3256  * only if the argument actually needs it.
3257  */
3259  {
3260  if (!methods.sbs_fetch_old)
3261  ereport(ERROR,
3262  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3263  errmsg("type %s does not support subscripted assignment",
3264  format_type_be(sbsref->refcontainertype))));
3265  scratch->opcode = EEOP_SBSREF_OLD;
3266  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch_old;
3267  scratch->d.sbsref.state = sbsrefstate;
3268  ExprEvalPushStep(state, scratch);
3269  }
3270 
3271  /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
3272  save_innermost_caseval = state->innermost_caseval;
3273  save_innermost_casenull = state->innermost_casenull;
3274  state->innermost_caseval = &sbsrefstate->prevvalue;
3275  state->innermost_casenull = &sbsrefstate->prevnull;
3276 
3277  /* evaluate replacement value into replacevalue/replacenull */
3279  &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
3280 
3281  state->innermost_caseval = save_innermost_caseval;
3282  state->innermost_casenull = save_innermost_casenull;
3283 
3284  /* and perform the assignment */
3285  scratch->opcode = EEOP_SBSREF_ASSIGN;
3286  scratch->d.sbsref.subscriptfunc = methods.sbs_assign;
3287  scratch->d.sbsref.state = sbsrefstate;
3288  ExprEvalPushStep(state, scratch);
3289  }
3290  else
3291  {
3292  /* array fetch is much simpler */
3293  scratch->opcode = EEOP_SBSREF_FETCH;
3294  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch;
3295  scratch->d.sbsref.state = sbsrefstate;
3296  ExprEvalPushStep(state, scratch);
3297  }
3298 
3299  /* adjust jump targets */
3300  foreach(lc, adjust_jumps)
3301  {
3302  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3303 
3304  if (as->opcode == EEOP_SBSREF_SUBSCRIPTS)
3305  {
3306  Assert(as->d.sbsref_subscript.jumpdone == -1);
3307  as->d.sbsref_subscript.jumpdone = state->steps_len;
3308  }
3309  else
3310  {
3312  Assert(as->d.jump.jumpdone == -1);
3313  as->d.jump.jumpdone = state->steps_len;
3314  }
3315  }
3316 }
3317 
3318 /*
3319  * Helper for preparing SubscriptingRef expressions for evaluation: is expr
3320  * a nested FieldStore or SubscriptingRef that needs the old element value
3321  * passed down?
3322  *
3323  * (We could use this in FieldStore too, but in that case passing the old
3324  * value is so cheap there's no need.)
3325  *
3326  * Note: it might seem that this needs to recurse, but in most cases it does
3327  * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the
3328  * top-level node. Nested-assignment situations give rise to expression
3329  * trees in which each level of assignment has its own CaseTestExpr, and the
3330  * recursive structure appears within the newvals or refassgnexpr field.
3331  * There is an exception, though: if the array is an array-of-domain, we will
3332  * have a CoerceToDomain or RelabelType as the refassgnexpr, and we need to
3333  * be able to look through that.
3334  */
3335 static bool
3337 {
3338  if (expr == NULL)
3339  return false; /* just paranoia */
3340  if (IsA(expr, FieldStore))
3341  {
3342  FieldStore *fstore = (FieldStore *) expr;
3343 
3344  if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
3345  return true;
3346  }
3347  else if (IsA(expr, SubscriptingRef))
3348  {
3349  SubscriptingRef *sbsRef = (SubscriptingRef *) expr;
3350 
3351  if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr))
3352  return true;
3353  }
3354  else if (IsA(expr, CoerceToDomain))
3355  {
3356  CoerceToDomain *cd = (CoerceToDomain *) expr;
3357 
3358  return isAssignmentIndirectionExpr(cd->arg);
3359  }
3360  else if (IsA(expr, RelabelType))
3361  {
3362  RelabelType *r = (RelabelType *) expr;
3363 
3364  return isAssignmentIndirectionExpr(r->arg);
3365  }
3366  return false;
3367 }
3368 
3369 /*
3370  * Prepare evaluation of a CoerceToDomain expression.
3371  */
3372 static void
3374  ExprState *state, Datum *resv, bool *resnull)
3375 {
3376  DomainConstraintRef *constraint_ref;
3377  Datum *domainval = NULL;
3378  bool *domainnull = NULL;
3379  ListCell *l;
3380 
3381  scratch->d.domaincheck.resulttype = ctest->resulttype;
3382  /* we'll allocate workspace only if needed */
3383  scratch->d.domaincheck.checkvalue = NULL;
3384  scratch->d.domaincheck.checknull = NULL;
3385  scratch->d.domaincheck.escontext = state->escontext;
3386 
3387  /*
3388  * Evaluate argument - it's fine to directly store it into resv/resnull,
3389  * if there's constraint failures there'll be errors, otherwise it's what
3390  * needs to be returned.
3391  */
3392  ExecInitExprRec(ctest->arg, state, resv, resnull);
3393 
3394  /*
3395  * Note: if the argument is of varlena type, it could be a R/W expanded
3396  * object. We want to return the R/W pointer as the final result, but we
3397  * have to pass a R/O pointer as the value to be tested by any functions
3398  * in check expressions. We don't bother to emit a MAKE_READONLY step
3399  * unless there's actually at least one check expression, though. Until
3400  * we've tested that, domainval/domainnull are NULL.
3401  */
3402 
3403  /*
3404  * Collect the constraints associated with the domain.
3405  *
3406  * Note: before PG v10 we'd recheck the set of constraints during each
3407  * evaluation of the expression. Now we bake them into the ExprState
3408  * during executor initialization. That means we don't need typcache.c to
3409  * provide compiled exprs.
3410  */
3411  constraint_ref = (DomainConstraintRef *)
3412  palloc(sizeof(DomainConstraintRef));
3414  constraint_ref,
3416  false);
3417 
3418  /*
3419  * Compile code to check each domain constraint. NOTNULL constraints can
3420  * just be applied on the resv/resnull value, but for CHECK constraints we
3421  * need more pushups.
3422  */
3423  foreach(l, constraint_ref->constraints)
3424  {
3426  Datum *save_innermost_domainval;
3427  bool *save_innermost_domainnull;
3428 
3429  scratch->d.domaincheck.constraintname = con->name;
3430 
3431  switch (con->constrainttype)
3432  {
3434  scratch->opcode = EEOP_DOMAIN_NOTNULL;
3435  ExprEvalPushStep(state, scratch);
3436  break;
3437  case DOM_CONSTRAINT_CHECK:
3438  /* Allocate workspace for CHECK output if we didn't yet */
3439  if (scratch->d.domaincheck.checkvalue == NULL)
3440  {
3441  scratch->d.domaincheck.checkvalue =
3442  (Datum *) palloc(sizeof(Datum));
3443  scratch->d.domaincheck.checknull =
3444  (bool *) palloc(sizeof(bool));
3445  }
3446 
3447  /*
3448  * If first time through, determine where CoerceToDomainValue
3449  * nodes should read from.
3450  */
3451  if (domainval == NULL)
3452  {
3453  /*
3454  * Since value might be read multiple times, force to R/O
3455  * - but only if it could be an expanded datum.
3456  */
3457  if (get_typlen(ctest->resulttype) == -1)
3458  {
3459  ExprEvalStep scratch2 = {0};
3460 
3461  /* Yes, so make output workspace for MAKE_READONLY */
3462  domainval = (Datum *) palloc(sizeof(Datum));
3463  domainnull = (bool *) palloc(sizeof(bool));
3464 
3465  /* Emit MAKE_READONLY */
3466  scratch2.opcode = EEOP_MAKE_READONLY;
3467  scratch2.resvalue = domainval;
3468  scratch2.resnull = domainnull;
3469  scratch2.d.make_readonly.value = resv;
3470  scratch2.d.make_readonly.isnull = resnull;
3471  ExprEvalPushStep(state, &scratch2);
3472  }
3473  else
3474  {
3475  /* No, so it's fine to read from resv/resnull */
3476  domainval = resv;
3477  domainnull = resnull;
3478  }
3479  }
3480 
3481  /*
3482  * Set up value to be returned by CoerceToDomainValue nodes.
3483  * We must save and restore innermost_domainval/null fields,
3484  * in case this node is itself within a check expression for
3485  * another domain.
3486  */
3487  save_innermost_domainval = state->innermost_domainval;
3488  save_innermost_domainnull = state->innermost_domainnull;
3489  state->innermost_domainval = domainval;
3490  state->innermost_domainnull = domainnull;
3491 
3492  /* evaluate check expression value */
3494  scratch->d.domaincheck.checkvalue,
3495  scratch->d.domaincheck.checknull);
3496 
3497  state->innermost_domainval = save_innermost_domainval;
3498  state->innermost_domainnull = save_innermost_domainnull;
3499 
3500  /* now test result */
3501  scratch->opcode = EEOP_DOMAIN_CHECK;
3502  ExprEvalPushStep(state, scratch);
3503 
3504  break;
3505  default:
3506  elog(ERROR, "unrecognized constraint type: %d",
3507  (int) con->constrainttype);
3508  break;
3509  }
3510  }
3511 }
3512 
3513 /*
3514  * Build transition/combine function invocations for all aggregate transition
3515  * / combination function invocations in a grouping sets phase. This has to
3516  * invoke all sort based transitions in a phase (if doSort is true), all hash
3517  * based transitions (if doHash is true), or both (both true).
3518  *
3519  * The resulting expression will, for each set of transition values, first
3520  * check for filters, evaluate aggregate input, check that that input is not
3521  * NULL for a strict transition function, and then finally invoke the
3522  * transition for each of the concurrently computed grouping sets.
3523  *
3524  * If nullcheck is true, the generated code will check for a NULL pointer to
3525  * the array of AggStatePerGroup, and skip evaluation if so.
3526  */
3527 ExprState *
3529  bool doSort, bool doHash, bool nullcheck)
3530 {
3532  PlanState *parent = &aggstate->ss.ps;
3533  ExprEvalStep scratch = {0};
3534  bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit);
3535  ExprSetupInfo deform = {0, 0, 0, NIL};
3536 
3537  state->expr = (Expr *) aggstate;
3538  state->parent = parent;
3539 
3540  scratch.resvalue = &state->resvalue;
3541  scratch.resnull = &state->resnull;
3542 
3543  /*
3544  * First figure out which slots, and how many columns from each, we're
3545  * going to need.
3546  */
3547  for (int transno = 0; transno < aggstate->numtrans; transno++)
3548  {
3549  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3550 
3551  expr_setup_walker((Node *) pertrans->aggref->aggdirectargs,
3552  &deform);
3553  expr_setup_walker((Node *) pertrans->aggref->args,
3554  &deform);
3555  expr_setup_walker((Node *) pertrans->aggref->aggorder,
3556  &deform);
3557  expr_setup_walker((Node *) pertrans->aggref->aggdistinct,
3558  &deform);
3559  expr_setup_walker((Node *) pertrans->aggref->aggfilter,
3560  &deform);
3561  }
3562  ExecPushExprSetupSteps(state, &deform);
3563 
3564  /*
3565  * Emit instructions for each transition value / grouping set combination.
3566  */
3567  for (int transno = 0; transno < aggstate->numtrans; transno++)
3568  {
3569  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3570  FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
3571  List *adjust_bailout = NIL;
3572  NullableDatum *strictargs = NULL;
3573  bool *strictnulls = NULL;
3574  int argno;
3575  ListCell *bail;
3576 
3577  /*
3578  * If filter present, emit. Do so before evaluating the input, to
3579  * avoid potentially unneeded computations, or even worse, unintended
3580  * side-effects. When combining, all the necessary filtering has
3581  * already been done.
3582  */
3583  if (pertrans->aggref->aggfilter && !isCombine)
3584  {
3585  /* evaluate filter expression */
3586  ExecInitExprRec(pertrans->aggref->aggfilter, state,
3587  &state->resvalue, &state->resnull);
3588  /* and jump out if false */
3589  scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
3590  scratch.d.jump.jumpdone = -1; /* adjust later */
3591  ExprEvalPushStep(state, &scratch);
3592  adjust_bailout = lappend_int(adjust_bailout,
3593  state->steps_len - 1);
3594  }
3595 
3596  /*
3597  * Evaluate arguments to aggregate/combine function.
3598  */
3599  argno = 0;
3600  if (isCombine)
3601  {
3602  /*
3603  * Combining two aggregate transition values. Instead of directly
3604  * coming from a tuple the input is a, potentially deserialized,
3605  * transition value.
3606  */
3607  TargetEntry *source_tle;
3608 
3609  Assert(pertrans->numSortCols == 0);
3610  Assert(list_length(pertrans->aggref->args) == 1);
3611 
3612  strictargs = trans_fcinfo->args + 1;
3613  source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
3614 
3615  /*
3616  * deserialfn_oid will be set if we must deserialize the input
3617  * state before calling the combine function.
3618  */
3619  if (!OidIsValid(pertrans->deserialfn_oid))
3620  {
3621  /*
3622  * Start from 1, since the 0th arg will be the transition
3623  * value
3624  */
3625  ExecInitExprRec(source_tle->expr, state,
3626  &trans_fcinfo->args[argno + 1].value,
3627  &trans_fcinfo->args[argno + 1].isnull);
3628  }
3629  else
3630  {
3631  FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
3632 
3633  /* evaluate argument */
3634  ExecInitExprRec(source_tle->expr, state,
3635  &ds_fcinfo->args[0].value,
3636  &ds_fcinfo->args[0].isnull);
3637 
3638  /* Dummy second argument for type-safety reasons */
3639  ds_fcinfo->args[1].value = PointerGetDatum(NULL);
3640  ds_fcinfo->args[1].isnull = false;
3641 
3642  /*
3643  * Don't call a strict deserialization function with NULL
3644  * input
3645  */
3646  if (pertrans->deserialfn.fn_strict)
3648  else
3649  scratch.opcode = EEOP_AGG_DESERIALIZE;
3650 
3651  scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
3652  scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
3653  scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
3654  scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
3655 
3656  ExprEvalPushStep(state, &scratch);
3657  /* don't add an adjustment unless the function is strict */
3658  if (pertrans->deserialfn.fn_strict)
3659  adjust_bailout = lappend_int(adjust_bailout,
3660  state->steps_len - 1);
3661 
3662  /* restore normal settings of scratch fields */
3663  scratch.resvalue = &state->resvalue;
3664  scratch.resnull = &state->resnull;
3665  }
3666  argno++;
3667 
3668  Assert(pertrans->numInputs == argno);
3669  }
3670  else if (!pertrans->aggsortrequired)
3671  {
3672  ListCell *arg;
3673 
3674  /*
3675  * Normal transition function without ORDER BY / DISTINCT or with
3676  * ORDER BY / DISTINCT but the planner has given us pre-sorted
3677  * input.
3678  */
3679  strictargs = trans_fcinfo->args + 1;
3680 
3681  foreach(arg, pertrans->aggref->args)
3682  {
3683  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3684 
3685  /*
3686  * Don't initialize args for any ORDER BY clause that might
3687  * exist in a presorted aggregate.
3688  */
3689  if (argno == pertrans->numTransInputs)
3690  break;
3691 
3692  /*
3693  * Start from 1, since the 0th arg will be the transition
3694  * value
3695  */
3696  ExecInitExprRec(source_tle->expr, state,
3697  &trans_fcinfo->args[argno + 1].value,
3698  &trans_fcinfo->args[argno + 1].isnull);
3699  argno++;
3700  }
3701  Assert(pertrans->numTransInputs == argno);
3702  }
3703  else if (pertrans->numInputs == 1)
3704  {
3705  /*
3706  * Non-presorted DISTINCT and/or ORDER BY case, with a single
3707  * column sorted on.
3708  */
3709  TargetEntry *source_tle =
3710  (TargetEntry *) linitial(pertrans->aggref->args);
3711 
3712  Assert(list_length(pertrans->aggref->args) == 1);
3713 
3714  ExecInitExprRec(source_tle->expr, state,
3715  &state->resvalue,
3716  &state->resnull);
3717  strictnulls = &state->resnull;
3718  argno++;
3719 
3720  Assert(pertrans->numInputs == argno);
3721  }
3722  else
3723  {
3724  /*
3725  * Non-presorted DISTINCT and/or ORDER BY case, with multiple
3726  * columns sorted on.
3727  */
3728  Datum *values = pertrans->sortslot->tts_values;
3729  bool *nulls = pertrans->sortslot->tts_isnull;
3730  ListCell *arg;
3731 
3732  strictnulls = nulls;
3733 
3734  foreach(arg, pertrans->aggref->args)
3735  {
3736  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3737 
3738  ExecInitExprRec(source_tle->expr, state,
3739  &values[argno], &nulls[argno]);
3740  argno++;
3741  }
3742  Assert(pertrans->numInputs == argno);
3743  }
3744 
3745  /*
3746  * For a strict transfn, nothing happens when there's a NULL input; we
3747  * just keep the prior transValue. This is true for both plain and
3748  * sorted/distinct aggregates.
3749  */
3750  if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
3751  {
3752  if (strictnulls)
3754  else
3756  scratch.d.agg_strict_input_check.nulls = strictnulls;
3757  scratch.d.agg_strict_input_check.args = strictargs;
3758  scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
3759  scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
3760  ExprEvalPushStep(state, &scratch);
3761  adjust_bailout = lappend_int(adjust_bailout,
3762  state->steps_len - 1);
3763  }
3764 
3765  /* Handle DISTINCT aggregates which have pre-sorted input */
3766  if (pertrans->numDistinctCols > 0 && !pertrans->aggsortrequired)
3767  {
3768  if (pertrans->numDistinctCols > 1)
3770  else
3772 
3773  scratch.d.agg_presorted_distinctcheck.pertrans = pertrans;
3774  scratch.d.agg_presorted_distinctcheck.jumpdistinct = -1; /* adjust later */
3775  ExprEvalPushStep(state, &scratch);
3776  adjust_bailout = lappend_int(adjust_bailout,
3777  state->steps_len - 1);
3778  }
3779 
3780  /*
3781  * Call transition function (once for each concurrently evaluated
3782  * grouping set). Do so for both sort and hash based computations, as
3783  * applicable.
3784  */
3785  if (doSort)
3786  {
3787  int processGroupingSets = Max(phase->numsets, 1);
3788  int setoff = 0;
3789 
3790  for (int setno = 0; setno < processGroupingSets; setno++)
3791  {
3792  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3793  pertrans, transno, setno, setoff, false,
3794  nullcheck);
3795  setoff++;
3796  }
3797  }
3798 
3799  if (doHash)
3800  {
3801  int numHashes = aggstate->num_hashes;
3802  int setoff;
3803 
3804  /* in MIXED mode, there'll be preceding transition values */
3805  if (aggstate->aggstrategy != AGG_HASHED)
3806  setoff = aggstate->maxsets;
3807  else
3808  setoff = 0;
3809 
3810  for (int setno = 0; setno < numHashes; setno++)
3811  {
3812  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3813  pertrans, transno, setno, setoff, true,
3814  nullcheck);
3815  setoff++;
3816  }
3817  }
3818 
3819  /* adjust early bail out jump target(s) */
3820  foreach(bail, adjust_bailout)
3821  {
3822  ExprEvalStep *as = &state->steps[lfirst_int(bail)];
3823 
3824  if (as->opcode == EEOP_JUMP_IF_NOT_TRUE)
3825  {
3826  Assert(as->d.jump.jumpdone == -1);
3827  as->d.jump.jumpdone = state->steps_len;
3828  }
3829  else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
3831  {
3832  Assert(as->d.agg_strict_input_check.jumpnull == -1);
3833  as->d.agg_strict_input_check.jumpnull = state->steps_len;
3834  }
3835  else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE)
3836  {
3837  Assert(as->d.agg_deserialize.jumpnull == -1);
3838  as->d.agg_deserialize.jumpnull = state->steps_len;
3839  }
3840  else if (as->opcode == EEOP_AGG_PRESORTED_DISTINCT_SINGLE ||
3842  {
3843  Assert(as->d.agg_presorted_distinctcheck.jumpdistinct == -1);
3844  as->d.agg_presorted_distinctcheck.jumpdistinct = state->steps_len;
3845  }
3846  else
3847  Assert(false);
3848  }
3849  }
3850 
3851  scratch.resvalue = NULL;
3852  scratch.resnull = NULL;
3853  scratch.opcode = EEOP_DONE;
3854  ExprEvalPushStep(state, &scratch);
3855 
3857 
3858  return state;
3859 }
3860 
3861 /*
3862  * Build transition/combine function invocation for a single transition
3863  * value. This is separated from ExecBuildAggTrans() because there are
3864  * multiple callsites (hash and sort in some grouping set cases).
3865  */
3866 static void
3868  ExprEvalStep *scratch,
3869  FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
3870  int transno, int setno, int setoff, bool ishash,
3871  bool nullcheck)
3872 {
3873  ExprContext *aggcontext;
3874  int adjust_jumpnull = -1;
3875 
3876  if (ishash)
3877  aggcontext = aggstate->hashcontext;
3878  else
3879  aggcontext = aggstate->aggcontexts[setno];
3880 
3881  /* add check for NULL pointer? */
3882  if (nullcheck)
3883  {
3885  scratch->d.agg_plain_pergroup_nullcheck.setoff = setoff;
3886  /* adjust later */
3887  scratch->d.agg_plain_pergroup_nullcheck.jumpnull = -1;
3888  ExprEvalPushStep(state, scratch);
3889  adjust_jumpnull = state->steps_len - 1;
3890  }
3891 
3892  /*
3893  * Determine appropriate transition implementation.
3894  *
3895  * For non-ordered aggregates and ORDER BY / DISTINCT aggregates with
3896  * presorted input:
3897  *
3898  * If the initial value for the transition state doesn't exist in the
3899  * pg_aggregate table then we will let the first non-NULL value returned
3900  * from the outer procNode become the initial value. (This is useful for
3901  * aggregates like max() and min().) The noTransValue flag signals that we
3902  * need to do so. If true, generate a
3903  * EEOP_AGG_INIT_STRICT_PLAIN_TRANS{,_BYVAL} step. This step also needs to
3904  * do the work described next:
3905  *
3906  * If the function is strict, but does have an initial value, choose
3907  * EEOP_AGG_STRICT_PLAIN_TRANS{,_BYVAL}, which skips the transition
3908  * function if the transition value has become NULL (because a previous
3909  * transition function returned NULL). This step also needs to do the work
3910  * described next:
3911  *
3912  * Otherwise we call EEOP_AGG_PLAIN_TRANS{,_BYVAL}, which does not have to
3913  * perform either of the above checks.
3914  *
3915  * Having steps with overlapping responsibilities is not nice, but
3916  * aggregations are very performance sensitive, making this worthwhile.
3917  *
3918  * For ordered aggregates:
3919  *
3920  * Only need to choose between the faster path for a single ordered
3921  * column, and the one between multiple columns. Checking strictness etc
3922  * is done when finalizing the aggregate. See
3923  * process_ordered_aggregate_{single, multi} and
3924  * advance_transition_function.
3925  */
3926  if (!pertrans->aggsortrequired)
3927  {
3928  if (pertrans->transtypeByVal)
3929  {
3930  if (fcinfo->flinfo->fn_strict &&
3931  pertrans->initValueIsNull)
3933  else if (fcinfo->flinfo->fn_strict)
3935  else
3937  }
3938  else
3939  {
3940  if (fcinfo->flinfo->fn_strict &&
3941  pertrans->initValueIsNull)
3943  else if (fcinfo->flinfo->fn_strict)
3945  else
3947  }
3948  }
3949  else if (pertrans->numInputs == 1)
3951  else
3953 
3954  scratch->d.agg_trans.pertrans = pertrans;
3955  scratch->d.agg_trans.setno = setno;
3956  scratch->d.agg_trans.setoff = setoff;
3957  scratch->d.agg_trans.transno = transno;
3958  scratch->d.agg_trans.aggcontext = aggcontext;
3959  ExprEvalPushStep(state, scratch);
3960 
3961  /* fix up jumpnull */
3962  if (adjust_jumpnull != -1)
3963  {
3964  ExprEvalStep *as = &state->steps[adjust_jumpnull];
3965 
3967  Assert(as->d.agg_plain_pergroup_nullcheck.jumpnull == -1);
3968  as->d.agg_plain_pergroup_nullcheck.jumpnull = state->steps_len;
3969  }
3970 }
3971 
3972 /*
3973  * Build an ExprState that calls the given hash function(s) on the given
3974  * 'hash_exprs'. When multiple expressions are present, the hash values
3975  * returned by each hash function are combined to produce a single hash value.
3976  *
3977  * desc: tuple descriptor for the to-be-hashed expressions
3978  * ops: TupleTableSlotOps for the TupleDesc
3979  * hashfunc_oids: Oid for each hash function to call, one for each 'hash_expr'
3980  * collations: collation to use when calling the hash function.
3981  * hash_expr: list of expressions to hash the value of
3982  * opstrict: array corresponding to the 'hashfunc_oids' to store op_strict()
3983  * parent: PlanState node that the 'hash_exprs' will be evaluated at
3984  * init_value: Normally 0, but can be set to other values to seed the hash
3985  * with some other value. Using non-zero is slightly less efficient but can
3986  * be useful.
3987  * keep_nulls: if true, evaluation of the returned ExprState will abort early
3988  * returning NULL if the given hash function is strict and the Datum to hash
3989  * is null. When set to false, any NULL input Datums are skipped.
3990  */
3991 ExprState *
3993  const Oid *hashfunc_oids, const List *collations,
3994  const List *hash_exprs, const bool *opstrict,
3995  PlanState *parent, uint32 init_value, bool keep_nulls)
3996 {
3998  ExprEvalStep scratch = {0};
3999  List *adjust_jumps = NIL;
4000  ListCell *lc;
4001  ListCell *lc2;
4002  intptr_t strict_opcode;
4003  intptr_t opcode;
4004 
4005  Assert(list_length(hash_exprs) == list_length(collations));
4006 
4007  state->parent = parent;
4008 
4009  /* Insert setup steps as needed. */
4010  ExecCreateExprSetupSteps(state, (Node *) hash_exprs);
4011 
4012  if (init_value == 0)
4013  {
4014  /*
4015  * No initial value, so we can assign the result of the hash function
4016  * for the first hash_expr without having to concern ourselves with
4017  * combining the result with any initial value.
4018  */
4019  strict_opcode = EEOP_HASHDATUM_FIRST_STRICT;
4020  opcode = EEOP_HASHDATUM_FIRST;
4021  }
4022  else
4023  {
4024  /* Set up operation to set the initial value. */
4026  scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4027  scratch.resvalue = &state->resvalue;
4028  scratch.resnull = &state->resnull;
4029 
4030  ExprEvalPushStep(state, &scratch);
4031 
4032  /*
4033  * When using an initial value use the NEXT32/NEXT32_STRICT ops as the
4034  * FIRST/FIRST_STRICT ops would overwrite the stored initial value.
4035  */
4036  strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT;
4037  opcode = EEOP_HASHDATUM_NEXT32;
4038  }
4039 
4040  forboth(lc, hash_exprs, lc2, collations)
4041  {
4042  Expr *expr = (Expr *) lfirst(lc);
4043  FmgrInfo *finfo;
4044  FunctionCallInfo fcinfo;
4045  int i = foreach_current_index(lc);
4046  Oid funcid;
4047  Oid inputcollid = lfirst_oid(lc2);
4048 
4049  funcid = hashfunc_oids[i];
4050 
4051  /* Allocate hash function lookup data. */
4052  finfo = palloc0(sizeof(FmgrInfo));
4053  fcinfo = palloc0(SizeForFunctionCallInfo(1));
4054 
4055  fmgr_info(funcid, finfo);
4056 
4057  /*
4058  * Build the steps to evaluate the hash function's argument have it so
4059  * the value of that is stored in the 0th argument of the hash func.
4060  */
4061  ExecInitExprRec(expr,
4062  state,
4063  &fcinfo->args[0].value,
4064  &fcinfo->args[0].isnull);
4065 
4066  scratch.resvalue = &state->resvalue;
4067  scratch.resnull = &state->resnull;
4068 
4069  /* Initialize function call parameter structure too */
4070  InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4071 
4072  scratch.d.hashdatum.finfo = finfo;
4073  scratch.d.hashdatum.fcinfo_data = fcinfo;
4074  scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4075 
4076  scratch.opcode = opstrict[i] && !keep_nulls ? strict_opcode : opcode;
4077  scratch.d.hashdatum.jumpdone = -1;
4078 
4079  ExprEvalPushStep(state, &scratch);
4080  adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1);
4081 
4082  /*
4083  * For subsequent keys we must combine the hash value with the
4084  * previous hashes.
4085  */
4086  strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT;
4087  opcode = EEOP_HASHDATUM_NEXT32;
4088  }
4089 
4090  /* adjust jump targets */
4091  foreach(lc, adjust_jumps)
4092  {
4093  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4094 
4097  as->opcode == EEOP_HASHDATUM_NEXT32 ||
4099  Assert(as->d.hashdatum.jumpdone == -1);
4100  as->d.hashdatum.jumpdone = state->steps_len;
4101  }
4102 
4103  scratch.resvalue = NULL;
4104  scratch.resnull = NULL;
4105  scratch.opcode = EEOP_DONE;
4106  ExprEvalPushStep(state, &scratch);
4107 
4109 
4110  return state;
4111 }
4112 
4113 /*
4114  * Build equality expression that can be evaluated using ExecQual(), returning
4115  * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e
4116  * two nulls match, a null and a not-null don't match.
4117  *
4118  * desc: tuple descriptor of the to-be-compared tuples
4119  * numCols: the number of attributes to be examined
4120  * keyColIdx: array of attribute column numbers
4121  * eqFunctions: array of function oids of the equality functions to use
4122  * parent: parent executor node
4123  */
4124 ExprState *
4126  const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
4127  int numCols,
4128  const AttrNumber *keyColIdx,
4129  const Oid *eqfunctions,
4130  const Oid *collations,
4131  PlanState *parent)
4132 {
4134  ExprEvalStep scratch = {0};
4135  int maxatt = -1;
4136  List *adjust_jumps = NIL;
4137  ListCell *lc;
4138 
4139  /*
4140  * When no columns are actually compared, the result's always true. See
4141  * special case in ExecQual().
4142  */
4143  if (numCols == 0)
4144  return NULL;
4145 
4146  state->expr = NULL;
4147  state->flags = EEO_FLAG_IS_QUAL;
4148  state->parent = parent;
4149 
4150  scratch.resvalue = &state->resvalue;
4151  scratch.resnull = &state->resnull;
4152 
4153  /* compute max needed attribute */
4154  for (int natt = 0; natt < numCols; natt++)
4155  {
4156  int attno = keyColIdx[natt];
4157 
4158  if (attno > maxatt)
4159  maxatt = attno;
4160  }
4161  Assert(maxatt >= 0);
4162 
4163  /* push deform steps */
4164  scratch.opcode = EEOP_INNER_FETCHSOME;
4165  scratch.d.fetch.last_var = maxatt;
4166  scratch.d.fetch.fixed = false;
4167  scratch.d.fetch.known_desc = ldesc;
4168  scratch.d.fetch.kind = lops;
4169  if (ExecComputeSlotInfo(state, &scratch))
4170  ExprEvalPushStep(state, &scratch);
4171 
4172  scratch.opcode = EEOP_OUTER_FETCHSOME;
4173  scratch.d.fetch.last_var = maxatt;
4174  scratch.d.fetch.fixed = false;
4175  scratch.d.fetch.known_desc = rdesc;
4176  scratch.d.fetch.kind = rops;
4177  if (ExecComputeSlotInfo(state, &scratch))
4178  ExprEvalPushStep(state, &scratch);
4179 
4180  /*
4181  * Start comparing at the last field (least significant sort key). That's
4182  * the most likely to be different if we are dealing with sorted input.
4183  */
4184  for (int natt = numCols; --natt >= 0;)
4185  {
4186  int attno = keyColIdx[natt];
4187  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4188  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4189  Oid foid = eqfunctions[natt];
4190  Oid collid = collations[natt];
4191  FmgrInfo *finfo;
4192  FunctionCallInfo fcinfo;
4193  AclResult aclresult;
4194 
4195  /* Check permission to call function */
4196  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4197  if (aclresult != ACLCHECK_OK)
4198  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4199 
4201 
4202  /* Set up the primary fmgr lookup information */
4203  finfo = palloc0(sizeof(FmgrInfo));
4204  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4205  fmgr_info(foid, finfo);
4206  fmgr_info_set_expr(NULL, finfo);
4207  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4208  collid, NULL, NULL);
4209 
4210  /* left arg */
4211  scratch.opcode = EEOP_INNER_VAR;
4212  scratch.d.var.attnum = attno - 1;
4213  scratch.d.var.vartype = latt->atttypid;
4214  scratch.resvalue = &fcinfo->args[0].value;
4215  scratch.resnull = &fcinfo->args[0].isnull;
4216  ExprEvalPushStep(state, &scratch);
4217 
4218  /* right arg */
4219  scratch.opcode = EEOP_OUTER_VAR;
4220  scratch.d.var.attnum = attno - 1;
4221  scratch.d.var.vartype = ratt->atttypid;
4222  scratch.resvalue = &fcinfo->args[1].value;
4223  scratch.resnull = &fcinfo->args[1].isnull;
4224  ExprEvalPushStep(state, &scratch);
4225 
4226  /* evaluate distinctness */
4227  scratch.opcode = EEOP_NOT_DISTINCT;
4228  scratch.d.func.finfo = finfo;
4229  scratch.d.func.fcinfo_data = fcinfo;
4230  scratch.d.func.fn_addr = finfo->fn_addr;
4231  scratch.d.func.nargs = 2;
4232  scratch.resvalue = &state->resvalue;
4233  scratch.resnull = &state->resnull;
4234  ExprEvalPushStep(state, &scratch);
4235 
4236  /* then emit EEOP_QUAL to detect if result is false (or null) */
4237  scratch.opcode = EEOP_QUAL;
4238  scratch.d.qualexpr.jumpdone = -1;
4239  scratch.resvalue = &state->resvalue;
4240  scratch.resnull = &state->resnull;
4241  ExprEvalPushStep(state, &scratch);
4242  adjust_jumps = lappend_int(adjust_jumps,
4243  state->steps_len - 1);
4244  }
4245 
4246  /* adjust jump targets */
4247  foreach(lc, adjust_jumps)
4248  {
4249  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4250 
4251  Assert(as->opcode == EEOP_QUAL);
4252  Assert(as->d.qualexpr.jumpdone == -1);
4253  as->d.qualexpr.jumpdone = state->steps_len;
4254  }
4255 
4256  scratch.resvalue = NULL;
4257  scratch.resnull = NULL;
4258  scratch.opcode = EEOP_DONE;
4259  ExprEvalPushStep(state, &scratch);
4260 
4262 
4263  return state;
4264 }
4265 
4266 /*
4267  * Build equality expression that can be evaluated using ExecQual(), returning
4268  * true if the expression context's inner/outer tuples are equal. Datums in
4269  * the inner/outer slots are assumed to be in the same order and quantity as
4270  * the 'eqfunctions' parameter. NULLs are treated as equal.
4271  *
4272  * desc: tuple descriptor of the to-be-compared tuples
4273  * lops: the slot ops for the inner tuple slots
4274  * rops: the slot ops for the outer tuple slots
4275  * eqFunctions: array of function oids of the equality functions to use
4276  * this must be the same length as the 'param_exprs' list.
4277  * collations: collation Oids to use for equality comparison. Must be the
4278  * same length as the 'param_exprs' list.
4279  * parent: parent executor node
4280  */
4281 ExprState *
4283  const TupleTableSlotOps *lops,
4284  const TupleTableSlotOps *rops,
4285  const Oid *eqfunctions,
4286  const Oid *collations,
4287  const List *param_exprs,
4288  PlanState *parent)
4289 {
4291  ExprEvalStep scratch = {0};
4292  int maxatt = list_length(param_exprs);
4293  List *adjust_jumps = NIL;
4294  ListCell *lc;
4295 
4296  state->expr = NULL;
4297  state->flags = EEO_FLAG_IS_QUAL;
4298  state->parent = parent;
4299 
4300  scratch.resvalue = &state->resvalue;
4301  scratch.resnull = &state->resnull;
4302 
4303  /* push deform steps */
4304  scratch.opcode = EEOP_INNER_FETCHSOME;
4305  scratch.d.fetch.last_var = maxatt;
4306  scratch.d.fetch.fixed = false;
4307  scratch.d.fetch.known_desc = desc;
4308  scratch.d.fetch.kind = lops;
4309  if (ExecComputeSlotInfo(state, &scratch))
4310  ExprEvalPushStep(state, &scratch);
4311 
4312  scratch.opcode = EEOP_OUTER_FETCHSOME;
4313  scratch.d.fetch.last_var = maxatt;
4314  scratch.d.fetch.fixed = false;
4315  scratch.d.fetch.known_desc = desc;
4316  scratch.d.fetch.kind = rops;
4317  if (ExecComputeSlotInfo(state, &scratch))
4318  ExprEvalPushStep(state, &scratch);
4319 
4320  for (int attno = 0; attno < maxatt; attno++)
4321  {
4322  Form_pg_attribute att = TupleDescAttr(desc, attno);
4323  Oid foid = eqfunctions[attno];
4324  Oid collid = collations[attno];
4325  FmgrInfo *finfo;
4326  FunctionCallInfo fcinfo;
4327  AclResult aclresult;
4328 
4329  /* Check permission to call function */
4330  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4331  if (aclresult != ACLCHECK_OK)
4332  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4333 
4335 
4336  /* Set up the primary fmgr lookup information */
4337  finfo = palloc0(sizeof(FmgrInfo));
4338  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4339  fmgr_info(foid, finfo);
4340  fmgr_info_set_expr(NULL, finfo);
4341  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4342  collid, NULL, NULL);
4343 
4344  /* left arg */
4345  scratch.opcode = EEOP_INNER_VAR;
4346  scratch.d.var.attnum = attno;
4347  scratch.d.var.vartype = att->atttypid;
4348  scratch.resvalue = &fcinfo->args[0].value;
4349  scratch.resnull = &fcinfo->args[0].isnull;
4350  ExprEvalPushStep(state, &scratch);
4351 
4352  /* right arg */
4353  scratch.opcode = EEOP_OUTER_VAR;
4354  scratch.d.var.attnum = attno;
4355  scratch.d.var.vartype = att->atttypid;
4356  scratch.resvalue = &fcinfo->args[1].value;
4357  scratch.resnull = &fcinfo->args[1].isnull;
4358  ExprEvalPushStep(state, &scratch);
4359 
4360  /* evaluate distinctness */
4361  scratch.opcode = EEOP_NOT_DISTINCT;
4362  scratch.d.func.finfo = finfo;
4363  scratch.d.func.fcinfo_data = fcinfo;
4364  scratch.d.func.fn_addr = finfo->fn_addr;
4365  scratch.d.func.nargs = 2;
4366  scratch.resvalue = &state->resvalue;
4367  scratch.resnull = &state->resnull;
4368  ExprEvalPushStep(state, &scratch);
4369 
4370  /* then emit EEOP_QUAL to detect if result is false (or null) */
4371  scratch.opcode = EEOP_QUAL;
4372  scratch.d.qualexpr.jumpdone = -1;
4373  scratch.resvalue = &state->resvalue;
4374  scratch.resnull = &state->resnull;
4375  ExprEvalPushStep(state, &scratch);
4376  adjust_jumps = lappend_int(adjust_jumps,
4377  state->steps_len - 1);
4378  }
4379 
4380  /* adjust jump targets */
4381  foreach(lc, adjust_jumps)
4382  {
4383  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4384 
4385  Assert(as->opcode == EEOP_QUAL);
4386  Assert(as->d.qualexpr.jumpdone == -1);
4387  as->d.qualexpr.jumpdone = state->steps_len;
4388  }
4389 
4390  scratch.resvalue = NULL;
4391  scratch.resnull = NULL;
4392  scratch.opcode = EEOP_DONE;
4393  ExprEvalPushStep(state, &scratch);
4394 
4396 
4397  return state;
4398 }
4399 
4400 /*
4401  * Push steps to evaluate a JsonExpr and its various subsidiary expressions.
4402  */
4403 static void
4405  Datum *resv, bool *resnull,
4406  ExprEvalStep *scratch)
4407 {
4408  JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
4409  ListCell *argexprlc;
4410  ListCell *argnamelc;
4411  List *jumps_return_null = NIL;
4412  List *jumps_to_end = NIL;
4413  ListCell *lc;
4414  ErrorSaveContext *escontext;
4415  bool returning_domain =
4416  get_typtype(jsexpr->returning->typid) == TYPTYPE_DOMAIN;
4417 
4418  Assert(jsexpr->on_error != NULL);
4419 
4420  jsestate->jsexpr = jsexpr;
4421 
4422  /*
4423  * Evaluate formatted_expr storing the result into
4424  * jsestate->formatted_expr.
4425  */
4427  &jsestate->formatted_expr.value,
4428  &jsestate->formatted_expr.isnull);
4429 
4430  /* JUMP to return NULL if formatted_expr evaluates to NULL */
4431  jumps_return_null = lappend_int(jumps_return_null, state->steps_len);
4432  scratch->opcode = EEOP_JUMP_IF_NULL;
4433  scratch->resnull = &jsestate->formatted_expr.isnull;
4434  scratch->d.jump.jumpdone = -1; /* set below */
4435  ExprEvalPushStep(state, scratch);
4436 
4437  /*
4438  * Evaluate pathspec expression storing the result into
4439  * jsestate->pathspec.
4440  */
4441  ExecInitExprRec((Expr *) jsexpr->path_spec, state,
4442  &jsestate->pathspec.value,
4443  &jsestate->pathspec.isnull);
4444 
4445  /* JUMP to return NULL if path_spec evaluates to NULL */
4446  jumps_return_null = lappend_int(jumps_return_null, state->steps_len);
4447  scratch->opcode = EEOP_JUMP_IF_NULL;
4448  scratch->resnull = &jsestate->pathspec.isnull;
4449  scratch->d.jump.jumpdone = -1; /* set below */
4450  ExprEvalPushStep(state, scratch);
4451 
4452  /* Steps to compute PASSING args. */
4453  jsestate->args = NIL;
4454  forboth(argexprlc, jsexpr->passing_values,
4455  argnamelc, jsexpr->passing_names)
4456  {
4457  Expr *argexpr = (Expr *) lfirst(argexprlc);
4458  String *argname = lfirst_node(String, argnamelc);
4459  JsonPathVariable *var = palloc(sizeof(*var));
4460 
4461  var->name = argname->sval;
4462  var->namelen = strlen(var->name);
4463  var->typid = exprType((Node *) argexpr);
4464  var->typmod = exprTypmod((Node *) argexpr);
4465 
4466  ExecInitExprRec((Expr *) argexpr, state, &var->value, &var->isnull);
4467 
4468  jsestate->args = lappend(jsestate->args, var);
4469  }
4470 
4471  /* Step for jsonpath evaluation; see ExecEvalJsonExprPath(). */
4472  scratch->opcode = EEOP_JSONEXPR_PATH;
4473  scratch->resvalue = resv;
4474  scratch->resnull = resnull;
4475  scratch->d.jsonexpr.jsestate = jsestate;
4476  ExprEvalPushStep(state, scratch);
4477 
4478  /*
4479  * Step to return NULL after jumping to skip the EEOP_JSONEXPR_PATH step
4480  * when either formatted_expr or pathspec is NULL. Adjust jump target
4481  * addresses of JUMPs that we added above.
4482  */
4483  foreach(lc, jumps_return_null)
4484  {
4485  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4486 
4487  as->d.jump.jumpdone = state->steps_len;
4488  }
4489  scratch->opcode = EEOP_CONST;
4490  scratch->resvalue = resv;
4491  scratch->resnull = resnull;
4492  scratch->d.constval.value = (Datum) 0;
4493  scratch->d.constval.isnull = true;
4494  ExprEvalPushStep(state, scratch);
4495 
4496  escontext = jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR ?
4497  &jsestate->escontext : NULL;
4498 
4499  /*
4500  * To handle coercion errors softly, use the following ErrorSaveContext to
4501  * pass to ExecInitExprRec() when initializing the coercion expressions
4502  * and in the EEOP_JSONEXPR_COERCION step.
4503  */
4504  jsestate->escontext.type = T_ErrorSaveContext;
4505 
4506  /*
4507  * Steps to coerce the result value computed by EEOP_JSONEXPR_PATH or the
4508  * NULL returned on NULL input as described above.
4509  */
4510  jsestate->jump_eval_coercion = -1;
4511  if (jsexpr->use_json_coercion)
4512  {
4513  jsestate->jump_eval_coercion = state->steps_len;
4514 
4515  ExecInitJsonCoercion(state, jsexpr->returning, escontext,
4516  jsexpr->omit_quotes,
4517  jsexpr->op == JSON_EXISTS_OP,
4518  resv, resnull);
4519  }
4520  else if (jsexpr->use_io_coercion)
4521  {
4522  /*
4523  * Here we only need to initialize the FunctionCallInfo for the target
4524  * type's input function, which is called by ExecEvalJsonExprPath()
4525  * itself, so no additional step is necessary.
4526  */
4527  Oid typinput;
4528  Oid typioparam;
4529  FmgrInfo *finfo;
4530  FunctionCallInfo fcinfo;
4531 
4532  getTypeInputInfo(jsexpr->returning->typid, &typinput, &typioparam);
4533  finfo = palloc0(sizeof(FmgrInfo));
4534  fcinfo = palloc0(SizeForFunctionCallInfo(3));
4535  fmgr_info(typinput, finfo);
4536  fmgr_info_set_expr((Node *) jsexpr->returning, finfo);
4537  InitFunctionCallInfoData(*fcinfo, finfo, 3, InvalidOid, NULL, NULL);
4538 
4539  /*
4540  * We can preload the second and third arguments for the input
4541  * function, since they're constants.
4542  */
4543  fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
4544  fcinfo->args[1].isnull = false;
4545  fcinfo->args[2].value = Int32GetDatum(jsexpr->returning->typmod);
4546  fcinfo->args[2].isnull = false;
4547  fcinfo->context = (Node *) escontext;
4548 
4549  jsestate->input_fcinfo = fcinfo;
4550  }
4551 
4552  /*
4553  * Add a special step, if needed, to check if the coercion evaluation ran
4554  * into an error but was not thrown because the ON ERROR behavior is not
4555  * ERROR. It will set jsestate->error if an error did occur.
4556  */
4557  if (jsestate->jump_eval_coercion >= 0 && escontext != NULL)
4558  {
4560  scratch->d.jsonexpr.jsestate = jsestate;
4561  ExprEvalPushStep(state, scratch);
4562  }
4563 
4564  jsestate->jump_empty = jsestate->jump_error = -1;
4565 
4566  /*
4567  * Step to check jsestate->error and return the ON ERROR expression if
4568  * there is one. This handles both the errors that occur during jsonpath
4569  * evaluation in EEOP_JSONEXPR_PATH and subsequent coercion evaluation.
4570  *
4571  * Speed up common cases by avoiding extra steps for a NULL-valued ON
4572  * ERROR expression unless RETURNING a domain type, where constraints must
4573  * be checked. ExecEvalJsonExprPath() already returns NULL on error,
4574  * making additional steps unnecessary in typical scenarios. Note that the
4575  * default ON ERROR behavior for JSON_VALUE() and JSON_QUERY() is to
4576  * return NULL.
4577  */
4578  if (jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR &&
4579  (!(IsA(jsexpr->on_error->expr, Const) &&
4580  ((Const *) jsexpr->on_error->expr)->constisnull) ||
4581  returning_domain))
4582  {
4583  ErrorSaveContext *saved_escontext;
4584 
4585  jsestate->jump_error = state->steps_len;
4586 
4587  /* JUMP to end if false, that is, skip the ON ERROR expression. */
4588  jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4589  scratch->opcode = EEOP_JUMP_IF_NOT_TRUE;
4590  scratch->resvalue = &jsestate->error.value;
4591  scratch->resnull = &jsestate->error.isnull;
4592  scratch->d.jump.jumpdone = -1; /* set below */
4593  ExprEvalPushStep(state, scratch);
4594 
4595  /*
4596  * Steps to evaluate the ON ERROR expression; handle errors softly to
4597  * rethrow them in COERCION_FINISH step that will be added later.
4598  */
4599  saved_escontext = state->escontext;
4600  state->escontext = escontext;
4601  ExecInitExprRec((Expr *) jsexpr->on_error->expr,
4602  state, resv, resnull);
4603  state->escontext = saved_escontext;
4604 
4605  /* Step to coerce the ON ERROR expression if needed */
4606  if (jsexpr->on_error->coerce)
4607  ExecInitJsonCoercion(state, jsexpr->returning, escontext,
4608  jsexpr->omit_quotes, false,
4609  resv, resnull);
4610 
4611  /*
4612  * Add a COERCION_FINISH step to check for errors that may occur when
4613  * coercing and rethrow them.
4614  */
4615  if (jsexpr->on_error->coerce ||
4616  IsA(jsexpr->on_error->expr, CoerceViaIO) ||
4617  IsA(jsexpr->on_error->expr, CoerceToDomain))
4618  {
4620  scratch->resvalue = resv;
4621  scratch->resnull = resnull;
4622  scratch->d.jsonexpr.jsestate = jsestate;
4623  ExprEvalPushStep(state, scratch);
4624  }
4625 
4626  /* JUMP to end to skip the ON EMPTY steps added below. */
4627  jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4628  scratch->opcode = EEOP_JUMP;
4629  scratch->d.jump.jumpdone = -1;
4630  ExprEvalPushStep(state, scratch);
4631  }
4632 
4633  /*
4634  * Step to check jsestate->empty and return the ON EMPTY expression if
4635  * there is one.
4636  *
4637  * See the comment above for details on the optimization for NULL-valued
4638  * expressions.
4639  */
4640  if (jsexpr->on_empty != NULL &&
4641  jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR &&
4642  (!(IsA(jsexpr->on_empty->expr, Const) &&
4643  ((Const *) jsexpr->on_empty->expr)->constisnull) ||
4644  returning_domain))
4645  {
4646  ErrorSaveContext *saved_escontext;
4647 
4648  jsestate->jump_empty = state->steps_len;
4649 
4650  /* JUMP to end if false, that is, skip the ON EMPTY expression. */
4651  jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4652  scratch->opcode = EEOP_JUMP_IF_NOT_TRUE;
4653  scratch->resvalue = &jsestate->empty.value;
4654  scratch->resnull = &jsestate->empty.isnull;
4655  scratch->d.jump.jumpdone = -1; /* set below */
4656  ExprEvalPushStep(state, scratch);
4657 
4658  /*
4659  * Steps to evaluate the ON EMPTY expression; handle errors softly to
4660  * rethrow them in COERCION_FINISH step that will be added later.
4661  */
4662  saved_escontext = state->escontext;
4663  state->escontext = escontext;
4664  ExecInitExprRec((Expr *) jsexpr->on_empty->expr,
4665  state, resv, resnull);
4666  state->escontext = saved_escontext;
4667 
4668  /* Step to coerce the ON EMPTY expression if needed */
4669  if (jsexpr->on_empty->coerce)
4670  ExecInitJsonCoercion(state, jsexpr->returning, escontext,
4671  jsexpr->omit_quotes, false,
4672  resv, resnull);
4673 
4674  /*
4675  * Add a COERCION_FINISH step to check for errors that may occur when
4676  * coercing and rethrow them.
4677  */
4678  if (jsexpr->on_empty->coerce ||
4679  IsA(jsexpr->on_empty->expr, CoerceViaIO) ||
4680  IsA(jsexpr->on_empty->expr, CoerceToDomain))
4681  {
4682 
4684  scratch->resvalue = resv;
4685  scratch->resnull = resnull;
4686  scratch->d.jsonexpr.jsestate = jsestate;
4687  ExprEvalPushStep(state, scratch);
4688  }
4689  }
4690 
4691  foreach(lc, jumps_to_end)
4692  {
4693  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4694 
4695  as->d.jump.jumpdone = state->steps_len;
4696  }
4697 
4698  jsestate->jump_end = state->steps_len;
4699 }
4700 
4701 /*
4702  * Initialize a EEOP_JSONEXPR_COERCION step to coerce the value given in resv
4703  * to the given RETURNING type.
4704  */
4705 static void
4707  ErrorSaveContext *escontext, bool omit_quotes,
4708  bool exists_coerce,
4709  Datum *resv, bool *resnull)
4710 {
4711  ExprEvalStep scratch = {0};
4712 
4713  /* For json_populate_type() */
4714  scratch.opcode = EEOP_JSONEXPR_COERCION;
4715  scratch.resvalue = resv;
4716  scratch.resnull = resnull;
4717  scratch.d.jsonexpr_coercion.targettype = returning->typid;
4718  scratch.d.jsonexpr_coercion.targettypmod = returning->typmod;
4719  scratch.d.jsonexpr_coercion.json_coercion_cache = NULL;
4720  scratch.d.jsonexpr_coercion.escontext = escontext;
4721  scratch.d.jsonexpr_coercion.omit_quotes = omit_quotes;
4722  scratch.d.jsonexpr_coercion.exists_coerce = exists_coerce;
4723  scratch.d.jsonexpr_coercion.exists_cast_to_int = exists_coerce &&
4724  getBaseType(returning->typid) == INT4OID;
4725  scratch.d.jsonexpr_coercion.exists_check_domain = exists_coerce &&
4726  DomainHasConstraints(returning->typid);
4727  ExprEvalPushStep(state, &scratch);
4728 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2703
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3891
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
static Datum values[MAXATTR]
Definition: bootstrap.c:150
unsigned int uint32
Definition: c.h:509
#define MAXALIGN(LEN)
Definition: c.h:814
#define Max(x, y)
Definition: c.h:1001
#define Assert(condition)
Definition: c.h:861
unsigned char bool
Definition: c.h:459
#define OidIsValid(objectId)
Definition: c.h:778
Oid collid
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1180
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
void ExecReadyInterpretedExpr(ExprState *state)
static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:3373
static void ExecInitSubPlanExpr(SubPlan *subplan, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:2717
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:743
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:850
static void ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info)
Definition: execExpr.c:2793
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:897
static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate, ExprEvalStep *scratch, FunctionCallInfo fcinfo, AggStatePerTrans pertrans, int transno, int setno, int setoff, bool ishash, bool nullcheck)
Definition: execExpr.c:3867
ExprState * ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
Definition: execExpr.c:175
static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
Definition: execExpr.c:3021
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:330
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2582
ProjectionInfo * ExecBuildUpdateProjection(List *targetList, bool evalTargetList, List *targetColnos, TupleDesc relDesc, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent)
Definition: execExpr.c:525
struct ExprSetupInfo ExprSetupInfo
ExprState * ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
Definition: execExpr.c:3528
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
static bool isAssignmentIndirectionExpr(Expr *expr)
Definition: execExpr.c:3336
static void ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:3094
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:794
static bool expr_setup_walker(Node *node, ExprSetupInfo *info)
Definition: execExpr.c:2859
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:138
static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning, ErrorSaveContext *escontext, bool omit_quotes, bool exists_coerce, Datum *resv, bool *resnull)
Definition: execExpr.c:4706
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition: execExpr.c:310
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2923
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:771
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:365
ExprState * ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, const AttrNumber *keyColIdx, const Oid *eqfunctions, const Oid *collations, PlanState *parent)
Definition: execExpr.c:4125
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition: execExpr.c:817
static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, Oid inputcollid, ExprState *state)
Definition: execExpr.c:2608
static void ExecCreateExprSetupSteps(ExprState *state, Node *node)
Definition: execExpr.c:2777
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:880
ExprState * ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, const Oid *hashfunc_oids, const List *collations, const List *hash_exprs, const bool *opstrict, PlanState *parent, uint32 init_value, bool keep_nulls)
Definition: execExpr.c:3992
static void ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, Datum *resv, bool *resnull, ExprEvalStep *scratch)
Definition: execExpr.c:4404
ExprState * ExecBuildParamSetEqual(TupleDesc desc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, const Oid *eqfunctions, const Oid *collations, const List *param_exprs, PlanState *parent)
Definition: execExpr.c:4282
ExprEvalOp
Definition: execExpr.h:67
@ EEOP_ASSIGN_TMP
Definition: execExpr.h:99
@ EEOP_SUBPLAN
Definition: execExpr.h:259
@ EEOP_CONVERT_ROWTYPE
Definition: execExpr.h:246
@ EEOP_FUNCEXPR_STRICT_FUSAGE
Definition: execExpr.h:114
@ EEOP_ARRAYEXPR
Definition: execExpr.h:181
@ EEOP_JSONEXPR_PATH
Definition: execExpr.h:252
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:176
@ EEOP_DOMAIN_TESTVAL
Definition: execExpr.h:230
@ EEOP_PARAM_EXTERN
Definition: execExpr.h:161
@ EEOP_HASHDATUM_NEXT32_STRICT
Definition: execExpr.h:243
@ EEOP_IOCOERCE_SAFE
Definition: execExpr.h:174
@ EEOP_BOOL_AND_STEP
Definition: execExpr.h:123
@ EEOP_WHOLEROW
Definition: execExpr.h:87
@ EEOP_JSONEXPR_COERCION_FINISH
Definition: execExpr.h:254
@ EEOP_HASHDATUM_FIRST_STRICT
Definition: execExpr.h:241
@ EEOP_AGGREF
Definition: execExpr.h:255
@ EEOP_INNER_VAR
Definition: execExpr.h:77
@ EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
Definition: execExpr.h:266
@ EEOP_HASHDATUM_NEXT32
Definition: execExpr.h:242
@ EEOP_ROWCOMPARE_FINAL
Definition: execExpr.h:192
@ EEOP_AGG_STRICT_DESERIALIZE
Definition: execExpr.h:262
@ EEOP_IOCOERCE
Definition: execExpr.h:173
@ EEOP_GROUPING_FUNC
Definition: execExpr.h:256
@ EEOP_DOMAIN_CHECK
Definition: execExpr.h:236
@ EEOP_BOOLTEST_IS_NOT_FALSE
Definition: execExpr.h:157
@ EEOP_PARAM_SET
Definition: execExpr.h:164
@ EEOP_NEXTVALUEEXPR
Definition: execExpr.h:180
@ EEOP_DONE
Definition: execExpr.h:69
@ EEOP_AGG_PLAIN_TRANS_BYREF
Definition: execExpr.h:272
@ EEOP_QUAL
Definition: execExpr.h:135
@ EEOP_AGG_PRESORTED_DISTINCT_MULTI
Definition: execExpr.h:274
@ EEOP_AGG_PLAIN_TRANS_BYVAL
Definition: execExpr.h:269
@ EEOP_SCAN_VAR
Definition: execExpr.h:79
@ EEOP_BOOL_NOT_STEP
Definition: execExpr.h:132
@ EEOP_ASSIGN_SCAN_VAR
Definition: execExpr.h:96
@ EEOP_SCAN_SYSVAR
Definition: execExpr.h:84
@ EEOP_SCALARARRAYOP
Definition: execExpr.h:247
@ EEOP_DOMAIN_NOTNULL
Definition: execExpr.h:233
@ EEOP_WINDOW_FUNC
Definition: execExpr.h:257
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_NULLTEST_ROWISNOTNULL
Definition: execExpr.h:151
@ EEOP_ASSIGN_OUTER_VAR
Definition: execExpr.h:95
@ EEOP_ROW
Definition: execExpr.h:183
@ EEOP_MAKE_READONLY
Definition: execExpr.h:170
@ EEOP_FIELDSTORE_FORM
Definition: execExpr.h:211
@ EEOP_SBSREF_SUBSCRIPTS
Definition: execExpr.h:214
@ EEOP_SBSREF_FETCH
Definition: execExpr.h:227
@ EEOP_FUNCEXPR_STRICT
Definition: execExpr.h:112
@ EEOP_NULLIF
Definition: execExpr.h:177
@ EEOP_CURRENTOFEXPR
Definition: execExpr.h:179
@ EEOP_INNER_SYSVAR
Definition: execExpr.h:82
@ EEOP_ASSIGN_TMP_MAKE_RO
Definition: execExpr.h:101
@ EEOP_CONST
Definition: execExpr.h:104
@ EEOP_BOOL_OR_STEP_LAST
Definition: execExpr.h:129
@ EEOP_JSONEXPR_COERCION
Definition: execExpr.h:253
@ EEOP_BOOL_OR_STEP_FIRST
Definition: execExpr.h:127
@ EEOP_XMLEXPR
Definition: execExpr.h:249
@ EEOP_AGG_STRICT_INPUT_CHECK_NULLS
Definition: execExpr.h:265
@ EEOP_SBSREF_ASSIGN
Definition: execExpr.h:224
@ EEOP_OUTER_SYSVAR
Definition: execExpr.h:83
@ EEOP_ASSIGN_INNER_VAR
Definition: execExpr.h:94
@ EEOP_BOOL_OR_STEP
Definition: execExpr.h:128
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:73
@ EEOP_AGG_STRICT_INPUT_CHECK_ARGS
Definition: execExpr.h:264
@ EEOP_NULLTEST_ROWISNULL
Definition: execExpr.h:150
@ EEOP_BOOLTEST_IS_TRUE
Definition: execExpr.h:154
@ EEOP_FUNCEXPR
Definition: execExpr.h:111
@ EEOP_NULLTEST_ISNOTNULL
Definition: execExpr.h:147
@ EEOP_ROWCOMPARE_STEP
Definition: execExpr.h:189
@ EEOP_MERGE_SUPPORT_FUNC
Definition: execExpr.h:258
@ EEOP_AGG_DESERIALIZE
Definition: execExpr.h:263
@ EEOP_HASHDATUM_FIRST
Definition: execExpr.h:240
@ EEOP_DISTINCT
Definition: execExpr.h:175
@ EEOP_JUMP_IF_NOT_TRUE
Definition: execExpr.h:143
@ EEOP_FUNCEXPR_FUSAGE
Definition: execExpr.h:113
@ EEOP_AGG_PRESORTED_DISTINCT_SINGLE
Definition: execExpr.h:273
@ EEOP_BOOL_AND_STEP_FIRST
Definition: execExpr.h:122
@ EEOP_JUMP
Definition: execExpr.h:138
@ EEOP_BOOL_AND_STEP_LAST
Definition: execExpr.h:124
@ EEOP_AGG_ORDERED_TRANS_DATUM
Definition: execExpr.h:275
@ EEOP_SBSREF_OLD
Definition: execExpr.h:221
@ EEOP_SQLVALUEFUNCTION
Definition: execExpr.h:178
@ EEOP_HASHDATUM_SET_INITVAL
Definition: execExpr.h:239
@ EEOP_JUMP_IF_NOT_NULL
Definition: execExpr.h:142
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
Definition: execExpr.h:271
@ EEOP_FIELDSTORE_DEFORM
Definition: execExpr.h:204
@ EEOP_BOOLTEST_IS_FALSE
Definition: execExpr.h:156
@ EEOP_BOOLTEST_IS_NOT_TRUE
Definition: execExpr.h:155
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
Definition: execExpr.h:267
@ EEOP_PARAM_EXEC
Definition: execExpr.h:160
@ EEOP_JSON_CONSTRUCTOR
Definition: execExpr.h:250
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
Definition: execExpr.h:268
@ EEOP_NULLTEST_ISNULL
Definition: execExpr.h:146
@ EEOP_MINMAX
Definition: execExpr.h:195
@ EEOP_JUMP_IF_NULL
Definition: execExpr.h:141
@ EEOP_ARRAYCOERCE
Definition: execExpr.h:182
@ EEOP_FIELDSELECT
Definition: execExpr.h:198
@ EEOP_CASE_TESTVAL
Definition: execExpr.h:167
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
Definition: execExpr.h:270
@ EEOP_HASHED_SCALARARRAYOP
Definition: execExpr.h:248
@ EEOP_OUTER_VAR
Definition: execExpr.h:78
@ EEOP_AGG_ORDERED_TRANS_TUPLE
Definition: execExpr.h:276
@ EEOP_SCAN_FETCHSOME
Definition: execExpr.h:74
@ EEOP_IS_JSON
Definition: execExpr.h:251
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
Definition: execJunk.c:60
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2158
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2117
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1918
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:2084
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:493
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:502
int executor_errposition(EState *estate, int location)
Definition: execUtils.c:870
#define outerPlanState(node)
Definition: execnodes.h:1219
#define innerPlanState(node)
Definition: execnodes.h:1218
@ DOM_CONSTRAINT_CHECK
Definition: execnodes.h:1008
@ DOM_CONSTRAINT_NOTNULL
Definition: execnodes.h:1007
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:76
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:359
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
bool jit_compile_expr(struct ExprState *state)
Definition: jit.c:151
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5976
JsonTypeCategory
Definition: jsonfuncs.h:69
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:136
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2759
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:796
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2874
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1608
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2197
char get_typtype(Oid typid)
Definition: lsyscache.c:2629
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3130
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2521
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:339
Expr * make_ands_explicit(List *andclauses)
Definition: makefuncs.c:726
void * palloc0(Size size)
Definition: mcxt.c:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * palloc(Size size)
Definition: mcxt.c:1317
Oid GetUserId(void)
Definition: miscinit.c:514
#define BTORDER_PROC
Definition: nbtree.h:707
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1380
#define expression_tree_walker(n, w, c)
Definition: nodeFuncs.h:153
SubPlanState * ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
Definition: nodeSubplan.c:819
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:385
@ CMD_MERGE
Definition: nodes.h:269
@ AGG_HASHED
Definition: nodes.h:356
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
@ OBJECT_FUNCTION
Definition: parsenodes.h:2276
#define ACL_EXECUTE
Definition: parsenodes.h:83
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
void * arg
#define FUNC_MAX_ARGS
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define foreach_current_index(var_or_cell)
Definition: pg_list.h:403
#define lfirst_int(lc)
Definition: pg_list.h:173
#define foreach_ptr(type, var, lst)
Definition: pg_list.h:469
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5)
Definition: pg_list.h:588
#define lfirst_oid(lc)
Definition: pg_list.h:174
#define foreach_int(var, lst)
Definition: pg_list.h:470
#define bail(...)
Definition: pg_regress.c:168
Expr * expression_planner(Expr *expr)
Definition: planner.c:6687
void check_stack_depth(void)
Definition: postgres.c:3564
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:232
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
e
Definition: preproc-init.c:82
@ IS_NOT_TRUE
Definition: primnodes.h:1972
@ IS_NOT_FALSE
Definition: primnodes.h:1972
@ IS_NOT_UNKNOWN
Definition: primnodes.h:1972
@ IS_TRUE
Definition: primnodes.h:1972
@ IS_UNKNOWN
Definition: primnodes.h:1972
@ IS_FALSE
Definition: primnodes.h:1972
@ MULTIEXPR_SUBLINK
Definition: primnodes.h:1002
@ JS_FORMAT_JSONB
Definition: primnodes.h:1640
@ AND_EXPR
Definition: primnodes.h:931
@ OR_EXPR
Definition: primnodes.h:931
@ NOT_EXPR
Definition: primnodes.h:931
@ PARAM_EXTERN
Definition: primnodes.h:367
@ PARAM_EXEC
Definition: primnodes.h:368
@ JSON_BEHAVIOR_ERROR
Definition: primnodes.h:1762
@ JSON_TABLE_OP
Definition: primnodes.h:1801
@ JSON_EXISTS_OP
Definition: primnodes.h:1798
@ IS_NULL
Definition: primnodes.h:1948
@ IS_NOT_NULL
Definition: primnodes.h:1948
#define OUTER_VAR
Definition: primnodes.h:237
@ JSCTOR_JSON_SERIALIZE
Definition: primnodes.h:1692
@ JSCTOR_JSON_PARSE
Definition: primnodes.h:1690
@ JSCTOR_JSON_SCALAR
Definition: primnodes.h:1691
#define INNER_VAR
Definition: primnodes.h:236
MemoryContextSwitchTo(old_ctx)
TupleTableSlot * sortslot
Definition: nodeAgg.h:141
Aggref * aggref
Definition: nodeAgg.h:44
FmgrInfo deserialfn
Definition: nodeAgg.h:92
FunctionCallInfo deserialfn_fcinfo
Definition: nodeAgg.h:175
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:170
ScanState ss
Definition: execnodes.h:2493
List * aggs
Definition: execnodes.h:2494
AggStatePerTrans pertrans
Definition: execnodes.h:2503
AggStrategy aggstrategy
Definition: execnodes.h:2497
int numtrans
Definition: execnodes.h:2496
ExprContext * hashcontext
Definition: execnodes.h:2504
AggSplit aggsplit
Definition: execnodes.h:2498
int num_hashes
Definition: execnodes.h:2534
int maxsets
Definition: execnodes.h:2523
ExprContext ** aggcontexts
Definition: execnodes.h:2505
Definition: plannodes.h: