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-2022, 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_type.h"
36 #include "executor/execExpr.h"
37 #include "executor/nodeSubplan.h"
38 #include "funcapi.h"
39 #include "jit/jit.h"
40 #include "miscadmin.h"
41 #include "nodes/makefuncs.h"
42 #include "nodes/nodeFuncs.h"
43 #include "nodes/subscripting.h"
44 #include "optimizer/optimizer.h"
45 #include "pgstat.h"
46 #include "utils/acl.h"
47 #include "utils/array.h"
48 #include "utils/builtins.h"
49 #include "utils/datum.h"
50 #include "utils/json.h"
51 #include "utils/jsonb.h"
52 #include "utils/jsonpath.h"
53 #include "utils/lsyscache.h"
54 #include "utils/typcache.h"
55 
56 
57 typedef struct LastAttnumInfo
58 {
63 
64 static void ExecReadyExpr(ExprState *state);
65 static void ExecInitExprRec(Expr *node, ExprState *state,
66  Datum *resv, bool *resnull);
67 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
68  Oid funcid, Oid inputcollid,
69  ExprState *state);
70 static void ExecInitExprSlots(ExprState *state, Node *node);
71 static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info);
72 static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
74 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
75  ExprState *state);
76 static void ExecInitSubscriptingRef(ExprEvalStep *scratch,
77  SubscriptingRef *sbsref,
79  Datum *resv, bool *resnull);
80 static bool isAssignmentIndirectionExpr(Expr *expr);
81 static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
83  Datum *resv, bool *resnull);
84 static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
85  ExprEvalStep *scratch,
86  FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
87  int transno, int setno, int setoff, bool ishash,
88  bool nullcheck);
89 
90 
91 static ExprState *
92 ExecInitExprInternal(Expr *node, PlanState *parent, ParamListInfo ext_params,
93  Datum *caseval, bool *casenull)
94 {
96  ExprEvalStep scratch = {0};
97 
98  /* Special case: NULL expression produces a NULL ExprState pointer */
99  if (node == NULL)
100  return NULL;
101 
102  /* Initialize ExprState with empty step list */
104  state->expr = node;
105  state->parent = parent;
106  state->ext_params = ext_params;
107  state->innermost_caseval = caseval;
108  state->innermost_casenull = casenull;
109 
110  /* Insert EEOP_*_FETCHSOME steps as needed */
111  ExecInitExprSlots(state, (Node *) node);
112 
113  /* Compile the expression proper */
114  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
115 
116  /* Finally, append a DONE step */
117  scratch.opcode = EEOP_DONE;
118  ExprEvalPushStep(state, &scratch);
119 
121 
122  return state;
123 }
124 
125 /*
126  * ExecInitExpr: prepare an expression tree for execution
127  *
128  * This function builds and returns an ExprState implementing the given
129  * Expr node tree. The return ExprState can then be handed to ExecEvalExpr
130  * for execution. Because the Expr tree itself is read-only as far as
131  * ExecInitExpr and ExecEvalExpr are concerned, several different executions
132  * of the same plan tree can occur concurrently. (But note that an ExprState
133  * does mutate at runtime, so it can't be re-used concurrently.)
134  *
135  * This must be called in a memory context that will last as long as repeated
136  * executions of the expression are needed. Typically the context will be
137  * the same as the per-query context of the associated ExprContext.
138  *
139  * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to
140  * the lists of such nodes held by the parent PlanState.
141  *
142  * Note: there is no ExecEndExpr function; we assume that any resource
143  * cleanup needed will be handled by just releasing the memory context
144  * in which the state tree is built. Functions that require additional
145  * cleanup work can register a shutdown callback in the ExprContext.
146  *
147  * 'node' is the root of the expression tree to compile.
148  * 'parent' is the PlanState node that owns the expression.
149  *
150  * 'parent' may be NULL if we are preparing an expression that is not
151  * associated with a plan tree. (If so, it can't have aggs or subplans.)
152  * Such cases should usually come through ExecPrepareExpr, not directly here.
153  *
154  * Also, if 'node' is NULL, we just return NULL. This is convenient for some
155  * callers that may or may not have an expression that needs to be compiled.
156  * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr,
157  * although ExecQual and ExecCheck will accept one (and treat it as "true").
158  */
159 ExprState *
160 ExecInitExpr(Expr *node, PlanState *parent)
161 {
162  return ExecInitExprInternal(node, parent, NULL, NULL, NULL);
163 }
164 
165 /*
166  * ExecInitExprWithParams: prepare a standalone expression tree for execution
167  *
168  * This is the same as ExecInitExpr, except that there is no parent PlanState,
169  * and instead we may have a ParamListInfo describing PARAM_EXTERN Params.
170  */
171 ExprState *
173 {
174  return ExecInitExprInternal(node, NULL, ext_params, NULL, NULL);
175 }
176 
177 /*
178  * ExecInitExprWithCaseValue: prepare an expression tree for execution
179  *
180  * This is the same as ExecInitExpr, except that a pointer to the value for
181  * CasTestExpr is passed here.
182  */
183 ExprState *
185  Datum *caseval, bool *casenull)
186 {
187  return ExecInitExprInternal(node, parent, NULL, caseval, casenull);
188 }
189 
190 /*
191  * ExecInitQual: prepare a qual for execution by ExecQual
192  *
193  * Prepares for the evaluation of a conjunctive boolean expression (qual list
194  * with implicit AND semantics) that returns true if none of the
195  * subexpressions are false.
196  *
197  * We must return true if the list is empty. Since that's a very common case,
198  * we optimize it a bit further by translating to a NULL ExprState pointer
199  * rather than setting up an ExprState that computes constant TRUE. (Some
200  * especially hot-spot callers of ExecQual detect this and avoid calling
201  * ExecQual at all.)
202  *
203  * If any of the subexpressions yield NULL, then the result of the conjunction
204  * is false. This makes ExecQual primarily useful for evaluating WHERE
205  * clauses, since SQL specifies that tuples with null WHERE results do not
206  * get selected.
207  */
208 ExprState *
209 ExecInitQual(List *qual, PlanState *parent)
210 {
211  ExprState *state;
212  ExprEvalStep scratch = {0};
213  List *adjust_jumps = NIL;
214  ListCell *lc;
215 
216  /* short-circuit (here and in ExecQual) for empty restriction list */
217  if (qual == NIL)
218  return NULL;
219 
220  Assert(IsA(qual, List));
221 
223  state->expr = (Expr *) qual;
224  state->parent = parent;
225  state->ext_params = NULL;
226 
227  /* mark expression as to be used with ExecQual() */
228  state->flags = EEO_FLAG_IS_QUAL;
229 
230  /* Insert EEOP_*_FETCHSOME steps as needed */
231  ExecInitExprSlots(state, (Node *) qual);
232 
233  /*
234  * ExecQual() needs to return false for an expression returning NULL. That
235  * allows us to short-circuit the evaluation the first time a NULL is
236  * encountered. As qual evaluation is a hot-path this warrants using a
237  * special opcode for qual evaluation that's simpler than BOOL_AND (which
238  * has more complex NULL handling).
239  */
240  scratch.opcode = EEOP_QUAL;
241 
242  /*
243  * We can use ExprState's resvalue/resnull as target for each qual expr.
244  */
245  scratch.resvalue = &state->resvalue;
246  scratch.resnull = &state->resnull;
247 
248  foreach(lc, qual)
249  {
250  Expr *node = (Expr *) lfirst(lc);
251 
252  /* first evaluate expression */
253  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
254 
255  /* then emit EEOP_QUAL to detect if it's false (or null) */
256  scratch.d.qualexpr.jumpdone = -1;
257  ExprEvalPushStep(state, &scratch);
258  adjust_jumps = lappend_int(adjust_jumps,
259  state->steps_len - 1);
260  }
261 
262  /* adjust jump targets */
263  foreach(lc, adjust_jumps)
264  {
265  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
266 
267  Assert(as->opcode == EEOP_QUAL);
268  Assert(as->d.qualexpr.jumpdone == -1);
269  as->d.qualexpr.jumpdone = state->steps_len;
270  }
271 
272  /*
273  * At the end, we don't need to do anything more. The last qual expr must
274  * have yielded TRUE, and since its result is stored in the desired output
275  * location, we're done.
276  */
277  scratch.opcode = EEOP_DONE;
278  ExprEvalPushStep(state, &scratch);
279 
281 
282  return state;
283 }
284 
285 /*
286  * ExecInitCheck: prepare a check constraint for execution by ExecCheck
287  *
288  * This is much like ExecInitQual/ExecQual, except that a null result from
289  * the conjunction is treated as TRUE. This behavior is appropriate for
290  * evaluating CHECK constraints, since SQL specifies that NULL constraint
291  * conditions are not failures.
292  *
293  * Note that like ExecInitQual, this expects input in implicit-AND format.
294  * Users of ExecCheck that have expressions in normal explicit-AND format
295  * can just apply ExecInitExpr to produce suitable input for ExecCheck.
296  */
297 ExprState *
298 ExecInitCheck(List *qual, PlanState *parent)
299 {
300  /* short-circuit (here and in ExecCheck) for empty restriction list */
301  if (qual == NIL)
302  return NULL;
303 
304  Assert(IsA(qual, List));
305 
306  /*
307  * Just convert the implicit-AND list to an explicit AND (if there's more
308  * than one entry), and compile normally. Unlike ExecQual, we can't
309  * short-circuit on NULL results, so the regular AND behavior is needed.
310  */
311  return ExecInitExpr(make_ands_explicit(qual), parent);
312 }
313 
314 /*
315  * Call ExecInitExpr() on a list of expressions, return a list of ExprStates.
316  */
317 List *
319 {
320  List *result = NIL;
321  ListCell *lc;
322 
323  foreach(lc, nodes)
324  {
325  Expr *e = lfirst(lc);
326 
327  result = lappend(result, ExecInitExpr(e, parent));
328  }
329 
330  return result;
331 }
332 
333 /*
334  * ExecBuildProjectionInfo
335  *
336  * Build a ProjectionInfo node for evaluating the given tlist in the given
337  * econtext, and storing the result into the tuple slot. (Caller must have
338  * ensured that tuple slot has a descriptor matching the tlist!)
339  *
340  * inputDesc can be NULL, but if it is not, we check to see whether simple
341  * Vars in the tlist match the descriptor. It is important to provide
342  * inputDesc for relation-scan plan nodes, as a cross check that the relation
343  * hasn't been changed since the plan was made. At higher levels of a plan,
344  * there is no need to recheck.
345  *
346  * This is implemented by internally building an ExprState that performs the
347  * whole projection in one go.
348  *
349  * Caution: before PG v10, the targetList was a list of ExprStates; now it
350  * should be the planner-created targetlist, since we do the compilation here.
351  */
354  ExprContext *econtext,
355  TupleTableSlot *slot,
356  PlanState *parent,
357  TupleDesc inputDesc)
358 {
360  ExprState *state;
361  ExprEvalStep scratch = {0};
362  ListCell *lc;
363 
364  projInfo->pi_exprContext = econtext;
365  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
366  projInfo->pi_state.type = T_ExprState;
367  state = &projInfo->pi_state;
368  state->expr = (Expr *) targetList;
369  state->parent = parent;
370  state->ext_params = NULL;
371 
372  state->resultslot = slot;
373 
374  /* Insert EEOP_*_FETCHSOME steps as needed */
375  ExecInitExprSlots(state, (Node *) targetList);
376 
377  /* Now compile each tlist column */
378  foreach(lc, targetList)
379  {
380  TargetEntry *tle = lfirst_node(TargetEntry, lc);
381  Var *variable = NULL;
382  AttrNumber attnum = 0;
383  bool isSafeVar = false;
384 
385  /*
386  * If tlist expression is a safe non-system Var, use the fast-path
387  * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
388  * CheckVarSlotCompatibility() during plan startup. If a source slot
389  * was provided, we make the equivalent tests here; if a slot was not
390  * provided, we assume that no check is needed because we're dealing
391  * with a non-relation-scan-level expression.
392  */
393  if (tle->expr != NULL &&
394  IsA(tle->expr, Var) &&
395  ((Var *) tle->expr)->varattno > 0)
396  {
397  /* Non-system Var, but how safe is it? */
398  variable = (Var *) tle->expr;
399  attnum = variable->varattno;
400 
401  if (inputDesc == NULL)
402  isSafeVar = true; /* can't check, just assume OK */
403  else if (attnum <= inputDesc->natts)
404  {
405  Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
406 
407  /*
408  * If user attribute is dropped or has a type mismatch, don't
409  * use ASSIGN_*_VAR. Instead let the normal expression
410  * machinery handle it (which'll possibly error out).
411  */
412  if (!attr->attisdropped && variable->vartype == attr->atttypid)
413  {
414  isSafeVar = true;
415  }
416  }
417  }
418 
419  if (isSafeVar)
420  {
421  /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
422  switch (variable->varno)
423  {
424  case INNER_VAR:
425  /* get the tuple from the inner node */
426  scratch.opcode = EEOP_ASSIGN_INNER_VAR;
427  break;
428 
429  case OUTER_VAR:
430  /* get the tuple from the outer node */
431  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
432  break;
433 
434  /* INDEX_VAR is handled by default case */
435 
436  default:
437  /* get the tuple from the relation being scanned */
438  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
439  break;
440  }
441 
442  scratch.d.assign_var.attnum = attnum - 1;
443  scratch.d.assign_var.resultnum = tle->resno - 1;
444  ExprEvalPushStep(state, &scratch);
445  }
446  else
447  {
448  /*
449  * Otherwise, compile the column expression normally.
450  *
451  * We can't tell the expression to evaluate directly into the
452  * result slot, as the result slot (and the exprstate for that
453  * matter) can change between executions. We instead evaluate
454  * into the ExprState's resvalue/resnull and then move.
455  */
456  ExecInitExprRec(tle->expr, state,
457  &state->resvalue, &state->resnull);
458 
459  /*
460  * Column might be referenced multiple times in upper nodes, so
461  * force value to R/O - but only if it could be an expanded datum.
462  */
463  if (get_typlen(exprType((Node *) tle->expr)) == -1)
465  else
466  scratch.opcode = EEOP_ASSIGN_TMP;
467  scratch.d.assign_tmp.resultnum = tle->resno - 1;
468  ExprEvalPushStep(state, &scratch);
469  }
470  }
471 
472  scratch.opcode = EEOP_DONE;
473  ExprEvalPushStep(state, &scratch);
474 
476 
477  return projInfo;
478 }
479 
480 /*
481  * ExecBuildUpdateProjection
482  *
483  * Build a ProjectionInfo node for constructing a new tuple during UPDATE.
484  * The projection will be executed in the given econtext and the result will
485  * be stored into the given tuple slot. (Caller must have ensured that tuple
486  * slot has a descriptor matching the target rel!)
487  *
488  * When evalTargetList is false, targetList contains the UPDATE ... SET
489  * expressions that have already been computed by a subplan node; the values
490  * from this tlist are assumed to be available in the "outer" tuple slot.
491  * When evalTargetList is true, targetList contains the UPDATE ... SET
492  * expressions that must be computed (which could contain references to
493  * the outer, inner, or scan tuple slots).
494  *
495  * In either case, targetColnos contains a list of the target column numbers
496  * corresponding to the non-resjunk entries of targetList. The tlist values
497  * are assigned into these columns of the result tuple slot. Target columns
498  * not listed in targetColnos are filled from the UPDATE's old tuple, which
499  * is assumed to be available in the "scan" tuple slot.
500  *
501  * targetList can also contain resjunk columns. These must be evaluated
502  * if evalTargetList is true, but their values are discarded.
503  *
504  * relDesc must describe the relation we intend to update.
505  *
506  * This is basically a specialized variant of ExecBuildProjectionInfo.
507  * However, it also performs sanity checks equivalent to ExecCheckPlanOutput.
508  * Since we never make a normal tlist equivalent to the whole
509  * tuple-to-be-assigned, there is no convenient way to apply
510  * ExecCheckPlanOutput, so we must do our safety checks here.
511  */
514  bool evalTargetList,
515  List *targetColnos,
516  TupleDesc relDesc,
517  ExprContext *econtext,
518  TupleTableSlot *slot,
519  PlanState *parent)
520 {
522  ExprState *state;
523  int nAssignableCols;
524  bool sawJunk;
525  Bitmapset *assignedCols;
526  LastAttnumInfo deform = {0, 0, 0};
527  ExprEvalStep scratch = {0};
528  int outerattnum;
529  ListCell *lc,
530  *lc2;
531 
532  projInfo->pi_exprContext = econtext;
533  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
534  projInfo->pi_state.type = T_ExprState;
535  state = &projInfo->pi_state;
536  if (evalTargetList)
537  state->expr = (Expr *) targetList;
538  else
539  state->expr = NULL; /* not used */
540  state->parent = parent;
541  state->ext_params = NULL;
542 
543  state->resultslot = slot;
544 
545  /*
546  * Examine the targetList to see how many non-junk columns there are, and
547  * to verify that the non-junk columns come before the junk ones.
548  */
549  nAssignableCols = 0;
550  sawJunk = false;
551  foreach(lc, targetList)
552  {
553  TargetEntry *tle = lfirst_node(TargetEntry, lc);
554 
555  if (tle->resjunk)
556  sawJunk = true;
557  else
558  {
559  if (sawJunk)
560  elog(ERROR, "subplan target list is out of order");
561  nAssignableCols++;
562  }
563  }
564 
565  /* We should have one targetColnos entry per non-junk column */
566  if (nAssignableCols != list_length(targetColnos))
567  elog(ERROR, "targetColnos does not match subplan target list");
568 
569  /*
570  * Build a bitmapset of the columns in targetColnos. (We could just use
571  * list_member_int() tests, but that risks O(N^2) behavior with many
572  * columns.)
573  */
574  assignedCols = NULL;
575  foreach(lc, targetColnos)
576  {
577  AttrNumber targetattnum = lfirst_int(lc);
578 
579  assignedCols = bms_add_member(assignedCols, targetattnum);
580  }
581 
582  /*
583  * We need to insert EEOP_*_FETCHSOME steps to ensure the input tuples are
584  * sufficiently deconstructed. The scan tuple must be deconstructed at
585  * least as far as the last old column we need.
586  */
587  for (int attnum = relDesc->natts; attnum > 0; attnum--)
588  {
589  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
590 
591  if (attr->attisdropped)
592  continue;
593  if (bms_is_member(attnum, assignedCols))
594  continue;
595  deform.last_scan = attnum;
596  break;
597  }
598 
599  /*
600  * If we're actually evaluating the tlist, incorporate its input
601  * requirements too; otherwise, we'll just need to fetch the appropriate
602  * number of columns of the "outer" tuple.
603  */
604  if (evalTargetList)
605  get_last_attnums_walker((Node *) targetList, &deform);
606  else
607  deform.last_outer = nAssignableCols;
608 
609  ExecPushExprSlots(state, &deform);
610 
611  /*
612  * Now generate code to evaluate the tlist's assignable expressions or
613  * fetch them from the outer tuple, incidentally validating that they'll
614  * be of the right data type. The checks above ensure that the forboth()
615  * will iterate over exactly the non-junk columns.
616  */
617  outerattnum = 0;
618  forboth(lc, targetList, lc2, targetColnos)
619  {
620  TargetEntry *tle = lfirst_node(TargetEntry, lc);
621  AttrNumber targetattnum = lfirst_int(lc2);
622  Form_pg_attribute attr;
623 
624  Assert(!tle->resjunk);
625 
626  /*
627  * Apply sanity checks comparable to ExecCheckPlanOutput().
628  */
629  if (targetattnum <= 0 || targetattnum > relDesc->natts)
630  ereport(ERROR,
631  (errcode(ERRCODE_DATATYPE_MISMATCH),
632  errmsg("table row type and query-specified row type do not match"),
633  errdetail("Query has too many columns.")));
634  attr = TupleDescAttr(relDesc, targetattnum - 1);
635 
636  if (attr->attisdropped)
637  ereport(ERROR,
638  (errcode(ERRCODE_DATATYPE_MISMATCH),
639  errmsg("table row type and query-specified row type do not match"),
640  errdetail("Query provides a value for a dropped column at ordinal position %d.",
641  targetattnum)));
642  if (exprType((Node *) tle->expr) != attr->atttypid)
643  ereport(ERROR,
644  (errcode(ERRCODE_DATATYPE_MISMATCH),
645  errmsg("table row type and query-specified row type do not match"),
646  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
647  format_type_be(attr->atttypid),
648  targetattnum,
649  format_type_be(exprType((Node *) tle->expr)))));
650 
651  /* OK, generate code to perform the assignment. */
652  if (evalTargetList)
653  {
654  /*
655  * We must evaluate the TLE's expression and assign it. We do not
656  * bother jumping through hoops for "safe" Vars like
657  * ExecBuildProjectionInfo does; this is a relatively less-used
658  * path and it doesn't seem worth expending code for that.
659  */
660  ExecInitExprRec(tle->expr, state,
661  &state->resvalue, &state->resnull);
662  /* Needn't worry about read-only-ness here, either. */
663  scratch.opcode = EEOP_ASSIGN_TMP;
664  scratch.d.assign_tmp.resultnum = targetattnum - 1;
665  ExprEvalPushStep(state, &scratch);
666  }
667  else
668  {
669  /* Just assign from the outer tuple. */
670  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
671  scratch.d.assign_var.attnum = outerattnum;
672  scratch.d.assign_var.resultnum = targetattnum - 1;
673  ExprEvalPushStep(state, &scratch);
674  }
675  outerattnum++;
676  }
677 
678  /*
679  * If we're evaluating the tlist, must evaluate any resjunk columns too.
680  * (This matters for things like MULTIEXPR_SUBLINK SubPlans.)
681  */
682  if (evalTargetList)
683  {
684  for_each_cell(lc, targetList, lc)
685  {
686  TargetEntry *tle = lfirst_node(TargetEntry, lc);
687 
688  Assert(tle->resjunk);
689  ExecInitExprRec(tle->expr, state,
690  &state->resvalue, &state->resnull);
691  }
692  }
693 
694  /*
695  * Now generate code to copy over any old columns that were not assigned
696  * to, and to ensure that dropped columns are set to NULL.
697  */
698  for (int attnum = 1; attnum <= relDesc->natts; attnum++)
699  {
700  Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1);
701 
702  if (attr->attisdropped)
703  {
704  /* Put a null into the ExprState's resvalue/resnull ... */
705  scratch.opcode = EEOP_CONST;
706  scratch.resvalue = &state->resvalue;
707  scratch.resnull = &state->resnull;
708  scratch.d.constval.value = (Datum) 0;
709  scratch.d.constval.isnull = true;
710  ExprEvalPushStep(state, &scratch);
711  /* ... then assign it to the result slot */
712  scratch.opcode = EEOP_ASSIGN_TMP;
713  scratch.d.assign_tmp.resultnum = attnum - 1;
714  ExprEvalPushStep(state, &scratch);
715  }
716  else if (!bms_is_member(attnum, assignedCols))
717  {
718  /* Certainly the right type, so needn't check */
719  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
720  scratch.d.assign_var.attnum = attnum - 1;
721  scratch.d.assign_var.resultnum = attnum - 1;
722  ExprEvalPushStep(state, &scratch);
723  }
724  }
725 
726  scratch.opcode = EEOP_DONE;
727  ExprEvalPushStep(state, &scratch);
728 
730 
731  return projInfo;
732 }
733 
734 /*
735  * ExecPrepareExpr --- initialize for expression execution outside a normal
736  * Plan tree context.
737  *
738  * This differs from ExecInitExpr in that we don't assume the caller is
739  * already running in the EState's per-query context. Also, we run the
740  * passed expression tree through expression_planner() to prepare it for
741  * execution. (In ordinary Plan trees the regular planning process will have
742  * made the appropriate transformations on expressions, but for standalone
743  * expressions this won't have happened.)
744  */
745 ExprState *
746 ExecPrepareExpr(Expr *node, EState *estate)
747 {
748  ExprState *result;
749  MemoryContext oldcontext;
750 
751  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
752 
753  node = expression_planner(node);
754 
755  result = ExecInitExpr(node, NULL);
756 
757  MemoryContextSwitchTo(oldcontext);
758 
759  return result;
760 }
761 
762 /*
763  * ExecPrepareQual --- initialize for qual execution outside a normal
764  * Plan tree context.
765  *
766  * This differs from ExecInitQual in that we don't assume the caller is
767  * already running in the EState's per-query context. Also, we run the
768  * passed expression tree through expression_planner() to prepare it for
769  * execution. (In ordinary Plan trees the regular planning process will have
770  * made the appropriate transformations on expressions, but for standalone
771  * expressions this won't have happened.)
772  */
773 ExprState *
774 ExecPrepareQual(List *qual, EState *estate)
775 {
776  ExprState *result;
777  MemoryContext oldcontext;
778 
779  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
780 
781  qual = (List *) expression_planner((Expr *) qual);
782 
783  result = ExecInitQual(qual, NULL);
784 
785  MemoryContextSwitchTo(oldcontext);
786 
787  return result;
788 }
789 
790 /*
791  * ExecPrepareCheck -- initialize check constraint for execution outside a
792  * normal Plan tree context.
793  *
794  * See ExecPrepareExpr() and ExecInitCheck() for details.
795  */
796 ExprState *
797 ExecPrepareCheck(List *qual, EState *estate)
798 {
799  ExprState *result;
800  MemoryContext oldcontext;
801 
802  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
803 
804  qual = (List *) expression_planner((Expr *) qual);
805 
806  result = ExecInitCheck(qual, NULL);
807 
808  MemoryContextSwitchTo(oldcontext);
809 
810  return result;
811 }
812 
813 /*
814  * Call ExecPrepareExpr() on each member of a list of Exprs, and return
815  * a list of ExprStates.
816  *
817  * See ExecPrepareExpr() for details.
818  */
819 List *
821 {
822  List *result = NIL;
823  MemoryContext oldcontext;
824  ListCell *lc;
825 
826  /* Ensure that the list cell nodes are in the right context too */
827  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
828 
829  foreach(lc, nodes)
830  {
831  Expr *e = (Expr *) lfirst(lc);
832 
833  result = lappend(result, ExecPrepareExpr(e, estate));
834  }
835 
836  MemoryContextSwitchTo(oldcontext);
837 
838  return result;
839 }
840 
841 /*
842  * ExecCheck - evaluate a check constraint
843  *
844  * For check constraints, a null result is taken as TRUE, ie the constraint
845  * passes.
846  *
847  * The check constraint may have been prepared with ExecInitCheck
848  * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND
849  * format, but a regular boolean expression prepared with ExecInitExpr or
850  * ExecPrepareExpr works too.
851  */
852 bool
854 {
855  Datum ret;
856  bool isnull;
857 
858  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
859  if (state == NULL)
860  return true;
861 
862  /* verify that expression was not compiled using ExecInitQual */
863  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
864 
865  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
866 
867  if (isnull)
868  return true;
869 
870  return DatumGetBool(ret);
871 }
872 
873 /*
874  * Prepare a compiled expression for execution. This has to be called for
875  * every ExprState before it can be executed.
876  *
877  * NB: While this currently only calls ExecReadyInterpretedExpr(),
878  * this will likely get extended to further expression evaluation methods.
879  * Therefore this should be used instead of directly calling
880  * ExecReadyInterpretedExpr().
881  */
882 static void
884 {
885  if (jit_compile_expr(state))
886  return;
887 
889 }
890 
891 /*
892  * Append the steps necessary for the evaluation of node to ExprState->steps,
893  * possibly recursing into sub-expressions of node.
894  *
895  * node - expression to evaluate
896  * state - ExprState to whose ->steps to append the necessary operations
897  * resv / resnull - where to store the result of the node into
898  */
899 static void
901  Datum *resv, bool *resnull)
902 {
903  ExprEvalStep scratch = {0};
904 
905  /* Guard against stack overflow due to overly complex expressions */
907 
908  /* Step's output location is always what the caller gave us */
909  Assert(resv != NULL && resnull != NULL);
910  scratch.resvalue = resv;
911  scratch.resnull = resnull;
912 
913  /* cases should be ordered as they are in enum NodeTag */
914  switch (nodeTag(node))
915  {
916  case T_Var:
917  {
918  Var *variable = (Var *) node;
919 
920  if (variable->varattno == InvalidAttrNumber)
921  {
922  /* whole-row Var */
923  ExecInitWholeRowVar(&scratch, variable, state);
924  }
925  else if (variable->varattno <= 0)
926  {
927  /* system column */
928  scratch.d.var.attnum = variable->varattno;
929  scratch.d.var.vartype = variable->vartype;
930  switch (variable->varno)
931  {
932  case INNER_VAR:
933  scratch.opcode = EEOP_INNER_SYSVAR;
934  break;
935  case OUTER_VAR:
936  scratch.opcode = EEOP_OUTER_SYSVAR;
937  break;
938 
939  /* INDEX_VAR is handled by default case */
940 
941  default:
942  scratch.opcode = EEOP_SCAN_SYSVAR;
943  break;
944  }
945  }
946  else
947  {
948  /* regular user column */
949  scratch.d.var.attnum = variable->varattno - 1;
950  scratch.d.var.vartype = variable->vartype;
951  switch (variable->varno)
952  {
953  case INNER_VAR:
954  scratch.opcode = EEOP_INNER_VAR;
955  break;
956  case OUTER_VAR:
957  scratch.opcode = EEOP_OUTER_VAR;
958  break;
959 
960  /* INDEX_VAR is handled by default case */
961 
962  default:
963  scratch.opcode = EEOP_SCAN_VAR;
964  break;
965  }
966  }
967 
968  ExprEvalPushStep(state, &scratch);
969  break;
970  }
971 
972  case T_Const:
973  {
974  Const *con = (Const *) node;
975 
976  scratch.opcode = EEOP_CONST;
977  scratch.d.constval.value = con->constvalue;
978  scratch.d.constval.isnull = con->constisnull;
979 
980  ExprEvalPushStep(state, &scratch);
981  break;
982  }
983 
984  case T_Param:
985  {
986  Param *param = (Param *) node;
987  ParamListInfo params;
988 
989  switch (param->paramkind)
990  {
991  case PARAM_EXEC:
992  scratch.opcode = EEOP_PARAM_EXEC;
993  scratch.d.param.paramid = param->paramid;
994  scratch.d.param.paramtype = param->paramtype;
995  ExprEvalPushStep(state, &scratch);
996  break;
997  case PARAM_EXTERN:
998 
999  /*
1000  * If we have a relevant ParamCompileHook, use it;
1001  * otherwise compile a standard EEOP_PARAM_EXTERN
1002  * step. ext_params, if supplied, takes precedence
1003  * over info from the parent node's EState (if any).
1004  */
1005  if (state->ext_params)
1006  params = state->ext_params;
1007  else if (state->parent &&
1008  state->parent->state)
1009  params = state->parent->state->es_param_list_info;
1010  else
1011  params = NULL;
1012  if (params && params->paramCompile)
1013  {
1014  params->paramCompile(params, param, state,
1015  resv, resnull);
1016  }
1017  else
1018  {
1019  scratch.opcode = EEOP_PARAM_EXTERN;
1020  scratch.d.param.paramid = param->paramid;
1021  scratch.d.param.paramtype = param->paramtype;
1022  ExprEvalPushStep(state, &scratch);
1023  }
1024  break;
1025  default:
1026  elog(ERROR, "unrecognized paramkind: %d",
1027  (int) param->paramkind);
1028  break;
1029  }
1030  break;
1031  }
1032 
1033  case T_Aggref:
1034  {
1035  Aggref *aggref = (Aggref *) node;
1036 
1037  scratch.opcode = EEOP_AGGREF;
1038  scratch.d.aggref.aggno = aggref->aggno;
1039 
1040  if (state->parent && IsA(state->parent, AggState))
1041  {
1042  AggState *aggstate = (AggState *) state->parent;
1043 
1044  aggstate->aggs = lappend(aggstate->aggs, aggref);
1045  }
1046  else
1047  {
1048  /* planner messed up */
1049  elog(ERROR, "Aggref found in non-Agg plan node");
1050  }
1051 
1052  ExprEvalPushStep(state, &scratch);
1053  break;
1054  }
1055 
1056  case T_GroupingFunc:
1057  {
1058  GroupingFunc *grp_node = (GroupingFunc *) node;
1059  Agg *agg;
1060 
1061  if (!state->parent || !IsA(state->parent, AggState) ||
1062  !IsA(state->parent->plan, Agg))
1063  elog(ERROR, "GroupingFunc found in non-Agg plan node");
1064 
1065  scratch.opcode = EEOP_GROUPING_FUNC;
1066 
1067  agg = (Agg *) (state->parent->plan);
1068 
1069  if (agg->groupingSets)
1070  scratch.d.grouping_func.clauses = grp_node->cols;
1071  else
1072  scratch.d.grouping_func.clauses = NIL;
1073 
1074  ExprEvalPushStep(state, &scratch);
1075  break;
1076  }
1077 
1078  case T_WindowFunc:
1079  {
1080  WindowFunc *wfunc = (WindowFunc *) node;
1082 
1083  wfstate->wfunc = wfunc;
1084 
1085  if (state->parent && IsA(state->parent, WindowAggState))
1086  {
1087  WindowAggState *winstate = (WindowAggState *) state->parent;
1088  int nfuncs;
1089 
1090  winstate->funcs = lappend(winstate->funcs, wfstate);
1091  nfuncs = ++winstate->numfuncs;
1092  if (wfunc->winagg)
1093  winstate->numaggs++;
1094 
1095  /* for now initialize agg using old style expressions */
1096  wfstate->args = ExecInitExprList(wfunc->args,
1097  state->parent);
1098  wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
1099  state->parent);
1100 
1101  /*
1102  * Complain if the windowfunc's arguments contain any
1103  * windowfuncs; nested window functions are semantically
1104  * nonsensical. (This should have been caught earlier,
1105  * but we defend against it here anyway.)
1106  */
1107  if (nfuncs != winstate->numfuncs)
1108  ereport(ERROR,
1109  (errcode(ERRCODE_WINDOWING_ERROR),
1110  errmsg("window function calls cannot be nested")));
1111  }
1112  else
1113  {
1114  /* planner messed up */
1115  elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
1116  }
1117 
1118  scratch.opcode = EEOP_WINDOW_FUNC;
1119  scratch.d.window_func.wfstate = wfstate;
1120  ExprEvalPushStep(state, &scratch);
1121  break;
1122  }
1123 
1124  case T_SubscriptingRef:
1125  {
1126  SubscriptingRef *sbsref = (SubscriptingRef *) node;
1127 
1128  ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull);
1129  break;
1130  }
1131 
1132  case T_FuncExpr:
1133  {
1134  FuncExpr *func = (FuncExpr *) node;
1135 
1136  ExecInitFunc(&scratch, node,
1137  func->args, func->funcid, func->inputcollid,
1138  state);
1139  ExprEvalPushStep(state, &scratch);
1140  break;
1141  }
1142 
1143  case T_OpExpr:
1144  {
1145  OpExpr *op = (OpExpr *) node;
1146 
1147  ExecInitFunc(&scratch, node,
1148  op->args, op->opfuncid, op->inputcollid,
1149  state);
1150  ExprEvalPushStep(state, &scratch);
1151  break;
1152  }
1153 
1154  case T_DistinctExpr:
1155  {
1156  DistinctExpr *op = (DistinctExpr *) node;
1157 
1158  ExecInitFunc(&scratch, node,
1159  op->args, op->opfuncid, op->inputcollid,
1160  state);
1161 
1162  /*
1163  * Change opcode of call instruction to EEOP_DISTINCT.
1164  *
1165  * XXX: historically we've not called the function usage
1166  * pgstat infrastructure - that seems inconsistent given that
1167  * we do so for normal function *and* operator evaluation. If
1168  * we decided to do that here, we'd probably want separate
1169  * opcodes for FUSAGE or not.
1170  */
1171  scratch.opcode = EEOP_DISTINCT;
1172  ExprEvalPushStep(state, &scratch);
1173  break;
1174  }
1175 
1176  case T_NullIfExpr:
1177  {
1178  NullIfExpr *op = (NullIfExpr *) node;
1179 
1180  ExecInitFunc(&scratch, node,
1181  op->args, op->opfuncid, op->inputcollid,
1182  state);
1183 
1184  /*
1185  * Change opcode of call instruction to EEOP_NULLIF.
1186  *
1187  * XXX: historically we've not called the function usage
1188  * pgstat infrastructure - that seems inconsistent given that
1189  * we do so for normal function *and* operator evaluation. If
1190  * we decided to do that here, we'd probably want separate
1191  * opcodes for FUSAGE or not.
1192  */
1193  scratch.opcode = EEOP_NULLIF;
1194  ExprEvalPushStep(state, &scratch);
1195  break;
1196  }
1197 
1198  case T_ScalarArrayOpExpr:
1199  {
1200  ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
1201  Expr *scalararg;
1202  Expr *arrayarg;
1203  FmgrInfo *finfo;
1204  FunctionCallInfo fcinfo;
1205  AclResult aclresult;
1206  FmgrInfo *hash_finfo;
1207  FunctionCallInfo hash_fcinfo;
1208  Oid cmpfuncid;
1209 
1210  /*
1211  * Select the correct comparison function. When we do hashed
1212  * NOT IN clauses, the opfuncid will be the inequality
1213  * comparison function and negfuncid will be set to equality.
1214  * We need to use the equality function for hash probes.
1215  */
1216  if (OidIsValid(opexpr->negfuncid))
1217  {
1218  Assert(OidIsValid(opexpr->hashfuncid));
1219  cmpfuncid = opexpr->negfuncid;
1220  }
1221  else
1222  cmpfuncid = opexpr->opfuncid;
1223 
1224  Assert(list_length(opexpr->args) == 2);
1225  scalararg = (Expr *) linitial(opexpr->args);
1226  arrayarg = (Expr *) lsecond(opexpr->args);
1227 
1228  /* Check permission to call function */
1229  aclresult = pg_proc_aclcheck(cmpfuncid,
1230  GetUserId(),
1231  ACL_EXECUTE);
1232  if (aclresult != ACLCHECK_OK)
1233  aclcheck_error(aclresult, OBJECT_FUNCTION,
1234  get_func_name(cmpfuncid));
1235  InvokeFunctionExecuteHook(cmpfuncid);
1236 
1237  if (OidIsValid(opexpr->hashfuncid))
1238  {
1239  aclresult = pg_proc_aclcheck(opexpr->hashfuncid,
1240  GetUserId(),
1241  ACL_EXECUTE);
1242  if (aclresult != ACLCHECK_OK)
1243  aclcheck_error(aclresult, OBJECT_FUNCTION,
1244  get_func_name(opexpr->hashfuncid));
1246  }
1247 
1248  /* Set up the primary fmgr lookup information */
1249  finfo = palloc0(sizeof(FmgrInfo));
1250  fcinfo = palloc0(SizeForFunctionCallInfo(2));
1251  fmgr_info(cmpfuncid, finfo);
1252  fmgr_info_set_expr((Node *) node, finfo);
1253  InitFunctionCallInfoData(*fcinfo, finfo, 2,
1254  opexpr->inputcollid, NULL, NULL);
1255 
1256  /*
1257  * If hashfuncid is set, we create a EEOP_HASHED_SCALARARRAYOP
1258  * step instead of a EEOP_SCALARARRAYOP. This provides much
1259  * faster lookup performance than the normal linear search
1260  * when the number of items in the array is anything but very
1261  * small.
1262  */
1263  if (OidIsValid(opexpr->hashfuncid))
1264  {
1265  hash_finfo = palloc0(sizeof(FmgrInfo));
1266  hash_fcinfo = palloc0(SizeForFunctionCallInfo(1));
1267  fmgr_info(opexpr->hashfuncid, hash_finfo);
1268  fmgr_info_set_expr((Node *) node, hash_finfo);
1269  InitFunctionCallInfoData(*hash_fcinfo, hash_finfo,
1270  1, opexpr->inputcollid, NULL,
1271  NULL);
1272 
1273  scratch.d.hashedscalararrayop.hash_finfo = hash_finfo;
1274  scratch.d.hashedscalararrayop.hash_fcinfo_data = hash_fcinfo;
1275  scratch.d.hashedscalararrayop.hash_fn_addr = hash_finfo->fn_addr;
1276 
1277  /* Evaluate scalar directly into left function argument */
1278  ExecInitExprRec(scalararg, state,
1279  &fcinfo->args[0].value, &fcinfo->args[0].isnull);
1280 
1281  /*
1282  * Evaluate array argument into our return value. There's
1283  * no danger in that, because the return value is
1284  * guaranteed to be overwritten by
1285  * EEOP_HASHED_SCALARARRAYOP, and will not be passed to
1286  * any other expression.
1287  */
1288  ExecInitExprRec(arrayarg, state, resv, resnull);
1289 
1290  /* And perform the operation */
1292  scratch.d.hashedscalararrayop.inclause = opexpr->useOr;
1293  scratch.d.hashedscalararrayop.finfo = finfo;
1294  scratch.d.hashedscalararrayop.fcinfo_data = fcinfo;
1295  scratch.d.hashedscalararrayop.fn_addr = finfo->fn_addr;
1296 
1297  scratch.d.hashedscalararrayop.hash_finfo = hash_finfo;
1298  scratch.d.hashedscalararrayop.hash_fcinfo_data = hash_fcinfo;
1299  scratch.d.hashedscalararrayop.hash_fn_addr = hash_finfo->fn_addr;
1300 
1301  ExprEvalPushStep(state, &scratch);
1302  }
1303  else
1304  {
1305  /* Evaluate scalar directly into left function argument */
1306  ExecInitExprRec(scalararg, state,
1307  &fcinfo->args[0].value,
1308  &fcinfo->args[0].isnull);
1309 
1310  /*
1311  * Evaluate array argument into our return value. There's
1312  * no danger in that, because the return value is
1313  * guaranteed to be overwritten by EEOP_SCALARARRAYOP, and
1314  * will not be passed to any other expression.
1315  */
1316  ExecInitExprRec(arrayarg, state, resv, resnull);
1317 
1318  /* And perform the operation */
1319  scratch.opcode = EEOP_SCALARARRAYOP;
1320  scratch.d.scalararrayop.element_type = InvalidOid;
1321  scratch.d.scalararrayop.useOr = opexpr->useOr;
1322  scratch.d.scalararrayop.finfo = finfo;
1323  scratch.d.scalararrayop.fcinfo_data = fcinfo;
1324  scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
1325  ExprEvalPushStep(state, &scratch);
1326  }
1327  break;
1328  }
1329 
1330  case T_BoolExpr:
1331  {
1332  BoolExpr *boolexpr = (BoolExpr *) node;
1333  int nargs = list_length(boolexpr->args);
1334  List *adjust_jumps = NIL;
1335  int off;
1336  ListCell *lc;
1337 
1338  /* allocate scratch memory used by all steps of AND/OR */
1339  if (boolexpr->boolop != NOT_EXPR)
1340  scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
1341 
1342  /*
1343  * For each argument evaluate the argument itself, then
1344  * perform the bool operation's appropriate handling.
1345  *
1346  * We can evaluate each argument into our result area, since
1347  * the short-circuiting logic means we only need to remember
1348  * previous NULL values.
1349  *
1350  * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
1351  * or more) / STEP_LAST (one) steps, as each of those has to
1352  * perform different work. The FIRST/LAST split is valid
1353  * because AND/OR have at least two arguments.
1354  */
1355  off = 0;
1356  foreach(lc, boolexpr->args)
1357  {
1358  Expr *arg = (Expr *) lfirst(lc);
1359 
1360  /* Evaluate argument into our output variable */
1361  ExecInitExprRec(arg, state, resv, resnull);
1362 
1363  /* Perform the appropriate step type */
1364  switch (boolexpr->boolop)
1365  {
1366  case AND_EXPR:
1367  Assert(nargs >= 2);
1368 
1369  if (off == 0)
1370  scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
1371  else if (off + 1 == nargs)
1372  scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
1373  else
1374  scratch.opcode = EEOP_BOOL_AND_STEP;
1375  break;
1376  case OR_EXPR:
1377  Assert(nargs >= 2);
1378 
1379  if (off == 0)
1380  scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1381  else if (off + 1 == nargs)
1382  scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1383  else
1384  scratch.opcode = EEOP_BOOL_OR_STEP;
1385  break;
1386  case NOT_EXPR:
1387  Assert(nargs == 1);
1388 
1389  scratch.opcode = EEOP_BOOL_NOT_STEP;
1390  break;
1391  default:
1392  elog(ERROR, "unrecognized boolop: %d",
1393  (int) boolexpr->boolop);
1394  break;
1395  }
1396 
1397  scratch.d.boolexpr.jumpdone = -1;
1398  ExprEvalPushStep(state, &scratch);
1399  adjust_jumps = lappend_int(adjust_jumps,
1400  state->steps_len - 1);
1401  off++;
1402  }
1403 
1404  /* adjust jump targets */
1405  foreach(lc, adjust_jumps)
1406  {
1407  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1408 
1409  Assert(as->d.boolexpr.jumpdone == -1);
1410  as->d.boolexpr.jumpdone = state->steps_len;
1411  }
1412 
1413  break;
1414  }
1415 
1416  case T_SubPlan:
1417  {
1418  SubPlan *subplan = (SubPlan *) node;
1419  SubPlanState *sstate;
1420 
1421  if (!state->parent)
1422  elog(ERROR, "SubPlan found with no parent plan");
1423 
1424  sstate = ExecInitSubPlan(subplan, state->parent);
1425 
1426  /* add SubPlanState nodes to state->parent->subPlan */
1427  state->parent->subPlan = lappend(state->parent->subPlan,
1428  sstate);
1429 
1430  scratch.opcode = EEOP_SUBPLAN;
1431  scratch.d.subplan.sstate = sstate;
1432 
1433  ExprEvalPushStep(state, &scratch);
1434  break;
1435  }
1436 
1437  case T_FieldSelect:
1438  {
1439  FieldSelect *fselect = (FieldSelect *) node;
1440 
1441  /* evaluate row/record argument into result area */
1442  ExecInitExprRec(fselect->arg, state, resv, resnull);
1443 
1444  /* and extract field */
1445  scratch.opcode = EEOP_FIELDSELECT;
1446  scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1447  scratch.d.fieldselect.resulttype = fselect->resulttype;
1448  scratch.d.fieldselect.rowcache.cacheptr = NULL;
1449 
1450  ExprEvalPushStep(state, &scratch);
1451  break;
1452  }
1453 
1454  case T_FieldStore:
1455  {
1456  FieldStore *fstore = (FieldStore *) node;
1457  TupleDesc tupDesc;
1458  ExprEvalRowtypeCache *rowcachep;
1459  Datum *values;
1460  bool *nulls;
1461  int ncolumns;
1462  ListCell *l1,
1463  *l2;
1464 
1465  /* find out the number of columns in the composite type */
1466  tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1467  ncolumns = tupDesc->natts;
1468  ReleaseTupleDesc(tupDesc);
1469 
1470  /* create workspace for column values */
1471  values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1472  nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1473 
1474  /* create shared composite-type-lookup cache struct */
1475  rowcachep = palloc(sizeof(ExprEvalRowtypeCache));
1476  rowcachep->cacheptr = NULL;
1477 
1478  /* emit code to evaluate the composite input value */
1479  ExecInitExprRec(fstore->arg, state, resv, resnull);
1480 
1481  /* next, deform the input tuple into our workspace */
1482  scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1483  scratch.d.fieldstore.fstore = fstore;
1484  scratch.d.fieldstore.rowcache = rowcachep;
1485  scratch.d.fieldstore.values = values;
1486  scratch.d.fieldstore.nulls = nulls;
1487  scratch.d.fieldstore.ncolumns = ncolumns;
1488  ExprEvalPushStep(state, &scratch);
1489 
1490  /* evaluate new field values, store in workspace columns */
1491  forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1492  {
1493  Expr *e = (Expr *) lfirst(l1);
1494  AttrNumber fieldnum = lfirst_int(l2);
1495  Datum *save_innermost_caseval;
1496  bool *save_innermost_casenull;
1497 
1498  if (fieldnum <= 0 || fieldnum > ncolumns)
1499  elog(ERROR, "field number %d is out of range in FieldStore",
1500  fieldnum);
1501 
1502  /*
1503  * Use the CaseTestExpr mechanism to pass down the old
1504  * value of the field being replaced; this is needed in
1505  * case the newval is itself a FieldStore or
1506  * SubscriptingRef that has to obtain and modify the old
1507  * value. It's safe to reuse the CASE mechanism because
1508  * there cannot be a CASE between here and where the value
1509  * would be needed, and a field assignment can't be within
1510  * a CASE either. (So saving and restoring
1511  * innermost_caseval is just paranoia, but let's do it
1512  * anyway.)
1513  *
1514  * Another non-obvious point is that it's safe to use the
1515  * field's values[]/nulls[] entries as both the caseval
1516  * source and the result address for this subexpression.
1517  * That's okay only because (1) both FieldStore and
1518  * SubscriptingRef evaluate their arg or refexpr inputs
1519  * first, and (2) any such CaseTestExpr is directly the
1520  * arg or refexpr input. So any read of the caseval will
1521  * occur before there's a chance to overwrite it. Also,
1522  * if multiple entries in the newvals/fieldnums lists
1523  * target the same field, they'll effectively be applied
1524  * left-to-right which is what we want.
1525  */
1526  save_innermost_caseval = state->innermost_caseval;
1527  save_innermost_casenull = state->innermost_casenull;
1528  state->innermost_caseval = &values[fieldnum - 1];
1529  state->innermost_casenull = &nulls[fieldnum - 1];
1530 
1532  &values[fieldnum - 1],
1533  &nulls[fieldnum - 1]);
1534 
1535  state->innermost_caseval = save_innermost_caseval;
1536  state->innermost_casenull = save_innermost_casenull;
1537  }
1538 
1539  /* finally, form result tuple */
1540  scratch.opcode = EEOP_FIELDSTORE_FORM;
1541  scratch.d.fieldstore.fstore = fstore;
1542  scratch.d.fieldstore.rowcache = rowcachep;
1543  scratch.d.fieldstore.values = values;
1544  scratch.d.fieldstore.nulls = nulls;
1545  scratch.d.fieldstore.ncolumns = ncolumns;
1546  ExprEvalPushStep(state, &scratch);
1547  break;
1548  }
1549 
1550  case T_RelabelType:
1551  {
1552  /* relabel doesn't need to do anything at runtime */
1553  RelabelType *relabel = (RelabelType *) node;
1554 
1555  ExecInitExprRec(relabel->arg, state, resv, resnull);
1556  break;
1557  }
1558 
1559  case T_CoerceViaIO:
1560  {
1561  CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1562  Oid iofunc;
1563  bool typisvarlena;
1564  Oid typioparam;
1565  FunctionCallInfo fcinfo_in;
1566 
1567  /* evaluate argument into step's result area */
1568  ExecInitExprRec(iocoerce->arg, state, resv, resnull);
1569 
1570  /*
1571  * Prepare both output and input function calls, to be
1572  * evaluated inside a single evaluation step for speed - this
1573  * can be a very common operation.
1574  *
1575  * We don't check permissions here as a type's input/output
1576  * function are assumed to be executable by everyone.
1577  */
1578  scratch.opcode = EEOP_IOCOERCE;
1579 
1580  /* lookup the source type's output function */
1581  scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1582  scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
1583 
1584  getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1585  &iofunc, &typisvarlena);
1586  fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1587  fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1588  InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1589  scratch.d.iocoerce.finfo_out,
1590  1, InvalidOid, NULL, NULL);
1591 
1592  /* lookup the result type's input function */
1593  scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1594  scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
1595 
1596  getTypeInputInfo(iocoerce->resulttype,
1597  &iofunc, &typioparam);
1598  fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1599  fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1600  InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1601  scratch.d.iocoerce.finfo_in,
1602  3, InvalidOid, NULL, NULL);
1603 
1604  /*
1605  * We can preload the second and third arguments for the input
1606  * function, since they're constants.
1607  */
1608  fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1609  fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam);
1610  fcinfo_in->args[1].isnull = false;
1611  fcinfo_in->args[2].value = Int32GetDatum(-1);
1612  fcinfo_in->args[2].isnull = false;
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 */
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_NullTest:
2307  {
2308  NullTest *ntest = (NullTest *) node;
2309 
2310  if (ntest->nulltesttype == IS_NULL)
2311  {
2312  if (ntest->argisrow)
2313  scratch.opcode = EEOP_NULLTEST_ROWISNULL;
2314  else
2315  scratch.opcode = EEOP_NULLTEST_ISNULL;
2316  }
2317  else if (ntest->nulltesttype == IS_NOT_NULL)
2318  {
2319  if (ntest->argisrow)
2321  else
2322  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2323  }
2324  else
2325  {
2326  elog(ERROR, "unrecognized nulltesttype: %d",
2327  (int) ntest->nulltesttype);
2328  }
2329  /* initialize cache in case it's a row test */
2330  scratch.d.nulltest_row.rowcache.cacheptr = NULL;
2331 
2332  /* first evaluate argument into result variable */
2333  ExecInitExprRec(ntest->arg, state,
2334  resv, resnull);
2335 
2336  /* then push the test of that argument */
2337  ExprEvalPushStep(state, &scratch);
2338  break;
2339  }
2340 
2341  case T_BooleanTest:
2342  {
2343  BooleanTest *btest = (BooleanTest *) node;
2344 
2345  /*
2346  * Evaluate argument, directly into result datum. That's ok,
2347  * because resv/resnull is definitely not used anywhere else,
2348  * and will get overwritten by the below EEOP_BOOLTEST_IS_*
2349  * step.
2350  */
2351  ExecInitExprRec(btest->arg, state, resv, resnull);
2352 
2353  switch (btest->booltesttype)
2354  {
2355  case IS_TRUE:
2356  scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
2357  break;
2358  case IS_NOT_TRUE:
2360  break;
2361  case IS_FALSE:
2362  scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
2363  break;
2364  case IS_NOT_FALSE:
2366  break;
2367  case IS_UNKNOWN:
2368  /* Same as scalar IS NULL test */
2369  scratch.opcode = EEOP_NULLTEST_ISNULL;
2370  break;
2371  case IS_NOT_UNKNOWN:
2372  /* Same as scalar IS NOT NULL test */
2373  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2374  break;
2375  default:
2376  elog(ERROR, "unrecognized booltesttype: %d",
2377  (int) btest->booltesttype);
2378  }
2379 
2380  ExprEvalPushStep(state, &scratch);
2381  break;
2382  }
2383 
2384  case T_CoerceToDomain:
2385  {
2386  CoerceToDomain *ctest = (CoerceToDomain *) node;
2387 
2388  ExecInitCoerceToDomain(&scratch, ctest, state,
2389  resv, resnull);
2390  break;
2391  }
2392 
2393  case T_CoerceToDomainValue:
2394  {
2395  /*
2396  * Read from location identified by innermost_domainval. Note
2397  * that innermost_domainval could be NULL, if we're compiling
2398  * a standalone domain check rather than one embedded in a
2399  * larger expression. In that case we must read from
2400  * econtext->domainValue_datum. We'll take care of that
2401  * scenario at runtime.
2402  */
2403  scratch.opcode = EEOP_DOMAIN_TESTVAL;
2404  /* we share instruction union variant with case testval */
2405  scratch.d.casetest.value = state->innermost_domainval;
2406  scratch.d.casetest.isnull = state->innermost_domainnull;
2407 
2408  ExprEvalPushStep(state, &scratch);
2409  break;
2410  }
2411 
2412  case T_CurrentOfExpr:
2413  {
2414  scratch.opcode = EEOP_CURRENTOFEXPR;
2415  ExprEvalPushStep(state, &scratch);
2416  break;
2417  }
2418 
2419  case T_NextValueExpr:
2420  {
2421  NextValueExpr *nve = (NextValueExpr *) node;
2422 
2423  scratch.opcode = EEOP_NEXTVALUEEXPR;
2424  scratch.d.nextvalueexpr.seqid = nve->seqid;
2425  scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2426 
2427  ExprEvalPushStep(state, &scratch);
2428  break;
2429  }
2430 
2431  case T_JsonValueExpr:
2432  {
2433  JsonValueExpr *jve = (JsonValueExpr *) node;
2434 
2435  ExecInitExprRec(jve->raw_expr, state, resv, resnull);
2436 
2437  if (jve->formatted_expr)
2438  {
2439  Datum *innermost_caseval = state->innermost_caseval;
2440  bool *innermost_isnull = state->innermost_casenull;
2441 
2442  state->innermost_caseval = resv;
2443  state->innermost_casenull = resnull;
2444 
2445  ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
2446 
2447  state->innermost_caseval = innermost_caseval;
2448  state->innermost_casenull = innermost_isnull;
2449  }
2450  break;
2451  }
2452 
2453  case T_JsonConstructorExpr:
2454  {
2455  JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
2456  List *args = ctor->args;
2457  ListCell *lc;
2458  int nargs = list_length(args);
2459  int argno = 0;
2460 
2461  if (ctor->func)
2462  {
2463  ExecInitExprRec(ctor->func, state, resv, resnull);
2464  }
2465  else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) ||
2466  ctor->type == JSCTOR_JSON_SERIALIZE)
2467  {
2468  /* Use the value of the first argument as a result */
2469  ExecInitExprRec(linitial(args), state, resv, resnull);
2470  }
2471  else
2472  {
2473  scratch.opcode = EEOP_JSON_CONSTRUCTOR;
2474  scratch.d.json_constructor.constructor = ctor;
2475  scratch.d.json_constructor.arg_values = palloc(sizeof(Datum) * nargs);
2476  scratch.d.json_constructor.arg_nulls = palloc(sizeof(bool) * nargs);
2477  scratch.d.json_constructor.arg_types = palloc(sizeof(Oid) * nargs);
2478  scratch.d.json_constructor.nargs = nargs;
2479 
2480  foreach(lc, args)
2481  {
2482  Expr *arg = (Expr *) lfirst(lc);
2483 
2484  scratch.d.json_constructor.arg_types[argno] = exprType((Node *) arg);
2485 
2486  if (IsA(arg, Const))
2487  {
2488  /* Don't evaluate const arguments every round */
2489  Const *con = (Const *) arg;
2490 
2491  scratch.d.json_constructor.arg_values[argno] = con->constvalue;
2492  scratch.d.json_constructor.arg_nulls[argno] = con->constisnull;
2493  }
2494  else
2495  {
2497  &scratch.d.json_constructor.arg_values[argno],
2498  &scratch.d.json_constructor.arg_nulls[argno]);
2499  }
2500  argno++;
2501  }
2502 
2503  /* prepare type cache for datum_to_json[b]() */
2504  if (ctor->type == JSCTOR_JSON_SCALAR)
2505  {
2506  bool is_jsonb =
2508 
2509  scratch.d.json_constructor.arg_type_cache =
2510  palloc(sizeof(*scratch.d.json_constructor.arg_type_cache) * nargs);
2511 
2512  for (int i = 0; i < nargs; i++)
2513  {
2514  int category;
2515  Oid outfuncid;
2516  Oid typid = scratch.d.json_constructor.arg_types[i];
2517 
2518  if (is_jsonb)
2519  {
2520  JsonbTypeCategory jbcat;
2521 
2522  jsonb_categorize_type(typid, &jbcat, &outfuncid);
2523 
2524  category = (int) jbcat;
2525  }
2526  else
2527  {
2528  JsonTypeCategory jscat;
2529 
2530  json_categorize_type(typid, &jscat, &outfuncid);
2531 
2532  category = (int) jscat;
2533  }
2534 
2535  scratch.d.json_constructor.arg_type_cache[i].outfuncid = outfuncid;
2536  scratch.d.json_constructor.arg_type_cache[i].category = category;
2537  }
2538  }
2539 
2540  ExprEvalPushStep(state, &scratch);
2541  }
2542 
2543  if (ctor->coercion)
2544  {
2545  Datum *innermost_caseval = state->innermost_caseval;
2546  bool *innermost_isnull = state->innermost_casenull;
2547 
2548  state->innermost_caseval = resv;
2549  state->innermost_casenull = resnull;
2550 
2551  ExecInitExprRec(ctor->coercion, state, resv, resnull);
2552 
2553  state->innermost_caseval = innermost_caseval;
2554  state->innermost_casenull = innermost_isnull;
2555  }
2556  }
2557  break;
2558 
2559  case T_JsonIsPredicate:
2560  {
2561  JsonIsPredicate *pred = (JsonIsPredicate *) node;
2562 
2563  ExecInitExprRec((Expr *) pred->expr, state, resv, resnull);
2564 
2565  scratch.opcode = EEOP_IS_JSON;
2566  scratch.d.is_json.pred = pred;
2567 
2568  ExprEvalPushStep(state, &scratch);
2569  break;
2570  }
2571 
2572  case T_JsonExpr:
2573  {
2574  JsonExpr *jexpr = castNode(JsonExpr, node);
2575  ListCell *argexprlc;
2576  ListCell *argnamelc;
2577 
2578  scratch.opcode = EEOP_JSONEXPR;
2579  scratch.d.jsonexpr.jsexpr = jexpr;
2580 
2581  scratch.d.jsonexpr.formatted_expr =
2582  palloc(sizeof(*scratch.d.jsonexpr.formatted_expr));
2583 
2585  &scratch.d.jsonexpr.formatted_expr->value,
2586  &scratch.d.jsonexpr.formatted_expr->isnull);
2587 
2588  scratch.d.jsonexpr.pathspec =
2589  palloc(sizeof(*scratch.d.jsonexpr.pathspec));
2590 
2591  ExecInitExprRec((Expr *) jexpr->path_spec, state,
2592  &scratch.d.jsonexpr.pathspec->value,
2593  &scratch.d.jsonexpr.pathspec->isnull);
2594 
2595  scratch.d.jsonexpr.res_expr =
2596  palloc(sizeof(*scratch.d.jsonexpr.res_expr));
2597 
2598  scratch.d.jsonexpr.result_expr = jexpr->result_coercion
2600  state->parent,
2601  &scratch.d.jsonexpr.res_expr->value,
2602  &scratch.d.jsonexpr.res_expr->isnull)
2603  : NULL;
2604 
2605  scratch.d.jsonexpr.default_on_empty = !jexpr->on_empty ? NULL :
2606  ExecInitExpr((Expr *) jexpr->on_empty->default_expr,
2607  state->parent);
2608 
2609  scratch.d.jsonexpr.default_on_error =
2610  ExecInitExpr((Expr *) jexpr->on_error->default_expr,
2611  state->parent);
2612 
2613  if (jexpr->omit_quotes ||
2614  (jexpr->result_coercion && jexpr->result_coercion->via_io))
2615  {
2616  Oid typinput;
2617 
2618  /* lookup the result type's input function */
2619  getTypeInputInfo(jexpr->returning->typid, &typinput,
2620  &scratch.d.jsonexpr.input.typioparam);
2621  fmgr_info(typinput, &scratch.d.jsonexpr.input.func);
2622  }
2623 
2624  scratch.d.jsonexpr.args = NIL;
2625 
2626  forboth(argexprlc, jexpr->passing_values,
2627  argnamelc, jexpr->passing_names)
2628  {
2629  Expr *argexpr = (Expr *) lfirst(argexprlc);
2630  String *argname = lfirst_node(String, argnamelc);
2631  JsonPathVariableEvalContext *var = palloc(sizeof(*var));
2632 
2633  var->name = pstrdup(argname->sval);
2634  var->typid = exprType((Node *) argexpr);
2635  var->typmod = exprTypmod((Node *) argexpr);
2636  var->estate = ExecInitExpr(argexpr, state->parent);
2637  var->econtext = NULL;
2638  var->mcxt = NULL;
2639  var->evaluated = false;
2640  var->value = (Datum) 0;
2641  var->isnull = true;
2642 
2643  scratch.d.jsonexpr.args =
2644  lappend(scratch.d.jsonexpr.args, var);
2645  }
2646 
2647  scratch.d.jsonexpr.cache = NULL;
2648 
2649  if (jexpr->coercions)
2650  {
2651  JsonCoercion **coercion;
2652  struct JsonCoercionState *cstate;
2653  Datum *caseval;
2654  bool *casenull;
2655 
2656  scratch.d.jsonexpr.coercion_expr =
2657  palloc(sizeof(*scratch.d.jsonexpr.coercion_expr));
2658 
2659  caseval = &scratch.d.jsonexpr.coercion_expr->value;
2660  casenull = &scratch.d.jsonexpr.coercion_expr->isnull;
2661 
2662  for (cstate = &scratch.d.jsonexpr.coercions.null,
2663  coercion = &jexpr->coercions->null;
2664  coercion <= &jexpr->coercions->composite;
2665  coercion++, cstate++)
2666  {
2667  cstate->coercion = *coercion;
2668  cstate->estate = *coercion ?
2669  ExecInitExprWithCaseValue((Expr *) (*coercion)->expr,
2670  state->parent,
2671  caseval, casenull) : NULL;
2672  }
2673  }
2674 
2675  ExprEvalPushStep(state, &scratch);
2676  break;
2677  }
2678 
2679  default:
2680  elog(ERROR, "unrecognized node type: %d",
2681  (int) nodeTag(node));
2682  break;
2683  }
2684 }
2685 
2686 /*
2687  * Add another expression evaluation step to ExprState->steps.
2688  *
2689  * Note that this potentially re-allocates es->steps, therefore no pointer
2690  * into that array may be used while the expression is still being built.
2691  */
2692 void
2694 {
2695  if (es->steps_alloc == 0)
2696  {
2697  es->steps_alloc = 16;
2698  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2699  }
2700  else if (es->steps_alloc == es->steps_len)
2701  {
2702  es->steps_alloc *= 2;
2703  es->steps = repalloc(es->steps,
2704  sizeof(ExprEvalStep) * es->steps_alloc);
2705  }
2706 
2707  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2708 }
2709 
2710 /*
2711  * Perform setup necessary for the evaluation of a function-like expression,
2712  * appending argument evaluation steps to the steps list in *state, and
2713  * setting up *scratch so it is ready to be pushed.
2714  *
2715  * *scratch is not pushed here, so that callers may override the opcode,
2716  * which is useful for function-like cases like DISTINCT.
2717  */
2718 static void
2719 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2720  Oid inputcollid, ExprState *state)
2721 {
2722  int nargs = list_length(args);
2723  AclResult aclresult;
2724  FmgrInfo *flinfo;
2725  FunctionCallInfo fcinfo;
2726  int argno;
2727  ListCell *lc;
2728 
2729  /* Check permission to call function */
2730  aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
2731  if (aclresult != ACLCHECK_OK)
2732  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2733  InvokeFunctionExecuteHook(funcid);
2734 
2735  /*
2736  * Safety check on nargs. Under normal circumstances this should never
2737  * fail, as parser should check sooner. But possibly it might fail if
2738  * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2739  * declared in pg_proc?
2740  */
2741  if (nargs > FUNC_MAX_ARGS)
2742  ereport(ERROR,
2743  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2744  errmsg_plural("cannot pass more than %d argument to a function",
2745  "cannot pass more than %d arguments to a function",
2746  FUNC_MAX_ARGS,
2747  FUNC_MAX_ARGS)));
2748 
2749  /* Allocate function lookup data and parameter workspace for this call */
2750  scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2751  scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2752  flinfo = scratch->d.func.finfo;
2753  fcinfo = scratch->d.func.fcinfo_data;
2754 
2755  /* Set up the primary fmgr lookup information */
2756  fmgr_info(funcid, flinfo);
2757  fmgr_info_set_expr((Node *) node, flinfo);
2758 
2759  /* Initialize function call parameter structure too */
2760  InitFunctionCallInfoData(*fcinfo, flinfo,
2761  nargs, inputcollid, NULL, NULL);
2762 
2763  /* Keep extra copies of this info to save an indirection at runtime */
2764  scratch->d.func.fn_addr = flinfo->fn_addr;
2765  scratch->d.func.nargs = nargs;
2766 
2767  /* We only support non-set functions here */
2768  if (flinfo->fn_retset)
2769  ereport(ERROR,
2770  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2771  errmsg("set-valued function called in context that cannot accept a set"),
2772  state->parent ?
2773  executor_errposition(state->parent->state,
2774  exprLocation((Node *) node)) : 0));
2775 
2776  /* Build code to evaluate arguments directly into the fcinfo struct */
2777  argno = 0;
2778  foreach(lc, args)
2779  {
2780  Expr *arg = (Expr *) lfirst(lc);
2781 
2782  if (IsA(arg, Const))
2783  {
2784  /*
2785  * Don't evaluate const arguments every round; especially
2786  * interesting for constants in comparisons.
2787  */
2788  Const *con = (Const *) arg;
2789 
2790  fcinfo->args[argno].value = con->constvalue;
2791  fcinfo->args[argno].isnull = con->constisnull;
2792  }
2793  else
2794  {
2796  &fcinfo->args[argno].value,
2797  &fcinfo->args[argno].isnull);
2798  }
2799  argno++;
2800  }
2801 
2802  /* Insert appropriate opcode depending on strictness and stats level */
2803  if (pgstat_track_functions <= flinfo->fn_stats)
2804  {
2805  if (flinfo->fn_strict && nargs > 0)
2806  scratch->opcode = EEOP_FUNCEXPR_STRICT;
2807  else
2808  scratch->opcode = EEOP_FUNCEXPR;
2809  }
2810  else
2811  {
2812  if (flinfo->fn_strict && nargs > 0)
2814  else
2815  scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2816  }
2817 }
2818 
2819 /*
2820  * Add expression steps deforming the ExprState's inner/outer/scan slots
2821  * as much as required by the expression.
2822  */
2823 static void
2825 {
2826  LastAttnumInfo info = {0, 0, 0};
2827 
2828  /*
2829  * Figure out which attributes we're going to need.
2830  */
2831  get_last_attnums_walker(node, &info);
2832 
2833  ExecPushExprSlots(state, &info);
2834 }
2835 
2836 /*
2837  * Add steps deforming the ExprState's inner/out/scan slots as much as
2838  * indicated by info. This is useful when building an ExprState covering more
2839  * than one expression.
2840  */
2841 static void
2843 {
2844  ExprEvalStep scratch = {0};
2845 
2846  scratch.resvalue = NULL;
2847  scratch.resnull = NULL;
2848 
2849  /* Emit steps as needed */
2850  if (info->last_inner > 0)
2851  {
2852  scratch.opcode = EEOP_INNER_FETCHSOME;
2853  scratch.d.fetch.last_var = info->last_inner;
2854  scratch.d.fetch.fixed = false;
2855  scratch.d.fetch.kind = NULL;
2856  scratch.d.fetch.known_desc = NULL;
2857  if (ExecComputeSlotInfo(state, &scratch))
2858  ExprEvalPushStep(state, &scratch);
2859  }
2860  if (info->last_outer > 0)
2861  {
2862  scratch.opcode = EEOP_OUTER_FETCHSOME;
2863  scratch.d.fetch.last_var = info->last_outer;
2864  scratch.d.fetch.fixed = false;
2865  scratch.d.fetch.kind = NULL;
2866  scratch.d.fetch.known_desc = NULL;
2867  if (ExecComputeSlotInfo(state, &scratch))
2868  ExprEvalPushStep(state, &scratch);
2869  }
2870  if (info->last_scan > 0)
2871  {
2872  scratch.opcode = EEOP_SCAN_FETCHSOME;
2873  scratch.d.fetch.last_var = info->last_scan;
2874  scratch.d.fetch.fixed = false;
2875  scratch.d.fetch.kind = NULL;
2876  scratch.d.fetch.known_desc = NULL;
2877  if (ExecComputeSlotInfo(state, &scratch))
2878  ExprEvalPushStep(state, &scratch);
2879  }
2880 }
2881 
2882 /*
2883  * get_last_attnums_walker: expression walker for ExecInitExprSlots
2884  */
2885 static bool
2887 {
2888  if (node == NULL)
2889  return false;
2890  if (IsA(node, Var))
2891  {
2892  Var *variable = (Var *) node;
2893  AttrNumber attnum = variable->varattno;
2894 
2895  switch (variable->varno)
2896  {
2897  case INNER_VAR:
2898  info->last_inner = Max(info->last_inner, attnum);
2899  break;
2900 
2901  case OUTER_VAR:
2902  info->last_outer = Max(info->last_outer, attnum);
2903  break;
2904 
2905  /* INDEX_VAR is handled by default case */
2906 
2907  default:
2908  info->last_scan = Max(info->last_scan, attnum);
2909  break;
2910  }
2911  return false;
2912  }
2913 
2914  /*
2915  * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2916  * because those do not represent expressions to be evaluated within the
2917  * calling expression's econtext. GroupingFunc arguments are never
2918  * evaluated at all.
2919  */
2920  if (IsA(node, Aggref))
2921  return false;
2922  if (IsA(node, WindowFunc))
2923  return false;
2924  if (IsA(node, GroupingFunc))
2925  return false;
2927  (void *) info);
2928 }
2929 
2930 /*
2931  * Compute additional information for EEOP_*_FETCHSOME ops.
2932  *
2933  * The goal is to determine whether a slot is 'fixed', that is, every
2934  * evaluation of the expression will have the same type of slot, with an
2935  * equivalent descriptor.
2936  *
2937  * Returns true if the deforming step is required, false otherwise.
2938  */
2939 static bool
2941 {
2942  PlanState *parent = state->parent;
2943  TupleDesc desc = NULL;
2944  const TupleTableSlotOps *tts_ops = NULL;
2945  bool isfixed = false;
2946  ExprEvalOp opcode = op->opcode;
2947 
2948  Assert(opcode == EEOP_INNER_FETCHSOME ||
2949  opcode == EEOP_OUTER_FETCHSOME ||
2950  opcode == EEOP_SCAN_FETCHSOME);
2951 
2952  if (op->d.fetch.known_desc != NULL)
2953  {
2954  desc = op->d.fetch.known_desc;
2955  tts_ops = op->d.fetch.kind;
2956  isfixed = op->d.fetch.kind != NULL;
2957  }
2958  else if (!parent)
2959  {
2960  isfixed = false;
2961  }
2962  else if (opcode == EEOP_INNER_FETCHSOME)
2963  {
2964  PlanState *is = innerPlanState(parent);
2965 
2966  if (parent->inneropsset && !parent->inneropsfixed)
2967  {
2968  isfixed = false;
2969  }
2970  else if (parent->inneropsset && parent->innerops)
2971  {
2972  isfixed = true;
2973  tts_ops = parent->innerops;
2974  desc = ExecGetResultType(is);
2975  }
2976  else if (is)
2977  {
2978  tts_ops = ExecGetResultSlotOps(is, &isfixed);
2979  desc = ExecGetResultType(is);
2980  }
2981  }
2982  else if (opcode == EEOP_OUTER_FETCHSOME)
2983  {
2984  PlanState *os = outerPlanState(parent);
2985 
2986  if (parent->outeropsset && !parent->outeropsfixed)
2987  {
2988  isfixed = false;
2989  }
2990  else if (parent->outeropsset && parent->outerops)
2991  {
2992  isfixed = true;
2993  tts_ops = parent->outerops;
2994  desc = ExecGetResultType(os);
2995  }
2996  else if (os)
2997  {
2998  tts_ops = ExecGetResultSlotOps(os, &isfixed);
2999  desc = ExecGetResultType(os);
3000  }
3001  }
3002  else if (opcode == EEOP_SCAN_FETCHSOME)
3003  {
3004  desc = parent->scandesc;
3005 
3006  if (parent->scanops)
3007  tts_ops = parent->scanops;
3008 
3009  if (parent->scanopsset)
3010  isfixed = parent->scanopsfixed;
3011  }
3012 
3013  if (isfixed && desc != NULL && tts_ops != NULL)
3014  {
3015  op->d.fetch.fixed = true;
3016  op->d.fetch.kind = tts_ops;
3017  op->d.fetch.known_desc = desc;
3018  }
3019  else
3020  {
3021  op->d.fetch.fixed = false;
3022  op->d.fetch.kind = NULL;
3023  op->d.fetch.known_desc = NULL;
3024  }
3025 
3026  /* if the slot is known to always virtual we never need to deform */
3027  if (op->d.fetch.fixed && op->d.fetch.kind == &TTSOpsVirtual)
3028  return false;
3029 
3030  return true;
3031 }
3032 
3033 /*
3034  * Prepare step for the evaluation of a whole-row variable.
3035  * The caller still has to push the step.
3036  */
3037 static void
3039 {
3040  PlanState *parent = state->parent;
3041 
3042  /* fill in all but the target */
3043  scratch->opcode = EEOP_WHOLEROW;
3044  scratch->d.wholerow.var = variable;
3045  scratch->d.wholerow.first = true;
3046  scratch->d.wholerow.slow = false;
3047  scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
3048  scratch->d.wholerow.junkFilter = NULL;
3049 
3050  /*
3051  * If the input tuple came from a subquery, it might contain "resjunk"
3052  * columns (such as GROUP BY or ORDER BY columns), which we don't want to
3053  * keep in the whole-row result. We can get rid of such columns by
3054  * passing the tuple through a JunkFilter --- but to make one, we have to
3055  * lay our hands on the subquery's targetlist. Fortunately, there are not
3056  * very many cases where this can happen, and we can identify all of them
3057  * by examining our parent PlanState. We assume this is not an issue in
3058  * standalone expressions that don't have parent plans. (Whole-row Vars
3059  * can occur in such expressions, but they will always be referencing
3060  * table rows.)
3061  */
3062  if (parent)
3063  {
3064  PlanState *subplan = NULL;
3065 
3066  switch (nodeTag(parent))
3067  {
3068  case T_SubqueryScanState:
3069  subplan = ((SubqueryScanState *) parent)->subplan;
3070  break;
3071  case T_CteScanState:
3072  subplan = ((CteScanState *) parent)->cteplanstate;
3073  break;
3074  default:
3075  break;
3076  }
3077 
3078  if (subplan)
3079  {
3080  bool junk_filter_needed = false;
3081  ListCell *tlist;
3082 
3083  /* Detect whether subplan tlist actually has any junk columns */
3084  foreach(tlist, subplan->plan->targetlist)
3085  {
3086  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
3087 
3088  if (tle->resjunk)
3089  {
3090  junk_filter_needed = true;
3091  break;
3092  }
3093  }
3094 
3095  /* If so, build the junkfilter now */
3096  if (junk_filter_needed)
3097  {
3098  scratch->d.wholerow.junkFilter =
3100  ExecInitExtraTupleSlot(parent->state, NULL,
3101  &TTSOpsVirtual));
3102  }
3103  }
3104  }
3105 }
3106 
3107 /*
3108  * Prepare evaluation of a SubscriptingRef expression.
3109  */
3110 static void
3112  ExprState *state, Datum *resv, bool *resnull)
3113 {
3114  bool isAssignment = (sbsref->refassgnexpr != NULL);
3115  int nupper = list_length(sbsref->refupperindexpr);
3116  int nlower = list_length(sbsref->reflowerindexpr);
3117  const SubscriptRoutines *sbsroutines;
3118  SubscriptingRefState *sbsrefstate;
3119  SubscriptExecSteps methods;
3120  char *ptr;
3121  List *adjust_jumps = NIL;
3122  ListCell *lc;
3123  int i;
3124 
3125  /* Look up the subscripting support methods */
3126  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
3127  if (!sbsroutines)
3128  ereport(ERROR,
3129  (errcode(ERRCODE_DATATYPE_MISMATCH),
3130  errmsg("cannot subscript type %s because it does not support subscripting",
3131  format_type_be(sbsref->refcontainertype)),
3132  state->parent ?
3133  executor_errposition(state->parent->state,
3134  exprLocation((Node *) sbsref)) : 0));
3135 
3136  /* Allocate sbsrefstate, with enough space for per-subscript arrays too */
3137  sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +
3138  (nupper + nlower) * (sizeof(Datum) +
3139  2 * sizeof(bool)));
3140 
3141  /* Fill constant fields of SubscriptingRefState */
3142  sbsrefstate->isassignment = isAssignment;
3143  sbsrefstate->numupper = nupper;
3144  sbsrefstate->numlower = nlower;
3145  /* Set up per-subscript arrays */
3146  ptr = ((char *) sbsrefstate) + MAXALIGN(sizeof(SubscriptingRefState));
3147  sbsrefstate->upperindex = (Datum *) ptr;
3148  ptr += nupper * sizeof(Datum);
3149  sbsrefstate->lowerindex = (Datum *) ptr;
3150  ptr += nlower * sizeof(Datum);
3151  sbsrefstate->upperprovided = (bool *) ptr;
3152  ptr += nupper * sizeof(bool);
3153  sbsrefstate->lowerprovided = (bool *) ptr;
3154  ptr += nlower * sizeof(bool);
3155  sbsrefstate->upperindexnull = (bool *) ptr;
3156  ptr += nupper * sizeof(bool);
3157  sbsrefstate->lowerindexnull = (bool *) ptr;
3158  /* ptr += nlower * sizeof(bool); */
3159 
3160  /*
3161  * Let the container-type-specific code have a chance. It must fill the
3162  * "methods" struct with function pointers for us to possibly use in
3163  * execution steps below; and it can optionally set up some data pointed
3164  * to by the workspace field.
3165  */
3166  memset(&methods, 0, sizeof(methods));
3167  sbsroutines->exec_setup(sbsref, sbsrefstate, &methods);
3168 
3169  /*
3170  * Evaluate array input. It's safe to do so into resv/resnull, because we
3171  * won't use that as target for any of the other subexpressions, and it'll
3172  * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
3173  * pushed last.
3174  */
3175  ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
3176 
3177  /*
3178  * If refexpr yields NULL, and the operation should be strict, then result
3179  * is NULL. We can implement this with just JUMP_IF_NULL, since we
3180  * evaluated the array into the desired target location.
3181  */
3182  if (!isAssignment && sbsroutines->fetch_strict)
3183  {
3184  scratch->opcode = EEOP_JUMP_IF_NULL;
3185  scratch->d.jump.jumpdone = -1; /* adjust later */
3186  ExprEvalPushStep(state, scratch);
3187  adjust_jumps = lappend_int(adjust_jumps,
3188  state->steps_len - 1);
3189  }
3190 
3191  /* Evaluate upper subscripts */
3192  i = 0;
3193  foreach(lc, sbsref->refupperindexpr)
3194  {
3195  Expr *e = (Expr *) lfirst(lc);
3196 
3197  /* When slicing, individual subscript bounds can be omitted */
3198  if (!e)
3199  {
3200  sbsrefstate->upperprovided[i] = false;
3201  sbsrefstate->upperindexnull[i] = true;
3202  }
3203  else
3204  {
3205  sbsrefstate->upperprovided[i] = true;
3206  /* Each subscript is evaluated into appropriate array entry */
3208  &sbsrefstate->upperindex[i],
3209  &sbsrefstate->upperindexnull[i]);
3210  }
3211  i++;
3212  }
3213 
3214  /* Evaluate lower subscripts similarly */
3215  i = 0;
3216  foreach(lc, sbsref->reflowerindexpr)
3217  {
3218  Expr *e = (Expr *) lfirst(lc);
3219 
3220  /* When slicing, individual subscript bounds can be omitted */
3221  if (!e)
3222  {
3223  sbsrefstate->lowerprovided[i] = false;
3224  sbsrefstate->lowerindexnull[i] = true;
3225  }
3226  else
3227  {
3228  sbsrefstate->lowerprovided[i] = true;
3229  /* Each subscript is evaluated into appropriate array entry */
3231  &sbsrefstate->lowerindex[i],
3232  &sbsrefstate->lowerindexnull[i]);
3233  }
3234  i++;
3235  }
3236 
3237  /* SBSREF_SUBSCRIPTS checks and converts all the subscripts at once */
3238  if (methods.sbs_check_subscripts)
3239  {
3240  scratch->opcode = EEOP_SBSREF_SUBSCRIPTS;
3241  scratch->d.sbsref_subscript.subscriptfunc = methods.sbs_check_subscripts;
3242  scratch->d.sbsref_subscript.state = sbsrefstate;
3243  scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
3244  ExprEvalPushStep(state, scratch);
3245  adjust_jumps = lappend_int(adjust_jumps,
3246  state->steps_len - 1);
3247  }
3248 
3249  if (isAssignment)
3250  {
3251  Datum *save_innermost_caseval;
3252  bool *save_innermost_casenull;
3253 
3254  /* Check for unimplemented methods */
3255  if (!methods.sbs_assign)
3256  ereport(ERROR,
3257  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3258  errmsg("type %s does not support subscripted assignment",
3259  format_type_be(sbsref->refcontainertype))));
3260 
3261  /*
3262  * We might have a nested-assignment situation, in which the
3263  * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
3264  * to obtain and modify the previous value of the array element or
3265  * slice being replaced. If so, we have to extract that value from
3266  * the array and pass it down via the CaseTestExpr mechanism. It's
3267  * safe to reuse the CASE mechanism because there cannot be a CASE
3268  * between here and where the value would be needed, and an array
3269  * assignment can't be within a CASE either. (So saving and restoring
3270  * innermost_caseval is just paranoia, but let's do it anyway.)
3271  *
3272  * Since fetching the old element might be a nontrivial expense, do it
3273  * only if the argument actually needs it.
3274  */
3276  {
3277  if (!methods.sbs_fetch_old)
3278  ereport(ERROR,
3279  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3280  errmsg("type %s does not support subscripted assignment",
3281  format_type_be(sbsref->refcontainertype))));
3282  scratch->opcode = EEOP_SBSREF_OLD;
3283  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch_old;
3284  scratch->d.sbsref.state = sbsrefstate;
3285  ExprEvalPushStep(state, scratch);
3286  }
3287 
3288  /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
3289  save_innermost_caseval = state->innermost_caseval;
3290  save_innermost_casenull = state->innermost_casenull;
3291  state->innermost_caseval = &sbsrefstate->prevvalue;
3292  state->innermost_casenull = &sbsrefstate->prevnull;
3293 
3294  /* evaluate replacement value into replacevalue/replacenull */
3296  &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
3297 
3298  state->innermost_caseval = save_innermost_caseval;
3299  state->innermost_casenull = save_innermost_casenull;
3300 
3301  /* and perform the assignment */
3302  scratch->opcode = EEOP_SBSREF_ASSIGN;
3303  scratch->d.sbsref.subscriptfunc = methods.sbs_assign;
3304  scratch->d.sbsref.state = sbsrefstate;
3305  ExprEvalPushStep(state, scratch);
3306  }
3307  else
3308  {
3309  /* array fetch is much simpler */
3310  scratch->opcode = EEOP_SBSREF_FETCH;
3311  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch;
3312  scratch->d.sbsref.state = sbsrefstate;
3313  ExprEvalPushStep(state, scratch);
3314  }
3315 
3316  /* adjust jump targets */
3317  foreach(lc, adjust_jumps)
3318  {
3319  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3320 
3321  if (as->opcode == EEOP_SBSREF_SUBSCRIPTS)
3322  {
3323  Assert(as->d.sbsref_subscript.jumpdone == -1);
3324  as->d.sbsref_subscript.jumpdone = state->steps_len;
3325  }
3326  else
3327  {
3329  Assert(as->d.jump.jumpdone == -1);
3330  as->d.jump.jumpdone = state->steps_len;
3331  }
3332  }
3333 }
3334 
3335 /*
3336  * Helper for preparing SubscriptingRef expressions for evaluation: is expr
3337  * a nested FieldStore or SubscriptingRef that needs the old element value
3338  * passed down?
3339  *
3340  * (We could use this in FieldStore too, but in that case passing the old
3341  * value is so cheap there's no need.)
3342  *
3343  * Note: it might seem that this needs to recurse, but in most cases it does
3344  * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the
3345  * top-level node. Nested-assignment situations give rise to expression
3346  * trees in which each level of assignment has its own CaseTestExpr, and the
3347  * recursive structure appears within the newvals or refassgnexpr field.
3348  * There is an exception, though: if the array is an array-of-domain, we will
3349  * have a CoerceToDomain as the refassgnexpr, and we need to be able to look
3350  * through that.
3351  */
3352 static bool
3354 {
3355  if (expr == NULL)
3356  return false; /* just paranoia */
3357  if (IsA(expr, FieldStore))
3358  {
3359  FieldStore *fstore = (FieldStore *) expr;
3360 
3361  if (fstore->arg && IsA(fstore->arg, CaseTestExpr))
3362  return true;
3363  }
3364  else if (IsA(expr, SubscriptingRef))
3365  {
3366  SubscriptingRef *sbsRef = (SubscriptingRef *) expr;
3367 
3368  if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr))
3369  return true;
3370  }
3371  else if (IsA(expr, CoerceToDomain))
3372  {
3373  CoerceToDomain *cd = (CoerceToDomain *) expr;
3374 
3375  return isAssignmentIndirectionExpr(cd->arg);
3376  }
3377  return false;
3378 }
3379 
3380 /*
3381  * Prepare evaluation of a CoerceToDomain expression.
3382  */
3383 static void
3385  ExprState *state, Datum *resv, bool *resnull)
3386 {
3387  DomainConstraintRef *constraint_ref;
3388  Datum *domainval = NULL;
3389  bool *domainnull = NULL;
3390  ListCell *l;
3391 
3392  scratch->d.domaincheck.resulttype = ctest->resulttype;
3393  /* we'll allocate workspace only if needed */
3394  scratch->d.domaincheck.checkvalue = NULL;
3395  scratch->d.domaincheck.checknull = NULL;
3396 
3397  /*
3398  * Evaluate argument - it's fine to directly store it into resv/resnull,
3399  * if there's constraint failures there'll be errors, otherwise it's what
3400  * needs to be returned.
3401  */
3402  ExecInitExprRec(ctest->arg, state, resv, resnull);
3403 
3404  /*
3405  * Note: if the argument is of varlena type, it could be a R/W expanded
3406  * object. We want to return the R/W pointer as the final result, but we
3407  * have to pass a R/O pointer as the value to be tested by any functions
3408  * in check expressions. We don't bother to emit a MAKE_READONLY step
3409  * unless there's actually at least one check expression, though. Until
3410  * we've tested that, domainval/domainnull are NULL.
3411  */
3412 
3413  /*
3414  * Collect the constraints associated with the domain.
3415  *
3416  * Note: before PG v10 we'd recheck the set of constraints during each
3417  * evaluation of the expression. Now we bake them into the ExprState
3418  * during executor initialization. That means we don't need typcache.c to
3419  * provide compiled exprs.
3420  */
3421  constraint_ref = (DomainConstraintRef *)
3422  palloc(sizeof(DomainConstraintRef));
3424  constraint_ref,
3426  false);
3427 
3428  /*
3429  * Compile code to check each domain constraint. NOTNULL constraints can
3430  * just be applied on the resv/resnull value, but for CHECK constraints we
3431  * need more pushups.
3432  */
3433  foreach(l, constraint_ref->constraints)
3434  {
3436  Datum *save_innermost_domainval;
3437  bool *save_innermost_domainnull;
3438 
3439  scratch->d.domaincheck.constraintname = con->name;
3440 
3441  switch (con->constrainttype)
3442  {
3444  scratch->opcode = EEOP_DOMAIN_NOTNULL;
3445  ExprEvalPushStep(state, scratch);
3446  break;
3447  case DOM_CONSTRAINT_CHECK:
3448  /* Allocate workspace for CHECK output if we didn't yet */
3449  if (scratch->d.domaincheck.checkvalue == NULL)
3450  {
3451  scratch->d.domaincheck.checkvalue =
3452  (Datum *) palloc(sizeof(Datum));
3453  scratch->d.domaincheck.checknull =
3454  (bool *) palloc(sizeof(bool));
3455  }
3456 
3457  /*
3458  * If first time through, determine where CoerceToDomainValue
3459  * nodes should read from.
3460  */
3461  if (domainval == NULL)
3462  {
3463  /*
3464  * Since value might be read multiple times, force to R/O
3465  * - but only if it could be an expanded datum.
3466  */
3467  if (get_typlen(ctest->resulttype) == -1)
3468  {
3469  ExprEvalStep scratch2 = {0};
3470 
3471  /* Yes, so make output workspace for MAKE_READONLY */
3472  domainval = (Datum *) palloc(sizeof(Datum));
3473  domainnull = (bool *) palloc(sizeof(bool));
3474 
3475  /* Emit MAKE_READONLY */
3476  scratch2.opcode = EEOP_MAKE_READONLY;
3477  scratch2.resvalue = domainval;
3478  scratch2.resnull = domainnull;
3479  scratch2.d.make_readonly.value = resv;
3480  scratch2.d.make_readonly.isnull = resnull;
3481  ExprEvalPushStep(state, &scratch2);
3482  }
3483  else
3484  {
3485  /* No, so it's fine to read from resv/resnull */
3486  domainval = resv;
3487  domainnull = resnull;
3488  }
3489  }
3490 
3491  /*
3492  * Set up value to be returned by CoerceToDomainValue nodes.
3493  * We must save and restore innermost_domainval/null fields,
3494  * in case this node is itself within a check expression for
3495  * another domain.
3496  */
3497  save_innermost_domainval = state->innermost_domainval;
3498  save_innermost_domainnull = state->innermost_domainnull;
3499  state->innermost_domainval = domainval;
3500  state->innermost_domainnull = domainnull;
3501 
3502  /* evaluate check expression value */
3504  scratch->d.domaincheck.checkvalue,
3505  scratch->d.domaincheck.checknull);
3506 
3507  state->innermost_domainval = save_innermost_domainval;
3508  state->innermost_domainnull = save_innermost_domainnull;
3509 
3510  /* now test result */
3511  scratch->opcode = EEOP_DOMAIN_CHECK;
3512  ExprEvalPushStep(state, scratch);
3513 
3514  break;
3515  default:
3516  elog(ERROR, "unrecognized constraint type: %d",
3517  (int) con->constrainttype);
3518  break;
3519  }
3520  }
3521 }
3522 
3523 /*
3524  * Build transition/combine function invocations for all aggregate transition
3525  * / combination function invocations in a grouping sets phase. This has to
3526  * invoke all sort based transitions in a phase (if doSort is true), all hash
3527  * based transitions (if doHash is true), or both (both true).
3528  *
3529  * The resulting expression will, for each set of transition values, first
3530  * check for filters, evaluate aggregate input, check that that input is not
3531  * NULL for a strict transition function, and then finally invoke the
3532  * transition for each of the concurrently computed grouping sets.
3533  *
3534  * If nullcheck is true, the generated code will check for a NULL pointer to
3535  * the array of AggStatePerGroup, and skip evaluation if so.
3536  */
3537 ExprState *
3539  bool doSort, bool doHash, bool nullcheck)
3540 {
3542  PlanState *parent = &aggstate->ss.ps;
3543  ExprEvalStep scratch = {0};
3544  bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit);
3545  LastAttnumInfo deform = {0, 0, 0};
3546 
3547  state->expr = (Expr *) aggstate;
3548  state->parent = parent;
3549 
3550  scratch.resvalue = &state->resvalue;
3551  scratch.resnull = &state->resnull;
3552 
3553  /*
3554  * First figure out which slots, and how many columns from each, we're
3555  * going to need.
3556  */
3557  for (int transno = 0; transno < aggstate->numtrans; transno++)
3558  {
3559  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3560 
3562  &deform);
3563  get_last_attnums_walker((Node *) pertrans->aggref->args,
3564  &deform);
3566  &deform);
3568  &deform);
3570  &deform);
3571  }
3572  ExecPushExprSlots(state, &deform);
3573 
3574  /*
3575  * Emit instructions for each transition value / grouping set combination.
3576  */
3577  for (int transno = 0; transno < aggstate->numtrans; transno++)
3578  {
3579  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3580  FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
3581  List *adjust_bailout = NIL;
3582  NullableDatum *strictargs = NULL;
3583  bool *strictnulls = NULL;
3584  int argno;
3585  ListCell *bail;
3586 
3587  /*
3588  * If filter present, emit. Do so before evaluating the input, to
3589  * avoid potentially unneeded computations, or even worse, unintended
3590  * side-effects. When combining, all the necessary filtering has
3591  * already been done.
3592  */
3593  if (pertrans->aggref->aggfilter && !isCombine)
3594  {
3595  /* evaluate filter expression */
3596  ExecInitExprRec(pertrans->aggref->aggfilter, state,
3597  &state->resvalue, &state->resnull);
3598  /* and jump out if false */
3599  scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
3600  scratch.d.jump.jumpdone = -1; /* adjust later */
3601  ExprEvalPushStep(state, &scratch);
3602  adjust_bailout = lappend_int(adjust_bailout,
3603  state->steps_len - 1);
3604  }
3605 
3606  /*
3607  * Evaluate arguments to aggregate/combine function.
3608  */
3609  argno = 0;
3610  if (isCombine)
3611  {
3612  /*
3613  * Combining two aggregate transition values. Instead of directly
3614  * coming from a tuple the input is a, potentially deserialized,
3615  * transition value.
3616  */
3617  TargetEntry *source_tle;
3618 
3619  Assert(pertrans->numSortCols == 0);
3620  Assert(list_length(pertrans->aggref->args) == 1);
3621 
3622  strictargs = trans_fcinfo->args + 1;
3623  source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
3624 
3625  /*
3626  * deserialfn_oid will be set if we must deserialize the input
3627  * state before calling the combine function.
3628  */
3629  if (!OidIsValid(pertrans->deserialfn_oid))
3630  {
3631  /*
3632  * Start from 1, since the 0th arg will be the transition
3633  * value
3634  */
3635  ExecInitExprRec(source_tle->expr, state,
3636  &trans_fcinfo->args[argno + 1].value,
3637  &trans_fcinfo->args[argno + 1].isnull);
3638  }
3639  else
3640  {
3641  FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
3642 
3643  /* evaluate argument */
3644  ExecInitExprRec(source_tle->expr, state,
3645  &ds_fcinfo->args[0].value,
3646  &ds_fcinfo->args[0].isnull);
3647 
3648  /* Dummy second argument for type-safety reasons */
3649  ds_fcinfo->args[1].value = PointerGetDatum(NULL);
3650  ds_fcinfo->args[1].isnull = false;
3651 
3652  /*
3653  * Don't call a strict deserialization function with NULL
3654  * input
3655  */
3656  if (pertrans->deserialfn.fn_strict)
3658  else
3659  scratch.opcode = EEOP_AGG_DESERIALIZE;
3660 
3661  scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
3662  scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
3663  scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
3664  scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
3665 
3666  ExprEvalPushStep(state, &scratch);
3667  /* don't add an adjustment unless the function is strict */
3668  if (pertrans->deserialfn.fn_strict)
3669  adjust_bailout = lappend_int(adjust_bailout,
3670  state->steps_len - 1);
3671 
3672  /* restore normal settings of scratch fields */
3673  scratch.resvalue = &state->resvalue;
3674  scratch.resnull = &state->resnull;
3675  }
3676  argno++;
3677  }
3678  else if (pertrans->numSortCols == 0)
3679  {
3680  ListCell *arg;
3681 
3682  /*
3683  * Normal transition function without ORDER BY / DISTINCT.
3684  */
3685  strictargs = trans_fcinfo->args + 1;
3686 
3687  foreach(arg, pertrans->aggref->args)
3688  {
3689  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3690 
3691  /*
3692  * Start from 1, since the 0th arg will be the transition
3693  * value
3694  */
3695  ExecInitExprRec(source_tle->expr, state,
3696  &trans_fcinfo->args[argno + 1].value,
3697  &trans_fcinfo->args[argno + 1].isnull);
3698  argno++;
3699  }
3700  }
3701  else if (pertrans->numInputs == 1)
3702  {
3703  /*
3704  * DISTINCT and/or ORDER BY case, with a single column sorted on.
3705  */
3706  TargetEntry *source_tle =
3707  (TargetEntry *) linitial(pertrans->aggref->args);
3708 
3709  Assert(list_length(pertrans->aggref->args) == 1);
3710 
3711  ExecInitExprRec(source_tle->expr, state,
3712  &state->resvalue,
3713  &state->resnull);
3714  strictnulls = &state->resnull;
3715  argno++;
3716  }
3717  else
3718  {
3719  /*
3720  * DISTINCT and/or ORDER BY case, with multiple columns sorted on.
3721  */
3722  Datum *values = pertrans->sortslot->tts_values;
3723  bool *nulls = pertrans->sortslot->tts_isnull;
3724  ListCell *arg;
3725 
3726  strictnulls = nulls;
3727 
3728  foreach(arg, pertrans->aggref->args)
3729  {
3730  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3731 
3732  ExecInitExprRec(source_tle->expr, state,
3733  &values[argno], &nulls[argno]);
3734  argno++;
3735  }
3736  }
3737  Assert(pertrans->numInputs == argno);
3738 
3739  /*
3740  * For a strict transfn, nothing happens when there's a NULL input; we
3741  * just keep the prior transValue. This is true for both plain and
3742  * sorted/distinct aggregates.
3743  */
3744  if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
3745  {
3746  if (strictnulls)
3748  else
3750  scratch.d.agg_strict_input_check.nulls = strictnulls;
3751  scratch.d.agg_strict_input_check.args = strictargs;
3752  scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
3753  scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
3754  ExprEvalPushStep(state, &scratch);
3755  adjust_bailout = lappend_int(adjust_bailout,
3756  state->steps_len - 1);
3757  }
3758 
3759  /*
3760  * Call transition function (once for each concurrently evaluated
3761  * grouping set). Do so for both sort and hash based computations, as
3762  * applicable.
3763  */
3764  if (doSort)
3765  {
3766  int processGroupingSets = Max(phase->numsets, 1);
3767  int setoff = 0;
3768 
3769  for (int setno = 0; setno < processGroupingSets; setno++)
3770  {
3771  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3772  pertrans, transno, setno, setoff, false,
3773  nullcheck);
3774  setoff++;
3775  }
3776  }
3777 
3778  if (doHash)
3779  {
3780  int numHashes = aggstate->num_hashes;
3781  int setoff;
3782 
3783  /* in MIXED mode, there'll be preceding transition values */
3784  if (aggstate->aggstrategy != AGG_HASHED)
3785  setoff = aggstate->maxsets;
3786  else
3787  setoff = 0;
3788 
3789  for (int setno = 0; setno < numHashes; setno++)
3790  {
3791  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3792  pertrans, transno, setno, setoff, true,
3793  nullcheck);
3794  setoff++;
3795  }
3796  }
3797 
3798  /* adjust early bail out jump target(s) */
3799  foreach(bail, adjust_bailout)
3800  {
3801  ExprEvalStep *as = &state->steps[lfirst_int(bail)];
3802 
3803  if (as->opcode == EEOP_JUMP_IF_NOT_TRUE)
3804  {
3805  Assert(as->d.jump.jumpdone == -1);
3806  as->d.jump.jumpdone = state->steps_len;
3807  }
3808  else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
3810  {
3811  Assert(as->d.agg_strict_input_check.jumpnull == -1);
3812  as->d.agg_strict_input_check.jumpnull = state->steps_len;
3813  }
3814  else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE)
3815  {
3816  Assert(as->d.agg_deserialize.jumpnull == -1);
3817  as->d.agg_deserialize.jumpnull = state->steps_len;
3818  }
3819  else
3820  Assert(false);
3821  }
3822  }
3823 
3824  scratch.resvalue = NULL;
3825  scratch.resnull = NULL;
3826  scratch.opcode = EEOP_DONE;
3827  ExprEvalPushStep(state, &scratch);
3828 
3830 
3831  return state;
3832 }
3833 
3834 /*
3835  * Build transition/combine function invocation for a single transition
3836  * value. This is separated from ExecBuildAggTrans() because there are
3837  * multiple callsites (hash and sort in some grouping set cases).
3838  */
3839 static void
3841  ExprEvalStep *scratch,
3842  FunctionCallInfo fcinfo, AggStatePerTrans pertrans,
3843  int transno, int setno, int setoff, bool ishash,
3844  bool nullcheck)
3845 {
3846  ExprContext *aggcontext;
3847  int adjust_jumpnull = -1;
3848 
3849  if (ishash)
3850  aggcontext = aggstate->hashcontext;
3851  else
3852  aggcontext = aggstate->aggcontexts[setno];
3853 
3854  /* add check for NULL pointer? */
3855  if (nullcheck)
3856  {
3858  scratch->d.agg_plain_pergroup_nullcheck.setoff = setoff;
3859  /* adjust later */
3860  scratch->d.agg_plain_pergroup_nullcheck.jumpnull = -1;
3861  ExprEvalPushStep(state, scratch);
3862  adjust_jumpnull = state->steps_len - 1;
3863  }
3864 
3865  /*
3866  * Determine appropriate transition implementation.
3867  *
3868  * For non-ordered aggregates:
3869  *
3870  * If the initial value for the transition state doesn't exist in the
3871  * pg_aggregate table then we will let the first non-NULL value returned
3872  * from the outer procNode become the initial value. (This is useful for
3873  * aggregates like max() and min().) The noTransValue flag signals that we
3874  * need to do so. If true, generate a
3875  * EEOP_AGG_INIT_STRICT_PLAIN_TRANS{,_BYVAL} step. This step also needs to
3876  * do the work described next:
3877  *
3878  * If the function is strict, but does have an initial value, choose
3879  * EEOP_AGG_STRICT_PLAIN_TRANS{,_BYVAL}, which skips the transition
3880  * function if the transition value has become NULL (because a previous
3881  * transition function returned NULL). This step also needs to do the work
3882  * described next:
3883  *
3884  * Otherwise we call EEOP_AGG_PLAIN_TRANS{,_BYVAL}, which does not have to
3885  * perform either of the above checks.
3886  *
3887  * Having steps with overlapping responsibilities is not nice, but
3888  * aggregations are very performance sensitive, making this worthwhile.
3889  *
3890  * For ordered aggregates:
3891  *
3892  * Only need to choose between the faster path for a single ordered
3893  * column, and the one between multiple columns. Checking strictness etc
3894  * is done when finalizing the aggregate. See
3895  * process_ordered_aggregate_{single, multi} and
3896  * advance_transition_function.
3897  */
3898  if (pertrans->numSortCols == 0)
3899  {
3900  if (pertrans->transtypeByVal)
3901  {
3902  if (fcinfo->flinfo->fn_strict &&
3903  pertrans->initValueIsNull)
3905  else if (fcinfo->flinfo->fn_strict)
3907  else
3909  }
3910  else
3911  {
3912  if (fcinfo->flinfo->fn_strict &&
3913  pertrans->initValueIsNull)
3915  else if (fcinfo->flinfo->fn_strict)
3917  else
3919  }
3920  }
3921  else if (pertrans->numInputs == 1)
3923  else
3925 
3926  scratch->d.agg_trans.pertrans = pertrans;
3927  scratch->d.agg_trans.setno = setno;
3928  scratch->d.agg_trans.setoff = setoff;
3929  scratch->d.agg_trans.transno = transno;
3930  scratch->d.agg_trans.aggcontext = aggcontext;
3931  ExprEvalPushStep(state, scratch);
3932 
3933  /* fix up jumpnull */
3934  if (adjust_jumpnull != -1)
3935  {
3936  ExprEvalStep *as = &state->steps[adjust_jumpnull];
3937 
3939  Assert(as->d.agg_plain_pergroup_nullcheck.jumpnull == -1);
3940  as->d.agg_plain_pergroup_nullcheck.jumpnull = state->steps_len;
3941  }
3942 }
3943 
3944 /*
3945  * Build equality expression that can be evaluated using ExecQual(), returning
3946  * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e
3947  * two nulls match, a null and a not-null don't match.
3948  *
3949  * desc: tuple descriptor of the to-be-compared tuples
3950  * numCols: the number of attributes to be examined
3951  * keyColIdx: array of attribute column numbers
3952  * eqFunctions: array of function oids of the equality functions to use
3953  * parent: parent executor node
3954  */
3955 ExprState *
3957  const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
3958  int numCols,
3959  const AttrNumber *keyColIdx,
3960  const Oid *eqfunctions,
3961  const Oid *collations,
3962  PlanState *parent)
3963 {
3965  ExprEvalStep scratch = {0};
3966  int maxatt = -1;
3967  List *adjust_jumps = NIL;
3968  ListCell *lc;
3969 
3970  /*
3971  * When no columns are actually compared, the result's always true. See
3972  * special case in ExecQual().
3973  */
3974  if (numCols == 0)
3975  return NULL;
3976 
3977  state->expr = NULL;
3978  state->flags = EEO_FLAG_IS_QUAL;
3979  state->parent = parent;
3980 
3981  scratch.resvalue = &state->resvalue;
3982  scratch.resnull = &state->resnull;
3983 
3984  /* compute max needed attribute */
3985  for (int natt = 0; natt < numCols; natt++)
3986  {
3987  int attno = keyColIdx[natt];
3988 
3989  if (attno > maxatt)
3990  maxatt = attno;
3991  }
3992  Assert(maxatt >= 0);
3993 
3994  /* push deform steps */
3995  scratch.opcode = EEOP_INNER_FETCHSOME;
3996  scratch.d.fetch.last_var = maxatt;
3997  scratch.d.fetch.fixed = false;
3998  scratch.d.fetch.known_desc = ldesc;
3999  scratch.d.fetch.kind = lops;
4000  if (ExecComputeSlotInfo(state, &scratch))
4001  ExprEvalPushStep(state, &scratch);
4002 
4003  scratch.opcode = EEOP_OUTER_FETCHSOME;
4004  scratch.d.fetch.last_var = maxatt;
4005  scratch.d.fetch.fixed = false;
4006  scratch.d.fetch.known_desc = rdesc;
4007  scratch.d.fetch.kind = rops;
4008  if (ExecComputeSlotInfo(state, &scratch))
4009  ExprEvalPushStep(state, &scratch);
4010 
4011  /*
4012  * Start comparing at the last field (least significant sort key). That's
4013  * the most likely to be different if we are dealing with sorted input.
4014  */
4015  for (int natt = numCols; --natt >= 0;)
4016  {
4017  int attno = keyColIdx[natt];
4018  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
4019  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
4020  Oid foid = eqfunctions[natt];
4021  Oid collid = collations[natt];
4022  FmgrInfo *finfo;
4023  FunctionCallInfo fcinfo;
4024  AclResult aclresult;
4025 
4026  /* Check permission to call function */
4027  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
4028  if (aclresult != ACLCHECK_OK)
4029  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4030 
4032 
4033  /* Set up the primary fmgr lookup information */
4034  finfo = palloc0(sizeof(FmgrInfo));
4035  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4036  fmgr_info(foid, finfo);
4037  fmgr_info_set_expr(NULL, finfo);
4038  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4039  collid, NULL, NULL);
4040 
4041  /* left arg */
4042  scratch.opcode = EEOP_INNER_VAR;
4043  scratch.d.var.attnum = attno - 1;
4044  scratch.d.var.vartype = latt->atttypid;
4045  scratch.resvalue = &fcinfo->args[0].value;
4046  scratch.resnull = &fcinfo->args[0].isnull;
4047  ExprEvalPushStep(state, &scratch);
4048 
4049  /* right arg */
4050  scratch.opcode = EEOP_OUTER_VAR;
4051  scratch.d.var.attnum = attno - 1;
4052  scratch.d.var.vartype = ratt->atttypid;
4053  scratch.resvalue = &fcinfo->args[1].value;
4054  scratch.resnull = &fcinfo->args[1].isnull;
4055  ExprEvalPushStep(state, &scratch);
4056 
4057  /* evaluate distinctness */
4058  scratch.opcode = EEOP_NOT_DISTINCT;
4059  scratch.d.func.finfo = finfo;
4060  scratch.d.func.fcinfo_data = fcinfo;
4061  scratch.d.func.fn_addr = finfo->fn_addr;
4062  scratch.d.func.nargs = 2;
4063  scratch.resvalue = &state->resvalue;
4064  scratch.resnull = &state->resnull;
4065  ExprEvalPushStep(state, &scratch);
4066 
4067  /* then emit EEOP_QUAL to detect if result is false (or null) */
4068  scratch.opcode = EEOP_QUAL;
4069  scratch.d.qualexpr.jumpdone = -1;
4070  scratch.resvalue = &state->resvalue;
4071  scratch.resnull = &state->resnull;
4072  ExprEvalPushStep(state, &scratch);
4073  adjust_jumps = lappend_int(adjust_jumps,
4074  state->steps_len - 1);
4075  }
4076 
4077  /* adjust jump targets */
4078  foreach(lc, adjust_jumps)
4079  {
4080  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4081 
4082  Assert(as->opcode == EEOP_QUAL);
4083  Assert(as->d.qualexpr.jumpdone == -1);
4084  as->d.qualexpr.jumpdone = state->steps_len;
4085  }
4086 
4087  scratch.resvalue = NULL;
4088  scratch.resnull = NULL;
4089  scratch.opcode = EEOP_DONE;
4090  ExprEvalPushStep(state, &scratch);
4091 
4093 
4094  return state;
4095 }
4096 
4097 /*
4098  * Build equality expression that can be evaluated using ExecQual(), returning
4099  * true if the expression context's inner/outer tuples are equal. Datums in
4100  * the inner/outer slots are assumed to be in the same order and quantity as
4101  * the 'eqfunctions' parameter. NULLs are treated as equal.
4102  *
4103  * desc: tuple descriptor of the to-be-compared tuples
4104  * lops: the slot ops for the inner tuple slots
4105  * rops: the slot ops for the outer tuple slots
4106  * eqFunctions: array of function oids of the equality functions to use
4107  * this must be the same length as the 'param_exprs' list.
4108  * collations: collation Oids to use for equality comparison. Must be the
4109  * same length as the 'param_exprs' list.
4110  * parent: parent executor node
4111  */
4112 ExprState *
4114  const TupleTableSlotOps *lops,
4115  const TupleTableSlotOps *rops,
4116  const Oid *eqfunctions,
4117  const Oid *collations,
4118  const List *param_exprs,
4119  PlanState *parent)
4120 {
4122  ExprEvalStep scratch = {0};
4123  int maxatt = list_length(param_exprs);
4124  List *adjust_jumps = NIL;
4125  ListCell *lc;
4126 
4127  state->expr = NULL;
4128  state->flags = EEO_FLAG_IS_QUAL;
4129  state->parent = parent;
4130 
4131  scratch.resvalue = &state->resvalue;
4132  scratch.resnull = &state->resnull;
4133 
4134  /* push deform steps */
4135  scratch.opcode = EEOP_INNER_FETCHSOME;
4136  scratch.d.fetch.last_var = maxatt;
4137  scratch.d.fetch.fixed = false;
4138  scratch.d.fetch.known_desc = desc;
4139  scratch.d.fetch.kind = lops;
4140  if (ExecComputeSlotInfo(state, &scratch))
4141  ExprEvalPushStep(state, &scratch);
4142 
4143  scratch.opcode = EEOP_OUTER_FETCHSOME;
4144  scratch.d.fetch.last_var = maxatt;
4145  scratch.d.fetch.fixed = false;
4146  scratch.d.fetch.known_desc = desc;
4147  scratch.d.fetch.kind = rops;
4148  if (ExecComputeSlotInfo(state, &scratch))
4149  ExprEvalPushStep(state, &scratch);
4150 
4151  for (int attno = 0; attno < maxatt; attno++)
4152  {
4153  Form_pg_attribute att = TupleDescAttr(desc, attno);
4154  Oid foid = eqfunctions[attno];
4155  Oid collid = collations[attno];
4156  FmgrInfo *finfo;
4157  FunctionCallInfo fcinfo;
4158  AclResult aclresult;
4159 
4160  /* Check permission to call function */
4161  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
4162  if (aclresult != ACLCHECK_OK)
4163  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
4164 
4166 
4167  /* Set up the primary fmgr lookup information */
4168  finfo = palloc0(sizeof(FmgrInfo));
4169  fcinfo = palloc0(SizeForFunctionCallInfo(2));
4170  fmgr_info(foid, finfo);
4171  fmgr_info_set_expr(NULL, finfo);
4172  InitFunctionCallInfoData(*fcinfo, finfo, 2,
4173  collid, NULL, NULL);
4174 
4175  /* left arg */
4176  scratch.opcode = EEOP_INNER_VAR;
4177  scratch.d.var.attnum = attno;
4178  scratch.d.var.vartype = att->atttypid;
4179  scratch.resvalue = &fcinfo->args[0].value;
4180  scratch.resnull = &fcinfo->args[0].isnull;
4181  ExprEvalPushStep(state, &scratch);
4182 
4183  /* right arg */
4184  scratch.opcode = EEOP_OUTER_VAR;
4185  scratch.d.var.attnum = attno;
4186  scratch.d.var.vartype = att->atttypid;
4187  scratch.resvalue = &fcinfo->args[1].value;
4188  scratch.resnull = &fcinfo->args[1].isnull;
4189  ExprEvalPushStep(state, &scratch);
4190 
4191  /* evaluate distinctness */
4192  scratch.opcode = EEOP_NOT_DISTINCT;
4193  scratch.d.func.finfo = finfo;
4194  scratch.d.func.fcinfo_data = fcinfo;
4195  scratch.d.func.fn_addr = finfo->fn_addr;
4196  scratch.d.func.nargs = 2;
4197  scratch.resvalue = &state->resvalue;
4198  scratch.resnull = &state->resnull;
4199  ExprEvalPushStep(state, &scratch);
4200 
4201  /* then emit EEOP_QUAL to detect if result is false (or null) */
4202  scratch.opcode = EEOP_QUAL;
4203  scratch.d.qualexpr.jumpdone = -1;
4204  scratch.resvalue = &state->resvalue;
4205  scratch.resnull = &state->resnull;
4206  ExprEvalPushStep(state, &scratch);
4207  adjust_jumps = lappend_int(adjust_jumps,
4208  state->steps_len - 1);
4209  }
4210 
4211  /* adjust jump targets */
4212  foreach(lc, adjust_jumps)
4213  {
4214  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
4215 
4216  Assert(as->opcode == EEOP_QUAL);
4217  Assert(as->d.qualexpr.jumpdone == -1);
4218  as->d.qualexpr.jumpdone = state->steps_len;
4219  }
4220 
4221  scratch.resvalue = NULL;
4222  scratch.resnull = NULL;
4223  scratch.opcode = EEOP_DONE;
4224  ExprEvalPushStep(state, &scratch);
4225 
4227 
4228  return state;
4229 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3512
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:5071
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:738
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define MAXALIGN(LEN)
Definition: c.h:757
#define Max(x, y)
Definition: c.h:980
unsigned char bool
Definition: c.h:391
#define OidIsValid(objectId)
Definition: c.h:710
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1014
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
void ExecReadyInterpretedExpr(ExprState *state)
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2824
static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:3384
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:746
static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info)
Definition: execExpr.c:2886
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:853
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:900
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:3840
ExprState * ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
Definition: execExpr.c:172
static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
Definition: execExpr.c:3038
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:318
struct LastAttnumInfo LastAttnumInfo
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2693
ProjectionInfo * ExecBuildUpdateProjection(List *targetList, bool evalTargetList, List *targetColnos, TupleDesc relDesc, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent)
Definition: execExpr.c:513
ExprState * ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
Definition: execExpr.c:3538
static ExprState * ExecInitExprInternal(Expr *node, PlanState *parent, ParamListInfo ext_params, Datum *caseval, bool *casenull)
Definition: execExpr.c:92
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
static bool isAssignmentIndirectionExpr(Expr *expr)
Definition: execExpr.c:3353
static void ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:3111
ExprState * ExecPrepareCheck(List *qual, EState *estate)
Definition: execExpr.c:797
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:160
ExprState * ExecInitExprWithCaseValue(Expr *node, PlanState *parent, Datum *caseval, bool *casenull)
Definition: execExpr.c:184
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition: execExpr.c:298
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2940
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:774
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:353
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
Definition: execExpr.c:2842
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:3956
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition: execExpr.c:820
static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, Oid inputcollid, ExprState *state)
Definition: execExpr.c:2719
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:883
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:4113
ExprEvalOp
Definition: execExpr.h:66
@ EEOP_ASSIGN_TMP
Definition: execExpr.h:98
@ EEOP_SUBPLAN
Definition: execExpr.h:242
@ EEOP_CONVERT_ROWTYPE
Definition: execExpr.h:235
@ EEOP_FUNCEXPR_STRICT_FUSAGE
Definition: execExpr.h:113
@ EEOP_ARRAYEXPR
Definition: execExpr.h:177
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:172
@ EEOP_DOMAIN_TESTVAL
Definition: execExpr.h:226
@ EEOP_PARAM_EXTERN
Definition: execExpr.h:160
@ EEOP_BOOL_AND_STEP
Definition: execExpr.h:122
@ EEOP_WHOLEROW
Definition: execExpr.h:86
@ EEOP_AGGREF
Definition: execExpr.h:239
@ EEOP_INNER_VAR
Definition: execExpr.h:76
@ EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
Definition: execExpr.h:252
@ EEOP_ROWCOMPARE_FINAL
Definition: execExpr.h:188
@ EEOP_AGG_STRICT_DESERIALIZE
Definition: execExpr.h:248
@ EEOP_IOCOERCE
Definition: execExpr.h:170
@ EEOP_GROUPING_FUNC
Definition: execExpr.h:240
@ EEOP_DOMAIN_CHECK
Definition: execExpr.h:232
@ EEOP_BOOLTEST_IS_NOT_FALSE
Definition: execExpr.h:156
@ EEOP_NEXTVALUEEXPR
Definition: execExpr.h:176
@ EEOP_DONE
Definition: execExpr.h:68
@ EEOP_AGG_PLAIN_TRANS_BYREF
Definition: execExpr.h:258
@ EEOP_QUAL
Definition: execExpr.h:134
@ EEOP_AGG_PLAIN_TRANS_BYVAL
Definition: execExpr.h:255
@ EEOP_SCAN_VAR
Definition: execExpr.h:78
@ EEOP_BOOL_NOT_STEP
Definition: execExpr.h:131
@ EEOP_ASSIGN_SCAN_VAR
Definition: execExpr.h:95
@ EEOP_SCAN_SYSVAR
Definition: execExpr.h:83
@ EEOP_SCALARARRAYOP
Definition: execExpr.h:236
@ EEOP_DOMAIN_NOTNULL
Definition: execExpr.h:229
@ EEOP_WINDOW_FUNC
Definition: execExpr.h:241
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:71
@ EEOP_NULLTEST_ROWISNOTNULL
Definition: execExpr.h:150
@ EEOP_ASSIGN_OUTER_VAR
Definition: execExpr.h:94
@ EEOP_ROW
Definition: execExpr.h:179
@ EEOP_MAKE_READONLY
Definition: execExpr.h:167
@ EEOP_FIELDSTORE_FORM
Definition: execExpr.h:207
@ EEOP_SBSREF_SUBSCRIPTS
Definition: execExpr.h:210
@ EEOP_SBSREF_FETCH
Definition: execExpr.h:223
@ EEOP_FUNCEXPR_STRICT
Definition: execExpr.h:111
@ EEOP_NULLIF
Definition: execExpr.h:173
@ EEOP_CURRENTOFEXPR
Definition: execExpr.h:175
@ EEOP_INNER_SYSVAR
Definition: execExpr.h:81
@ EEOP_ASSIGN_TMP_MAKE_RO
Definition: execExpr.h:100
@ EEOP_CONST
Definition: execExpr.h:103
@ EEOP_BOOL_OR_STEP_LAST
Definition: execExpr.h:128
@ EEOP_JSONEXPR
Definition: execExpr.h:245
@ EEOP_BOOL_OR_STEP_FIRST
Definition: execExpr.h:126
@ EEOP_XMLEXPR
Definition: execExpr.h:238
@ EEOP_AGG_STRICT_INPUT_CHECK_NULLS
Definition: execExpr.h:251
@ EEOP_SBSREF_ASSIGN
Definition: execExpr.h:220
@ EEOP_OUTER_SYSVAR
Definition: execExpr.h:82
@ EEOP_ASSIGN_INNER_VAR
Definition: execExpr.h:93
@ EEOP_BOOL_OR_STEP
Definition: execExpr.h:127
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_AGG_STRICT_INPUT_CHECK_ARGS
Definition: execExpr.h:250
@ EEOP_NULLTEST_ROWISNULL
Definition: execExpr.h:149
@ EEOP_BOOLTEST_IS_TRUE
Definition: execExpr.h:153
@ EEOP_FUNCEXPR
Definition: execExpr.h:110
@ EEOP_NULLTEST_ISNOTNULL
Definition: execExpr.h:146
@ EEOP_ROWCOMPARE_STEP
Definition: execExpr.h:185
@ EEOP_AGG_DESERIALIZE
Definition: execExpr.h:249
@ EEOP_DISTINCT
Definition: execExpr.h:171
@ EEOP_JUMP_IF_NOT_TRUE
Definition: execExpr.h:142
@ EEOP_FUNCEXPR_FUSAGE
Definition: execExpr.h:112
@ EEOP_BOOL_AND_STEP_FIRST
Definition: execExpr.h:121
@ EEOP_JUMP
Definition: execExpr.h:137
@ EEOP_BOOL_AND_STEP_LAST
Definition: execExpr.h:123
@ EEOP_AGG_ORDERED_TRANS_DATUM
Definition: execExpr.h:259
@ EEOP_SBSREF_OLD
Definition: execExpr.h:217
@ EEOP_SQLVALUEFUNCTION
Definition: execExpr.h:174
@ EEOP_JUMP_IF_NOT_NULL
Definition: execExpr.h:141
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
Definition: execExpr.h:257
@ EEOP_FIELDSTORE_DEFORM
Definition: execExpr.h:200
@ EEOP_BOOLTEST_IS_FALSE
Definition: execExpr.h:155
@ EEOP_BOOLTEST_IS_NOT_TRUE
Definition: execExpr.h:154
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
Definition: execExpr.h:253
@ EEOP_PARAM_EXEC
Definition: execExpr.h:159
@ EEOP_JSON_CONSTRUCTOR
Definition: execExpr.h:243
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
Definition: execExpr.h:254
@ EEOP_NULLTEST_ISNULL
Definition: execExpr.h:145
@ EEOP_MINMAX
Definition: execExpr.h:191
@ EEOP_JUMP_IF_NULL
Definition: execExpr.h:140
@ EEOP_ARRAYCOERCE
Definition: execExpr.h:178
@ EEOP_FIELDSELECT
Definition: execExpr.h:194
@ EEOP_CASE_TESTVAL
Definition: execExpr.h:164
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
Definition: execExpr.h:256
@ EEOP_HASHED_SCALARARRAYOP
Definition: execExpr.h:237
@ EEOP_OUTER_VAR
Definition: execExpr.h:77
@ EEOP_AGG_ORDERED_TRANS_TUPLE
Definition: execExpr.h:260
@ EEOP_SCAN_FETCHSOME
Definition: execExpr.h:73
@ EEOP_IS_JSON
Definition: execExpr.h:244
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
Definition: execJunk.c:60
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2071
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2030
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1831
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:1997
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:490
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:499
int executor_errposition(EState *estate, int location)
Definition: execUtils.c:898
#define outerPlanState(node)
Definition: execnodes.h:1094
#define innerPlanState(node)
Definition: execnodes.h:1093
@ DOM_CONSTRAINT_CHECK
Definition: execnodes.h:956
@ DOM_CONSTRAINT_NOTNULL
Definition: execnodes.h:955
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:60
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:335
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#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
bool jit_compile_expr(struct ExprState *state)
Definition: jit.c:153
void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: json.c:166
JsonTypeCategory
Definition: json.h:20
void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:613
JsonbTypeCategory
Definition: jsonb.h:381
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:336
List * lappend_int(List *list, int datum)
Definition: list.c:354
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:134
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2716
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2228
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:794
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2831
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1589
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2154
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3087
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:338
Expr * make_ands_explicit(List *andclauses)
Definition: makefuncs.c:709
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void * palloc0(Size size)
Definition: mcxt.c:1099
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
void * palloc(Size size)
Definition: mcxt.c:1068
Oid GetUserId(void)
Definition: miscinit.c:492
#define BTORDER_PROC
Definition: nbtree.h:702
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:286
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:2015
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1343
SubPlanState * ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
Definition: nodeSubplan.c:789
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
#define nodeTag(nodeptr)
Definition: nodes.h:578
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:838
@ AGG_HASHED
Definition: nodes.h:809
@ T_FieldStore
Definition: nodes.h:175
@ T_CoalesceExpr
Definition: nodes.h:187
@ T_CoerceToDomainValue
Definition: nodes.h:194
@ T_WindowFunc
Definition: nodes.h:162
@ T_FieldSelect
Definition: nodes.h:174
@ T_ArrayExpr
Definition: nodes.h:184
@ T_BoolExpr
Definition: nodes.h:170
@ T_OpExpr
Definition: nodes.h:166
@ T_ScalarArrayOpExpr
Definition: nodes.h:169
@ T_CaseExpr
Definition: nodes.h:181
@ T_RelabelType
Definition: nodes.h:176
@ T_XmlExpr
Definition: nodes.h:190
@ T_ExprState
Definition: nodes.h:227
@ T_ConvertRowtypeExpr
Definition: nodes.h:179
@ T_SubqueryScanState
Definition: nodes.h:123
@ T_JsonConstructorExpr
Definition: nodes.h:211
@ T_CteScanState
Definition: nodes.h:127
@ T_RowExpr
Definition: nodes.h:185
@ T_ArrayCoerceExpr
Definition: nodes.h:178
@ T_MinMaxExpr
Definition: nodes.h:188
@ T_CurrentOfExpr
Definition: nodes.h:196
@ T_Aggref
Definition: nodes.h:160
@ T_BooleanTest
Definition: nodes.h:192
@ T_JsonIsPredicate
Definition: nodes.h:518
@ T_JsonValueExpr
Definition: nodes.h:207
@ T_SubPlan
Definition: nodes.h:172
@ T_SQLValueFunction
Definition: nodes.h:189
@ T_Const
Definition: nodes.h:158
@ T_CoerceViaIO
Definition: nodes.h:177
@ T_JsonExpr
Definition: nodes.h:212
@ T_NextValueExpr
Definition: nodes.h:197
@ T_Param
Definition: nodes.h:159
@ T_CoerceToDomain
Definition: nodes.h:193
@ T_GroupingFunc
Definition: nodes.h:161
@ T_DistinctExpr
Definition: nodes.h:167
@ T_FuncExpr
Definition: nodes.h:164
@ T_Var
Definition: nodes.h:157
@ T_RowCompareExpr
Definition: nodes.h:186
@ T_CaseTestExpr
Definition: nodes.h:183
@ T_NullTest
Definition: nodes.h:191
@ T_SubscriptingRef
Definition: nodes.h:163
@ T_NullIfExpr
Definition: nodes.h:168
#define makeNode(_type_)
Definition: nodes.h:621
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
@ OBJECT_FUNCTION
Definition: parsenodes.h:2153
#define ACL_EXECUTE
Definition: parsenodes.h:89
int16 attnum
Definition: pg_attribute.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
void * arg
#define FUNC_MAX_ARGS
#define lfirst(lc)
Definition: pg_list.h:169
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
#define lfirst_int(lc)
Definition: pg_list.h:170
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:417
#define linitial(l)
Definition: pg_list.h:174
#define lsecond(l)
Definition: pg_list.h:179
#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5)
Definition: pg_list.h:516
#define lfirst_oid(lc)
Definition: pg_list.h:171
Expr * expression_planner(Expr *expr)
Definition: planner.c:5882
void check_stack_depth(void)
Definition: postgres.c:3500
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetBool(X)
Definition: postgres.h:437
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define Int32GetDatum(X)
Definition: postgres.h:523
#define PointerGetDatum(X)
Definition: postgres.h:600
#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:1543
@ IS_NOT_FALSE
Definition: primnodes.h:1543
@ IS_NOT_UNKNOWN
Definition: primnodes.h:1543
@ IS_TRUE
Definition: primnodes.h:1543
@ IS_UNKNOWN
Definition: primnodes.h:1543
@ IS_FALSE
Definition: primnodes.h:1543
@ JS_FORMAT_JSONB
Definition: primnodes.h:1277
@ AND_EXPR
Definition: primnodes.h:628
@ OR_EXPR
Definition: primnodes.h:628
@ NOT_EXPR
Definition: primnodes.h:628
@ PARAM_EXTERN
Definition: primnodes.h:267
@ PARAM_EXEC
Definition: primnodes.h:268
@ IS_NULL
Definition: primnodes.h:1520
@ IS_NOT_NULL
Definition: primnodes.h:1520
#define OUTER_VAR
Definition: primnodes.h:185
@ JSCTOR_JSON_SERIALIZE
Definition: primnodes.h:1355
@ JSCTOR_JSON_PARSE
Definition: primnodes.h:1356
@ JSCTOR_JSON_SCALAR
Definition: primnodes.h:1354
#define INNER_VAR
Definition: primnodes.h:184
TupleTableSlot * sortslot
Definition: nodeAgg.h:136
Aggref * aggref
Definition: nodeAgg.h:44
FmgrInfo deserialfn
Definition: nodeAgg.h:87
FunctionCallInfo deserialfn_fcinfo
Definition: nodeAgg.h:167
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:162
ScanState ss
Definition: execnodes.h:2326
List * aggs
Definition: execnodes.h:2327
AggStatePerTrans pertrans
Definition: execnodes.h:2336
AggStrategy aggstrategy
Definition: execnodes.h:2330
int numtrans
Definition: execnodes.h:2329
ExprContext * hashcontext
Definition: execnodes.h:2337
AggSplit aggsplit
Definition: execnodes.h:2331
int num_hashes
Definition: execnodes.h:2367
int maxsets
Definition: execnodes.h:2356
ExprContext ** aggcontexts
Definition: execnodes.h:2338
Definition: plannodes.h:895
List * groupingSets
Definition: plannodes.h:907
List * aggdistinct
Definition: primnodes.h:341
List * aggdirectargs
Definition: primnodes.h:338
List * args
Definition: primnodes.h:339
Expr * aggfilter
Definition: primnodes.h:342
List * aggorder
Definition: primnodes.h:340
int aggno
Definition: primnodes.h:349
Expr * elemexpr
Definition: primnodes.h:914
bool multidims
Definition: primnodes.h:1047
List * elements
Definition: primnodes.h:1046
Oid element_typeid
Definition: primnodes.h:1045
BoolExprType boolop
Definition: primnodes.h:634
List * args
Definition: primnodes.h:635
BoolTestType booltesttype
Definition: primnodes.h:1550
Expr * arg
Definition: primnodes.h:1549
Expr * arg
Definition: primnodes.h:987
Expr * defresult
Definition: primnodes.h:989
List * args
Definition: primnodes.h:988
List * args
Definition: primnodes.h:1139
Expr * arg
Definition: primnodes.h:889
Oid resulttype
Definition: primnodes.h:890
Datum constvalue
Definition: primnodes.h:228
bool constisnull
Definition: primnodes.h:229
DomainConstraintType constrainttype
Definition: execnodes.h:962
MemoryContext es_query_cxt
Definition: execnodes.h:632
struct ExprEvalStep::@52::@95 is_json
struct ExprEvalStep::@52::@62 jump
struct ExprEvalStep::@52::@68 iocoerce
struct ExprEvalStep::@52::@81 domaincheck
struct ExprEvalStep::@52::@56 assign_var
struct ExprEvalStep::@52::@78 fieldstore
struct ExprEvalStep::@52::@75 rowcompare_final
struct ExprEvalStep::@52::@77 fieldselect
struct ExprEvalStep::@52::@53 fetch
struct ExprEvalStep::@52::@85 xmlexpr
struct ExprEvalStep::@52::@87 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:274
struct ExprEvalStep::@52::@93 agg_trans
Datum * resvalue
Definition: execExpr.h:277
struct ExprEvalStep::@52::@70 nextvalueexpr
struct ExprEvalStep::@52::@63 nulltest_row
struct ExprEvalStep::@52::@54 var
struct ExprEvalStep::@52::@96 jsonexpr
struct ExprEvalStep::@52::@76 minmax
struct ExprEvalStep::@52::@55 wholerow
union ExprEvalStep::@52 d
struct ExprEvalStep::@52::@94 json_constructor
struct ExprEvalStep::@52::@57 assign_tmp
struct ExprEvalStep::@52::@72 arraycoerce
struct ExprEvalStep::@52::@82 convert_rowtype
struct ExprEvalStep::@52::@58 constval
struct ExprEvalStep::@52::@90 agg_deserialize
bool * resnull
Definition: execExpr.h:278
struct ExprEvalStep::@52::@74 rowcompare_step
struct ExprEvalStep::@52::@92 agg_plain_pergroup_nullcheck
struct ExprEvalStep::@52::@83 scalararrayop
struct ExprEvalStep::@52::@84 hashedscalararrayop
struct ExprEvalStep::@52::@86 aggref
struct ExprEvalStep::@52::@66 casetest
struct ExprEvalStep::@52::@89 subplan
struct ExprEvalStep::@52::@91 agg_strict_input_check
struct ExprEvalStep::@52::@69 sqlvaluefunction
struct ExprEvalStep::@52::@60 boolexpr
struct ExprEvalStep::@52::@73 row
struct ExprEvalStep::@52::@88 window_func
struct ExprEvalStep::@52::@64 param
struct ExprEvalStep::@52::@71 arrayexpr
Expr * expr
Definition: execnodes.h:95
NodeTag type
Definition: execnodes.h:64
Datum resvalue
Definition: execnodes.h:75
struct ExprEvalStep * steps
Definition: execnodes.h:86
int steps_alloc
Definition: execnodes.h:106
bool resnull
Definition: execnodes.h:73
ParamListInfo ext_params
Definition: execnodes.h:110
struct PlanState * parent
Definition: execnodes.h:109
bool * innermost_casenull
Definition: execnodes.h:113
Datum * innermost_caseval
Definition: execnodes.h:112
int steps_len
Definition: execnodes.h:105
AttrNumber fieldnum
Definition: primnodes.h:818
Oid resulttype
Definition: primnodes.h:819
Expr * arg
Definition: primnodes.h:817
List * newvals
Definition: primnodes.h:847
Expr * arg
Definition: primnodes.h:846
Oid resulttype
Definition: primnodes.h:849
List * fieldnums
Definition: primnodes.h:848
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:504
List * args
Definition: primnodes.h:512
Oid inputcollid
Definition: primnodes.h:511
FmgrInfo * flinfo
Definition: fmgr.h:87
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
List * cols
Definition: primnodes.h:384
Node * default_expr
Definition: primnodes.h:1410
Node * expr
Definition: primnodes.h:1420
JsonReturning * returning
Definition: primnodes.h:1370
JsonConstructorType type
Definition: primnodes.h:1366
Node * formatted_expr
Definition: primnodes.h:1454
List * passing_values
Definition: primnodes.h:1459
JsonBehavior * on_empty
Definition: primnodes.h:1461
JsonItemCoercions * coercions
Definition: primnodes.h:1463
List * passing_names
Definition: primnodes.h:1458
Node * path_spec
Definition: primnodes.h:1457
JsonCoercion * result_coercion
Definition: primnodes.h:1455
JsonReturning * returning
Definition: primnodes.h:1460
JsonBehavior * on_error
Definition: primnodes.h:1462
bool omit_quotes
Definition: primnodes.h:1465
JsonFormatType format_type
Definition: primnodes.h:1319
JsonCoercion * null
Definition: primnodes.h:1434
struct ExprState * estate
Definition: jsonpath.h:266
struct ExprContext * econtext
Definition: jsonpath.h:265
JsonFormat * format
Definition: primnodes.h:1331
Expr * formatted_expr
Definition: primnodes.h:1344
Expr * raw_expr
Definition: primnodes.h:1343
AttrNumber last_outer
Definition: execExpr.c:60
AttrNumber last_inner
Definition: execExpr.c:59
AttrNumber last_scan
Definition: execExpr.c:61
Definition: pg_list.h:51
Oid inputcollid
Definition: primnodes.h:1157
List * args
Definition: primnodes.h:1159
MinMaxOp op
Definition: primnodes.h:1158
Oid minmaxtype
Definition: primnodes.h:1155
Definition: nodes.h:574
NullTestType nulltesttype
Definition: primnodes.h:1527
bool argisrow
Definition: primnodes.h:1528
Expr * arg
Definition: primnodes.h:1526
Datum value
Definition: postgres.h:422
List * args
Definition: primnodes.h:557
Oid opfuncid
Definition: primnodes.h:552
Oid inputcollid
Definition: primnodes.h:556
ParamCompileHook paramCompile
Definition: params.h:114
int paramid
Definition: primnodes.h:277
Oid paramtype
Definition: primnodes.h:278
ParamKind paramkind
Definition: primnodes.h:276
bool inneropsset
Definition: execnodes.h:1082
bool outeropsset
Definition: execnodes.h:1081
const TupleTableSlotOps * outerops
Definition: execnodes.h:1073
const TupleTableSlotOps * innerops
Definition: execnodes.h:1074
const TupleTableSlotOps * scanops
Definition: execnodes.h:1072
Plan * plan
Definition: execnodes.h:998
bool outeropsfixed
Definition: execnodes.h:1077
EState * state
Definition: execnodes.h:1000
bool scanopsset
Definition: execnodes.h:1080
TupleDesc scandesc
Definition: execnodes.h:1047
bool scanopsfixed
Definition: execnodes.h:1076
bool inneropsfixed
Definition: execnodes.h:1078
List * targetlist
Definition: plannodes.h:142
ExprState pi_state
Definition: execnodes.h:339
ExprContext * pi_exprContext
Definition: execnodes.h:341
Expr * arg
Definition: primnodes.h:869
RowCompareType rctype
Definition: primnodes.h:1123
List * opfamilies
Definition: primnodes.h:1125
List * inputcollids
Definition: primnodes.h:1126
Oid row_typeid
Definition: primnodes.h:1076
List * args
Definition: primnodes.h:1075
List * colnames
Definition: primnodes.h:1091
PlanState ps
Definition: execnodes.h:1423
Definition: value.h:58
char * sval
Definition: value.h:60
ExecEvalSubroutine sbs_fetch_old
Definition: execExpr.h:782
ExecEvalBoolSubroutine sbs_check_subscripts
Definition: execExpr.h:779
ExecEvalSubroutine sbs_assign
Definition: execExpr.h:781
ExecEvalSubroutine sbs_fetch
Definition: execExpr.h:780
SubscriptExecSetup exec_setup
Definition: subscripting.h:161