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->raw_expr != NULL);
2311  ExecInitExprRec(jve->raw_expr, state, resv, resnull);
2312  Assert(jve->formatted_expr != NULL);
2313  ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
2314  break;
2315  }
2316 
2317  case T_JsonConstructorExpr:
2318  {
2319  JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
2320  List *args = ctor->args;
2321  ListCell *lc;
2322  int nargs = list_length(args);
2323  int argno = 0;
2324 
2325  if (ctor->func)
2326  {
2327  ExecInitExprRec(ctor->func, state, resv, resnull);
2328  }
2329  else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) ||
2330  ctor->type == JSCTOR_JSON_SERIALIZE)
2331  {
2332  /* Use the value of the first argument as result */
2333  ExecInitExprRec(linitial(args), state, resv, resnull);
2334  }
2335  else
2336  {
2337  JsonConstructorExprState *jcstate;
2338 
2339  jcstate = palloc0(sizeof(JsonConstructorExprState));
2340 
2341  scratch.opcode = EEOP_JSON_CONSTRUCTOR;
2342  scratch.d.json_constructor.jcstate = jcstate;
2343 
2344  jcstate->constructor = ctor;
2345  jcstate->arg_values = (Datum *) palloc(sizeof(Datum) * nargs);
2346  jcstate->arg_nulls = (bool *) palloc(sizeof(bool) * nargs);
2347  jcstate->arg_types = (Oid *) palloc(sizeof(Oid) * nargs);
2348  jcstate->nargs = nargs;
2349 
2350  foreach(lc, args)
2351  {
2352  Expr *arg = (Expr *) lfirst(lc);
2353 
2354  jcstate->arg_types[argno] = exprType((Node *) arg);
2355 
2356  if (IsA(arg, Const))
2357  {
2358  /* Don't evaluate const arguments every round */
2359  Const *con = (Const *) arg;
2360 
2361  jcstate->arg_values[argno] = con->constvalue;
2362  jcstate->arg_nulls[argno] = con->constisnull;
2363  }
2364  else
2365  {
2367  &jcstate->arg_values[argno],
2368  &jcstate->arg_nulls[argno]);
2369  }
2370  argno++;
2371  }
2372 
2373  /* prepare type cache for datum_to_json[b]() */
2374  if (ctor->type == JSCTOR_JSON_SCALAR)
2375  {
2376  bool is_jsonb =
2378 
2379  jcstate->arg_type_cache =
2380  palloc(sizeof(*jcstate->arg_type_cache) * nargs);
2381 
2382  for (int i = 0; i < nargs; i++)
2383  {
2384  JsonTypeCategory category;
2385  Oid outfuncid;
2386  Oid typid = jcstate->arg_types[i];
2387 
2388  json_categorize_type(typid, is_jsonb,
2389  &category, &outfuncid);
2390 
2391  jcstate->arg_type_cache[i].outfuncid = outfuncid;
2392  jcstate->arg_type_cache[i].category = (int) category;
2393  }
2394  }
2395 
2396  ExprEvalPushStep(state, &scratch);
2397  }
2398 
2399  if (ctor->coercion)
2400  {
2401  Datum *innermost_caseval = state->innermost_caseval;
2402  bool *innermost_isnull = state->innermost_casenull;
2403 
2404  state->innermost_caseval = resv;
2405  state->innermost_casenull = resnull;
2406 
2407  ExecInitExprRec(ctor->coercion, state, resv, resnull);
2408 
2409  state->innermost_caseval = innermost_caseval;
2410  state->innermost_casenull = innermost_isnull;
2411  }
2412  }
2413  break;
2414 
2415  case T_JsonIsPredicate:
2416  {
2417  JsonIsPredicate *pred = (JsonIsPredicate *) node;
2418 
2419  ExecInitExprRec((Expr *) pred->expr, state, resv, resnull);
2420 
2421  scratch.opcode = EEOP_IS_JSON;
2422  scratch.d.is_json.pred = pred;
2423 
2424  ExprEvalPushStep(state, &scratch);
2425  break;
2426  }
2427 
2428  case T_JsonExpr:
2429  {
2430  JsonExpr *jsexpr = castNode(JsonExpr, node);
2431 
2432  /*
2433  * No need to initialize a full JsonExprState For
2434  * JSON_TABLE(), because the upstream caller tfuncFetchRows()
2435  * is only interested in the value of formatted_expr.
2436  */
2437  if (jsexpr->op == JSON_TABLE_OP)
2439  resv, resnull);
2440  else
2441  ExecInitJsonExpr(jsexpr, state, resv, resnull, &scratch);
2442  break;
2443  }
2444 
2445  case T_NullTest:
2446  {
2447  NullTest *ntest = (NullTest *) node;
2448 
2449  if (ntest->nulltesttype == IS_NULL)
2450  {
2451  if (ntest->argisrow)
2452  scratch.opcode = EEOP_NULLTEST_ROWISNULL;
2453  else
2454  scratch.opcode = EEOP_NULLTEST_ISNULL;
2455  }
2456  else if (ntest->nulltesttype == IS_NOT_NULL)
2457  {
2458  if (ntest->argisrow)
2460  else
2461  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2462  }
2463  else
2464  {
2465  elog(ERROR, "unrecognized nulltesttype: %d",
2466  (int) ntest->nulltesttype);
2467  }
2468  /* initialize cache in case it's a row test */
2469  scratch.d.nulltest_row.rowcache.cacheptr = NULL;
2470 
2471  /* first evaluate argument into result variable */
2472  ExecInitExprRec(ntest->arg, state,
2473  resv, resnull);
2474 
2475  /* then push the test of that argument */
2476  ExprEvalPushStep(state, &scratch);
2477  break;
2478  }
2479 
2480  case T_BooleanTest:
2481  {
2482  BooleanTest *btest = (BooleanTest *) node;
2483 
2484  /*
2485  * Evaluate argument, directly into result datum. That's ok,
2486  * because resv/resnull is definitely not used anywhere else,
2487  * and will get overwritten by the below EEOP_BOOLTEST_IS_*
2488  * step.
2489  */
2490  ExecInitExprRec(btest->arg, state, resv, resnull);
2491 
2492  switch (btest->booltesttype)
2493  {
2494  case IS_TRUE:
2495  scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
2496  break;
2497  case IS_NOT_TRUE:
2499  break;
2500  case IS_FALSE:
2501  scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
2502  break;
2503  case IS_NOT_FALSE:
2505  break;
2506  case IS_UNKNOWN:
2507  /* Same as scalar IS NULL test */
2508  scratch.opcode = EEOP_NULLTEST_ISNULL;
2509  break;
2510  case IS_NOT_UNKNOWN:
2511  /* Same as scalar IS NOT NULL test */
2512  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2513  break;
2514  default:
2515  elog(ERROR, "unrecognized booltesttype: %d",
2516  (int) btest->booltesttype);
2517  }
2518 
2519  ExprEvalPushStep(state, &scratch);
2520  break;
2521  }
2522 
2523  case T_CoerceToDomain:
2524  {
2525  CoerceToDomain *ctest = (CoerceToDomain *) node;
2526 
2527  ExecInitCoerceToDomain(&scratch, ctest, state,
2528  resv, resnull);
2529  break;
2530  }
2531 
2532  case T_CoerceToDomainValue:
2533  {
2534  /*
2535  * Read from location identified by innermost_domainval. Note
2536  * that innermost_domainval could be NULL, if we're compiling
2537  * a standalone domain check rather than one embedded in a
2538  * larger expression. In that case we must read from
2539  * econtext->domainValue_datum. We'll take care of that
2540  * scenario at runtime.
2541  */
2542  scratch.opcode = EEOP_DOMAIN_TESTVAL;
2543  /* we share instruction union variant with case testval */
2544  scratch.d.casetest.value = state->innermost_domainval;
2545  scratch.d.casetest.isnull = state->innermost_domainnull;
2546 
2547  ExprEvalPushStep(state, &scratch);
2548  break;
2549  }
2550 
2551  case T_CurrentOfExpr:
2552  {
2553  scratch.opcode = EEOP_CURRENTOFEXPR;
2554  ExprEvalPushStep(state, &scratch);
2555  break;
2556  }
2557 
2558  case T_NextValueExpr:
2559  {
2560  NextValueExpr *nve = (NextValueExpr *) node;
2561 
2562  scratch.opcode = EEOP_NEXTVALUEEXPR;
2563  scratch.d.nextvalueexpr.seqid = nve->seqid;
2564  scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2565 
2566  ExprEvalPushStep(state, &scratch);
2567  break;
2568  }
2569 
2570  default:
2571  elog(ERROR, "unrecognized node type: %d",
2572  (int) nodeTag(node));
2573  break;
2574  }
2575 }
2576 
2577 /*
2578  * Add another expression evaluation step to ExprState->steps.
2579  *
2580  * Note that this potentially re-allocates es->steps, therefore no pointer
2581  * into that array may be used while the expression is still being built.
2582  */
2583 void
2585 {
2586  if (es->steps_alloc == 0)
2587  {
2588  es->steps_alloc = 16;
2589  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2590  }
2591  else if (es->steps_alloc == es->steps_len)
2592  {
2593  es->steps_alloc *= 2;
2594  es->steps = repalloc(es->steps,
2595  sizeof(ExprEvalStep) * es->steps_alloc);
2596  }
2597 
2598  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2599 }
2600 
2601 /*
2602  * Perform setup necessary for the evaluation of a function-like expression,
2603  * appending argument evaluation steps to the steps list in *state, and
2604  * setting up *scratch so it is ready to be pushed.
2605  *
2606  * *scratch is not pushed here, so that callers may override the opcode,
2607  * which is useful for function-like cases like DISTINCT.
2608  */
2609 static void
2610 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2611  Oid inputcollid, ExprState *state)
2612 {
2613  int nargs = list_length(args);
2614  AclResult aclresult;
2615  FmgrInfo *flinfo;
2616  FunctionCallInfo fcinfo;
2617  int argno;
2618  ListCell *lc;
2619 
2620  /* Check permission to call function */
2621  aclresult = object_aclcheck(ProcedureRelationId, funcid, GetUserId(), ACL_EXECUTE);
2622  if (aclresult != ACLCHECK_OK)
2623  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2624  InvokeFunctionExecuteHook(funcid);
2625 
2626  /*
2627  * Safety check on nargs. Under normal circumstances this should never
2628  * fail, as parser should check sooner. But possibly it might fail if
2629  * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2630  * declared in pg_proc?
2631  */
2632  if (nargs > FUNC_MAX_ARGS)
2633  ereport(ERROR,
2634  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2635  errmsg_plural("cannot pass more than %d argument to a function",
2636  "cannot pass more than %d arguments to a function",
2637  FUNC_MAX_ARGS,
2638  FUNC_MAX_ARGS)));
2639 
2640  /* Allocate function lookup data and parameter workspace for this call */
2641  scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2642  scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2643  flinfo = scratch->d.func.finfo;
2644  fcinfo = scratch->d.func.fcinfo_data;
2645 
2646  /* Set up the primary fmgr lookup information */
2647  fmgr_info(funcid, flinfo);
2648  fmgr_info_set_expr((Node *) node, flinfo);
2649 
2650  /* Initialize function call parameter structure too */
2651  InitFunctionCallInfoData(*fcinfo, flinfo,
2652  nargs, inputcollid, NULL, NULL);
2653 
2654  /* Keep extra copies of this info to save an indirection at runtime */
2655  scratch->d.func.fn_addr = flinfo->fn_addr;
2656  scratch->d.func.nargs = nargs;
2657 
2658  /* We only support non-set functions here */
2659  if (flinfo->fn_retset)
2660  ereport(ERROR,
2661  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2662  errmsg("set-valued function called in context that cannot accept a set"),
2663  state->parent ?
2664  executor_errposition(state->parent->state,
2665  exprLocation((Node *) node)) : 0));
2666 
2667  /* Build code to evaluate arguments directly into the fcinfo struct */
2668  argno = 0;
2669  foreach(lc, args)
2670  {
2671  Expr *arg = (Expr *) lfirst(lc);
2672 
2673  if (IsA(arg, Const))
2674  {
2675  /*
2676  * Don't evaluate const arguments every round; especially
2677  * interesting for constants in comparisons.
2678  */
2679  Const *con = (Const *) arg;
2680 
2681  fcinfo->args[argno].value = con->constvalue;
2682  fcinfo->args[argno].isnull = con->constisnull;
2683  }
2684  else
2685  {
2687  &fcinfo->args[argno].value,
2688  &fcinfo->args[argno].isnull);
2689  }
2690  argno++;
2691  }
2692 
2693  /* Insert appropriate opcode depending on strictness and stats level */
2694  if (pgstat_track_functions <= flinfo->fn_stats)
2695  {
2696  if (flinfo->fn_strict && nargs > 0)
2697  scratch->opcode = EEOP_FUNCEXPR_STRICT;
2698  else
2699  scratch->opcode = EEOP_FUNCEXPR;
2700  }
2701  else
2702  {
2703  if (flinfo->fn_strict && nargs > 0)
2705  else
2706  scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2707  }
2708 }
2709 
2710 /*
2711  * Append the steps necessary for the evaluation of a SubPlan node to
2712  * ExprState->steps.
2713  *
2714  * subplan - SubPlan expression to evaluate
2715  * state - ExprState to whose ->steps to append the necessary operations
2716  * resv / resnull - where to store the result of the node into
2717  */
2718 static void
2720  ExprState *state,
2721  Datum *resv, bool *resnull)
2722 {
2723  ExprEvalStep scratch = {0};
2724  SubPlanState *sstate;
2725  ListCell *pvar;
2726  ListCell *l;
2727 
2728  if (!state->parent)
2729  elog(ERROR, "SubPlan found with no parent plan");
2730 
2731  /*
2732  * Generate steps to evaluate input arguments for the subplan.
2733  *
2734  * We evaluate the argument expressions into ExprState's resvalue/resnull,
2735  * and then use PARAM_SET to update the parameter. We do that, instead of
2736  * evaluating directly into the param, to avoid depending on the pointer
2737  * value remaining stable / being included in the generated expression. No
2738  * danger of conflicts with other uses of resvalue/resnull as storing and
2739  * using the value always is in subsequent steps.
2740  *
2741  * Any calculation we have to do can be done in the parent econtext, since
2742  * the Param values don't need to have per-query lifetime.
2743  */
2744  Assert(list_length(subplan->parParam) == list_length(subplan->args));
2745  forboth(l, subplan->parParam, pvar, subplan->args)
2746  {
2747  int paramid = lfirst_int(l);
2748  Expr *arg = (Expr *) lfirst(pvar);
2749 
2751  &state->resvalue, &state->resnull);
2752 
2753  scratch.opcode = EEOP_PARAM_SET;
2754  scratch.d.param.paramid = paramid;
2755  /* paramtype's not actually used, but we might as well fill it */
2756  scratch.d.param.paramtype = exprType((Node *) arg);
2757  ExprEvalPushStep(state, &scratch);
2758  }
2759 
2760  sstate = ExecInitSubPlan(subplan, state->parent);
2761 
2762  /* add SubPlanState nodes to state->parent->subPlan */
2763  state->parent->subPlan = lappend(state->parent->subPlan,
2764  sstate);
2765 
2766  scratch.opcode = EEOP_SUBPLAN;
2767  scratch.resvalue = resv;
2768  scratch.resnull = resnull;
2769  scratch.d.subplan.sstate = sstate;
2770 
2771  ExprEvalPushStep(state, &scratch);
2772 }
2773 
2774 /*
2775  * Add expression steps performing setup that's needed before any of the
2776  * main execution of the expression.
2777  */
2778 static void
2780 {
2781  ExprSetupInfo info = {0, 0, 0, NIL};
2782 
2783  /* Prescan to find out what we need. */
2784  expr_setup_walker(node, &info);
2785 
2786  /* And generate those steps. */
2787  ExecPushExprSetupSteps(state, &info);
2788 }
2789 
2790 /*
2791  * Add steps performing expression setup as indicated by "info".
2792  * This is useful when building an ExprState covering more than one expression.
2793  */
2794 static void
2796 {
2797  ExprEvalStep scratch = {0};
2798  ListCell *lc;
2799 
2800  scratch.resvalue = NULL;
2801  scratch.resnull = NULL;
2802 
2803  /*
2804  * Add steps deforming the ExprState's inner/outer/scan slots as much as
2805  * required by any Vars appearing in the expression.
2806  */
2807  if (info->last_inner > 0)
2808  {
2809  scratch.opcode = EEOP_INNER_FETCHSOME;
2810  scratch.d.fetch.last_var = info->last_inner;
2811  scratch.d.fetch.fixed = false;
2812  scratch.d.fetch.kind = NULL;
2813  scratch.d.fetch.known_desc = NULL;
2814  if (ExecComputeSlotInfo(state, &scratch))
2815  ExprEvalPushStep(state, &scratch);
2816  }
2817  if (info->last_outer > 0)
2818  {
2819  scratch.opcode = EEOP_OUTER_FETCHSOME;
2820  scratch.d.fetch.last_var = info->last_outer;
2821  scratch.d.fetch.fixed = false;
2822  scratch.d.fetch.kind = NULL;
2823  scratch.d.fetch.known_desc = NULL;
2824  if (ExecComputeSlotInfo(state, &scratch))
2825  ExprEvalPushStep(state, &scratch);
2826  }
2827  if (info->last_scan > 0)
2828  {
2829  scratch.opcode = EEOP_SCAN_FETCHSOME;
2830  scratch.d.fetch.last_var = info->last_scan;
2831  scratch.d.fetch.fixed = false;
2832  scratch.d.fetch.kind = NULL;
2833  scratch.d.fetch.known_desc = NULL;
2834  if (ExecComputeSlotInfo(state, &scratch))
2835  ExprEvalPushStep(state, &scratch);
2836  }
2837 
2838  /*
2839  * Add steps to execute any MULTIEXPR SubPlans appearing in the
2840  * expression. We need to evaluate these before any of the Params
2841  * referencing their outputs are used, but after we've prepared for any
2842  * Var references they may contain. (There cannot be cross-references
2843  * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2844  */
2845  foreach(lc, info->multiexpr_subplans)
2846  {
2847  SubPlan *subplan = (SubPlan *) lfirst(lc);
2848 
2849  Assert(subplan->subLinkType == MULTIEXPR_SUBLINK);
2850 
2851  /* The result can be ignored, but we better put it somewhere */
2852  ExecInitSubPlanExpr(subplan, state,
2853  &state->resvalue, &state->resnull);
2854  }
2855 }
2856 
2857 /*
2858  * expr_setup_walker: expression walker for ExecCreateExprSetupSteps
2859  */
2860 static bool
2862 {
2863  if (node == NULL)
2864  return false;
2865  if (IsA(node, Var))
2866  {
2867  Var *variable = (Var *) node;
2868  AttrNumber attnum = variable->varattno;
2869 
2870  switch (variable->varno)
2871  {
2872  case INNER_VAR:
2873  info->last_inner = Max(info->last_inner, attnum);
2874  break;
2875 
2876  case OUTER_VAR:
2877  info->last_outer = Max(info->last_outer, attnum);
2878  break;
2879 
2880  /* INDEX_VAR is handled by default case */
2881 
2882  default:
2883  info->last_scan = Max(info->last_scan, attnum);
2884  break;
2885  }
2886  return false;
2887  }
2888 
2889  /* Collect all MULTIEXPR SubPlans, too */
2890  if (IsA(node, SubPlan))
2891  {
2892  SubPlan *subplan = (SubPlan *) node;
2893 
2894  if (subplan->subLinkType == MULTIEXPR_SUBLINK)
2896  subplan);
2897  }
2898 
2899  /*
2900  * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2901  * because those do not represent expressions to be evaluated within the
2902  * calling expression's econtext. GroupingFunc arguments are never
2903  * evaluated at all.
2904  */
2905  if (IsA(node, Aggref))
2906  return false;
2907  if (IsA(node, WindowFunc))
2908  return false;
2909  if (IsA(node, GroupingFunc))
2910  return false;
2912  (void *) info);
2913 }
2914 
2915 /*
2916  * Compute additional information for EEOP_*_FETCHSOME ops.
2917  *
2918  * The goal is to determine whether a slot is 'fixed', that is, every
2919  * evaluation of the expression will have the same type of slot, with an
2920  * equivalent descriptor.
2921  *
2922  * Returns true if the deforming step is required, false otherwise.
2923  */
2924 static bool
2926 {
2927  PlanState *parent = state->parent;
2928  TupleDesc desc = NULL;
2929  const TupleTableSlotOps *tts_ops = NULL;
2930  bool isfixed = false;
2931  ExprEvalOp opcode = op->opcode;
2932 
2933  Assert(opcode == EEOP_INNER_FETCHSOME ||
2934  opcode == EEOP_OUTER_FETCHSOME ||
2935  opcode == EEOP_SCAN_FETCHSOME);
2936 
2937  if (op->d.fetch.known_desc != NULL)
2938  {
2939  desc = op->d.fetch.known_desc;
2940  tts_ops = op->d.fetch.kind;
2941  isfixed = op->d.fetch.kind != NULL;
2942  }
2943  else if (!parent)
2944  {
2945  isfixed = false;
2946  }
2947  else if (opcode == EEOP_INNER_FETCHSOME)
2948  {
2949  PlanState *is = innerPlanState(parent);
2950 
2951  if (parent->inneropsset && !parent->inneropsfixed)
2952  {
2953  isfixed = false;
2954  }
2955  else if (parent->inneropsset && parent->innerops)
2956  {
2957  isfixed = true;
2958  tts_ops = parent->innerops;
2959  desc = ExecGetResultType(is);
2960  }
2961  else if (is)
2962  {
2963  tts_ops = ExecGetResultSlotOps(is, &isfixed);
2964  desc = ExecGetResultType(is);
2965  }
2966  }
2967  else if (opcode == EEOP_OUTER_FETCHSOME)
2968  {
2969  PlanState *os = outerPlanState(parent);
2970 
2971  if (parent->outeropsset && !parent->outeropsfixed)
2972  {
2973  isfixed = false;
2974  }
2975  else if (parent->outeropsset && parent->outerops)
2976  {
2977  isfixed = true;
2978  tts_ops = parent->outerops;
2979  desc = ExecGetResultType(os);
2980  }
2981  else if (os)
2982  {
2983  tts_ops = ExecGetResultSlotOps(os, &isfixed);
2984  desc = ExecGetResultType(os);
2985  }
2986  }
2987  else if (opcode == EEOP_SCAN_FETCHSOME)
2988  {
2989  desc = parent->scandesc;
2990 
2991  if (parent->scanops)
2992  tts_ops = parent->scanops;
2993 
2994  if (parent->scanopsset)
2995  isfixed = parent->scanopsfixed;
2996  }
2997 
2998  if (isfixed && desc != NULL && tts_ops != NULL)
2999  {
3000  op->d.fetch.fixed = true;
3001  op->d.fetch.kind = tts_ops;
3002  op->d.fetch.known_desc = desc;
3003  }
3004  else
3005  {
3006  op->d.fetch.fixed = false;
3007  op->d.fetch.kind = NULL;
3008  op->d.fetch.known_desc = NULL;
3009  }
3010 
3011  /* if the slot is known to always virtual we never need to deform */
3012  if (op->d.fetch.fixed && op->d.fetch.kind == &TTSOpsVirtual)
3013  return false;
3014 
3015  return true;
3016 }
3017 
3018 /*
3019  * Prepare step for the evaluation of a whole-row variable.
3020  * The caller still has to push the step.
3021  */
3022 static void
3024 {
3025  PlanState *parent = state->parent;
3026 
3027  /* fill in all but the target */
3028  scratch->opcode = EEOP_WHOLEROW;
3029  scratch->d.wholerow.var = variable;
3030  scratch->d.wholerow.first = true;
3031  scratch->d.wholerow.slow = false;
3032  scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
3033  scratch->d.wholerow.junkFilter = NULL;
3034 
3035  /*
3036  * If the input tuple came from a subquery, it might contain "resjunk"
3037  * columns (such as GROUP BY or ORDER BY columns), which we don't want to
3038  * keep in the whole-row result. We can get rid of such columns by
3039  * passing the tuple through a JunkFilter --- but to make one, we have to
3040  * lay our hands on the subquery's targetlist. Fortunately, there are not
3041  * very many cases where this can happen, and we can identify all of them
3042  * by examining our parent PlanState. We assume this is not an issue in
3043  * standalone expressions that don't have parent plans. (Whole-row Vars
3044  * can occur in such expressions, but they will always be referencing
3045  * table rows.)
3046  */
3047  if (parent)
3048  {
3049  PlanState *subplan = NULL;
3050 
3051  switch (nodeTag(parent))
3052  {
3053  case T_SubqueryScanState:
3054  subplan = ((SubqueryScanState *) parent)->subplan;
3055  break;
3056  case T_CteScanState:
3057  subplan = ((CteScanState *) parent)->cteplanstate;
3058  break;
3059  default:
3060  break;
3061  }
3062 
3063  if (subplan)
3064  {
3065  bool junk_filter_needed = false;
3066  ListCell *tlist;
3067 
3068  /* Detect whether subplan tlist actually has any junk columns */
3069  foreach(tlist, subplan->plan->targetlist)
3070  {
3071  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
3072 
3073  if (tle->resjunk)
3074  {
3075  junk_filter_needed = true;
3076  break;
3077  }
3078  }
3079 
3080  /* If so, build the junkfilter now */
3081  if (junk_filter_needed)
3082  {
3083  scratch->d.wholerow.junkFilter =
3085  ExecInitExtraTupleSlot(parent->state, NULL,
3086  &TTSOpsVirtual));
3087  }
3088  }
3089  }
3090 }
3091 
3092 /*
3093  * Prepare evaluation of a SubscriptingRef expression.
3094  */
3095 static void
3097  ExprState *state, Datum *resv, bool *resnull)
3098 {
3099  bool isAssignment = (sbsref->refassgnexpr != NULL);
3100  int nupper = list_length(sbsref->refupperindexpr);
3101  int nlower = list_length(sbsref->reflowerindexpr);
3102  const SubscriptRoutines *sbsroutines;
3103  SubscriptingRefState *sbsrefstate;
3104  SubscriptExecSteps methods;
3105  char *ptr;
3106  List *adjust_jumps = NIL;
3107  ListCell *lc;
3108  int i;
3109 
3110  /* Look up the subscripting support methods */
3111  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
3112  if (!sbsroutines)
3113  ereport(ERROR,
3114  (errcode(ERRCODE_DATATYPE_MISMATCH),
3115  errmsg("cannot subscript type %s because it does not support subscripting",
3116  format_type_be(sbsref->refcontainertype)),
3117  state->parent ?
3118  executor_errposition(state->parent->state,
3119  exprLocation((Node *) sbsref)) : 0));
3120 
3121  /* Allocate sbsrefstate, with enough space for per-subscript arrays too */
3122  sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +
3123  (nupper + nlower) * (sizeof(Datum) +
3124  2 * sizeof(bool)));
3125 
3126  /* Fill constant fields of SubscriptingRefState */
3127  sbsrefstate->isassignment = isAssignment;
3128  sbsrefstate->numupper = nupper;
3129  sbsrefstate->numlower = nlower;
3130  /* Set up per-subscript arrays */
3131  ptr = ((char *) sbsrefstate) + MAXALIGN(sizeof(SubscriptingRefState));
3132  sbsrefstate->upperindex = (Datum *) ptr;
3133  ptr += nupper * sizeof(Datum);
3134  sbsrefstate->lowerindex = (Datum *) ptr;
3135  ptr += nlower * sizeof(Datum);
3136  sbsrefstate->upperprovided = (bool *) ptr;
3137  ptr += nupper * sizeof(bool);
3138  sbsrefstate->lowerprovided = (bool *) ptr;
3139  ptr += nlower * sizeof(bool);
3140  sbsrefstate->upperindexnull = (bool *) ptr;
3141  ptr += nupper * sizeof(bool);
3142  sbsrefstate->lowerindexnull = (bool *) ptr;
3143  /* ptr += nlower * sizeof(bool); */
3144 
3145  /*
3146  * Let the container-type-specific code have a chance. It must fill the
3147  * "methods" struct with function pointers for us to possibly use in
3148  * execution steps below; and it can optionally set up some data pointed
3149  * to by the workspace field.
3150  */
3151  memset(&methods, 0, sizeof(methods));
3152  sbsroutines->exec_setup(sbsref, sbsrefstate, &methods);
3153 
3154  /*
3155  * Evaluate array input. It's safe to do so into resv/resnull, because we
3156  * won't use that as target for any of the other subexpressions, and it'll
3157  * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
3158  * pushed last.
3159  */
3160  ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
3161 
3162  /*
3163  * If refexpr yields NULL, and the operation should be strict, then result
3164  * is NULL. We can implement this with just JUMP_IF_NULL, since we
3165  * evaluated the array into the desired target location.
3166  */
3167  if (!isAssignment && sbsroutines->fetch_strict)
3168  {
3169  scratch->opcode = EEOP_JUMP_IF_NULL;
3170  scratch->d.jump.jumpdone = -1; /* adjust later */
3171  ExprEvalPushStep(state, scratch);
3172  adjust_jumps = lappend_int(adjust_jumps,
3173  state->steps_len - 1);
3174  }
3175 
3176  /* Evaluate upper subscripts */
3177  i = 0;
3178  foreach(lc, sbsref->refupperindexpr)
3179  {
3180  Expr *e = (Expr *) lfirst(lc);
3181 
3182  /* When slicing, individual subscript bounds can be omitted */
3183  if (!e)
3184  {
3185  sbsrefstate->upperprovided[i] = false;
3186  sbsrefstate->upperindexnull[i] = true;
3187  }
3188  else
3189  {
3190  sbsrefstate->upperprovided[i] = true;
3191  /* Each subscript is evaluated into appropriate array entry */
3193  &sbsrefstate->upperindex[i],
3194  &sbsrefstate->upperindexnull[i]);
3195  }
3196  i++;
3197  }
3198 
3199  /* Evaluate lower subscripts similarly */
3200  i = 0;
3201  foreach(lc, sbsref->reflowerindexpr)
3202  {
3203  Expr *e = (Expr *) lfirst(lc);
3204 
3205  /* When slicing, individual subscript bounds can be omitted */
3206  if (!e)
3207  {
3208  sbsrefstate->lowerprovided[i] = false;
3209  sbsrefstate->lowerindexnull[i] = true;
3210  }
3211  else
3212  {
3213  sbsrefstate->lowerprovided[i] = true;
3214  /* Each subscript is evaluated into appropriate array entry */
3216  &sbsrefstate->lowerindex[i],
3217  &sbsrefstate->lowerindexnull[i]);
3218  }
3219  i++;
3220  }
3221 
3222  /* SBSREF_SUBSCRIPTS checks and converts all the subscripts at once */
3223  if (methods.sbs_check_subscripts)
3224  {
3225  scratch->opcode = EEOP_SBSREF_SUBSCRIPTS;
3226  scratch->d.sbsref_subscript.subscriptfunc = methods.sbs_check_subscripts;
3227  scratch->d.sbsref_subscript.state = sbsrefstate;
3228  scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
3229  ExprEvalPushStep(state, scratch);
3230  adjust_jumps = lappend_int(adjust_jumps,
3231  state->steps_len - 1);
3232  }
3233 
3234  if (isAssignment)
3235  {
3236  Datum *save_innermost_caseval;
3237  bool *save_innermost_casenull;
3238 
3239  /* Check for unimplemented methods */
3240  if (!methods.sbs_assign)
3241  ereport(ERROR,
3242  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3243  errmsg("type %s does not support subscripted assignment",
3244  format_type_be(sbsref->refcontainertype))));
3245 
3246  /*
3247  * We might have a nested-assignment situation, in which the
3248  * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
3249  * to obtain and modify the previous value of the array element or
3250  * slice being replaced. If so, we have to extract that value from
3251  * the array and pass it down via the CaseTestExpr mechanism. It's
3252  * safe to reuse the CASE mechanism because there cannot be a CASE
3253  * between here and where the value would be needed, and an array
3254  * assignment can't be within a CASE either. (So saving and restoring
3255  * innermost_caseval is just paranoia, but let's do it anyway.)
3256  *
3257  * Since fetching the old element might be a nontrivial expense, do it
3258  * only if the argument actually needs it.
3259  */
3261  {
3262  if (!methods.sbs_fetch_old)
3263  ereport(ERROR,
3264  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3265  errmsg("type %s does not support subscripted assignment",
3266  format_type_be(sbsref->refcontainertype))));
3267  scratch->opcode = EEOP_SBSREF_OLD;
3268  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch_old;
3269  scratch->d.sbsref.state = sbsrefstate;
3270  ExprEvalPushStep(state, scratch);
3271  }
3272 
3273  /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
3274  save_innermost_caseval = state->innermost_caseval;
3275  save_innermost_casenull = state->innermost_casenull;
3276  state->innermost_caseval = &sbsrefstate->prevvalue;
3277  state->innermost_casenull = &sbsrefstate->prevnull;
3278 
3279  /* evaluate replacement value into replacevalue/replacenull */
3281  &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
3282 
3283  state->innermost_caseval = save_innermost_caseval;
3284  state->innermost_casenull = save_innermost_casenull;
3285 
3286  /* and perform the assignment */
3287  scratch->opcode = EEOP_SBSREF_ASSIGN;
3288  scratch->d.sbsref.subscriptfunc = methods.sbs_assign;
3289  scratch->d.sbsref.state = sbsrefstate;
3290  ExprEvalPushStep(state, scratch);
3291  }
3292  else
3293  {
3294  /* array fetch is much simpler */
3295  scratch->opcode = EEOP_SBSREF_FETCH;
3296  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch;
3297  scratch->d.sbsref.state = sbsrefstate;
3298  ExprEvalPushStep(state, scratch);
3299  }
3300 
3301  /* adjust jump targets */
3302  foreach(lc, adjust_jumps)
3303  {
3304  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3305 
3306  if (as->opcode == EEOP_SBSREF_SUBSCRIPTS)
3307  {
3308  Assert(as->d.sbsref_subscript.jumpdone == -1);
3309  as->d.sbsref_subscript.jumpdone = state->steps_len;
3310  }
3311  else
3312  {
3314  Assert(as->d.jump.jumpdone == -1);
3315  as->d.jump.jumpdone = state->steps_len;
3316  }
3317  }
3318 }
3319 
3320 /*
3321  * Helper for preparing SubscriptingRef expressions for evaluation: is expr
3322  * a nested FieldStore or SubscriptingRef that needs the old element value
3323  * passed down?
3324  *
3325  * (We could use this in FieldStore too, but in that case passing the old
3326  * value is so cheap there's no need.)
3327  *
3328  * Note: it might seem that this needs to recurse, but in most cases it does
3329  * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the
3330  * top-level node. Nested-assignment situations give rise to expression
3331  * trees in which each level of assignment has its own CaseTestExpr, and the
3332  * recursive structure appears within the newvals or refassgnexpr field.
3333  * There is an exception, though: if the array is an array-of-domain, we will
3334  * have a CoerceToDomain or RelabelType as the refassgnexpr, and we need to
3335  * be able to look through that.
3336  */
3337 static bool
3339 {
3340  if (expr == NULL)
3341  return false; /* just paranoia */
3342  if (IsA(expr, FieldStore))
3343  {
3344  FieldStore *fstore = (FieldStore *) expr;
3345 
3346  if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
3347  return true;
3348  }
3349  else if (IsA(expr, SubscriptingRef))
3350  {
3351  SubscriptingRef *sbsRef = (SubscriptingRef *) expr;
3352 
3353  if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr))
3354  return true;
3355  }
3356  else if (IsA(expr, CoerceToDomain))
3357  {
3358  CoerceToDomain *cd = (CoerceToDomain *) expr;
3359 
3360  return isAssignmentIndirectionExpr(cd->arg);
3361  }
3362  else if (IsA(expr, RelabelType))
3363  {
3364  RelabelType *r = (RelabelType *) expr;
3365 
3366  return isAssignmentIndirectionExpr(r->arg);
3367  }
3368  return false;
3369 }
3370 
3371 /*
3372  * Prepare evaluation of a CoerceToDomain expression.
3373  */
3374 static void
3376  ExprState *state, Datum *resv, bool *resnull)
3377 {
3378  DomainConstraintRef *constraint_ref;
3379  Datum *domainval = NULL;
3380  bool *domainnull = NULL;
3381  ListCell *l;
3382 
3383  scratch->d.domaincheck.resulttype = ctest->resulttype;
3384  /* we'll allocate workspace only if needed */
3385  scratch->d.domaincheck.checkvalue = NULL;
3386  scratch->d.domaincheck.checknull = NULL;
3387  scratch->d.domaincheck.escontext = state->escontext;
3388 
3389  /*
3390  * Evaluate argument - it's fine to directly store it into resv/resnull,
3391  * if there's constraint failures there'll be errors, otherwise it's what
3392  * needs to be returned.
3393  */
3394  ExecInitExprRec(ctest->arg, state, resv, resnull);
3395 
3396  /*
3397  * Note: if the argument is of varlena type, it could be a R/W expanded
3398  * object. We want to return the R/W pointer as the final result, but we
3399  * have to pass a R/O pointer as the value to be tested by any functions
3400  * in check expressions. We don't bother to emit a MAKE_READONLY step
3401  * unless there's actually at least one check expression, though. Until
3402  * we've tested that, domainval/domainnull are NULL.
3403  */
3404 
3405  /*
3406  * Collect the constraints associated with the domain.
3407  *
3408  * Note: before PG v10 we'd recheck the set of constraints during each
3409  * evaluation of the expression. Now we bake them into the ExprState
3410  * during executor initialization. That means we don't need typcache.c to
3411  * provide compiled exprs.
3412  */
3413  constraint_ref = (DomainConstraintRef *)
3414  palloc(sizeof(DomainConstraintRef));
3416  constraint_ref,
3418  false);
3419 
3420  /*
3421  * Compile code to check each domain constraint. NOTNULL constraints can
3422  * just be applied on the resv/resnull value, but for CHECK constraints we
3423  * need more pushups.
3424  */
3425  foreach(l, constraint_ref->constraints)
3426  {
3428  Datum *save_innermost_domainval;
3429  bool *save_innermost_domainnull;
3430 
3431  scratch->d.domaincheck.constraintname = con->name;
3432 
3433  switch (con->constrainttype)
3434  {
3436  scratch->opcode = EEOP_DOMAIN_NOTNULL;
3437  ExprEvalPushStep(state, scratch);
3438  break;
3439  case DOM_CONSTRAINT_CHECK:
3440  /* Allocate workspace for CHECK output if we didn't yet */
3441  if (scratch->d.domaincheck.checkvalue == NULL)
3442  {
3443  scratch->d.domaincheck.checkvalue =
3444  (Datum *) palloc(sizeof(Datum));
3445  scratch->d.domaincheck.checknull =
3446  (bool *) palloc(sizeof(bool));
3447  }
3448 
3449  /*
3450  * If first time through, determine where CoerceToDomainValue
3451  * nodes should read from.
3452  */
3453  if (domainval == NULL)
3454  {
3455  /*
3456  * Since value might be read multiple times, force to R/O
3457  * - but only if it could be an expanded datum.
3458  */
3459  if (get_typlen(ctest->resulttype) == -1)
3460  {
3461  ExprEvalStep scratch2 = {0};
3462 
3463  /* Yes, so make output workspace for MAKE_READONLY */
3464  domainval = (Datum *) palloc(sizeof(Datum));
3465  domainnull = (bool *) palloc(sizeof(bool));
3466 
3467  /* Emit MAKE_READONLY */
3468  scratch2.opcode = EEOP_MAKE_READONLY;
3469  scratch2.resvalue = domainval;
3470  scratch2.resnull = domainnull;
3471  scratch2.d.make_readonly.value = resv;
3472  scratch2.d.make_readonly.isnull = resnull;
3473  ExprEvalPushStep(state, &scratch2);
3474  }
3475  else
3476  {
3477  /* No, so it's fine to read from resv/resnull */
3478  domainval = resv;
3479  domainnull = resnull;
3480  }
3481  }
3482 
3483  /*
3484  * Set up value to be returned by CoerceToDomainValue nodes.
3485  * We must save and restore innermost_domainval/null fields,
3486  * in case this node is itself within a check expression for
3487  * another domain.
3488  */
3489  save_innermost_domainval = state->innermost_domainval;
3490  save_innermost_domainnull = state->innermost_domainnull;
3491  state->innermost_domainval = domainval;
3492  state->innermost_domainnull = domainnull;
3493 
3494  /* evaluate check expression value */
3496  scratch->d.domaincheck.checkvalue,
3497  scratch->d.domaincheck.checknull);
3498 
3499  state->innermost_domainval = save_innermost_domainval;
3500  state->innermost_domainnull = save_innermost_domainnull;
3501 
3502  /* now test result */
3503  scratch->opcode = EEOP_DOMAIN_CHECK;
3504  ExprEvalPushStep(state, scratch);
3505 
3506  break;
3507  default:
3508  elog(ERROR, "unrecognized constraint type: %d",
3509  (int) con->constrainttype);
3510  break;
3511  }
3512  }
3513 }
3514 
3515 /*
3516  * Build transition/combine function invocations for all aggregate transition
3517  * / combination function invocations in a grouping sets phase. This has to
3518  * invoke all sort based transitions in a phase (if doSort is true), all hash
3519  * based transitions (if doHash is true), or both (both true).
3520  *
3521  * The resulting expression will, for each set of transition values, first
3522  * check for filters, evaluate aggregate input, check that that input is not
3523  * NULL for a strict transition function, and then finally invoke the
3524  * transition for each of the concurrently computed grouping sets.
3525  *
3526  * If nullcheck is true, the generated code will check for a NULL pointer to
3527  * the array of AggStatePerGroup, and skip evaluation if so.
3528  */
3529 ExprState *
3531  bool doSort, bool doHash, bool nullcheck)
3532 {
3534  PlanState *parent = &aggstate->ss.ps;
3535  ExprEvalStep scratch = {0};
3536  bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit);
3537  ExprSetupInfo deform = {0, 0, 0, NIL};
3538 
3539  state->expr = (Expr *) aggstate;
3540  state->parent = parent;
3541 
3542  scratch.resvalue = &state->resvalue;
3543  scratch.resnull = &state->resnull;
3544 
3545  /*
3546  * First figure out which slots, and how many columns from each, we're
3547  * going to need.
3548  */
3549  for (int transno = 0; transno < aggstate->numtrans; transno++)
3550  {
3551  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3552 
3553  expr_setup_walker((Node *) pertrans->aggref->aggdirectargs,
3554  &deform);
3555  expr_setup_walker((Node *) pertrans->aggref->args,
3556  &deform);
3557  expr_setup_walker((Node *) pertrans->aggref->aggorder,
3558  &deform);
3559  expr_setup_walker((Node *) pertrans->aggref->aggdistinct,
3560  &deform);
3561  expr_setup_walker((Node *) pertrans->aggref->aggfilter,
3562  &deform);
3563  }
3564  ExecPushExprSetupSteps(state, &deform);
3565 
3566  /*
3567  * Emit instructions for each transition value / grouping set combination.
3568  */
3569  for (int transno = 0; transno < aggstate->numtrans; transno++)
3570  {
3571  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3572  FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
3573  List *adjust_bailout = NIL;
3574  NullableDatum *strictargs = NULL;
3575  bool *strictnulls = NULL;
3576  int argno;
3577  ListCell *bail;
3578 
3579  /*
3580  * If filter present, emit. Do so before evaluating the input, to
3581  * avoid potentially unneeded computations, or even worse, unintended
3582  * side-effects. When combining, all the necessary filtering has
3583  * already been done.
3584  */
3585  if (pertrans->aggref->aggfilter && !isCombine)
3586  {
3587  /* evaluate filter expression */
3588  ExecInitExprRec(pertrans->aggref->aggfilter, state,
3589  &state->resvalue, &state->resnull);
3590  /* and jump out if false */
3591  scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
3592  scratch.d.jump.jumpdone = -1; /* adjust later */
3593  ExprEvalPushStep(state, &scratch);
3594  adjust_bailout = lappend_int(adjust_bailout,
3595  state->steps_len - 1);
3596  }
3597 
3598  /*
3599  * Evaluate arguments to aggregate/combine function.
3600  */
3601  argno = 0;
3602  if (isCombine)
3603  {
3604  /*
3605  * Combining two aggregate transition values. Instead of directly
3606  * coming from a tuple the input is a, potentially deserialized,
3607  * transition value.
3608  */
3609  TargetEntry *source_tle;
3610 
3611  Assert(pertrans->numSortCols == 0);
3612  Assert(list_length(pertrans->aggref->args) == 1);
3613 
3614  strictargs = trans_fcinfo->args + 1;
3615  source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
3616 
3617  /*
3618  * deserialfn_oid will be set if we must deserialize the input
3619  * state before calling the combine function.
3620  */
3621  if (!OidIsValid(pertrans->deserialfn_oid))
3622  {
3623  /*
3624  * Start from 1, since the 0th arg will be the transition
3625  * value
3626  */
3627  ExecInitExprRec(source_tle->expr, state,
3628  &trans_fcinfo->args[argno + 1].value,
3629  &trans_fcinfo->args[argno + 1].isnull);
3630  }
3631  else
3632  {
3633  FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
3634 
3635  /* evaluate argument */
3636  ExecInitExprRec(source_tle->expr, state,
3637  &ds_fcinfo->args[0].value,
3638  &ds_fcinfo->args[0].isnull);
3639 
3640  /* Dummy second argument for type-safety reasons */
3641  ds_fcinfo->args[1].value = PointerGetDatum(NULL);
3642  ds_fcinfo->args[1].isnull = false;
3643 
3644  /*
3645  * Don't call a strict deserialization function with NULL
3646  * input
3647  */
3648  if (pertrans->deserialfn.fn_strict)
3650  else
3651  scratch.opcode = EEOP_AGG_DESERIALIZE;
3652 
3653  scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
3654  scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
3655  scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
3656  scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
3657 
3658  ExprEvalPushStep(state, &scratch);
3659  /* don't add an adjustment unless the function is strict */
3660  if (pertrans->deserialfn.fn_strict)
3661  adjust_bailout = lappend_int(adjust_bailout,
3662  state->steps_len - 1);
3663 
3664  /* restore normal settings of scratch fields */
3665  scratch.resvalue = &state->resvalue;
3666  scratch.resnull = &state->resnull;
3667  }
3668  argno++;
3669 
3670  Assert(pertrans->numInputs == argno);
3671  }
3672  else if (!pertrans->aggsortrequired)
3673  {
3674  ListCell *arg;
3675 
3676  /*
3677  * Normal transition function without ORDER BY / DISTINCT or with
3678  * ORDER BY / DISTINCT but the planner has given us pre-sorted
3679  * input.
3680  */
3681  strictargs = trans_fcinfo->args + 1;
3682 
3683  foreach(arg, pertrans->aggref->args)
3684  {
3685  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3686 
3687  /*
3688  * Don't initialize args for any ORDER BY clause that might
3689  * exist in a presorted aggregate.
3690  */
3691  if (argno == pertrans->numTransInputs)
3692  break;
3693 
3694  /*
3695  * Start from 1, since the 0th arg will be the transition
3696  * value
3697  */
3698  ExecInitExprRec(source_tle->expr, state,
3699  &trans_fcinfo->args[argno + 1].value,
3700  &trans_fcinfo->args[argno + 1].isnull);
3701  argno++;
3702  }
3703  Assert(pertrans->numTransInputs == argno);
3704  }
3705  else if (pertrans->numInputs == 1)
3706  {
3707  /*
3708  * Non-presorted DISTINCT and/or ORDER BY case, with a single
3709  * column sorted on.
3710  */
3711  TargetEntry *source_tle =
3712  (TargetEntry *) linitial(pertrans->aggref->args);
3713 
3714  Assert(list_length(pertrans->aggref->args) == 1);
3715 
3716  ExecInitExprRec(source_tle->expr, state,
3717  &state->resvalue,
3718  &state->resnull);
3719  strictnulls = &state->resnull;
3720  argno++;
3721 
3722  Assert(pertrans->numInputs == argno);
3723  }
3724  else
3725  {
3726  /*
3727  * Non-presorted DISTINCT and/or ORDER BY case, with multiple
3728  * columns sorted on.
3729  */
3730  Datum *values = pertrans->sortslot->tts_values;
3731  bool *nulls = pertrans->sortslot->tts_isnull;
3732  ListCell *arg;
3733 
3734  strictnulls = nulls;
3735 
3736  foreach(arg, pertrans->aggref->args)
3737  {
3738  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3739 
3740  ExecInitExprRec(source_tle->expr, state,
3741  &values[argno], &nulls[argno]);
3742  argno++;
3743  }
3744  Assert(pertrans->numInputs == argno);
3745  }
3746 
3747  /*
3748  * For a strict transfn, nothing happens when there's a NULL input; we
3749  * just keep the prior transValue. This is true for both plain and
3750  * sorted/distinct aggregates.
3751  */
3752  if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
3753  {
3754  if (strictnulls)
3756  else
3758  scratch.d.agg_strict_input_check.nulls = strictnulls;
3759  scratch.d.agg_strict_input_check.args = strictargs;
3760  scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
3761  scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
3762  ExprEvalPushStep(state, &scratch);
3763  adjust_bailout = lappend_int(adjust_bailout,
3764  state->steps_len - 1);
3765  }
3766 
3767  /* Handle DISTINCT aggregates which have pre-sorted input */
3768  if (pertrans->numDistinctCols > 0 && !pertrans->aggsortrequired)
3769  {
3770  if (pertrans->numDistinctCols > 1)
3772  else
3774 
3775  scratch.d.agg_presorted_distinctcheck.pertrans = pertrans;
3776  scratch.d.agg_presorted_distinctcheck.jumpdistinct = -1; /* adjust later */
3777  ExprEvalPushStep(state, &scratch);
3778  adjust_bailout = lappend_int(adjust_bailout,
3779  state->steps_len - 1);
3780  }
3781 
3782  /*
3783  * Call transition function (once for each concurrently evaluated
3784  * grouping set). Do so for both sort and hash based computations, as
3785  * applicable.
3786  */
3787  if (doSort)
3788  {
3789  int processGroupingSets = Max(phase->numsets, 1);
3790  int setoff = 0;
3791 
3792  for (int setno = 0; setno < processGroupingSets; setno++)
3793  {
3794  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3795  pertrans, transno, setno, setoff, false,
3796  nullcheck);
3797  setoff++;
3798  }
3799  }
3800 
3801  if (doHash)
3802  {
3803  int numHashes = aggstate->num_hashes;
3804  int setoff;
3805 
3806  /* in MIXED mode, there'll be preceding transition values */
3807  if (aggstate->aggstrategy != AGG_HASHED)
3808  setoff = aggstate->maxsets;
3809  else
3810  setoff = 0;
3811 
3812  for (int setno = 0; setno < numHashes; setno++)
3813  {
3814  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3815  pertrans, transno, setno, setoff, true,
3816  nullcheck);
3817  setoff++;
3818  }
3819  }
3820 
3821  /* adjust early bail out jump target(s) */
3822  foreach(bail, adjust_bailout)
3823  {
3824  ExprEvalStep *as = &state->steps[lfirst_int(bail)];
3825 
3826  if (as->opcode == EEOP_JUMP_IF_NOT_TRUE)
3827  {
3828  Assert(as->d.jump.jumpdone == -1);
3829  as->d.jump.jumpdone = state->steps_len;
3830  }
3831  else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
3833  {
3834  Assert(as->d.agg_strict_input_check.jumpnull == -1);
3835  as->d.agg_strict_input_check.jumpnull = state->steps_len;
3836  }
3837  else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE)
3838  {
3839  Assert(as->d.agg_deserialize.jumpnull == -1);
3840  as->d.agg_deserialize.jumpnull = state->steps_len;
3841  }
3842  else if (as->opcode == EEOP_AGG_PRESORTED_DISTINCT_SINGLE ||
3844  {
3845  Assert(as->d.agg_presorted_distinctcheck.jumpdistinct == -1);
3846  as->d.agg_presorted_distinctcheck.jumpdistinct = state->steps_len;
3847  }
3848  else
3849  Assert(false);
3850  }
3851  }
3852 
3853  scratch.resvalue = NULL;
3854  scratch.resnull = NULL;
3855  scratch.opcode = EEOP_DONE;
3856  ExprEvalPushStep(state, &scratch);
3857 
3859 
3860  return state;
3861 }
3862 
3863 /*
3864  * Build transition/combine function invocation for a single transition
3865  * value. This is separated from ExecBuildAggTrans() because there are
3866  * multiple callsites (hash and sort in some grouping set cases).
3867  */
3868 static void
3870  ExprEvalStep *scratch,
3871  FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
3872  int transno, int setno, int setoff, bool ishash,
3873  bool nullcheck)
3874 {
3875  ExprContext *aggcontext;
3876  int adjust_jumpnull = -1;
3877 
3878  if (ishash)
3879  aggcontext = aggstate->hashcontext;
3880  else
3881  aggcontext = aggstate->aggcontexts[setno];
3882 
3883  /* add check for NULL pointer? */
3884  if (nullcheck)
3885  {
3887  scratch->d.agg_plain_pergroup_nullcheck.setoff = setoff;
3888  /* adjust later */
3889  scratch->d.agg_plain_pergroup_nullcheck.jumpnull = -1;
3890  ExprEvalPushStep(state, scratch);
3891  adjust_jumpnull = state->steps_len - 1;
3892  }
3893 
3894  /*
3895  * Determine appropriate transition implementation.
3896  *
3897  * For non-ordered aggregates and ORDER BY / DISTINCT aggregates with
3898  * presorted input:
3899  *
3900  * If the initial value for the transition state doesn't exist in the
3901  * pg_aggregate table then we will let the first non-NULL value returned
3902  * from the outer procNode become the initial value. (This is useful for
3903  * aggregates like max() and min().) The noTransValue flag signals that we
3904  * need to do so. If true, generate a
3905  * EEOP_AGG_INIT_STRICT_PLAIN_TRANS{,_BYVAL} step. This step also needs to
3906  * do the work described next:
3907  *
3908  * If the function is strict, but does have an initial value, choose
3909  * EEOP_AGG_STRICT_PLAIN_TRANS{,_BYVAL}, which skips the transition
3910  * function if the transition value has become NULL (because a previous
3911  * transition function returned NULL). This step also needs to do the work
3912  * described next:
3913  *
3914  * Otherwise we call EEOP_AGG_PLAIN_TRANS{,_BYVAL}, which does not have to
3915  * perform either of the above checks.
3916  *
3917  * Having steps with overlapping responsibilities is not nice, but
3918  * aggregations are very performance sensitive, making this worthwhile.
3919  *
3920  * For ordered aggregates:
3921  *
3922  * Only need to choose between the faster path for a single ordered
3923  * column, and the one between multiple columns. Checking strictness etc
3924  * is done when finalizing the aggregate. See
3925  * process_ordered_aggregate_{single, multi} and
3926  * advance_transition_function.
3927  */
3928  if (!pertrans->aggsortrequired)
3929  {
3930  if (pertrans->transtypeByVal)
3931  {
3932  if (fcinfo->flinfo->fn_strict &&
3933  pertrans->initValueIsNull)
3935  else if (fcinfo->flinfo->fn_strict)
3937  else
3939  }
3940  else
3941  {
3942  if (fcinfo->flinfo->fn_strict &&
3943  pertrans->initValueIsNull)
3945  else if (fcinfo->flinfo->fn_strict)
3947  else
3949  }
3950  }
3951  else if (pertrans->numInputs == 1)
3953  else
3955 
3956  scratch->d.agg_trans.pertrans = pertrans;
3957  scratch->d.agg_trans.setno = setno;
3958  scratch->d.agg_trans.setoff = setoff;
3959  scratch->d.agg_trans.transno = transno;
3960  scratch->d.agg_trans.aggcontext = aggcontext;
3961  ExprEvalPushStep(state, scratch);
3962 
3963  /* fix up jumpnull */
3964  if (adjust_jumpnull != -1)
3965  {
3966  ExprEvalStep *as = &state->steps[adjust_jumpnull];
3967 
3969  Assert(as->d.agg_plain_pergroup_nullcheck.jumpnull == -1);
3970  as->d.agg_plain_pergroup_nullcheck.jumpnull = state->steps_len;
3971  }
3972 }
3973 
3974 /*
3975  * Build an ExprState that calls the given hash function(s) on the given
3976  * 'hash_exprs'. When multiple expressions are present, the hash values
3977  * returned by each hash function are combined to produce a single hash value.
3978  *
3979  * desc: tuple descriptor for the to-be-hashed expressions
3980  * ops: TupleTableSlotOps for the TupleDesc
3981  * hashfunc_oids: Oid for each hash function to call, one for each 'hash_expr'
3982  * collations: collation to use when calling the hash function.
3983  * hash_expr: list of expressions to hash the value of
3984  * opstrict: array corresponding to the 'hashfunc_oids' to store op_strict()
3985  * parent: PlanState node that the 'hash_exprs' will be evaluated at
3986  * init_value: Normally 0, but can be set to other values to seed the hash
3987  * with some other value. Using non-zero is slightly less efficient but can
3988  * be useful.
3989  * keep_nulls: if true, evaluation of the returned ExprState will abort early
3990  * returning NULL if the given hash function is strict and the Datum to hash
3991  * is null. When set to false, any NULL input Datums are skipped.
3992  */
3993 ExprState *
3995  const Oid *hashfunc_oids, const List *collations,
3996  const List *hash_exprs, const bool *opstrict,
3997  PlanState *parent, uint32 init_value, bool keep_nulls)
3998 {
4000  ExprEvalStep scratch = {0};
4001  NullableDatum *iresult = NULL;
4002  List *adjust_jumps = NIL;
4003  ListCell *lc;
4004  ListCell *lc2;
4005  intptr_t strict_opcode;
4006  intptr_t opcode;
4007 
4008  Assert(list_length(hash_exprs) == list_length(collations));
4009 
4010  state->parent = parent;
4011 
4012  /* Insert setup steps as needed. */
4013  ExecCreateExprSetupSteps(state, (Node *) hash_exprs);
4014 
4015  /*
4016  * When hashing more than 1 expression or if we have an init value, we
4017  * need somewhere to store the intermediate hash value so that it's
4018  * available to be combined with the result of subsequent hashing.
4019  */
4020  if (list_length(hash_exprs) > 1 || init_value != 0)
4021  iresult = palloc(sizeof(NullableDatum));
4022 
4023  if (init_value == 0)
4024  {
4025  /*
4026  * No initial value, so we can assign the result of the hash function
4027  * for the first hash_expr without having to concern ourselves with
4028  * combining the result with any initial value.
4029  */
4030  strict_opcode = EEOP_HASHDATUM_FIRST_STRICT;
4031  opcode = EEOP_HASHDATUM_FIRST;
4032  }
4033  else
4034  {
4035  /* Set up operation to set the initial value. */
4037  scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value);
4038  scratch.resvalue = &iresult->value;
4039  scratch.resnull = &iresult->isnull;
4040 
4041  ExprEvalPushStep(state, &scratch);
4042 
4043  /*
4044  * When using an initial value use the NEXT32/NEXT32_STRICT ops as the
4045  * FIRST/FIRST_STRICT ops would overwrite the stored initial value.
4046  */
4047  strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT;
4048  opcode = EEOP_HASHDATUM_NEXT32;
4049  }
4050 
4051  forboth(lc, hash_exprs, lc2, collations)
4052  {
4053  Expr *expr = (Expr *) lfirst(lc);
4054  FmgrInfo *finfo;
4055  FunctionCallInfo fcinfo;
4056  int i = foreach_current_index(lc);
4057  Oid funcid;
4058  Oid inputcollid = lfirst_oid(lc2);
4059 
4060  funcid = hashfunc_oids[i];
4061 
4062  /* Allocate hash function lookup data. */
4063  finfo = palloc0(sizeof(FmgrInfo));
4064  fcinfo = palloc0(SizeForFunctionCallInfo(1));
4065 
4066  fmgr_info(funcid, finfo);
4067 
4068  /*
4069  * Build the steps to evaluate the hash function's argument have it so
4070  * the value of that is stored in the 0th argument of the hash func.
4071  */
4072  ExecInitExprRec(expr,
4073  state,
4074  &fcinfo->args[0].value,
4075  &fcinfo->args[0].isnull);
4076 
4077  if (i == list_length(hash_exprs) - 1)
4078  {
4079  /* the result for hashing the final expr is stored in the state */
4080  scratch.resvalue = &state->resvalue;
4081  scratch.resnull = &state->resnull;
4082  }
4083  else
4084  {
4085  Assert(iresult != NULL);
4086 
4087  /* intermediate values are stored in an intermediate result */
4088  scratch.resvalue = &iresult->value;
4089  scratch.resnull = &iresult->isnull;
4090  }
4091 
4092  /*
4093  * NEXT32 opcodes need to look at the intermediate result. We might
4094  * as well just set this for all ops. FIRSTs won't look at it.
4095  */
4096  scratch.d.hashdatum.iresult = iresult;
4097 
4098  /* Initialize function call parameter structure too */
4099  InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL);
4100 
4101  scratch.d.hashdatum.finfo = finfo;
4102  scratch.d.hashdatum.fcinfo_data = fcinfo;
4103  scratch.d.hashdatum.fn_addr = finfo->fn_addr;
4104 
4105  scratch.opcode = opstrict[i] && !keep_nulls ? strict_opcode : opcode;
4106  scratch.d.hashdatum.jumpdone = -1;
4107 
4108  ExprEvalPushStep(state, &scratch);
4109  adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1);
4110 
4111  /*
4112  * For subsequent keys we must combine the hash value with the
4113  * previous hashes.
4114  */
4115  strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT;
4116  opcode = EEOP_HASHDATUM_NEXT32;
4117  }
4118 
4119  /* adjust jump targets */
4120  foreach(lc, adjust_jumps)
4121  {
4122  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4123 
4126  as->opcode == EEOP_HASHDATUM_NEXT32 ||
4128  Assert(as->d.hashdatum.jumpdone == -1);
4129  as->d.hashdatum.jumpdone = state->steps_len;
4130  }
4131 
4132  scratch.resvalue = NULL;
4133  scratch.resnull = NULL;
4134  scratch.opcode = EEOP_DONE;
4135  ExprEvalPushStep(state, &scratch);
4136 
4138 
4139  return state;
4140 }
4141 
4142 /*
4143  * Build equality expression that can be evaluated using ExecQual(), returning
4144  * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e
4145  * two nulls match, a null and a not-null don't match.
4146  *
4147  * desc: tuple descriptor of the to-be-compared tuples
4148  * numCols: the number of attributes to be examined
4149  * keyColIdx: array of attribute column numbers
4150  * eqFunctions: array of function oids of the equality functions to use
4151  * parent: parent executor node
4152  */
4153 ExprState *
4155  const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
4156  int numCols,
4157  const AttrNumber *keyColIdx,
4158  const Oid *eqfunctions,
4159  const Oid *collations,
4160  PlanState *parent)
4161 {
4163  ExprEvalStep scratch = {0};
4164  int maxatt = -1;
4165  List *adjust_jumps = NIL;
4166  ListCell *lc;
4167 
4168  /*
4169  * When no columns are actually compared, the result's always true. See
4170  * special case in ExecQual().
4171  */
4172  if (numCols == 0)
4173  return NULL;
4174 
4175  state->expr = NULL;
4176  state->flags = EEO_FLAG_IS_QUAL;
4177  state->parent = parent;
4178 
4179  scratch.resvalue = &state->resvalue;
4180  scratch.resnull = &state->resnull;
4181 
4182  /* compute max needed attribute */
4183  for (int natt = 0; natt < numCols; natt++)
4184  {
4185  int attno = keyColIdx[natt];
4186 
4187  if (attno > maxatt)
4188  maxatt = attno;
4189  }
4190  Assert(maxatt >= 0);
4191 
4192  /* push deform steps */
4193  scratch.opcode = EEOP_INNER_FETCHSOME;
4194  scratch.d.fetch.last_var = maxatt;
4195  scratch.d.fetch.fixed = false;
4196  scratch.d.fetch.known_desc = ldesc;
4197  scratch.d.fetch.kind = lops;
4198  if (ExecComputeSlotInfo(state, &scratch))
4199  ExprEvalPushStep(state, &scratch);
4200 
4201  scratch.opcode = EEOP_OUTER_FETCHSOME;
4202  scratch.d.fetch.last_var = maxatt;
4203  scratch.d.fetch.fixed = false;
4204  scratch.d.fetch.known_desc = rdesc;
4205  scratch.d.fetch.kind = rops;
4206  if (ExecComputeSlotInfo(state, &scratch))
4207  ExprEvalPushStep(state, &scratch);
4208 
4209  /*
4210  * Start comparing at the last field (least significant sort key). That's
4211  * the most likely to be different if we are dealing with sorted input.
4212  */
4213  for (int natt = numCols; --natt >= 0;)
4214  {
4215  int attno = keyColIdx[natt];
4216  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4217  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4218  Oid foid = eqfunctions[natt];
4219  Oid collid = collations[natt];
4220  FmgrInfo *finfo;
4221  FunctionCallInfo fcinfo;
4222  AclResult aclresult;
4223 
4224  /* Check permission to call function */
4225  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4226  if (aclresult != ACLCHECK_OK)
4227  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4228 
4230 
4231  /* Set up the primary fmgr lookup information */
4232  finfo = palloc0(sizeof(FmgrInfo));
4233  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4234  fmgr_info(foid, finfo);
4235  fmgr_info_set_expr(NULL, finfo);
4236  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4237  collid, NULL, NULL);
4238 
4239  /* left arg */
4240  scratch.opcode = EEOP_INNER_VAR;
4241  scratch.d.var.attnum = attno - 1;
4242  scratch.d.var.vartype = latt->atttypid;
4243  scratch.resvalue = &fcinfo->args[0].value;
4244  scratch.resnull = &fcinfo->args[0].isnull;
4245  ExprEvalPushStep(state, &scratch);
4246 
4247  /* right arg */
4248  scratch.opcode = EEOP_OUTER_VAR;
4249  scratch.d.var.attnum = attno - 1;
4250  scratch.d.var.vartype = ratt->atttypid;
4251  scratch.resvalue = &fcinfo->args[1].value;
4252  scratch.resnull = &fcinfo->args[1].isnull;
4253  ExprEvalPushStep(state, &scratch);
4254 
4255  /* evaluate distinctness */
4256  scratch.opcode = EEOP_NOT_DISTINCT;
4257  scratch.d.func.finfo = finfo;
4258  scratch.d.func.fcinfo_data = fcinfo;
4259  scratch.d.func.fn_addr = finfo->fn_addr;
4260  scratch.d.func.nargs = 2;
4261  scratch.resvalue = &state->resvalue;
4262  scratch.resnull = &state->resnull;
4263  ExprEvalPushStep(state, &scratch);
4264 
4265  /* then emit EEOP_QUAL to detect if result is false (or null) */
4266  scratch.opcode = EEOP_QUAL;
4267  scratch.d.qualexpr.jumpdone = -1;
4268  scratch.resvalue = &state->resvalue;
4269  scratch.resnull = &state->resnull;
4270  ExprEvalPushStep(state, &scratch);
4271  adjust_jumps = lappend_int(adjust_jumps,
4272  state->steps_len - 1);
4273  }
4274 
4275  /* adjust jump targets */
4276  foreach(lc, adjust_jumps)
4277  {
4278  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4279 
4280  Assert(as->opcode == EEOP_QUAL);
4281  Assert(as->d.qualexpr.jumpdone == -1);
4282  as->d.qualexpr.jumpdone = state->steps_len;
4283  }
4284 
4285  scratch.resvalue = NULL;
4286  scratch.resnull = NULL;
4287  scratch.opcode = EEOP_DONE;
4288  ExprEvalPushStep(state, &scratch);
4289 
4291 
4292  return state;
4293 }
4294 
4295 /*
4296  * Build equality expression that can be evaluated using ExecQual(), returning
4297  * true if the expression context's inner/outer tuples are equal. Datums in
4298  * the inner/outer slots are assumed to be in the same order and quantity as
4299  * the 'eqfunctions' parameter. NULLs are treated as equal.
4300  *
4301  * desc: tuple descriptor of the to-be-compared tuples
4302  * lops: the slot ops for the inner tuple slots
4303  * rops: the slot ops for the outer tuple slots
4304  * eqFunctions: array of function oids of the equality functions to use
4305  * this must be the same length as the 'param_exprs' list.
4306  * collations: collation Oids to use for equality comparison. Must be the
4307  * same length as the 'param_exprs' list.
4308  * parent: parent executor node
4309  */
4310 ExprState *
4312  const TupleTableSlotOps *lops,
4313  const TupleTableSlotOps *rops,
4314  const Oid *eqfunctions,
4315  const Oid *collations,
4316  const List *param_exprs,
4317  PlanState *parent)
4318 {
4320  ExprEvalStep scratch = {0};
4321  int maxatt = list_length(param_exprs);
4322  List *adjust_jumps = NIL;
4323  ListCell *lc;
4324 
4325  state->expr = NULL;
4326  state->flags = EEO_FLAG_IS_QUAL;
4327  state->parent = parent;
4328 
4329  scratch.resvalue = &state->resvalue;
4330  scratch.resnull = &state->resnull;
4331 
4332  /* push deform steps */
4333  scratch.opcode = EEOP_INNER_FETCHSOME;
4334  scratch.d.fetch.last_var = maxatt;
4335  scratch.d.fetch.fixed = false;
4336  scratch.d.fetch.known_desc = desc;
4337  scratch.d.fetch.kind = lops;
4338  if (ExecComputeSlotInfo(state, &scratch))
4339  ExprEvalPushStep(state, &scratch);
4340 
4341  scratch.opcode = EEOP_OUTER_FETCHSOME;
4342  scratch.d.fetch.last_var = maxatt;
4343  scratch.d.fetch.fixed = false;
4344  scratch.d.fetch.known_desc = desc;
4345  scratch.d.fetch.kind = rops;
4346  if (ExecComputeSlotInfo(state, &scratch))
4347  ExprEvalPushStep(state, &scratch);
4348 
4349  for (int attno = 0; attno < maxatt; attno++)
4350  {
4351  Form_pg_attribute att = TupleDescAttr(desc, attno);
4352  Oid foid = eqfunctions[attno];
4353  Oid collid = collations[attno];
4354  FmgrInfo *finfo;
4355  FunctionCallInfo fcinfo;
4356  AclResult aclresult;
4357 
4358  /* Check permission to call function */
4359  aclresult = object_aclcheck(ProcedureRelationId, foid, GetUserId(), ACL_EXECUTE);
4360  if (aclresult != ACLCHECK_OK)
4361  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4362 
4364 
4365  /* Set up the primary fmgr lookup information */
4366  finfo = palloc0(sizeof(FmgrInfo));
4367  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4368  fmgr_info(foid, finfo);
4369  fmgr_info_set_expr(NULL, finfo);
4370  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4371  collid, NULL, NULL);
4372 
4373  /* left arg */
4374  scratch.opcode = EEOP_INNER_VAR;
4375  scratch.d.var.attnum = attno;
4376  scratch.d.var.vartype = att->atttypid;
4377  scratch.resvalue = &fcinfo->args[0].value;
4378  scratch.resnull = &fcinfo->args[0].isnull;
4379  ExprEvalPushStep(state, &scratch);
4380 
4381  /* right arg */
4382  scratch.opcode = EEOP_OUTER_VAR;
4383  scratch.d.var.attnum = attno;
4384  scratch.d.var.vartype = att->atttypid;
4385  scratch.resvalue = &fcinfo->args[1].value;
4386  scratch.resnull = &fcinfo->args[1].isnull;
4387  ExprEvalPushStep(state, &scratch);
4388 
4389  /* evaluate distinctness */
4390  scratch.opcode = EEOP_NOT_DISTINCT;
4391  scratch.d.func.finfo = finfo;
4392  scratch.d.func.fcinfo_data = fcinfo;
4393  scratch.d.func.fn_addr = finfo->fn_addr;
4394  scratch.d.func.nargs = 2;
4395  scratch.resvalue = &state->resvalue;
4396  scratch.resnull = &state->resnull;
4397  ExprEvalPushStep(state, &scratch);
4398 
4399  /* then emit EEOP_QUAL to detect if result is false (or null) */
4400  scratch.opcode = EEOP_QUAL;
4401  scratch.d.qualexpr.jumpdone = -1;
4402  scratch.resvalue = &state->resvalue;
4403  scratch.resnull = &state->resnull;
4404  ExprEvalPushStep(state, &scratch);
4405  adjust_jumps = lappend_int(adjust_jumps,
4406  state->steps_len - 1);
4407  }
4408 
4409  /* adjust jump targets */
4410  foreach(lc, adjust_jumps)
4411  {
4412  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4413 
4414  Assert(as->opcode == EEOP_QUAL);
4415  Assert(as->d.qualexpr.jumpdone == -1);
4416  as->d.qualexpr.jumpdone = state->steps_len;
4417  }
4418 
4419  scratch.resvalue = NULL;
4420  scratch.resnull = NULL;
4421  scratch.opcode = EEOP_DONE;
4422  ExprEvalPushStep(state, &scratch);
4423 
4425 
4426  return state;
4427 }
4428 
4429 /*
4430  * Push steps to evaluate a JsonExpr and its various subsidiary expressions.
4431  */
4432 static void
4434  Datum *resv, bool *resnull,
4435  ExprEvalStep *scratch)
4436 {
4437  JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
4438  ListCell *argexprlc;
4439  ListCell *argnamelc;
4440  List *jumps_return_null = NIL;
4441  List *jumps_to_end = NIL;
4442  ListCell *lc;
4443  ErrorSaveContext *escontext;
4444  bool returning_domain =
4445  get_typtype(jsexpr->returning->typid) == TYPTYPE_DOMAIN;
4446 
4447  Assert(jsexpr->on_error != NULL);
4448 
4449  jsestate->jsexpr = jsexpr;
4450 
4451  /*
4452  * Evaluate formatted_expr storing the result into
4453  * jsestate->formatted_expr.
4454  */
4456  &jsestate->formatted_expr.value,
4457  &jsestate->formatted_expr.isnull);
4458 
4459  /* JUMP to return NULL if formatted_expr evaluates to NULL */
4460  jumps_return_null = lappend_int(jumps_return_null, state->steps_len);
4461  scratch->opcode = EEOP_JUMP_IF_NULL;
4462  scratch->resnull = &jsestate->formatted_expr.isnull;
4463  scratch->d.jump.jumpdone = -1; /* set below */
4464  ExprEvalPushStep(state, scratch);
4465 
4466  /*
4467  * Evaluate pathspec expression storing the result into
4468  * jsestate->pathspec.
4469  */
4470  ExecInitExprRec((Expr *) jsexpr->path_spec, state,
4471  &jsestate->pathspec.value,
4472  &jsestate->pathspec.isnull);
4473 
4474  /* JUMP to return NULL if path_spec evaluates to NULL */
4475  jumps_return_null = lappend_int(jumps_return_null, state->steps_len);
4476  scratch->opcode = EEOP_JUMP_IF_NULL;
4477  scratch->resnull = &jsestate->pathspec.isnull;
4478  scratch->d.jump.jumpdone = -1; /* set below */
4479  ExprEvalPushStep(state, scratch);
4480 
4481  /* Steps to compute PASSING args. */
4482  jsestate->args = NIL;
4483  forboth(argexprlc, jsexpr->passing_values,
4484  argnamelc, jsexpr->passing_names)
4485  {
4486  Expr *argexpr = (Expr *) lfirst(argexprlc);
4487  String *argname = lfirst_node(String, argnamelc);
4488  JsonPathVariable *var = palloc(sizeof(*var));
4489 
4490  var->name = argname->sval;
4491  var->namelen = strlen(var->name);
4492  var->typid = exprType((Node *) argexpr);
4493  var->typmod = exprTypmod((Node *) argexpr);
4494 
4495  ExecInitExprRec((Expr *) argexpr, state, &var->value, &var->isnull);
4496 
4497  jsestate->args = lappend(jsestate->args, var);
4498  }
4499 
4500  /* Step for jsonpath evaluation; see ExecEvalJsonExprPath(). */
4501  scratch->opcode = EEOP_JSONEXPR_PATH;
4502  scratch->resvalue = resv;
4503  scratch->resnull = resnull;
4504  scratch->d.jsonexpr.jsestate = jsestate;
4505  ExprEvalPushStep(state, scratch);
4506 
4507  /*
4508  * Step to return NULL after jumping to skip the EEOP_JSONEXPR_PATH step
4509  * when either formatted_expr or pathspec is NULL. Adjust jump target
4510  * addresses of JUMPs that we added above.
4511  */
4512  foreach(lc, jumps_return_null)
4513  {
4514  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4515 
4516  as->d.jump.jumpdone = state->steps_len;
4517  }
4518  scratch->opcode = EEOP_CONST;
4519  scratch->resvalue = resv;
4520  scratch->resnull = resnull;
4521  scratch->d.constval.value = (Datum) 0;
4522  scratch->d.constval.isnull = true;
4523  ExprEvalPushStep(state, scratch);
4524 
4525  escontext = jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR ?
4526  &jsestate->escontext : NULL;
4527 
4528  /*
4529  * To handle coercion errors softly, use the following ErrorSaveContext to
4530  * pass to ExecInitExprRec() when initializing the coercion expressions
4531  * and in the EEOP_JSONEXPR_COERCION step.
4532  */
4533  jsestate->escontext.type = T_ErrorSaveContext;
4534 
4535  /*
4536  * Steps to coerce the result value computed by EEOP_JSONEXPR_PATH or the
4537  * NULL returned on NULL input as described above.
4538  */
4539  jsestate->jump_eval_coercion = -1;
4540  if (jsexpr->use_json_coercion)
4541  {
4542  jsestate->jump_eval_coercion = state->steps_len;
4543 
4544  ExecInitJsonCoercion(state, jsexpr->returning, escontext,
4545  jsexpr->omit_quotes,
4546  jsexpr->op == JSON_EXISTS_OP,
4547  resv, resnull);
4548  }
4549  else if (jsexpr->use_io_coercion)
4550  {
4551  /*
4552  * Here we only need to initialize the FunctionCallInfo for the target
4553  * type's input function, which is called by ExecEvalJsonExprPath()
4554  * itself, so no additional step is necessary.
4555  */
4556  Oid typinput;
4557  Oid typioparam;
4558  FmgrInfo *finfo;
4559  FunctionCallInfo fcinfo;
4560 
4561  getTypeInputInfo(jsexpr->returning->typid, &typinput, &typioparam);
4562  finfo = palloc0(sizeof(FmgrInfo));
4563  fcinfo = palloc0(SizeForFunctionCallInfo(3));
4564  fmgr_info(typinput, finfo);
4565  fmgr_info_set_expr((Node *) jsexpr->returning, finfo);
4566  InitFunctionCallInfoData(*fcinfo, finfo, 3, InvalidOid, NULL, NULL);
4567 
4568  /*
4569  * We can preload the second and third arguments for the input
4570  * function, since they're constants.
4571  */
4572  fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
4573  fcinfo->args[1].isnull = false;
4574  fcinfo->args[2].value = Int32GetDatum(jsexpr->returning->typmod);
4575  fcinfo->args[2].isnull = false;
4576  fcinfo->context = (Node *) escontext;
4577 
4578  jsestate->input_fcinfo = fcinfo;
4579  }
4580 
4581  /*
4582  * Add a special step, if needed, to check if the coercion evaluation ran
4583  * into an error but was not thrown because the ON ERROR behavior is not
4584  * ERROR. It will set jsestate->error if an error did occur.
4585  */
4586  if (jsestate->jump_eval_coercion >= 0 && escontext != NULL)
4587  {
4589  scratch->d.jsonexpr.jsestate = jsestate;
4590  ExprEvalPushStep(state, scratch);
4591  }
4592 
4593  jsestate->jump_empty = jsestate->jump_error = -1;
4594 
4595  /*
4596  * Step to check jsestate->error and return the ON ERROR expression if
4597  * there is one. This handles both the errors that occur during jsonpath
4598  * evaluation in EEOP_JSONEXPR_PATH and subsequent coercion evaluation.
4599  *
4600  * Speed up common cases by avoiding extra steps for a NULL-valued ON
4601  * ERROR expression unless RETURNING a domain type, where constraints must
4602  * be checked. ExecEvalJsonExprPath() already returns NULL on error,
4603  * making additional steps unnecessary in typical scenarios. Note that the
4604  * default ON ERROR behavior for JSON_VALUE() and JSON_QUERY() is to
4605  * return NULL.
4606  */
4607  if (jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR &&
4608  (!(IsA(jsexpr->on_error->expr, Const) &&
4609  ((Const *) jsexpr->on_error->expr)->constisnull) ||
4610  returning_domain))
4611  {
4612  ErrorSaveContext *saved_escontext;
4613 
4614  jsestate->jump_error = state->steps_len;
4615 
4616  /* JUMP to end if false, that is, skip the ON ERROR expression. */
4617  jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4618  scratch->opcode = EEOP_JUMP_IF_NOT_TRUE;
4619  scratch->resvalue = &jsestate->error.value;
4620  scratch->resnull = &jsestate->error.isnull;
4621  scratch->d.jump.jumpdone = -1; /* set below */
4622  ExprEvalPushStep(state, scratch);
4623 
4624  /*
4625  * Steps to evaluate the ON ERROR expression; handle errors softly to
4626  * rethrow them in COERCION_FINISH step that will be added later.
4627  */
4628  saved_escontext = state->escontext;
4629  state->escontext = escontext;
4630  ExecInitExprRec((Expr *) jsexpr->on_error->expr,
4631  state, resv, resnull);
4632  state->escontext = saved_escontext;
4633 
4634  /* Step to coerce the ON ERROR expression if needed */
4635  if (jsexpr->on_error->coerce)
4636  ExecInitJsonCoercion(state, jsexpr->returning, escontext,
4637  jsexpr->omit_quotes, false,
4638  resv, resnull);
4639 
4640  /*
4641  * Add a COERCION_FINISH step to check for errors that may occur when
4642  * coercing and rethrow them.
4643  */
4644  if (jsexpr->on_error->coerce ||
4645  IsA(jsexpr->on_error->expr, CoerceViaIO) ||
4646  IsA(jsexpr->on_error->expr, CoerceToDomain))
4647  {
4649  scratch->resvalue = resv;
4650  scratch->resnull = resnull;
4651  scratch->d.jsonexpr.jsestate = jsestate;
4652  ExprEvalPushStep(state, scratch);
4653  }
4654 
4655  /* JUMP to end to skip the ON EMPTY steps added below. */
4656  jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4657  scratch->opcode = EEOP_JUMP;
4658  scratch->d.jump.jumpdone = -1;
4659  ExprEvalPushStep(state, scratch);
4660  }
4661 
4662  /*
4663  * Step to check jsestate->empty and return the ON EMPTY expression if
4664  * there is one.
4665  *
4666  * See the comment above for details on the optimization for NULL-valued
4667  * expressions.
4668  */
4669  if (jsexpr->on_empty != NULL &&
4670  jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR &&
4671  (!(IsA(jsexpr->on_empty->expr, Const) &&
4672  ((Const *) jsexpr->on_empty->expr)->constisnull) ||
4673  returning_domain))
4674  {
4675  ErrorSaveContext *saved_escontext;
4676 
4677  jsestate->jump_empty = state->steps_len;
4678 
4679  /* JUMP to end if false, that is, skip the ON EMPTY expression. */
4680  jumps_to_end = lappend_int(jumps_to_end, state->steps_len);
4681  scratch->opcode = EEOP_JUMP_IF_NOT_TRUE;
4682  scratch->resvalue = &jsestate->empty.value;
4683  scratch->resnull = &jsestate->empty.isnull;
4684  scratch->d.jump.jumpdone = -1; /* set below */
4685  ExprEvalPushStep(state, scratch);
4686 
4687  /*
4688  * Steps to evaluate the ON EMPTY expression; handle errors softly to
4689  * rethrow them in COERCION_FINISH step that will be added later.
4690  */
4691  saved_escontext = state->escontext;
4692  state->escontext = escontext;
4693  ExecInitExprRec((Expr *) jsexpr->on_empty->expr,
4694  state, resv, resnull);
4695  state->escontext = saved_escontext;
4696 
4697  /* Step to coerce the ON EMPTY expression if needed */
4698  if (jsexpr->on_empty->coerce)
4699  ExecInitJsonCoercion(state, jsexpr->returning, escontext,
4700  jsexpr->omit_quotes, false,
4701  resv, resnull);
4702 
4703  /*
4704  * Add a COERCION_FINISH step to check for errors that may occur when
4705  * coercing and rethrow them.
4706  */
4707  if (jsexpr->on_empty->coerce ||
4708  IsA(jsexpr->on_empty->expr, CoerceViaIO) ||
4709  IsA(jsexpr->on_empty->expr, CoerceToDomain))
4710  {
4711 
4713  scratch->resvalue = resv;
4714  scratch->resnull = resnull;
4715  scratch->d.jsonexpr.jsestate = jsestate;
4716  ExprEvalPushStep(state, scratch);
4717  }
4718  }
4719 
4720  foreach(lc, jumps_to_end)
4721  {
4722  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4723 
4724  as->d.jump.jumpdone = state->steps_len;
4725  }
4726 
4727  jsestate->jump_end = state->steps_len;
4728 }
4729 
4730 /*
4731  * Initialize a EEOP_JSONEXPR_COERCION step to coerce the value given in resv
4732  * to the given RETURNING type.
4733  */
4734 static void
4736  ErrorSaveContext *escontext, bool omit_quotes,
4737  bool exists_coerce,
4738  Datum *resv, bool *resnull)
4739 {
4740  ExprEvalStep scratch = {0};
4741 
4742  /* For json_populate_type() */
4743  scratch.opcode = EEOP_JSONEXPR_COERCION;
4744  scratch.resvalue = resv;
4745  scratch.resnull = resnull;
4746  scratch.d.jsonexpr_coercion.targettype = returning->typid;
4747  scratch.d.jsonexpr_coercion.targettypmod = returning->typmod;
4748  scratch.d.jsonexpr_coercion.json_coercion_cache = NULL;
4749  scratch.d.jsonexpr_coercion.escontext = escontext;
4750  scratch.d.jsonexpr_coercion.omit_quotes = omit_quotes;
4751  scratch.d.jsonexpr_coercion.exists_coerce = exists_coerce;
4752  scratch.d.jsonexpr_coercion.exists_cast_to_int = exists_coerce &&
4753  getBaseType(returning->typid) == INT4OID;
4754  scratch.d.jsonexpr_coercion.exists_check_domain = exists_coerce &&
4755  DomainHasConstraints(returning->typid);
4756  ExprEvalPushStep(state, &scratch);
4757 }
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:506
#define MAXALIGN(LEN)
Definition: c.h:802
#define Max(x, y)
Definition: c.h:989
#define Assert(condition)
Definition: c.h:849
unsigned char bool
Definition: c.h:459
#define OidIsValid(objectId)
Definition: c.h:766
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:3375
static void ExecInitSubPlanExpr(SubPlan *subplan, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:2719
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:2795
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:3869
ExprState * ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
Definition: execExpr.c:175
static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
Definition: execExpr.c:3023
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:330
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2584
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:3530
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
static bool isAssignmentIndirectionExpr(Expr *expr)
Definition: execExpr.c:3338
static void ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:3096
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:794
static bool expr_setup_walker(Node *node, ExprSetupInfo *info)
Definition: execExpr.c:2861
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:4735
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition: execExpr.c:310
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2925
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:4154
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:2610
static void ExecCreateExprSetupSteps(ExprState *state, Node *node)
Definition: execExpr.c:2779
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:3994
static void ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, Datum *resv, bool *resnull, ExprEvalStep *scratch)
Definition: execExpr.c:4433
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:4311
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:495
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:504
int executor_errposition(EState *estate, int location)
Definition: execUtils.c:872
#define outerPlanState(node)
Definition: execnodes.h:1224
#define innerPlanState(node)
Definition: execnodes.h:1223
@ DOM_CONSTRAINT_CHECK
Definition: execnodes.h:1013
@ DOM_CONSTRAINT_NOTNULL
Definition: execnodes.h:1012
#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:2277
#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:6688
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:1976
@ IS_NOT_FALSE
Definition: primnodes.h:1976
@ IS_NOT_UNKNOWN
Definition: primnodes.h:1976
@ IS_TRUE
Definition: primnodes.h:1976
@ IS_UNKNOWN
Definition: primnodes.h:1976
@ IS_FALSE
Definition: primnodes.h:1976
@ 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:1766
@ JSON_TABLE_OP
Definition: primnodes.h:1805
@ JSON_EXISTS_OP
Definition: primnodes.h:1802
@ IS_NULL
Definition: primnodes.h:1952
@ IS_NOT_NULL
Definition: primnodes.h:1952
#define OUTER_VAR
Definition: primnodes.h:237
@ JSCTOR_JSON_SERIALIZE
Definition: primnodes.h:1696
@ JSCTOR_JSON_PARSE
Definition: primnodes.h:1694
@ JSCTOR_JSON_SCALAR
Definition: primnodes.h:1695
#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:2498
List * aggs
Definition: execnodes.h:2499
AggStatePerTrans pertrans
Definition: execnodes.h:2508
AggStrategy aggstrategy
Definition: execnodes.h:2502
int numtrans
Definition: execnodes.h:2501
ExprContext * hashcontext
Definition: execnodes.h:2509
AggSplit aggsplit
Definition: execnodes.h:2503
int num_hashes
Definition: execnodes.h:2539
int maxsets
Definition: execnodes.h:2528
ExprContext ** aggcontexts
Definition: execnodes.h:2510
Definition: plannodes.h:998
List * groupingSets
Definition: plannodes.h:1029
List * aggdistinct
Definition: primnodes.h:474
List * aggdirectargs
Definition: primnodes.h:465
List * args
Definition: primnodes.h:468
Expr * aggfilter
Definition: primnodes.h:477
List * aggorder
Definition: primnodes.h:471
List * elements
Definition: primnodes.h:1380
BoolExprType boolop
Definition: primnodes.h:939
List * args
Definition: primnodes.h:940
BoolTestType booltesttype
Definition: primnodes.h:1983
Expr * arg
Definition: primnodes.h:1982
Expr * arg
Definition: primnodes.h:1313
Expr * defresult
Definition: primnodes.h:1315
List * args
Definition: primnodes.h:1314
List * args
Definition: primnodes.h:1492
Expr * arg
Definition: primnodes.h:1207
Oid resulttype
Definition: primnodes.h:1208
DomainConstraintType constrainttype
Definition: execnodes.h:1019
MemoryContext es_query_cxt
Definition: execnodes.h:675
NodeTag type
Definition: miscnodes.h:46
struct ExprEvalStep::@52::@62 jump
struct ExprEvalStep::@52::@68 iocoerce
struct ExprEvalStep::@52::@81 domaincheck
struct ExprEvalStep::@52::@56 assign_var
struct ExprEvalStep::@52::@95 agg_plain_pergroup_nullcheck
struct ExprEvalStep::@52::@78 fieldstore
struct ExprEvalStep::@52::@97 agg_trans
struct ExprEvalStep::@52::@75 rowcompare_final
struct ExprEvalStep::@52::@96 agg_presorted_distinctcheck
struct ExprEvalStep::@52::@77 fieldselect
struct ExprEvalStep::@52::@53 fetch
struct ExprEvalStep::@52::@92 subplan
struct ExprEvalStep::@52::@90 grouping_func
struct ExprEvalStep::@52::@79 sbsref_subscript
struct ExprEvalStep::@52::@59 func
struct ExprEvalStep::@52::@67 make_readonly
struct ExprEvalStep::@52::@80 sbsref
struct ExprEvalStep::@52::@61 qualexpr
intptr_t opcode
Definition: execExpr.h:290
struct ExprEvalStep::@52::@91 window_func
struct ExprEvalStep::@52::@98 is_json
Datum * resvalue
Definition: execExpr.h:293
struct ExprEvalStep::@52::@82 hashdatum_initvalue
struct ExprEvalStep::@52::@70 nextvalueexpr
struct ExprEvalStep::@52::@84 convert_rowtype
struct ExprEvalStep::@52::@63 nulltest_row
struct ExprEvalStep::@52::@54 var
struct ExprEvalStep::@52::@76 minmax
struct ExprEvalStep::@52::@55 wholerow
struct ExprEvalStep::@52::@87 xmlexpr
struct ExprEvalStep::@52::@100 jsonexpr_coercion
union ExprEvalStep::@52 d
struct ExprEvalStep::@52::@57 assign_tmp
struct ExprEvalStep::@52::@72 arraycoerce
struct ExprEvalStep::@52::@58 constval
struct ExprEvalStep::@52::@86 hashedscalararrayop
struct ExprEvalStep::@52::@99 jsonexpr
bool * resnull
Definition: execExpr.h:294
struct ExprEvalStep::@52::@94 agg_strict_input_check
struct ExprEvalStep::@52::@74 rowcompare_step
struct ExprEvalStep::@52::@85 scalararrayop
struct ExprEvalStep::@52::@89 aggref
struct ExprEvalStep::@52::@93 agg_deserialize
struct ExprEvalStep::@52::@66 casetest
struct ExprEvalStep::@52::@69 sqlvaluefunction
struct ExprEvalStep::@52::@83 hashdatum
struct ExprEvalStep::@52::@60 boolexpr
struct ExprEvalStep::@52::@88 json_constructor
struct ExprEvalStep::@52::@73 row
struct ExprEvalStep::@52::@64 param
struct ExprEvalStep::@52::@71 arrayexpr
AttrNumber last_inner
Definition: execExpr.c:59
List * multiexpr_subplans
Definition: execExpr.c:63
AttrNumber last_scan
Definition: execExpr.c:61
AttrNumber last_outer
Definition: execExpr.c:60
Expr * expr
Definition: execnodes.h:111
NodeTag type
Definition: execnodes.h:80
Datum resvalue
Definition: execnodes.h:91
struct ExprEvalStep * steps
Definition: execnodes.h:102
int steps_alloc
Definition: execnodes.h:122
bool resnull
Definition: execnodes.h:89
ParamListInfo ext_params
Definition: execnodes.h:126
struct PlanState * parent
Definition: execnodes.h:125
bool * innermost_casenull
Definition: execnodes.h:129
Datum * innermost_caseval
Definition: execnodes.h:128
int steps_len
Definition: execnodes.h:121
AttrNumber fieldnum
Definition: primnodes.h:1129
Expr * arg
Definition: primnodes.h:1128
List * newvals
Definition: primnodes.h:1160
Expr * arg
Definition: primnodes.h:1159
Definition: fmgr.h:57
PGFunction fn_addr
Definition: fmgr.h:58
bool fn_retset
Definition: fmgr.h:62
bool fn_strict
Definition: fmgr.h:61
Oid funcid
Definition: primnodes.h:750
List * args
Definition: primnodes.h:768
FmgrInfo * flinfo
Definition: fmgr.h:87
fmNodePtr context
Definition: fmgr.h:88
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Node * expr
Definition: primnodes.h:1791
JsonBehaviorType btype
Definition: primnodes.h:1790
JsonConstructorExpr * constructor
Definition: execExpr.h:796
struct JsonConstructorExprState::@101 * arg_type_cache
JsonReturning * returning
Definition: primnodes.h:1710
JsonConstructorType type
Definition: primnodes.h:1706
int jump_eval_coercion
Definition: execnodes.h:1070
NullableDatum empty
Definition: execnodes.h:1056
FunctionCallInfo input_fcinfo
Definition: execnodes.h:1084
JsonExpr * jsexpr
Definition: execnodes.h:1034
NullableDatum error
Definition: execnodes.h:1053
NullableDatum pathspec
Definition: execnodes.h:1040
ErrorSaveContext escontext
Definition: execnodes.h:1093
NullableDatum formatted_expr
Definition: execnodes.h:1037
Node * formatted_expr
Definition: primnodes.h:1823
List * passing_values
Definition: primnodes.h:1836
JsonBehavior * on_empty
Definition: primnodes.h:1839
List * passing_names
Definition: primnodes.h:1835
Node * path_spec
Definition: primnodes.h:1829
bool use_io_coercion
Definition: primnodes.h:1846
JsonReturning * returning
Definition: primnodes.h:1832
bool use_json_coercion
Definition: primnodes.h:1847
JsonExprOp op
Definition: primnodes.h:1817
JsonBehavior * on_error
Definition: primnodes.h:1840
bool omit_quotes
Definition: primnodes.h:1853
JsonFormatType format_type
Definition: primnodes.h:1651
JsonFormat * format
Definition: primnodes.h:1663
Expr * formatted_expr
Definition: primnodes.h:1684
Expr * raw_expr
Definition: primnodes.h:1683
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1518
MinMaxOp op
Definition: primnodes.h:1516
Definition: nodes.h:129
NullTestType nulltesttype
Definition: primnodes.h:1959
Expr * arg
Definition: primnodes.h:1958
Datum value
Definition: postgres.h:75
bool isnull
Definition: postgres.h:77
List * args
Definition: primnodes.h:836
ParamCompileHook paramCompile
Definition: params.h:114
int paramid
Definition: primnodes.h:377
Oid paramtype
Definition: primnodes.h:378
ParamKind paramkind
Definition: primnodes.h:376
bool inneropsset
Definition: execnodes.h:1212
bool outeropsset
Definition: execnodes.h:1211
const TupleTableSlotOps * outerops
Definition: execnodes.h:1203
const TupleTableSlotOps * innerops
Definition: execnodes.h:1204
const TupleTableSlotOps * scanops
Definition: execnodes.h:1202
Plan * plan
Definition: execnodes.h:1128
bool outeropsfixed
Definition: execnodes.h:1207
EState * state
Definition: execnodes.h:1130
bool scanopsset
Definition: execnodes.h:1210
TupleDesc scandesc
Definition: execnodes.h:1177
bool scanopsfixed
Definition: execnodes.h:1206
bool inneropsfixed
Definition: execnodes.h:1208
List * targetlist
Definition: plannodes.h:153
ExprState pi_state
Definition: execnodes.h:365
ExprContext * pi_exprContext
Definition: execnodes.h:367
Expr * arg
Definition: primnodes.h:1184
RowCompareType rctype
Definition: primnodes.h:1468
List * args
Definition: primnodes.h:1411
PlanState ps
Definition: execnodes.h:1575
Definition: value.h:64
char * sval
Definition: value.h:68
List * args
Definition: primnodes.h:1091
List * parParam
Definition: primnodes.h:1090
SubLinkType subLinkType
Definition: primnodes.h:1065
ExecEvalSubroutine sbs_fetch_old
Definition: execExpr.h:790
ExecEvalBoolSubroutine sbs_check_subscripts
Definition: execExpr.h:787
ExecEvalSubroutine sbs_assign
Definition: execExpr.h:789
ExecEvalSubroutine sbs_fetch
Definition: execExpr.h:788
SubscriptExecSetup exec_setup
Definition: subscripting.h:161
Expr * refassgnexpr
Definition: primnodes.h:703
List * refupperindexpr
Definition: primnodes.h:693
Expr * refexpr
Definition: primnodes.h:701
List * reflowerindexpr
Definition: primnodes.h:699
Expr * expr
Definition: primnodes.h:2190
AttrNumber resno
Definition: primnodes.h:2192
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
Definition: primnodes.h:248
WindowFunc * wfunc
Definition: execnodes.h:884
ExprState * aggfilter
Definition: execnodes.h:886
List * args
Definition: primnodes.h:575
Expr * aggfilter
Definition: primnodes.h:577
List * args
Definition: primnodes.h:1608
List * named_args
Definition: primnodes.h:1604
Definition: regguts.h:323
Definition: type.h:88
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref, MemoryContext refctx, bool need_exprstate)
Definition: typcache.c:1330
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1850
bool DomainHasConstraints(Oid type_id)
Definition: typcache.c:1417
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:356
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition: typcache.c:1884
#define TYPECACHE_CMP_PROC
Definition: typcache.h:140
static void convert(const int32 val, char *const buf)
Definition: zic.c:1992