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