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