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