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