PostgreSQL Source Code  git master
execExpr.c File Reference
#include "postgres.h"
#include "access/nbtree.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_type.h"
#include "executor/execExpr.h"
#include "executor/nodeSubplan.h"
#include "funcapi.h"
#include "jit/jit.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "pgstat.h"
#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
Include dependency graph for execExpr.c:

Go to the source code of this file.

Data Structures

struct  LastAttnumInfo
 

Typedefs

typedef struct LastAttnumInfo LastAttnumInfo
 

Functions

static void ExecReadyExpr (ExprState *state)
 
static void ExecInitExprRec (Expr *node, ExprState *state, Datum *resv, bool *resnull)
 
static void ExecInitFunc (ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, Oid inputcollid, ExprState *state)
 
static void ExecInitExprSlots (ExprState *state, Node *node)
 
static void ExecPushExprSlots (ExprState *state, LastAttnumInfo *info)
 
static bool get_last_attnums_walker (Node *node, LastAttnumInfo *info)
 
static bool ExecComputeSlotInfo (ExprState *state, ExprEvalStep *op)
 
static void ExecInitWholeRowVar (ExprEvalStep *scratch, Var *variable, ExprState *state)
 
static void ExecInitSubscriptingRef (ExprEvalStep *scratch, SubscriptingRef *sbsref, ExprState *state, Datum *resv, bool *resnull)
 
static bool isAssignmentIndirectionExpr (Expr *expr)
 
static void ExecInitCoerceToDomain (ExprEvalStep *scratch, CoerceToDomain *ctest, ExprState *state, Datum *resv, bool *resnull)
 
static void ExecBuildAggTransCall (ExprState *state, AggState *aggstate, ExprEvalStep *scratch, FunctionCallInfo fcinfo, AggStatePerTrans pertrans, int transno, int setno, int setoff, bool ishash, bool nullcheck)
 
ExprStateExecInitExpr (Expr *node, PlanState *parent)
 
ExprStateExecInitExprWithParams (Expr *node, ParamListInfo ext_params)
 
ExprStateExecInitQual (List *qual, PlanState *parent)
 
ExprStateExecInitCheck (List *qual, PlanState *parent)
 
ListExecInitExprList (List *nodes, PlanState *parent)
 
ProjectionInfoExecBuildProjectionInfo (List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
 
ExprStateExecPrepareExpr (Expr *node, EState *estate)
 
ExprStateExecPrepareQual (List *qual, EState *estate)
 
ExprStateExecPrepareCheck (List *qual, EState *estate)
 
ListExecPrepareExprList (List *nodes, EState *estate)
 
bool ExecCheck (ExprState *state, ExprContext *econtext)
 
void ExprEvalPushStep (ExprState *es, const ExprEvalStep *s)
 
ExprStateExecBuildAggTrans (AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
 
ExprStateExecBuildGroupingEqual (TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, const AttrNumber *keyColIdx, const Oid *eqfunctions, const Oid *collations, PlanState *parent)
 

Typedef Documentation

◆ LastAttnumInfo

Function Documentation

◆ ExecBuildAggTrans()

ExprState* ExecBuildAggTrans ( AggState aggstate,
AggStatePerPhase  phase,
bool  doSort,
bool  doHash,
bool  nullcheck 
)

Definition at line 2934 of file execExpr.c.

References ExprEvalStep::agg_deserialize, AGG_HASHED, ExprEvalStep::agg_strict_input_check, Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, Aggref::aggorder, AggStatePerTransData::aggref, AggState::aggsplit, AggState::aggstrategy, arg, FunctionCallInfoBaseData::args, Aggref::args, Assert, ExprEvalStep::d, AggStatePerTransData::deserialfn, AggStatePerTransData::deserialfn_fcinfo, AggStatePerTransData::deserialfn_oid, DO_AGGSPLIT_COMBINE, EEOP_AGG_DESERIALIZE, EEOP_AGG_STRICT_DESERIALIZE, EEOP_AGG_STRICT_INPUT_CHECK_ARGS, EEOP_AGG_STRICT_INPUT_CHECK_NULLS, EEOP_DONE, EEOP_JUMP_IF_NOT_TRUE, ExecBuildAggTransCall(), ExecInitExprRec(), ExecPushExprSlots(), ExecReadyExpr(), ExprState::expr, TargetEntry::expr, ExprEvalPushStep(), FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_strict, get_last_attnums_walker(), NullableDatum::isnull, ExprEvalStep::jump, lappend_int(), lfirst, lfirst_int, linitial, list_length(), makeNode, Max, AggState::maxsets, NIL, AggState::num_hashes, AggStatePerTransData::numInputs, AggStatePerPhaseData::numsets, AggStatePerTransData::numSortCols, AggState::numtrans, AggStatePerTransData::numTransInputs, OidIsValid, ExprEvalStep::opcode, ExprState::parent, AggState::pertrans, PointerGetDatum, ScanState::ps, ExprState::resnull, ExprEvalStep::resnull, ExprState::resvalue, ExprEvalStep::resvalue, AggStatePerTransData::sortslot, AggState::ss, ExprState::steps, ExprState::steps_len, AggStatePerTransData::transfn_fcinfo, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, NullableDatum::value, and values.

Referenced by ExecInitAgg(), and hashagg_recompile_expressions().

2936 {
2938  PlanState *parent = &aggstate->ss.ps;
2939  ExprEvalStep scratch = {0};
2940  bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit);
2941  LastAttnumInfo deform = {0, 0, 0};
2942 
2943  state->expr = (Expr *) aggstate;
2944  state->parent = parent;
2945 
2946  scratch.resvalue = &state->resvalue;
2947  scratch.resnull = &state->resnull;
2948 
2949  /*
2950  * First figure out which slots, and how many columns from each, we're
2951  * going to need.
2952  */
2953  for (int transno = 0; transno < aggstate->numtrans; transno++)
2954  {
2955  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
2956 
2958  &deform);
2959  get_last_attnums_walker((Node *) pertrans->aggref->args,
2960  &deform);
2962  &deform);
2964  &deform);
2966  &deform);
2967  }
2968  ExecPushExprSlots(state, &deform);
2969 
2970  /*
2971  * Emit instructions for each transition value / grouping set combination.
2972  */
2973  for (int transno = 0; transno < aggstate->numtrans; transno++)
2974  {
2975  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
2976  FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
2977  List *adjust_bailout = NIL;
2978  NullableDatum *strictargs = NULL;
2979  bool *strictnulls = NULL;
2980  int argno;
2981  ListCell *bail;
2982 
2983  /*
2984  * If filter present, emit. Do so before evaluating the input, to
2985  * avoid potentially unneeded computations, or even worse, unintended
2986  * side-effects. When combining, all the necessary filtering has
2987  * already been done.
2988  */
2989  if (pertrans->aggref->aggfilter && !isCombine)
2990  {
2991  /* evaluate filter expression */
2992  ExecInitExprRec(pertrans->aggref->aggfilter, state,
2993  &state->resvalue, &state->resnull);
2994  /* and jump out if false */
2995  scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
2996  scratch.d.jump.jumpdone = -1; /* adjust later */
2997  ExprEvalPushStep(state, &scratch);
2998  adjust_bailout = lappend_int(adjust_bailout,
2999  state->steps_len - 1);
3000  }
3001 
3002  /*
3003  * Evaluate arguments to aggregate/combine function.
3004  */
3005  argno = 0;
3006  if (isCombine)
3007  {
3008  /*
3009  * Combining two aggregate transition values. Instead of directly
3010  * coming from a tuple the input is a, potentially deserialized,
3011  * transition value.
3012  */
3013  TargetEntry *source_tle;
3014 
3015  Assert(pertrans->numSortCols == 0);
3016  Assert(list_length(pertrans->aggref->args) == 1);
3017 
3018  strictargs = trans_fcinfo->args + 1;
3019  source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
3020 
3021  /*
3022  * deserialfn_oid will be set if we must deserialize the input
3023  * state before calling the combine function.
3024  */
3025  if (!OidIsValid(pertrans->deserialfn_oid))
3026  {
3027  /*
3028  * Start from 1, since the 0th arg will be the transition
3029  * value
3030  */
3031  ExecInitExprRec(source_tle->expr, state,
3032  &trans_fcinfo->args[argno + 1].value,
3033  &trans_fcinfo->args[argno + 1].isnull);
3034  }
3035  else
3036  {
3037  FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
3038 
3039  /* evaluate argument */
3040  ExecInitExprRec(source_tle->expr, state,
3041  &ds_fcinfo->args[0].value,
3042  &ds_fcinfo->args[0].isnull);
3043 
3044  /* Dummy second argument for type-safety reasons */
3045  ds_fcinfo->args[1].value = PointerGetDatum(NULL);
3046  ds_fcinfo->args[1].isnull = false;
3047 
3048  /*
3049  * Don't call a strict deserialization function with NULL
3050  * input
3051  */
3052  if (pertrans->deserialfn.fn_strict)
3054  else
3055  scratch.opcode = EEOP_AGG_DESERIALIZE;
3056 
3057  scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
3058  scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
3059  scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
3060  scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
3061 
3062  ExprEvalPushStep(state, &scratch);
3063  adjust_bailout = lappend_int(adjust_bailout,
3064  state->steps_len - 1);
3065 
3066  /* restore normal settings of scratch fields */
3067  scratch.resvalue = &state->resvalue;
3068  scratch.resnull = &state->resnull;
3069  }
3070  argno++;
3071  }
3072  else if (pertrans->numSortCols == 0)
3073  {
3074  ListCell *arg;
3075 
3076  /*
3077  * Normal transition function without ORDER BY / DISTINCT.
3078  */
3079  strictargs = trans_fcinfo->args + 1;
3080 
3081  foreach(arg, pertrans->aggref->args)
3082  {
3083  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3084 
3085  /*
3086  * Start from 1, since the 0th arg will be the transition
3087  * value
3088  */
3089  ExecInitExprRec(source_tle->expr, state,
3090  &trans_fcinfo->args[argno + 1].value,
3091  &trans_fcinfo->args[argno + 1].isnull);
3092  argno++;
3093  }
3094  }
3095  else if (pertrans->numInputs == 1)
3096  {
3097  /*
3098  * DISTINCT and/or ORDER BY case, with a single column sorted on.
3099  */
3100  TargetEntry *source_tle =
3101  (TargetEntry *) linitial(pertrans->aggref->args);
3102 
3103  Assert(list_length(pertrans->aggref->args) == 1);
3104 
3105  ExecInitExprRec(source_tle->expr, state,
3106  &state->resvalue,
3107  &state->resnull);
3108  strictnulls = &state->resnull;
3109  argno++;
3110  }
3111  else
3112  {
3113  /*
3114  * DISTINCT and/or ORDER BY case, with multiple columns sorted on.
3115  */
3116  Datum *values = pertrans->sortslot->tts_values;
3117  bool *nulls = pertrans->sortslot->tts_isnull;
3118  ListCell *arg;
3119 
3120  strictnulls = nulls;
3121 
3122  foreach(arg, pertrans->aggref->args)
3123  {
3124  TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
3125 
3126  ExecInitExprRec(source_tle->expr, state,
3127  &values[argno], &nulls[argno]);
3128  argno++;
3129  }
3130  }
3131  Assert(pertrans->numInputs == argno);
3132 
3133  /*
3134  * For a strict transfn, nothing happens when there's a NULL input; we
3135  * just keep the prior transValue. This is true for both plain and
3136  * sorted/distinct aggregates.
3137  */
3138  if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
3139  {
3140  if (strictnulls)
3142  else
3144  scratch.d.agg_strict_input_check.nulls = strictnulls;
3145  scratch.d.agg_strict_input_check.args = strictargs;
3146  scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
3147  scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
3148  ExprEvalPushStep(state, &scratch);
3149  adjust_bailout = lappend_int(adjust_bailout,
3150  state->steps_len - 1);
3151  }
3152 
3153  /*
3154  * Call transition function (once for each concurrently evaluated
3155  * grouping set). Do so for both sort and hash based computations, as
3156  * applicable.
3157  */
3158  if (doSort)
3159  {
3160  int processGroupingSets = Max(phase->numsets, 1);
3161  int setoff = 0;
3162 
3163  for (int setno = 0; setno < processGroupingSets; setno++)
3164  {
3165  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3166  pertrans, transno, setno, setoff, false,
3167  nullcheck);
3168  setoff++;
3169  }
3170  }
3171 
3172  if (doHash)
3173  {
3174  int numHashes = aggstate->num_hashes;
3175  int setoff;
3176 
3177  /* in MIXED mode, there'll be preceding transition values */
3178  if (aggstate->aggstrategy != AGG_HASHED)
3179  setoff = aggstate->maxsets;
3180  else
3181  setoff = 0;
3182 
3183  for (int setno = 0; setno < numHashes; setno++)
3184  {
3185  ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo,
3186  pertrans, transno, setno, setoff, true,
3187  nullcheck);
3188  setoff++;
3189  }
3190  }
3191 
3192  /* adjust early bail out jump target(s) */
3193  foreach(bail, adjust_bailout)
3194  {
3195  ExprEvalStep *as = &state->steps[lfirst_int(bail)];
3196 
3197  if (as->opcode == EEOP_JUMP_IF_NOT_TRUE)
3198  {
3199  Assert(as->d.jump.jumpdone == -1);
3200  as->d.jump.jumpdone = state->steps_len;
3201  }
3202  else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
3204  {
3205  Assert(as->d.agg_strict_input_check.jumpnull == -1);
3206  as->d.agg_strict_input_check.jumpnull = state->steps_len;
3207  }
3208  else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE)
3209  {
3210  Assert(as->d.agg_deserialize.jumpnull == -1);
3211  as->d.agg_deserialize.jumpnull = state->steps_len;
3212  }
3213  else
3214  Assert(false);
3215  }
3216  }
3217 
3218  scratch.resvalue = NULL;
3219  scratch.resnull = NULL;
3220  scratch.opcode = EEOP_DONE;
3221  ExprEvalPushStep(state, &scratch);
3222 
3223  ExecReadyExpr(state);
3224 
3225  return state;
3226 }
List * aggdistinct
Definition: primnodes.h:321
#define NIL
Definition: pg_list.h:65
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:253
#define PointerGetDatum(X)
Definition: postgres.h:556
struct ExprEvalStep * steps
Definition: execnodes.h:85
ScanState ss
Definition: execnodes.h:2146
bool * resnull
Definition: execExpr.h:254
Definition: nodes.h:529
AggSplit aggsplit
Definition: execnodes.h:2151
List * args
Definition: primnodes.h:319
Datum * tts_values
Definition: tuptable.h:126
AggStatePerTrans pertrans
Definition: execnodes.h:2156
#define OidIsValid(objectId)
Definition: c.h:644
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:791
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:162
int numtrans
Definition: execnodes.h:2149
Aggref * aggref
Definition: nodeAgg.h:44
PlanState ps
Definition: execnodes.h:1332
int maxsets
Definition: execnodes.h:2173
#define linitial(l)
Definition: pg_list.h:195
AggStrategy aggstrategy
Definition: execnodes.h:2150
bool fn_strict
Definition: fmgr.h:61
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:191
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
bool * tts_isnull
Definition: tuptable.h:128
List * aggorder
Definition: primnodes.h:320
List * aggdirectargs
Definition: primnodes.h:318
Datum value
Definition: postgres.h:378
struct ExprEvalStep::@51::@90 agg_strict_input_check
List * lappend_int(List *list, int datum)
Definition: list.c:339
union ExprEvalStep::@51 d
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
Definition: execExpr.c:2274
int num_hashes
Definition: execnodes.h:2184
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
uintptr_t Datum
Definition: postgres.h:367
FmgrInfo * flinfo
Definition: fmgr.h:87
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
FmgrInfo deserialfn
Definition: nodeAgg.h:87
#define Max(x, y)
Definition: c.h:914
#define makeNode(_type_)
Definition: nodes.h:577
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
FunctionCallInfo deserialfn_fcinfo
Definition: nodeAgg.h:167
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
Expr * expr
Definition: primnodes.h:1407
static int list_length(const List *l)
Definition: pg_list.h:169
Expr * aggfilter
Definition: primnodes.h:322
static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info)
Definition: execExpr.c:2318
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int steps_len
Definition: execnodes.h:104
void * arg
struct ExprEvalStep::@51::@61 jump
TupleTableSlot * sortslot
Definition: nodeAgg.h:136
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74
struct ExprEvalStep::@51::@89 agg_deserialize
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:3234

◆ ExecBuildAggTransCall()

static void ExecBuildAggTransCall ( ExprState state,
AggState aggstate,
ExprEvalStep scratch,
FunctionCallInfo  fcinfo,
AggStatePerTrans  pertrans,
int  transno,
int  setno,
int  setoff,
bool  ishash,
bool  nullcheck 
)
static

Definition at line 3234 of file execExpr.c.

References ExprEvalStep::agg_plain_pergroup_nullcheck, ExprEvalStep::agg_trans, AggState::aggcontexts, Assert, ExprEvalStep::d, EEOP_AGG_ORDERED_TRANS_DATUM, EEOP_AGG_ORDERED_TRANS_TUPLE, EEOP_AGG_PLAIN_PERGROUP_NULLCHECK, EEOP_AGG_PLAIN_TRANS_BYREF, EEOP_AGG_PLAIN_TRANS_BYVAL, EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF, EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL, EEOP_AGG_PLAIN_TRANS_STRICT_BYREF, EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL, ExprEvalPushStep(), FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_strict, AggState::hashcontext, AggStatePerTransData::initValueIsNull, AggStatePerTransData::numInputs, AggStatePerTransData::numSortCols, ExprEvalStep::opcode, ExprState::steps, ExprState::steps_len, and AggStatePerTransData::transtypeByVal.

Referenced by ExecBuildAggTrans().

3239 {
3240  ExprContext *aggcontext;
3241  int adjust_jumpnull = -1;
3242 
3243  if (ishash)
3244  aggcontext = aggstate->hashcontext;
3245  else
3246  aggcontext = aggstate->aggcontexts[setno];
3247 
3248  /* add check for NULL pointer? */
3249  if (nullcheck)
3250  {
3252  scratch->d.agg_plain_pergroup_nullcheck.setoff = setoff;
3253  /* adjust later */
3254  scratch->d.agg_plain_pergroup_nullcheck.jumpnull = -1;
3255  ExprEvalPushStep(state, scratch);
3256  adjust_jumpnull = state->steps_len - 1;
3257  }
3258 
3259  /*
3260  * Determine appropriate transition implementation.
3261  *
3262  * For non-ordered aggregates:
3263  *
3264  * If the initial value for the transition state doesn't exist in the
3265  * pg_aggregate table then we will let the first non-NULL value returned
3266  * from the outer procNode become the initial value. (This is useful for
3267  * aggregates like max() and min().) The noTransValue flag signals that we
3268  * need to do so. If true, generate a
3269  * EEOP_AGG_INIT_STRICT_PLAIN_TRANS{,_BYVAL} step. This step also needs to
3270  * do the work described next:
3271  *
3272  * If the function is strict, but does have an initial value, choose
3273  * EEOP_AGG_STRICT_PLAIN_TRANS{,_BYVAL}, which skips the transition
3274  * function if the transition value has become NULL (because a previous
3275  * transition function returned NULL). This step also needs to do the work
3276  * described next:
3277  *
3278  * Otherwise we call EEOP_AGG_PLAIN_TRANS{,_BYVAL}, which does not have to
3279  * perform either of the above checks.
3280  *
3281  * Having steps with overlapping responsibilities is not nice, but
3282  * aggregations are very performance sensitive, making this worthwhile.
3283  *
3284  * For ordered aggregates:
3285  *
3286  * Only need to choose between the faster path for a single orderred
3287  * column, and the one between multiple columns. Checking strictness etc
3288  * is done when finalizing the aggregate. See
3289  * process_ordered_aggregate_{single, multi} and
3290  * advance_transition_function.
3291  */
3292  if (pertrans->numSortCols == 0)
3293  {
3294  if (pertrans->transtypeByVal)
3295  {
3296  if (fcinfo->flinfo->fn_strict &&
3297  pertrans->initValueIsNull)
3299  else if (fcinfo->flinfo->fn_strict)
3301  else
3303  }
3304  else
3305  {
3306  if (fcinfo->flinfo->fn_strict &&
3307  pertrans->initValueIsNull)
3309  else if (fcinfo->flinfo->fn_strict)
3311  else
3313  }
3314  }
3315  else if (pertrans->numInputs == 1)
3317  else
3319 
3320  scratch->d.agg_trans.pertrans = pertrans;
3321  scratch->d.agg_trans.setno = setno;
3322  scratch->d.agg_trans.setoff = setoff;
3323  scratch->d.agg_trans.transno = transno;
3324  scratch->d.agg_trans.aggcontext = aggcontext;
3325  ExprEvalPushStep(state, scratch);
3326 
3327  /* fix up jumpnull */
3328  if (adjust_jumpnull != -1)
3329  {
3330  ExprEvalStep *as = &state->steps[adjust_jumpnull];
3331 
3333  Assert(as->d.agg_plain_pergroup_nullcheck.jumpnull == -1);
3334  as->d.agg_plain_pergroup_nullcheck.jumpnull = state->steps_len;
3335  }
3336 }
struct ExprEvalStep * steps
Definition: execnodes.h:85
bool fn_strict
Definition: fmgr.h:61
struct ExprEvalStep::@51::@92 agg_trans
union ExprEvalStep::@51 d
ExprContext * hashcontext
Definition: execnodes.h:2157
FmgrInfo * flinfo
Definition: fmgr.h:87
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
ExprContext ** aggcontexts
Definition: execnodes.h:2158
#define Assert(condition)
Definition: c.h:738
intptr_t opcode
Definition: execExpr.h:250
struct ExprEvalStep::@51::@91 agg_plain_pergroup_nullcheck
int steps_len
Definition: execnodes.h:104

◆ ExecBuildGroupingEqual()

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 at line 3350 of file execExpr.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, FunctionCallInfoBaseData::args, Assert, ExprEvalStep::d, EEO_FLAG_IS_QUAL, EEOP_DONE, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, EEOP_NOT_DISTINCT, EEOP_OUTER_FETCHSOME, EEOP_OUTER_VAR, EEOP_QUAL, ExecComputeSlotInfo(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprEvalStep::fetch, ExprState::flags, fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, ExprEvalStep::func, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, NullableDatum::isnull, lappend_int(), lfirst_int, makeNode, NIL, OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprState::parent, pg_proc_aclcheck(), ExprEvalStep::qualexpr, ExprState::resnull, ExprEvalStep::resnull, ExprState::resvalue, ExprEvalStep::resvalue, SizeForFunctionCallInfo, ExprState::steps, ExprState::steps_len, TupleDescAttr, NullableDatum::value, and ExprEvalStep::var.

Referenced by BuildTupleHashTableExt(), ExecInitSubPlan(), ExecProcNode(), and execTuplesMatchPrepare().

3357 {
3359  ExprEvalStep scratch = {0};
3360  int maxatt = -1;
3361  List *adjust_jumps = NIL;
3362  ListCell *lc;
3363 
3364  /*
3365  * When no columns are actually compared, the result's always true. See
3366  * special case in ExecQual().
3367  */
3368  if (numCols == 0)
3369  return NULL;
3370 
3371  state->expr = NULL;
3372  state->flags = EEO_FLAG_IS_QUAL;
3373  state->parent = parent;
3374 
3375  scratch.resvalue = &state->resvalue;
3376  scratch.resnull = &state->resnull;
3377 
3378  /* compute max needed attribute */
3379  for (int natt = 0; natt < numCols; natt++)
3380  {
3381  int attno = keyColIdx[natt];
3382 
3383  if (attno > maxatt)
3384  maxatt = attno;
3385  }
3386  Assert(maxatt >= 0);
3387 
3388  /* push deform steps */
3389  scratch.opcode = EEOP_INNER_FETCHSOME;
3390  scratch.d.fetch.last_var = maxatt;
3391  scratch.d.fetch.fixed = false;
3392  scratch.d.fetch.known_desc = ldesc;
3393  scratch.d.fetch.kind = lops;
3394  if (ExecComputeSlotInfo(state, &scratch))
3395  ExprEvalPushStep(state, &scratch);
3396 
3397  scratch.opcode = EEOP_OUTER_FETCHSOME;
3398  scratch.d.fetch.last_var = maxatt;
3399  scratch.d.fetch.fixed = false;
3400  scratch.d.fetch.known_desc = rdesc;
3401  scratch.d.fetch.kind = rops;
3402  if (ExecComputeSlotInfo(state, &scratch))
3403  ExprEvalPushStep(state, &scratch);
3404 
3405  /*
3406  * Start comparing at the last field (least significant sort key). That's
3407  * the most likely to be different if we are dealing with sorted input.
3408  */
3409  for (int natt = numCols; --natt >= 0;)
3410  {
3411  int attno = keyColIdx[natt];
3412  Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1);
3413  Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1);
3414  Oid foid = eqfunctions[natt];
3415  Oid collid = collations[natt];
3416  FmgrInfo *finfo;
3417  FunctionCallInfo fcinfo;
3418  AclResult aclresult;
3419 
3420  /* Check permission to call function */
3421  aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
3422  if (aclresult != ACLCHECK_OK)
3423  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid));
3424 
3426 
3427  /* Set up the primary fmgr lookup information */
3428  finfo = palloc0(sizeof(FmgrInfo));
3429  fcinfo = palloc0(SizeForFunctionCallInfo(2));
3430  fmgr_info(foid, finfo);
3431  fmgr_info_set_expr(NULL, finfo);
3432  InitFunctionCallInfoData(*fcinfo, finfo, 2,
3433  collid, NULL, NULL);
3434 
3435  /* left arg */
3436  scratch.opcode = EEOP_INNER_VAR;
3437  scratch.d.var.attnum = attno - 1;
3438  scratch.d.var.vartype = latt->atttypid;
3439  scratch.resvalue = &fcinfo->args[0].value;
3440  scratch.resnull = &fcinfo->args[0].isnull;
3441  ExprEvalPushStep(state, &scratch);
3442 
3443  /* right arg */
3444  scratch.opcode = EEOP_OUTER_VAR;
3445  scratch.d.var.attnum = attno - 1;
3446  scratch.d.var.vartype = ratt->atttypid;
3447  scratch.resvalue = &fcinfo->args[1].value;
3448  scratch.resnull = &fcinfo->args[1].isnull;
3449  ExprEvalPushStep(state, &scratch);
3450 
3451  /* evaluate distinctness */
3452  scratch.opcode = EEOP_NOT_DISTINCT;
3453  scratch.d.func.finfo = finfo;
3454  scratch.d.func.fcinfo_data = fcinfo;
3455  scratch.d.func.fn_addr = finfo->fn_addr;
3456  scratch.d.func.nargs = 2;
3457  scratch.resvalue = &state->resvalue;
3458  scratch.resnull = &state->resnull;
3459  ExprEvalPushStep(state, &scratch);
3460 
3461  /* then emit EEOP_QUAL to detect if result is false (or null) */
3462  scratch.opcode = EEOP_QUAL;
3463  scratch.d.qualexpr.jumpdone = -1;
3464  scratch.resvalue = &state->resvalue;
3465  scratch.resnull = &state->resnull;
3466  ExprEvalPushStep(state, &scratch);
3467  adjust_jumps = lappend_int(adjust_jumps,
3468  state->steps_len - 1);
3469  }
3470 
3471  /* adjust jump targets */
3472  foreach(lc, adjust_jumps)
3473  {
3474  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
3475 
3476  Assert(as->opcode == EEOP_QUAL);
3477  Assert(as->d.qualexpr.jumpdone == -1);
3478  as->d.qualexpr.jumpdone = state->steps_len;
3479  }
3480 
3481  scratch.resvalue = NULL;
3482  scratch.resnull = NULL;
3483  scratch.opcode = EEOP_DONE;
3484  ExprEvalPushStep(state, &scratch);
3485 
3486  ExecReadyExpr(state);
3487 
3488  return state;
3489 }
#define NIL
Definition: pg_list.h:65
Definition: fmgr.h:56
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:253
Oid GetUserId(void)
Definition: miscinit.c:448
PGFunction fn_addr
Definition: fmgr.h:58
struct ExprEvalStep * steps
Definition: execnodes.h:85
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
struct ExprEvalStep::@51::@52 fetch
bool * resnull
Definition: execExpr.h:254
unsigned int Oid
Definition: postgres_ext.h:31
struct ExprEvalStep::@51::@58 func
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:191
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1520
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Datum value
Definition: postgres.h:378
List * lappend_int(List *list, int datum)
Definition: list.c:339
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
union ExprEvalStep::@51 d
void * palloc0(Size size)
Definition: mcxt.c:980
AclResult
Definition: acl.h:177
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2372
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
struct ExprEvalStep::@51::@53 var
#define makeNode(_type_)
Definition: nodes.h:577
#define Assert(condition)
Definition: c.h:738
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
int steps_len
Definition: execnodes.h:104
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
uint8 flags
Definition: execnodes.h:65
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74
struct ExprEvalStep::@51::@60 qualexpr

◆ ExecBuildProjectionInfo()

ProjectionInfo* ExecBuildProjectionInfo ( List targetList,
ExprContext econtext,
TupleTableSlot slot,
PlanState parent,
TupleDesc  inputDesc 
)

Definition at line 353 of file execExpr.c.

References ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, attnum, ExprEvalStep::d, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_ASSIGN_TMP_MAKE_RO, EEOP_DONE, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, TargetEntry::expr, ExprEvalPushStep(), exprType(), ExprState::ext_params, get_typlen(), INNER_VAR, IsA, lfirst_node, makeNode, ExprEvalStep::opcode, OUTER_VAR, ExprState::parent, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_state, TargetEntry::resno, ExprState::resnull, ExprState::resultslot, ExprState::resvalue, T_ExprState, ExprState::tag, TupleDescAttr, Var::varattno, Var::varno, and Var::vartype.

Referenced by ExecAssignProjectionInfo(), ExecInitModifyTable(), ExecInitPartitionInfo(), ExecInitSubPlan(), and ExecProcNode().

358 {
360  ExprState *state;
361  ExprEvalStep scratch = {0};
362  ListCell *lc;
363 
364  projInfo->pi_exprContext = econtext;
365  /* We embed ExprState into ProjectionInfo instead of doing extra palloc */
366  projInfo->pi_state.tag = T_ExprState;
367  state = &projInfo->pi_state;
368  state->expr = (Expr *) targetList;
369  state->parent = parent;
370  state->ext_params = NULL;
371 
372  state->resultslot = slot;
373 
374  /* Insert EEOP_*_FETCHSOME steps as needed */
375  ExecInitExprSlots(state, (Node *) targetList);
376 
377  /* Now compile each tlist column */
378  foreach(lc, targetList)
379  {
380  TargetEntry *tle = lfirst_node(TargetEntry, lc);
381  Var *variable = NULL;
382  AttrNumber attnum = 0;
383  bool isSafeVar = false;
384 
385  /*
386  * If tlist expression is a safe non-system Var, use the fast-path
387  * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply
388  * CheckVarSlotCompatibility() during plan startup. If a source slot
389  * was provided, we make the equivalent tests here; if a slot was not
390  * provided, we assume that no check is needed because we're dealing
391  * with a non-relation-scan-level expression.
392  */
393  if (tle->expr != NULL &&
394  IsA(tle->expr, Var) &&
395  ((Var *) tle->expr)->varattno > 0)
396  {
397  /* Non-system Var, but how safe is it? */
398  variable = (Var *) tle->expr;
399  attnum = variable->varattno;
400 
401  if (inputDesc == NULL)
402  isSafeVar = true; /* can't check, just assume OK */
403  else if (attnum <= inputDesc->natts)
404  {
405  Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1);
406 
407  /*
408  * If user attribute is dropped or has a type mismatch, don't
409  * use ASSIGN_*_VAR. Instead let the normal expression
410  * machinery handle it (which'll possibly error out).
411  */
412  if (!attr->attisdropped && variable->vartype == attr->atttypid)
413  {
414  isSafeVar = true;
415  }
416  }
417  }
418 
419  if (isSafeVar)
420  {
421  /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */
422  switch (variable->varno)
423  {
424  case INNER_VAR:
425  /* get the tuple from the inner node */
426  scratch.opcode = EEOP_ASSIGN_INNER_VAR;
427  break;
428 
429  case OUTER_VAR:
430  /* get the tuple from the outer node */
431  scratch.opcode = EEOP_ASSIGN_OUTER_VAR;
432  break;
433 
434  /* INDEX_VAR is handled by default case */
435 
436  default:
437  /* get the tuple from the relation being scanned */
438  scratch.opcode = EEOP_ASSIGN_SCAN_VAR;
439  break;
440  }
441 
442  scratch.d.assign_var.attnum = attnum - 1;
443  scratch.d.assign_var.resultnum = tle->resno - 1;
444  ExprEvalPushStep(state, &scratch);
445  }
446  else
447  {
448  /*
449  * Otherwise, compile the column expression normally.
450  *
451  * We can't tell the expression to evaluate directly into the
452  * result slot, as the result slot (and the exprstate for that
453  * matter) can change between executions. We instead evaluate
454  * into the ExprState's resvalue/resnull and then move.
455  */
456  ExecInitExprRec(tle->expr, state,
457  &state->resvalue, &state->resnull);
458 
459  /*
460  * Column might be referenced multiple times in upper nodes, so
461  * force value to R/O - but only if it could be an expanded datum.
462  */
463  if (get_typlen(exprType((Node *) tle->expr)) == -1)
465  else
466  scratch.opcode = EEOP_ASSIGN_TMP;
467  scratch.d.assign_tmp.resultnum = tle->resno - 1;
468  ExprEvalPushStep(state, &scratch);
469  }
470  }
471 
472  scratch.opcode = EEOP_DONE;
473  ExprEvalPushStep(state, &scratch);
474 
475  ExecReadyExpr(state);
476 
477  return projInfo;
478 }
NodeTag tag
Definition: execnodes.h:63
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
struct PlanState * parent
Definition: execnodes.h:108
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
ParamListInfo ext_params
Definition: execnodes.h:109
Definition: nodes.h:529
AttrNumber varattno
Definition: primnodes.h:186
struct ExprEvalStep::@51::@55 assign_var
TupleTableSlot * resultslot
Definition: execnodes.h:80
Definition: primnodes.h:181
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
Oid vartype
Definition: primnodes.h:188
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
#define lfirst_node(type, lc)
Definition: pg_list.h:193
AttrNumber resno
Definition: primnodes.h:1408
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
union ExprEvalStep::@51 d
Index varno
Definition: primnodes.h:184
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:171
#define makeNode(_type_)
Definition: nodes.h:577
struct ExprEvalStep::@51::@56 assign_tmp
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
Expr * expr
Definition: primnodes.h:1407
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2085
ExprState pi_state
Definition: execnodes.h:333
ExprContext * pi_exprContext
Definition: execnodes.h:335
Datum resvalue
Definition: execnodes.h:74
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:172

◆ ExecCheck()

bool ExecCheck ( ExprState state,
ExprContext econtext 
)

Definition at line 599 of file execExpr.c.

References Assert, DatumGetBool, EEO_FLAG_IS_QUAL, ExecEvalExprSwitchContext(), and ExprState::flags.

Referenced by ATRewriteTable(), check_default_partition_contents(), domain_check_input(), ExecPartitionCheck(), ExecQualAndReset(), ExecRelCheck(), and validateCheckConstraint().

600 {
601  Datum ret;
602  bool isnull;
603 
604  /* short-circuit (here and in ExecInitCheck) for empty restriction list */
605  if (state == NULL)
606  return true;
607 
608  /* verify that expression was not compiled using ExecInitQual */
609  Assert(!(state->flags & EEO_FLAG_IS_QUAL));
610 
611  ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
612 
613  if (isnull)
614  return true;
615 
616  return DatumGetBool(ret);
617 }
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:305
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
#define DatumGetBool(X)
Definition: postgres.h:393
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:738
uint8 flags
Definition: execnodes.h:65

◆ ExecComputeSlotInfo()

static bool ExecComputeSlotInfo ( ExprState state,
ExprEvalStep op 
)
static

Definition at line 2372 of file execExpr.c.

References Assert, ExprEvalStep::d, EEOP_INNER_FETCHSOME, EEOP_OUTER_FETCHSOME, EEOP_SCAN_FETCHSOME, ExecGetResultSlotOps(), ExecGetResultType(), ExprEvalStep::fetch, PlanState::innerops, PlanState::inneropsfixed, PlanState::inneropsset, innerPlanState, ExprEvalStep::opcode, PlanState::outerops, PlanState::outeropsfixed, PlanState::outeropsset, outerPlanState, ExprState::parent, PlanState::scandesc, PlanState::scanops, PlanState::scanopsfixed, PlanState::scanopsset, and TTSOpsVirtual.

Referenced by ExecBuildGroupingEqual(), and ExecPushExprSlots().

2373 {
2374  PlanState *parent = state->parent;
2375  TupleDesc desc = NULL;
2376  const TupleTableSlotOps *tts_ops = NULL;
2377  bool isfixed = false;
2378  ExprEvalOp opcode = op->opcode;
2379 
2380  Assert(opcode == EEOP_INNER_FETCHSOME ||
2381  opcode == EEOP_OUTER_FETCHSOME ||
2382  opcode == EEOP_SCAN_FETCHSOME);
2383 
2384  if (op->d.fetch.known_desc != NULL)
2385  {
2386  desc = op->d.fetch.known_desc;
2387  tts_ops = op->d.fetch.kind;
2388  isfixed = op->d.fetch.kind != NULL;
2389  }
2390  else if (!parent)
2391  {
2392  isfixed = false;
2393  }
2394  else if (opcode == EEOP_INNER_FETCHSOME)
2395  {
2396  PlanState *is = innerPlanState(parent);
2397 
2398  if (parent->inneropsset && !parent->inneropsfixed)
2399  {
2400  isfixed = false;
2401  }
2402  else if (parent->inneropsset && parent->innerops)
2403  {
2404  isfixed = true;
2405  tts_ops = parent->innerops;
2406  desc = ExecGetResultType(is);
2407  }
2408  else if (is)
2409  {
2410  tts_ops = ExecGetResultSlotOps(is, &isfixed);
2411  desc = ExecGetResultType(is);
2412  }
2413  }
2414  else if (opcode == EEOP_OUTER_FETCHSOME)
2415  {
2416  PlanState *os = outerPlanState(parent);
2417 
2418  if (parent->outeropsset && !parent->outeropsfixed)
2419  {
2420  isfixed = false;
2421  }
2422  else if (parent->outeropsset && parent->outerops)
2423  {
2424  isfixed = true;
2425  tts_ops = parent->outerops;
2426  desc = ExecGetResultType(os);
2427  }
2428  else if (os)
2429  {
2430  tts_ops = ExecGetResultSlotOps(os, &isfixed);
2431  desc = ExecGetResultType(os);
2432  }
2433  }
2434  else if (opcode == EEOP_SCAN_FETCHSOME)
2435  {
2436  desc = parent->scandesc;
2437 
2438  if (parent->scanops)
2439  tts_ops = parent->scanops;
2440 
2441  if (parent->scanopsset)
2442  isfixed = parent->scanopsfixed;
2443  }
2444 
2445  if (isfixed && desc != NULL && tts_ops != NULL)
2446  {
2447  op->d.fetch.fixed = true;
2448  op->d.fetch.kind = tts_ops;
2449  op->d.fetch.known_desc = desc;
2450  }
2451  else
2452  {
2453  op->d.fetch.fixed = false;
2454  op->d.fetch.kind = NULL;
2455  op->d.fetch.known_desc = NULL;
2456  }
2457 
2458  /* if the slot is known to always virtual we never need to deform */
2459  if (op->d.fetch.fixed && op->d.fetch.kind == &TTSOpsVirtual)
2460  return false;
2461 
2462  return true;
2463 }
const TupleTableSlotOps * innerops
Definition: execnodes.h:1019
struct PlanState * parent
Definition: execnodes.h:108
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:504
bool inneropsset
Definition: execnodes.h:1027
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
struct ExprEvalStep::@51::@52 fetch
ExprEvalOp
Definition: execExpr.h:44
bool inneropsfixed
Definition: execnodes.h:1023
#define outerPlanState(node)
Definition: execnodes.h:1039
const TupleTableSlotOps * scanops
Definition: execnodes.h:1017
bool outeropsset
Definition: execnodes.h:1026
union ExprEvalStep::@51 d
TupleDesc scandesc
Definition: execnodes.h:992
bool scanopsfixed
Definition: execnodes.h:1021
#define Assert(condition)
Definition: c.h:738
intptr_t opcode
Definition: execExpr.h:250
bool outeropsfixed
Definition: execnodes.h:1022
bool scanopsset
Definition: execnodes.h:1025
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:495
#define innerPlanState(node)
Definition: execnodes.h:1038
const TupleTableSlotOps * outerops
Definition: execnodes.h:1018

◆ ExecInitCheck()

ExprState* ExecInitCheck ( List qual,
PlanState parent 
)

Definition at line 298 of file execExpr.c.

References Assert, ExecInitExpr(), IsA, make_ands_explicit(), and NIL.

Referenced by ExecPrepareCheck(), and ExecProcNode().

299 {
300  /* short-circuit (here and in ExecCheck) for empty restriction list */
301  if (qual == NIL)
302  return NULL;
303 
304  Assert(IsA(qual, List));
305 
306  /*
307  * Just convert the implicit-AND list to an explicit AND (if there's more
308  * than one entry), and compile normally. Unlike ExecQual, we can't
309  * short-circuit on NULL results, so the regular AND behavior is needed.
310  */
311  return ExecInitExpr(make_ands_explicit(qual), parent);
312 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Expr * make_ands_explicit(List *andclauses)
Definition: makefuncs.c:705
#define Assert(condition)
Definition: c.h:738
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
Definition: pg_list.h:50

◆ ExecInitCoerceToDomain()

static void ExecInitCoerceToDomain ( ExprEvalStep scratch,
CoerceToDomain ctest,
ExprState state,
Datum resv,
bool resnull 
)
static

Definition at line 2780 of file execExpr.c.

References CoerceToDomain::arg, DomainConstraintState::check_expr, DomainConstraintRef::constraints, DomainConstraintState::constrainttype, CurrentMemoryContext, ExprEvalStep::d, DOM_CONSTRAINT_CHECK, DOM_CONSTRAINT_NOTNULL, ExprEvalStep::domaincheck, EEOP_DOMAIN_CHECK, EEOP_DOMAIN_NOTNULL, EEOP_MAKE_READONLY, elog, ERROR, ExecInitExprRec(), ExprEvalPushStep(), get_typlen(), InitDomainConstraintRef(), ExprState::innermost_domainnull, ExprState::innermost_domainval, lfirst, ExprEvalStep::make_readonly, DomainConstraintState::name, ExprEvalStep::opcode, palloc(), ExprEvalStep::resnull, CoerceToDomain::resulttype, and ExprEvalStep::resvalue.

Referenced by ExecInitExprRec().

2782 {
2783  DomainConstraintRef *constraint_ref;
2784  ListCell *l;
2785 
2786  scratch->d.domaincheck.resulttype = ctest->resulttype;
2787  /* we'll allocate workspace only if needed */
2788  scratch->d.domaincheck.checkvalue = NULL;
2789  scratch->d.domaincheck.checknull = NULL;
2790 
2791  /*
2792  * Evaluate argument - it's fine to directly store it into resv/resnull,
2793  * if there's constraint failures there'll be errors, otherwise it's what
2794  * needs to be returned.
2795  */
2796  ExecInitExprRec(ctest->arg, state, resv, resnull);
2797 
2798  /*
2799  * Note: if the argument is of varlena type, it could be a R/W expanded
2800  * object. We want to return the R/W pointer as the final result, but we
2801  * have to pass a R/O pointer as the value to be tested by any functions
2802  * in check expressions. We don't bother to emit a MAKE_READONLY step
2803  * unless there's actually at least one check expression, though. Until
2804  * we've tested that, domainval/domainnull are NULL.
2805  */
2806 
2807  /*
2808  * Collect the constraints associated with the domain.
2809  *
2810  * Note: before PG v10 we'd recheck the set of constraints during each
2811  * evaluation of the expression. Now we bake them into the ExprState
2812  * during executor initialization. That means we don't need typcache.c to
2813  * provide compiled exprs.
2814  */
2815  constraint_ref = (DomainConstraintRef *)
2816  palloc(sizeof(DomainConstraintRef));
2818  constraint_ref,
2820  false);
2821 
2822  /*
2823  * Compile code to check each domain constraint. NOTNULL constraints can
2824  * just be applied on the resv/resnull value, but for CHECK constraints we
2825  * need more pushups.
2826  */
2827  foreach(l, constraint_ref->constraints)
2828  {
2830  Datum *domainval = NULL;
2831  bool *domainnull = NULL;
2832  Datum *save_innermost_domainval;
2833  bool *save_innermost_domainnull;
2834 
2835  scratch->d.domaincheck.constraintname = con->name;
2836 
2837  switch (con->constrainttype)
2838  {
2840  scratch->opcode = EEOP_DOMAIN_NOTNULL;
2841  ExprEvalPushStep(state, scratch);
2842  break;
2843  case DOM_CONSTRAINT_CHECK:
2844  /* Allocate workspace for CHECK output if we didn't yet */
2845  if (scratch->d.domaincheck.checkvalue == NULL)
2846  {
2847  scratch->d.domaincheck.checkvalue =
2848  (Datum *) palloc(sizeof(Datum));
2849  scratch->d.domaincheck.checknull =
2850  (bool *) palloc(sizeof(bool));
2851  }
2852 
2853  /*
2854  * If first time through, determine where CoerceToDomainValue
2855  * nodes should read from.
2856  */
2857  if (domainval == NULL)
2858  {
2859  /*
2860  * Since value might be read multiple times, force to R/O
2861  * - but only if it could be an expanded datum.
2862  */
2863  if (get_typlen(ctest->resulttype) == -1)
2864  {
2865  ExprEvalStep scratch2 = {0};
2866 
2867  /* Yes, so make output workspace for MAKE_READONLY */
2868  domainval = (Datum *) palloc(sizeof(Datum));
2869  domainnull = (bool *) palloc(sizeof(bool));
2870 
2871  /* Emit MAKE_READONLY */
2872  scratch2.opcode = EEOP_MAKE_READONLY;
2873  scratch2.resvalue = domainval;
2874  scratch2.resnull = domainnull;
2875  scratch2.d.make_readonly.value = resv;
2876  scratch2.d.make_readonly.isnull = resnull;
2877  ExprEvalPushStep(state, &scratch2);
2878  }
2879  else
2880  {
2881  /* No, so it's fine to read from resv/resnull */
2882  domainval = resv;
2883  domainnull = resnull;
2884  }
2885  }
2886 
2887  /*
2888  * Set up value to be returned by CoerceToDomainValue nodes.
2889  * We must save and restore innermost_domainval/null fields,
2890  * in case this node is itself within a check expression for
2891  * another domain.
2892  */
2893  save_innermost_domainval = state->innermost_domainval;
2894  save_innermost_domainnull = state->innermost_domainnull;
2895  state->innermost_domainval = domainval;
2896  state->innermost_domainnull = domainnull;
2897 
2898  /* evaluate check expression value */
2899  ExecInitExprRec(con->check_expr, state,
2900  scratch->d.domaincheck.checkvalue,
2901  scratch->d.domaincheck.checknull);
2902 
2903  state->innermost_domainval = save_innermost_domainval;
2904  state->innermost_domainnull = save_innermost_domainnull;
2905 
2906  /* now test result */
2907  scratch->opcode = EEOP_DOMAIN_CHECK;
2908  ExprEvalPushStep(state, scratch);
2909 
2910  break;
2911  default:
2912  elog(ERROR, "unrecognized constraint type: %d",
2913  (int) con->constrainttype);
2914  break;
2915  }
2916  }
2917 }
Datum * resvalue
Definition: execExpr.h:253
DomainConstraintType constrainttype
Definition: execnodes.h:909
struct ExprEvalStep::@51::@80 domaincheck
bool * resnull
Definition: execExpr.h:254
Datum * innermost_domainval
Definition: execnodes.h:114
bool * innermost_domainnull
Definition: execnodes.h:115
#define ERROR
Definition: elog.h:43
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
union ExprEvalStep::@51 d
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
struct ExprEvalStep::@51::@66 make_readonly
uintptr_t Datum
Definition: postgres.h:367
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
#define lfirst(lc)
Definition: pg_list.h:190
intptr_t opcode
Definition: execExpr.h:250
void InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref, MemoryContext refctx, bool need_exprstate)
Definition: typcache.c:1260
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2085
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214

◆ ExecInitExpr()

ExprState* ExecInitExpr ( Expr node,
PlanState parent 
)

Definition at line 123 of file execExpr.c.

References EEOP_DONE, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprState::ext_params, makeNode, ExprEvalStep::opcode, ExprState::parent, ExprState::resnull, and ExprState::resvalue.

Referenced by ATRewriteTable(), BeginCopyFrom(), evaluate_expr(), ExecIndexBuildScanKeys(), ExecInitCheck(), ExecInitExprList(), ExecInitExprRec(), ExecInitLimit(), ExecInitProjectSet(), ExecInitPruningContext(), ExecInitSampleScan(), ExecInitSubPlan(), ExecInitTableFuncScan(), ExecInitTableFunctionResult(), ExecInitWindowAgg(), ExecPrepareExpr(), ExecProcNode(), get_cast_hashentry(), get_qual_for_range(), MJExamineQuals(), operator_predicate_proof(), prep_domain_constraints(), slot_fill_defaults(), and TidExprListCreate().

124 {
125  ExprState *state;
126  ExprEvalStep scratch = {0};
127 
128  /* Special case: NULL expression produces a NULL ExprState pointer */
129  if (node == NULL)
130  return NULL;
131 
132  /* Initialize ExprState with empty step list */
133  state = makeNode(ExprState);
134  state->expr = node;
135  state->parent = parent;
136  state->ext_params = NULL;
137 
138  /* Insert EEOP_*_FETCHSOME steps as needed */
139  ExecInitExprSlots(state, (Node *) node);
140 
141  /* Compile the expression proper */
142  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
143 
144  /* Finally, append a DONE step */
145  scratch.opcode = EEOP_DONE;
146  ExprEvalPushStep(state, &scratch);
147 
148  ExecReadyExpr(state);
149 
150  return state;
151 }
struct PlanState * parent
Definition: execnodes.h:108
ParamListInfo ext_params
Definition: execnodes.h:109
Definition: nodes.h:529
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
#define makeNode(_type_)
Definition: nodes.h:577
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
Datum resvalue
Definition: execnodes.h:74

◆ ExecInitExprList()

List* ExecInitExprList ( List nodes,
PlanState parent 
)

Definition at line 318 of file execExpr.c.

References ExecInitExpr(), lappend(), lfirst, and NIL.

Referenced by ExecInitAgg(), ExecInitExprRec(), ExecInitFunctionResultSet(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexScan(), ExecInitSampleScan(), ExecInitSubPlan(), ExecInitTableFuncScan(), ExecInitTableFunctionResult(), ExecInitValuesScan(), ExecProcNode(), prepare_query_params(), and ValuesNext().

319 {
320  List *result = NIL;
321  ListCell *lc;
322 
323  foreach(lc, nodes)
324  {
325  Expr *e = lfirst(lc);
326 
327  result = lappend(result, ExecInitExpr(e, parent));
328  }
329 
330  return result;
331 }
#define NIL
Definition: pg_list.h:65
List * lappend(List *list, void *datum)
Definition: list.c:321
#define lfirst(lc)
Definition: pg_list.h:190
e
Definition: preproc-init.c:82
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
Definition: pg_list.h:50

◆ ExecInitExprRec()

static void ExecInitExprRec ( Expr node,
ExprState state,
Datum resv,
bool resnull 
)
static

Definition at line 646 of file execExpr.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, WindowFunc::aggfilter, WindowFuncExprState::aggfilter, ExprEvalStep::aggref, AggrefExprState::aggref, AggState::aggs, ExprEvalStep::alternative_subplan, AND_EXPR, arg, FieldSelect::arg, FieldStore::arg, RelabelType::arg, CoerceViaIO::arg, ArrayCoerceExpr::arg, ConvertRowtypeExpr::arg, CaseExpr::arg, NullTest::arg, BooleanTest::arg, NullTest::argisrow, FunctionCallInfoBaseData::args, WindowFunc::args, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, WindowFuncExprState::args, CaseExpr::args, RowExpr::args, CoalesceExpr::args, MinMaxExpr::args, XmlExpr::args, ExprEvalStep::arraycoerce, ExprEvalStep::arrayexpr, Assert, BlessTupleDesc(), ExprEvalStep::boolexpr, BoolExpr::boolop, BooleanTest::booltesttype, BTORDER_PROC, ExprEvalStep::casetest, check_stack_depth(), TypeCacheEntry::cmp_proc, RowExpr::colnames, GroupingFunc::cols, Const::constisnull, ExprEvalStep::constval, Const::constvalue, convert(), ExprEvalStep::convert_rowtype, ExprEvalStep::d, DecrTupleDescRefCount(), CaseExpr::defresult, EEOP_AGGREF, EEOP_ALTERNATIVE_SUBPLAN, EEOP_ARRAYCOERCE, EEOP_ARRAYEXPR, EEOP_BOOL_AND_STEP, EEOP_BOOL_AND_STEP_FIRST, EEOP_BOOL_AND_STEP_LAST, EEOP_BOOL_NOT_STEP, EEOP_BOOL_OR_STEP, EEOP_BOOL_OR_STEP_FIRST, EEOP_BOOL_OR_STEP_LAST, EEOP_BOOLTEST_IS_FALSE, EEOP_BOOLTEST_IS_NOT_FALSE, EEOP_BOOLTEST_IS_NOT_TRUE, EEOP_BOOLTEST_IS_TRUE, EEOP_CASE_TESTVAL, EEOP_CONST, EEOP_CONVERT_ROWTYPE, EEOP_CURRENTOFEXPR, EEOP_DISTINCT, EEOP_DOMAIN_TESTVAL, EEOP_DONE, EEOP_FIELDSELECT, EEOP_FIELDSTORE_DEFORM, EEOP_FIELDSTORE_FORM, EEOP_GROUPING_FUNC, EEOP_INNER_SYSVAR, EEOP_INNER_VAR, EEOP_IOCOERCE, EEOP_JUMP, EEOP_JUMP_IF_NOT_NULL, EEOP_JUMP_IF_NOT_TRUE, EEOP_MAKE_READONLY, EEOP_MINMAX, EEOP_NEXTVALUEEXPR, EEOP_NULLIF, EEOP_NULLTEST_ISNOTNULL, EEOP_NULLTEST_ISNULL, EEOP_NULLTEST_ROWISNOTNULL, EEOP_NULLTEST_ROWISNULL, EEOP_OUTER_SYSVAR, EEOP_OUTER_VAR, EEOP_PARAM_EXEC, EEOP_PARAM_EXTERN, EEOP_ROW, EEOP_ROWCOMPARE_FINAL, EEOP_ROWCOMPARE_STEP, EEOP_SCALARARRAYOP, EEOP_SCAN_SYSVAR, EEOP_SCAN_VAR, EEOP_SQLVALUEFUNCTION, EEOP_SUBPLAN, EEOP_WINDOW_FUNC, EEOP_XMLEXPR, ArrayExpr::element_typeid, ArrayExpr::elements, ArrayCoerceExpr::elemexpr, elog, ereport, errcode(), errmsg(), ERROR, EState::es_param_list_info, ExecInitAlternativeSubPlan(), ExecInitCoerceToDomain(), ExecInitExpr(), ExecInitExprList(), ExecInitFunc(), ExecInitSubPlan(), ExecInitSubscriptingRef(), ExecInitWholeRowVar(), ExecReadyExpr(), ExecTypeFromExprList(), ExecTypeSetColNames(), ExprState::expr, CaseWhen::expr, ExprEvalPushStep(), exprType(), ExprState::ext_params, FieldSelect::fieldnum, FieldStore::fieldnums, ExprEvalStep::fieldselect, ExprEvalStep::fieldstore, fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, forboth, forfive, format_type_be(), FuncExpr::funcid, WindowAggState::funcs, get_element_type(), get_func_name(), get_op_opfamily_properties(), get_opfamily_proc(), get_typlen(), get_typlenbyvalalign(), getTypeInputInfo(), getTypeOutputInfo(), GetUserId(), ExprEvalStep::grouping_func, Agg::groupingSets, i, InitFunctionCallInfoData, INNER_VAR, ExprState::innermost_casenull, ExprState::innermost_caseval, ExprState::innermost_domainnull, ExprState::innermost_domainval, FuncExpr::inputcollid, OpExpr::inputcollid, ScalarArrayOpExpr::inputcollid, MinMaxExpr::inputcollid, RowCompareExpr::inputcollids, Int32GetDatum, InvalidAttrNumber, InvalidOid, InvokeFunctionExecuteHook, ExprEvalStep::iocoerce, IS_FALSE, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, IsA, NullableDatum::isnull, ExprEvalStep::jump, lappend(), lappend_int(), RowCompareExpr::largs, lfirst, lfirst_int, lfirst_oid, linitial, list_length(), lookup_rowtype_tupdesc(), lookup_rowtype_tupdesc_copy(), lookup_type_cache(), lsecond, ExprEvalStep::make_readonly, makeNode, makeNullConst(), Max, ExprEvalStep::minmax, MinMaxExpr::minmaxtype, ArrayExpr::multidims, XmlExpr::named_args, TupleDescData::natts, FieldStore::newvals, ExprEvalStep::nextvalueexpr, NIL, nodeTag, NOT_EXPR, ExprEvalStep::nulltest_row, NullTest::nulltesttype, AggState::numaggs, WindowAggState::numaggs, WindowAggState::numfuncs, OBJECT_FUNCTION, ObjectIdGetDatum, OidIsValid, MinMaxExpr::op, ExprEvalStep::opcode, RowCompareExpr::opfamilies, OpExpr::opfuncid, ScalarArrayOpExpr::opfuncid, RowCompareExpr::opnos, OR_EXPR, OUTER_VAR, palloc(), palloc0(), ExprEvalStep::param, PARAM_EXEC, PARAM_EXTERN, ParamListInfoData::paramCompile, Param::paramid, Param::paramkind, Param::paramtype, ExprState::parent, pg_proc_aclcheck(), PlanState::plan, RowCompareExpr::rargs, RowCompareExpr::rctype, ExprState::resnull, ExprEvalStep::resnull, CaseWhen::result, FieldSelect::resulttype, FieldStore::resulttype, CoerceViaIO::resulttype, ArrayCoerceExpr::resulttype, ExprState::resvalue, ExprEvalStep::resvalue, ExprEvalStep::row, RowExpr::row_typeid, ExprEvalStep::rowcompare_final, ExprEvalStep::rowcompare_step, ExprEvalStep::scalararrayop, NextValueExpr::seqid, SizeForFunctionCallInfo, ExprEvalStep::sqlvaluefunction, PlanState::state, ExprState::steps, ExprState::steps_len, ExprEvalStep::subplan, PlanState::subPlan, T_Aggref, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_GroupingFunc, T_MinMaxExpr, T_NextValueExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SQLValueFunction, T_SubPlan, T_SubscriptingRef, T_Var, T_WindowFunc, T_XmlExpr, TupleDescAttr, TYPECACHE_CMP_PROC, NextValueExpr::typeId, ScalarArrayOpExpr::useOr, NullableDatum::value, values, ExprEvalStep::var, Var::varattno, Var::varno, Var::vartype, WindowFuncExprState::wfunc, WindowFunc::winagg, ExprEvalStep::window_func, and ExprEvalStep::xmlexpr.

Referenced by ExecBuildAggTrans(), ExecBuildProjectionInfo(), ExecInitCoerceToDomain(), ExecInitExpr(), ExecInitExprWithParams(), ExecInitFunc(), ExecInitQual(), and ExecInitSubscriptingRef().

648 {
649  ExprEvalStep scratch = {0};
650 
651  /* Guard against stack overflow due to overly complex expressions */
653 
654  /* Step's output location is always what the caller gave us */
655  Assert(resv != NULL && resnull != NULL);
656  scratch.resvalue = resv;
657  scratch.resnull = resnull;
658 
659  /* cases should be ordered as they are in enum NodeTag */
660  switch (nodeTag(node))
661  {
662  case T_Var:
663  {
664  Var *variable = (Var *) node;
665 
666  if (variable->varattno == InvalidAttrNumber)
667  {
668  /* whole-row Var */
669  ExecInitWholeRowVar(&scratch, variable, state);
670  }
671  else if (variable->varattno <= 0)
672  {
673  /* system column */
674  scratch.d.var.attnum = variable->varattno;
675  scratch.d.var.vartype = variable->vartype;
676  switch (variable->varno)
677  {
678  case INNER_VAR:
679  scratch.opcode = EEOP_INNER_SYSVAR;
680  break;
681  case OUTER_VAR:
682  scratch.opcode = EEOP_OUTER_SYSVAR;
683  break;
684 
685  /* INDEX_VAR is handled by default case */
686 
687  default:
688  scratch.opcode = EEOP_SCAN_SYSVAR;
689  break;
690  }
691  }
692  else
693  {
694  /* regular user column */
695  scratch.d.var.attnum = variable->varattno - 1;
696  scratch.d.var.vartype = variable->vartype;
697  switch (variable->varno)
698  {
699  case INNER_VAR:
700  scratch.opcode = EEOP_INNER_VAR;
701  break;
702  case OUTER_VAR:
703  scratch.opcode = EEOP_OUTER_VAR;
704  break;
705 
706  /* INDEX_VAR is handled by default case */
707 
708  default:
709  scratch.opcode = EEOP_SCAN_VAR;
710  break;
711  }
712  }
713 
714  ExprEvalPushStep(state, &scratch);
715  break;
716  }
717 
718  case T_Const:
719  {
720  Const *con = (Const *) node;
721 
722  scratch.opcode = EEOP_CONST;
723  scratch.d.constval.value = con->constvalue;
724  scratch.d.constval.isnull = con->constisnull;
725 
726  ExprEvalPushStep(state, &scratch);
727  break;
728  }
729 
730  case T_Param:
731  {
732  Param *param = (Param *) node;
733  ParamListInfo params;
734 
735  switch (param->paramkind)
736  {
737  case PARAM_EXEC:
738  scratch.opcode = EEOP_PARAM_EXEC;
739  scratch.d.param.paramid = param->paramid;
740  scratch.d.param.paramtype = param->paramtype;
741  ExprEvalPushStep(state, &scratch);
742  break;
743  case PARAM_EXTERN:
744 
745  /*
746  * If we have a relevant ParamCompileHook, use it;
747  * otherwise compile a standard EEOP_PARAM_EXTERN
748  * step. ext_params, if supplied, takes precedence
749  * over info from the parent node's EState (if any).
750  */
751  if (state->ext_params)
752  params = state->ext_params;
753  else if (state->parent &&
754  state->parent->state)
755  params = state->parent->state->es_param_list_info;
756  else
757  params = NULL;
758  if (params && params->paramCompile)
759  {
760  params->paramCompile(params, param, state,
761  resv, resnull);
762  }
763  else
764  {
765  scratch.opcode = EEOP_PARAM_EXTERN;
766  scratch.d.param.paramid = param->paramid;
767  scratch.d.param.paramtype = param->paramtype;
768  ExprEvalPushStep(state, &scratch);
769  }
770  break;
771  default:
772  elog(ERROR, "unrecognized paramkind: %d",
773  (int) param->paramkind);
774  break;
775  }
776  break;
777  }
778 
779  case T_Aggref:
780  {
781  Aggref *aggref = (Aggref *) node;
783 
784  scratch.opcode = EEOP_AGGREF;
785  scratch.d.aggref.astate = astate;
786  astate->aggref = aggref;
787 
788  if (state->parent && IsA(state->parent, AggState))
789  {
790  AggState *aggstate = (AggState *) state->parent;
791 
792  aggstate->aggs = lappend(aggstate->aggs, astate);
793  aggstate->numaggs++;
794  }
795  else
796  {
797  /* planner messed up */
798  elog(ERROR, "Aggref found in non-Agg plan node");
799  }
800 
801  ExprEvalPushStep(state, &scratch);
802  break;
803  }
804 
805  case T_GroupingFunc:
806  {
807  GroupingFunc *grp_node = (GroupingFunc *) node;
808  Agg *agg;
809 
810  if (!state->parent || !IsA(state->parent, AggState) ||
811  !IsA(state->parent->plan, Agg))
812  elog(ERROR, "GroupingFunc found in non-Agg plan node");
813 
814  scratch.opcode = EEOP_GROUPING_FUNC;
815 
816  agg = (Agg *) (state->parent->plan);
817 
818  if (agg->groupingSets)
819  scratch.d.grouping_func.clauses = grp_node->cols;
820  else
821  scratch.d.grouping_func.clauses = NIL;
822 
823  ExprEvalPushStep(state, &scratch);
824  break;
825  }
826 
827  case T_WindowFunc:
828  {
829  WindowFunc *wfunc = (WindowFunc *) node;
831 
832  wfstate->wfunc = wfunc;
833 
834  if (state->parent && IsA(state->parent, WindowAggState))
835  {
836  WindowAggState *winstate = (WindowAggState *) state->parent;
837  int nfuncs;
838 
839  winstate->funcs = lappend(winstate->funcs, wfstate);
840  nfuncs = ++winstate->numfuncs;
841  if (wfunc->winagg)
842  winstate->numaggs++;
843 
844  /* for now initialize agg using old style expressions */
845  wfstate->args = ExecInitExprList(wfunc->args,
846  state->parent);
847  wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter,
848  state->parent);
849 
850  /*
851  * Complain if the windowfunc's arguments contain any
852  * windowfuncs; nested window functions are semantically
853  * nonsensical. (This should have been caught earlier,
854  * but we defend against it here anyway.)
855  */
856  if (nfuncs != winstate->numfuncs)
857  ereport(ERROR,
858  (errcode(ERRCODE_WINDOWING_ERROR),
859  errmsg("window function calls cannot be nested")));
860  }
861  else
862  {
863  /* planner messed up */
864  elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
865  }
866 
867  scratch.opcode = EEOP_WINDOW_FUNC;
868  scratch.d.window_func.wfstate = wfstate;
869  ExprEvalPushStep(state, &scratch);
870  break;
871  }
872 
873  case T_SubscriptingRef:
874  {
875  SubscriptingRef *sbsref = (SubscriptingRef *) node;
876 
877  ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull);
878  break;
879  }
880 
881  case T_FuncExpr:
882  {
883  FuncExpr *func = (FuncExpr *) node;
884 
885  ExecInitFunc(&scratch, node,
886  func->args, func->funcid, func->inputcollid,
887  state);
888  ExprEvalPushStep(state, &scratch);
889  break;
890  }
891 
892  case T_OpExpr:
893  {
894  OpExpr *op = (OpExpr *) node;
895 
896  ExecInitFunc(&scratch, node,
897  op->args, op->opfuncid, op->inputcollid,
898  state);
899  ExprEvalPushStep(state, &scratch);
900  break;
901  }
902 
903  case T_DistinctExpr:
904  {
905  DistinctExpr *op = (DistinctExpr *) node;
906 
907  ExecInitFunc(&scratch, node,
908  op->args, op->opfuncid, op->inputcollid,
909  state);
910 
911  /*
912  * Change opcode of call instruction to EEOP_DISTINCT.
913  *
914  * XXX: historically we've not called the function usage
915  * pgstat infrastructure - that seems inconsistent given that
916  * we do so for normal function *and* operator evaluation. If
917  * we decided to do that here, we'd probably want separate
918  * opcodes for FUSAGE or not.
919  */
920  scratch.opcode = EEOP_DISTINCT;
921  ExprEvalPushStep(state, &scratch);
922  break;
923  }
924 
925  case T_NullIfExpr:
926  {
927  NullIfExpr *op = (NullIfExpr *) node;
928 
929  ExecInitFunc(&scratch, node,
930  op->args, op->opfuncid, op->inputcollid,
931  state);
932 
933  /*
934  * Change opcode of call instruction to EEOP_NULLIF.
935  *
936  * XXX: historically we've not called the function usage
937  * pgstat infrastructure - that seems inconsistent given that
938  * we do so for normal function *and* operator evaluation. If
939  * we decided to do that here, we'd probably want separate
940  * opcodes for FUSAGE or not.
941  */
942  scratch.opcode = EEOP_NULLIF;
943  ExprEvalPushStep(state, &scratch);
944  break;
945  }
946 
947  case T_ScalarArrayOpExpr:
948  {
949  ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
950  Expr *scalararg;
951  Expr *arrayarg;
952  FmgrInfo *finfo;
953  FunctionCallInfo fcinfo;
954  AclResult aclresult;
955 
956  Assert(list_length(opexpr->args) == 2);
957  scalararg = (Expr *) linitial(opexpr->args);
958  arrayarg = (Expr *) lsecond(opexpr->args);
959 
960  /* Check permission to call function */
961  aclresult = pg_proc_aclcheck(opexpr->opfuncid,
962  GetUserId(),
963  ACL_EXECUTE);
964  if (aclresult != ACLCHECK_OK)
965  aclcheck_error(aclresult, OBJECT_FUNCTION,
966  get_func_name(opexpr->opfuncid));
968 
969  /* Set up the primary fmgr lookup information */
970  finfo = palloc0(sizeof(FmgrInfo));
971  fcinfo = palloc0(SizeForFunctionCallInfo(2));
972  fmgr_info(opexpr->opfuncid, finfo);
973  fmgr_info_set_expr((Node *) node, finfo);
974  InitFunctionCallInfoData(*fcinfo, finfo, 2,
975  opexpr->inputcollid, NULL, NULL);
976 
977  /* Evaluate scalar directly into left function argument */
978  ExecInitExprRec(scalararg, state,
979  &fcinfo->args[0].value, &fcinfo->args[0].isnull);
980 
981  /*
982  * Evaluate array argument into our return value. There's no
983  * danger in that, because the return value is guaranteed to
984  * be overwritten by EEOP_SCALARARRAYOP, and will not be
985  * passed to any other expression.
986  */
987  ExecInitExprRec(arrayarg, state, resv, resnull);
988 
989  /* And perform the operation */
990  scratch.opcode = EEOP_SCALARARRAYOP;
991  scratch.d.scalararrayop.element_type = InvalidOid;
992  scratch.d.scalararrayop.useOr = opexpr->useOr;
993  scratch.d.scalararrayop.finfo = finfo;
994  scratch.d.scalararrayop.fcinfo_data = fcinfo;
995  scratch.d.scalararrayop.fn_addr = finfo->fn_addr;
996  ExprEvalPushStep(state, &scratch);
997  break;
998  }
999 
1000  case T_BoolExpr:
1001  {
1002  BoolExpr *boolexpr = (BoolExpr *) node;
1003  int nargs = list_length(boolexpr->args);
1004  List *adjust_jumps = NIL;
1005  int off;
1006  ListCell *lc;
1007 
1008  /* allocate scratch memory used by all steps of AND/OR */
1009  if (boolexpr->boolop != NOT_EXPR)
1010  scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool));
1011 
1012  /*
1013  * For each argument evaluate the argument itself, then
1014  * perform the bool operation's appropriate handling.
1015  *
1016  * We can evaluate each argument into our result area, since
1017  * the short-circuiting logic means we only need to remember
1018  * previous NULL values.
1019  *
1020  * AND/OR is split into separate STEP_FIRST (one) / STEP (zero
1021  * or more) / STEP_LAST (one) steps, as each of those has to
1022  * perform different work. The FIRST/LAST split is valid
1023  * because AND/OR have at least two arguments.
1024  */
1025  off = 0;
1026  foreach(lc, boolexpr->args)
1027  {
1028  Expr *arg = (Expr *) lfirst(lc);
1029 
1030  /* Evaluate argument into our output variable */
1031  ExecInitExprRec(arg, state, resv, resnull);
1032 
1033  /* Perform the appropriate step type */
1034  switch (boolexpr->boolop)
1035  {
1036  case AND_EXPR:
1037  Assert(nargs >= 2);
1038 
1039  if (off == 0)
1040  scratch.opcode = EEOP_BOOL_AND_STEP_FIRST;
1041  else if (off + 1 == nargs)
1042  scratch.opcode = EEOP_BOOL_AND_STEP_LAST;
1043  else
1044  scratch.opcode = EEOP_BOOL_AND_STEP;
1045  break;
1046  case OR_EXPR:
1047  Assert(nargs >= 2);
1048 
1049  if (off == 0)
1050  scratch.opcode = EEOP_BOOL_OR_STEP_FIRST;
1051  else if (off + 1 == nargs)
1052  scratch.opcode = EEOP_BOOL_OR_STEP_LAST;
1053  else
1054  scratch.opcode = EEOP_BOOL_OR_STEP;
1055  break;
1056  case NOT_EXPR:
1057  Assert(nargs == 1);
1058 
1059  scratch.opcode = EEOP_BOOL_NOT_STEP;
1060  break;
1061  default:
1062  elog(ERROR, "unrecognized boolop: %d",
1063  (int) boolexpr->boolop);
1064  break;
1065  }
1066 
1067  scratch.d.boolexpr.jumpdone = -1;
1068  ExprEvalPushStep(state, &scratch);
1069  adjust_jumps = lappend_int(adjust_jumps,
1070  state->steps_len - 1);
1071  off++;
1072  }
1073 
1074  /* adjust jump targets */
1075  foreach(lc, adjust_jumps)
1076  {
1077  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1078 
1079  Assert(as->d.boolexpr.jumpdone == -1);
1080  as->d.boolexpr.jumpdone = state->steps_len;
1081  }
1082 
1083  break;
1084  }
1085 
1086  case T_SubPlan:
1087  {
1088  SubPlan *subplan = (SubPlan *) node;
1089  SubPlanState *sstate;
1090 
1091  if (!state->parent)
1092  elog(ERROR, "SubPlan found with no parent plan");
1093 
1094  sstate = ExecInitSubPlan(subplan, state->parent);
1095 
1096  /* add SubPlanState nodes to state->parent->subPlan */
1097  state->parent->subPlan = lappend(state->parent->subPlan,
1098  sstate);
1099 
1100  scratch.opcode = EEOP_SUBPLAN;
1101  scratch.d.subplan.sstate = sstate;
1102 
1103  ExprEvalPushStep(state, &scratch);
1104  break;
1105  }
1106 
1107  case T_AlternativeSubPlan:
1108  {
1109  AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
1110  AlternativeSubPlanState *asstate;
1111 
1112  if (!state->parent)
1113  elog(ERROR, "AlternativeSubPlan found with no parent plan");
1114 
1115  asstate = ExecInitAlternativeSubPlan(asplan, state->parent);
1116 
1117  scratch.opcode = EEOP_ALTERNATIVE_SUBPLAN;
1118  scratch.d.alternative_subplan.asstate = asstate;
1119 
1120  ExprEvalPushStep(state, &scratch);
1121  break;
1122  }
1123 
1124  case T_FieldSelect:
1125  {
1126  FieldSelect *fselect = (FieldSelect *) node;
1127 
1128  /* evaluate row/record argument into result area */
1129  ExecInitExprRec(fselect->arg, state, resv, resnull);
1130 
1131  /* and extract field */
1132  scratch.opcode = EEOP_FIELDSELECT;
1133  scratch.d.fieldselect.fieldnum = fselect->fieldnum;
1134  scratch.d.fieldselect.resulttype = fselect->resulttype;
1135  scratch.d.fieldselect.argdesc = NULL;
1136 
1137  ExprEvalPushStep(state, &scratch);
1138  break;
1139  }
1140 
1141  case T_FieldStore:
1142  {
1143  FieldStore *fstore = (FieldStore *) node;
1144  TupleDesc tupDesc;
1145  TupleDesc *descp;
1146  Datum *values;
1147  bool *nulls;
1148  int ncolumns;
1149  ListCell *l1,
1150  *l2;
1151 
1152  /* find out the number of columns in the composite type */
1153  tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
1154  ncolumns = tupDesc->natts;
1155  DecrTupleDescRefCount(tupDesc);
1156 
1157  /* create workspace for column values */
1158  values = (Datum *) palloc(sizeof(Datum) * ncolumns);
1159  nulls = (bool *) palloc(sizeof(bool) * ncolumns);
1160 
1161  /* create workspace for runtime tupdesc cache */
1162  descp = (TupleDesc *) palloc(sizeof(TupleDesc));
1163  *descp = NULL;
1164 
1165  /* emit code to evaluate the composite input value */
1166  ExecInitExprRec(fstore->arg, state, resv, resnull);
1167 
1168  /* next, deform the input tuple into our workspace */
1169  scratch.opcode = EEOP_FIELDSTORE_DEFORM;
1170  scratch.d.fieldstore.fstore = fstore;
1171  scratch.d.fieldstore.argdesc = descp;
1172  scratch.d.fieldstore.values = values;
1173  scratch.d.fieldstore.nulls = nulls;
1174  scratch.d.fieldstore.ncolumns = ncolumns;
1175  ExprEvalPushStep(state, &scratch);
1176 
1177  /* evaluate new field values, store in workspace columns */
1178  forboth(l1, fstore->newvals, l2, fstore->fieldnums)
1179  {
1180  Expr *e = (Expr *) lfirst(l1);
1181  AttrNumber fieldnum = lfirst_int(l2);
1182  Datum *save_innermost_caseval;
1183  bool *save_innermost_casenull;
1184 
1185  if (fieldnum <= 0 || fieldnum > ncolumns)
1186  elog(ERROR, "field number %d is out of range in FieldStore",
1187  fieldnum);
1188 
1189  /*
1190  * Use the CaseTestExpr mechanism to pass down the old
1191  * value of the field being replaced; this is needed in
1192  * case the newval is itself a FieldStore or
1193  * SubscriptingRef that has to obtain and modify the old
1194  * value. It's safe to reuse the CASE mechanism because
1195  * there cannot be a CASE between here and where the value
1196  * would be needed, and a field assignment can't be within
1197  * a CASE either. (So saving and restoring
1198  * innermost_caseval is just paranoia, but let's do it
1199  * anyway.)
1200  *
1201  * Another non-obvious point is that it's safe to use the
1202  * field's values[]/nulls[] entries as both the caseval
1203  * source and the result address for this subexpression.
1204  * That's okay only because (1) both FieldStore and
1205  * SubscriptingRef evaluate their arg or refexpr inputs
1206  * first, and (2) any such CaseTestExpr is directly the
1207  * arg or refexpr input. So any read of the caseval will
1208  * occur before there's a chance to overwrite it. Also,
1209  * if multiple entries in the newvals/fieldnums lists
1210  * target the same field, they'll effectively be applied
1211  * left-to-right which is what we want.
1212  */
1213  save_innermost_caseval = state->innermost_caseval;
1214  save_innermost_casenull = state->innermost_casenull;
1215  state->innermost_caseval = &values[fieldnum - 1];
1216  state->innermost_casenull = &nulls[fieldnum - 1];
1217 
1218  ExecInitExprRec(e, state,
1219  &values[fieldnum - 1],
1220  &nulls[fieldnum - 1]);
1221 
1222  state->innermost_caseval = save_innermost_caseval;
1223  state->innermost_casenull = save_innermost_casenull;
1224  }
1225 
1226  /* finally, form result tuple */
1227  scratch.opcode = EEOP_FIELDSTORE_FORM;
1228  scratch.d.fieldstore.fstore = fstore;
1229  scratch.d.fieldstore.argdesc = descp;
1230  scratch.d.fieldstore.values = values;
1231  scratch.d.fieldstore.nulls = nulls;
1232  scratch.d.fieldstore.ncolumns = ncolumns;
1233  ExprEvalPushStep(state, &scratch);
1234  break;
1235  }
1236 
1237  case T_RelabelType:
1238  {
1239  /* relabel doesn't need to do anything at runtime */
1240  RelabelType *relabel = (RelabelType *) node;
1241 
1242  ExecInitExprRec(relabel->arg, state, resv, resnull);
1243  break;
1244  }
1245 
1246  case T_CoerceViaIO:
1247  {
1248  CoerceViaIO *iocoerce = (CoerceViaIO *) node;
1249  Oid iofunc;
1250  bool typisvarlena;
1251  Oid typioparam;
1252  FunctionCallInfo fcinfo_in;
1253 
1254  /* evaluate argument into step's result area */
1255  ExecInitExprRec(iocoerce->arg, state, resv, resnull);
1256 
1257  /*
1258  * Prepare both output and input function calls, to be
1259  * evaluated inside a single evaluation step for speed - this
1260  * can be a very common operation.
1261  *
1262  * We don't check permissions here as a type's input/output
1263  * function are assumed to be executable by everyone.
1264  */
1265  scratch.opcode = EEOP_IOCOERCE;
1266 
1267  /* lookup the source type's output function */
1268  scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
1269  scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
1270 
1271  getTypeOutputInfo(exprType((Node *) iocoerce->arg),
1272  &iofunc, &typisvarlena);
1273  fmgr_info(iofunc, scratch.d.iocoerce.finfo_out);
1274  fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out);
1275  InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out,
1276  scratch.d.iocoerce.finfo_out,
1277  1, InvalidOid, NULL, NULL);
1278 
1279  /* lookup the result type's input function */
1280  scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
1281  scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
1282 
1283  getTypeInputInfo(iocoerce->resulttype,
1284  &iofunc, &typioparam);
1285  fmgr_info(iofunc, scratch.d.iocoerce.finfo_in);
1286  fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in);
1287  InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1288  scratch.d.iocoerce.finfo_in,
1289  3, InvalidOid, NULL, NULL);
1290 
1291  /*
1292  * We can preload the second and third arguments for the input
1293  * function, since they're constants.
1294  */
1295  fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
1296  fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam);
1297  fcinfo_in->args[1].isnull = false;
1298  fcinfo_in->args[2].value = Int32GetDatum(-1);
1299  fcinfo_in->args[2].isnull = false;
1300 
1301  ExprEvalPushStep(state, &scratch);
1302  break;
1303  }
1304 
1305  case T_ArrayCoerceExpr:
1306  {
1307  ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
1308  Oid resultelemtype;
1309  ExprState *elemstate;
1310 
1311  /* evaluate argument into step's result area */
1312  ExecInitExprRec(acoerce->arg, state, resv, resnull);
1313 
1314  resultelemtype = get_element_type(acoerce->resulttype);
1315  if (!OidIsValid(resultelemtype))
1316  ereport(ERROR,
1317  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1318  errmsg("target type is not an array")));
1319 
1320  /*
1321  * Construct a sub-expression for the per-element expression;
1322  * but don't ready it until after we check it for triviality.
1323  * We assume it hasn't any Var references, but does have a
1324  * CaseTestExpr representing the source array element values.
1325  */
1326  elemstate = makeNode(ExprState);
1327  elemstate->expr = acoerce->elemexpr;
1328  elemstate->parent = state->parent;
1329  elemstate->ext_params = state->ext_params;
1330 
1331  elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum));
1332  elemstate->innermost_casenull = (bool *) palloc(sizeof(bool));
1333 
1334  ExecInitExprRec(acoerce->elemexpr, elemstate,
1335  &elemstate->resvalue, &elemstate->resnull);
1336 
1337  if (elemstate->steps_len == 1 &&
1338  elemstate->steps[0].opcode == EEOP_CASE_TESTVAL)
1339  {
1340  /* Trivial, so we need no per-element work at runtime */
1341  elemstate = NULL;
1342  }
1343  else
1344  {
1345  /* Not trivial, so append a DONE step */
1346  scratch.opcode = EEOP_DONE;
1347  ExprEvalPushStep(elemstate, &scratch);
1348  /* and ready the subexpression */
1349  ExecReadyExpr(elemstate);
1350  }
1351 
1352  scratch.opcode = EEOP_ARRAYCOERCE;
1353  scratch.d.arraycoerce.elemexprstate = elemstate;
1354  scratch.d.arraycoerce.resultelemtype = resultelemtype;
1355 
1356  if (elemstate)
1357  {
1358  /* Set up workspace for array_map */
1359  scratch.d.arraycoerce.amstate =
1360  (ArrayMapState *) palloc0(sizeof(ArrayMapState));
1361  }
1362  else
1363  {
1364  /* Don't need workspace if there's no subexpression */
1365  scratch.d.arraycoerce.amstate = NULL;
1366  }
1367 
1368  ExprEvalPushStep(state, &scratch);
1369  break;
1370  }
1371 
1372  case T_ConvertRowtypeExpr:
1373  {
1375 
1376  /* evaluate argument into step's result area */
1377  ExecInitExprRec(convert->arg, state, resv, resnull);
1378 
1379  /* and push conversion step */
1380  scratch.opcode = EEOP_CONVERT_ROWTYPE;
1381  scratch.d.convert_rowtype.convert = convert;
1382  scratch.d.convert_rowtype.indesc = NULL;
1383  scratch.d.convert_rowtype.outdesc = NULL;
1384  scratch.d.convert_rowtype.map = NULL;
1385  scratch.d.convert_rowtype.initialized = false;
1386 
1387  ExprEvalPushStep(state, &scratch);
1388  break;
1389  }
1390 
1391  /* note that CaseWhen expressions are handled within this block */
1392  case T_CaseExpr:
1393  {
1394  CaseExpr *caseExpr = (CaseExpr *) node;
1395  List *adjust_jumps = NIL;
1396  Datum *caseval = NULL;
1397  bool *casenull = NULL;
1398  ListCell *lc;
1399 
1400  /*
1401  * If there's a test expression, we have to evaluate it and
1402  * save the value where the CaseTestExpr placeholders can find
1403  * it.
1404  */
1405  if (caseExpr->arg != NULL)
1406  {
1407  /* Evaluate testexpr into caseval/casenull workspace */
1408  caseval = palloc(sizeof(Datum));
1409  casenull = palloc(sizeof(bool));
1410 
1411  ExecInitExprRec(caseExpr->arg, state,
1412  caseval, casenull);
1413 
1414  /*
1415  * Since value might be read multiple times, force to R/O
1416  * - but only if it could be an expanded datum.
1417  */
1418  if (get_typlen(exprType((Node *) caseExpr->arg)) == -1)
1419  {
1420  /* change caseval in-place */
1421  scratch.opcode = EEOP_MAKE_READONLY;
1422  scratch.resvalue = caseval;
1423  scratch.resnull = casenull;
1424  scratch.d.make_readonly.value = caseval;
1425  scratch.d.make_readonly.isnull = casenull;
1426  ExprEvalPushStep(state, &scratch);
1427  /* restore normal settings of scratch fields */
1428  scratch.resvalue = resv;
1429  scratch.resnull = resnull;
1430  }
1431  }
1432 
1433  /*
1434  * Prepare to evaluate each of the WHEN clauses in turn; as
1435  * soon as one is true we return the value of the
1436  * corresponding THEN clause. If none are true then we return
1437  * the value of the ELSE clause, or NULL if there is none.
1438  */
1439  foreach(lc, caseExpr->args)
1440  {
1441  CaseWhen *when = (CaseWhen *) lfirst(lc);
1442  Datum *save_innermost_caseval;
1443  bool *save_innermost_casenull;
1444  int whenstep;
1445 
1446  /*
1447  * Make testexpr result available to CaseTestExpr nodes
1448  * within the condition. We must save and restore prior
1449  * setting of innermost_caseval fields, in case this node
1450  * is itself within a larger CASE.
1451  *
1452  * If there's no test expression, we don't actually need
1453  * to save and restore these fields; but it's less code to
1454  * just do so unconditionally.
1455  */
1456  save_innermost_caseval = state->innermost_caseval;
1457  save_innermost_casenull = state->innermost_casenull;
1458  state->innermost_caseval = caseval;
1459  state->innermost_casenull = casenull;
1460 
1461  /* evaluate condition into CASE's result variables */
1462  ExecInitExprRec(when->expr, state, resv, resnull);
1463 
1464  state->innermost_caseval = save_innermost_caseval;
1465  state->innermost_casenull = save_innermost_casenull;
1466 
1467  /* If WHEN result isn't true, jump to next CASE arm */
1468  scratch.opcode = EEOP_JUMP_IF_NOT_TRUE;
1469  scratch.d.jump.jumpdone = -1; /* computed later */
1470  ExprEvalPushStep(state, &scratch);
1471  whenstep = state->steps_len - 1;
1472 
1473  /*
1474  * If WHEN result is true, evaluate THEN result, storing
1475  * it into the CASE's result variables.
1476  */
1477  ExecInitExprRec(when->result, state, resv, resnull);
1478 
1479  /* Emit JUMP step to jump to end of CASE's code */
1480  scratch.opcode = EEOP_JUMP;
1481  scratch.d.jump.jumpdone = -1; /* computed later */
1482  ExprEvalPushStep(state, &scratch);
1483 
1484  /*
1485  * Don't know address for that jump yet, compute once the
1486  * whole CASE expression is built.
1487  */
1488  adjust_jumps = lappend_int(adjust_jumps,
1489  state->steps_len - 1);
1490 
1491  /*
1492  * But we can set WHEN test's jump target now, to make it
1493  * jump to the next WHEN subexpression or the ELSE.
1494  */
1495  state->steps[whenstep].d.jump.jumpdone = state->steps_len;
1496  }
1497 
1498  /* transformCaseExpr always adds a default */
1499  Assert(caseExpr->defresult);
1500 
1501  /* evaluate ELSE expr into CASE's result variables */
1502  ExecInitExprRec(caseExpr->defresult, state,
1503  resv, resnull);
1504 
1505  /* adjust jump targets */
1506  foreach(lc, adjust_jumps)
1507  {
1508  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1509 
1510  Assert(as->opcode == EEOP_JUMP);
1511  Assert(as->d.jump.jumpdone == -1);
1512  as->d.jump.jumpdone = state->steps_len;
1513  }
1514 
1515  break;
1516  }
1517 
1518  case T_CaseTestExpr:
1519  {
1520  /*
1521  * Read from location identified by innermost_caseval. Note
1522  * that innermost_caseval could be NULL, if this node isn't
1523  * actually within a CaseExpr, ArrayCoerceExpr, etc structure.
1524  * That can happen because some parts of the system abuse
1525  * CaseTestExpr to cause a read of a value externally supplied
1526  * in econtext->caseValue_datum. We'll take care of that
1527  * scenario at runtime.
1528  */
1529  scratch.opcode = EEOP_CASE_TESTVAL;
1530  scratch.d.casetest.value = state->innermost_caseval;
1531  scratch.d.casetest.isnull = state->innermost_casenull;
1532 
1533  ExprEvalPushStep(state, &scratch);
1534  break;
1535  }
1536 
1537  case T_ArrayExpr:
1538  {
1539  ArrayExpr *arrayexpr = (ArrayExpr *) node;
1540  int nelems = list_length(arrayexpr->elements);
1541  ListCell *lc;
1542  int elemoff;
1543 
1544  /*
1545  * Evaluate by computing each element, and then forming the
1546  * array. Elements are computed into scratch arrays
1547  * associated with the ARRAYEXPR step.
1548  */
1549  scratch.opcode = EEOP_ARRAYEXPR;
1550  scratch.d.arrayexpr.elemvalues =
1551  (Datum *) palloc(sizeof(Datum) * nelems);
1552  scratch.d.arrayexpr.elemnulls =
1553  (bool *) palloc(sizeof(bool) * nelems);
1554  scratch.d.arrayexpr.nelems = nelems;
1555 
1556  /* fill remaining fields of step */
1557  scratch.d.arrayexpr.multidims = arrayexpr->multidims;
1558  scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid;
1559 
1560  /* do one-time catalog lookup for type info */
1562  &scratch.d.arrayexpr.elemlength,
1563  &scratch.d.arrayexpr.elembyval,
1564  &scratch.d.arrayexpr.elemalign);
1565 
1566  /* prepare to evaluate all arguments */
1567  elemoff = 0;
1568  foreach(lc, arrayexpr->elements)
1569  {
1570  Expr *e = (Expr *) lfirst(lc);
1571 
1572  ExecInitExprRec(e, state,
1573  &scratch.d.arrayexpr.elemvalues[elemoff],
1574  &scratch.d.arrayexpr.elemnulls[elemoff]);
1575  elemoff++;
1576  }
1577 
1578  /* and then collect all into an array */
1579  ExprEvalPushStep(state, &scratch);
1580  break;
1581  }
1582 
1583  case T_RowExpr:
1584  {
1585  RowExpr *rowexpr = (RowExpr *) node;
1586  int nelems = list_length(rowexpr->args);
1587  TupleDesc tupdesc;
1588  int i;
1589  ListCell *l;
1590 
1591  /* Build tupdesc to describe result tuples */
1592  if (rowexpr->row_typeid == RECORDOID)
1593  {
1594  /* generic record, use types of given expressions */
1595  tupdesc = ExecTypeFromExprList(rowexpr->args);
1596  }
1597  else
1598  {
1599  /* it's been cast to a named type, use that */
1600  tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
1601  }
1602  /* In either case, adopt RowExpr's column aliases */
1603  ExecTypeSetColNames(tupdesc, rowexpr->colnames);
1604  /* Bless the tupdesc in case it's now of type RECORD */
1605  BlessTupleDesc(tupdesc);
1606 
1607  /*
1608  * In the named-type case, the tupdesc could have more columns
1609  * than are in the args list, since the type might have had
1610  * columns added since the ROW() was parsed. We want those
1611  * extra columns to go to nulls, so we make sure that the
1612  * workspace arrays are large enough and then initialize any
1613  * extra columns to read as NULLs.
1614  */
1615  Assert(nelems <= tupdesc->natts);
1616  nelems = Max(nelems, tupdesc->natts);
1617 
1618  /*
1619  * Evaluate by first building datums for each field, and then
1620  * a final step forming the composite datum.
1621  */
1622  scratch.opcode = EEOP_ROW;
1623  scratch.d.row.tupdesc = tupdesc;
1624 
1625  /* space for the individual field datums */
1626  scratch.d.row.elemvalues =
1627  (Datum *) palloc(sizeof(Datum) * nelems);
1628  scratch.d.row.elemnulls =
1629  (bool *) palloc(sizeof(bool) * nelems);
1630  /* as explained above, make sure any extra columns are null */
1631  memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems);
1632 
1633  /* Set up evaluation, skipping any deleted columns */
1634  i = 0;
1635  foreach(l, rowexpr->args)
1636  {
1637  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1638  Expr *e = (Expr *) lfirst(l);
1639 
1640  if (!att->attisdropped)
1641  {
1642  /*
1643  * Guard against ALTER COLUMN TYPE on rowtype since
1644  * the RowExpr was created. XXX should we check
1645  * typmod too? Not sure we can be sure it'll be the
1646  * same.
1647  */
1648  if (exprType((Node *) e) != att->atttypid)
1649  ereport(ERROR,
1650  (errcode(ERRCODE_DATATYPE_MISMATCH),
1651  errmsg("ROW() column has type %s instead of type %s",
1652  format_type_be(exprType((Node *) e)),
1653  format_type_be(att->atttypid))));
1654  }
1655  else
1656  {
1657  /*
1658  * Ignore original expression and insert a NULL. We
1659  * don't really care what type of NULL it is, so
1660  * always make an int4 NULL.
1661  */
1662  e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
1663  }
1664 
1665  /* Evaluate column expr into appropriate workspace slot */
1666  ExecInitExprRec(e, state,
1667  &scratch.d.row.elemvalues[i],
1668  &scratch.d.row.elemnulls[i]);
1669  i++;
1670  }
1671 
1672  /* And finally build the row value */
1673  ExprEvalPushStep(state, &scratch);
1674  break;
1675  }
1676 
1677  case T_RowCompareExpr:
1678  {
1679  RowCompareExpr *rcexpr = (RowCompareExpr *) node;
1680  int nopers = list_length(rcexpr->opnos);
1681  List *adjust_jumps = NIL;
1682  ListCell *l_left_expr,
1683  *l_right_expr,
1684  *l_opno,
1685  *l_opfamily,
1686  *l_inputcollid;
1687  ListCell *lc;
1688 
1689  /*
1690  * Iterate over each field, prepare comparisons. To handle
1691  * NULL results, prepare jumps to after the expression. If a
1692  * comparison yields a != 0 result, jump to the final step.
1693  */
1694  Assert(list_length(rcexpr->largs) == nopers);
1695  Assert(list_length(rcexpr->rargs) == nopers);
1696  Assert(list_length(rcexpr->opfamilies) == nopers);
1697  Assert(list_length(rcexpr->inputcollids) == nopers);
1698 
1699  forfive(l_left_expr, rcexpr->largs,
1700  l_right_expr, rcexpr->rargs,
1701  l_opno, rcexpr->opnos,
1702  l_opfamily, rcexpr->opfamilies,
1703  l_inputcollid, rcexpr->inputcollids)
1704  {
1705  Expr *left_expr = (Expr *) lfirst(l_left_expr);
1706  Expr *right_expr = (Expr *) lfirst(l_right_expr);
1707  Oid opno = lfirst_oid(l_opno);
1708  Oid opfamily = lfirst_oid(l_opfamily);
1709  Oid inputcollid = lfirst_oid(l_inputcollid);
1710  int strategy;
1711  Oid lefttype;
1712  Oid righttype;
1713  Oid proc;
1714  FmgrInfo *finfo;
1715  FunctionCallInfo fcinfo;
1716 
1717  get_op_opfamily_properties(opno, opfamily, false,
1718  &strategy,
1719  &lefttype,
1720  &righttype);
1721  proc = get_opfamily_proc(opfamily,
1722  lefttype,
1723  righttype,
1724  BTORDER_PROC);
1725  if (!OidIsValid(proc))
1726  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1727  BTORDER_PROC, lefttype, righttype, opfamily);
1728 
1729  /* Set up the primary fmgr lookup information */
1730  finfo = palloc0(sizeof(FmgrInfo));
1731  fcinfo = palloc0(SizeForFunctionCallInfo(2));
1732  fmgr_info(proc, finfo);
1733  fmgr_info_set_expr((Node *) node, finfo);
1734  InitFunctionCallInfoData(*fcinfo, finfo, 2,
1735  inputcollid, NULL, NULL);
1736 
1737  /*
1738  * If we enforced permissions checks on index support
1739  * functions, we'd need to make a check here. But the
1740  * index support machinery doesn't do that, and thus
1741  * neither does this code.
1742  */
1743 
1744  /* evaluate left and right args directly into fcinfo */
1745  ExecInitExprRec(left_expr, state,
1746  &fcinfo->args[0].value, &fcinfo->args[0].isnull);
1747  ExecInitExprRec(right_expr, state,
1748  &fcinfo->args[1].value, &fcinfo->args[1].isnull);
1749 
1750  scratch.opcode = EEOP_ROWCOMPARE_STEP;
1751  scratch.d.rowcompare_step.finfo = finfo;
1752  scratch.d.rowcompare_step.fcinfo_data = fcinfo;
1753  scratch.d.rowcompare_step.fn_addr = finfo->fn_addr;
1754  /* jump targets filled below */
1755  scratch.d.rowcompare_step.jumpnull = -1;
1756  scratch.d.rowcompare_step.jumpdone = -1;
1757 
1758  ExprEvalPushStep(state, &scratch);
1759  adjust_jumps = lappend_int(adjust_jumps,
1760  state->steps_len - 1);
1761  }
1762 
1763  /*
1764  * We could have a zero-column rowtype, in which case the rows
1765  * necessarily compare equal.
1766  */
1767  if (nopers == 0)
1768  {
1769  scratch.opcode = EEOP_CONST;
1770  scratch.d.constval.value = Int32GetDatum(0);
1771  scratch.d.constval.isnull = false;
1772  ExprEvalPushStep(state, &scratch);
1773  }
1774 
1775  /* Finally, examine the last comparison result */
1776  scratch.opcode = EEOP_ROWCOMPARE_FINAL;
1777  scratch.d.rowcompare_final.rctype = rcexpr->rctype;
1778  ExprEvalPushStep(state, &scratch);
1779 
1780  /* adjust jump targets */
1781  foreach(lc, adjust_jumps)
1782  {
1783  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1784 
1786  Assert(as->d.rowcompare_step.jumpdone == -1);
1787  Assert(as->d.rowcompare_step.jumpnull == -1);
1788 
1789  /* jump to comparison evaluation */
1790  as->d.rowcompare_step.jumpdone = state->steps_len - 1;
1791  /* jump to the following expression */
1792  as->d.rowcompare_step.jumpnull = state->steps_len;
1793  }
1794 
1795  break;
1796  }
1797 
1798  case T_CoalesceExpr:
1799  {
1800  CoalesceExpr *coalesce = (CoalesceExpr *) node;
1801  List *adjust_jumps = NIL;
1802  ListCell *lc;
1803 
1804  /* We assume there's at least one arg */
1805  Assert(coalesce->args != NIL);
1806 
1807  /*
1808  * Prepare evaluation of all coalesced arguments, after each
1809  * one push a step that short-circuits if not null.
1810  */
1811  foreach(lc, coalesce->args)
1812  {
1813  Expr *e = (Expr *) lfirst(lc);
1814 
1815  /* evaluate argument, directly into result datum */
1816  ExecInitExprRec(e, state, resv, resnull);
1817 
1818  /* if it's not null, skip to end of COALESCE expr */
1819  scratch.opcode = EEOP_JUMP_IF_NOT_NULL;
1820  scratch.d.jump.jumpdone = -1; /* adjust later */
1821  ExprEvalPushStep(state, &scratch);
1822 
1823  adjust_jumps = lappend_int(adjust_jumps,
1824  state->steps_len - 1);
1825  }
1826 
1827  /*
1828  * No need to add a constant NULL return - we only can get to
1829  * the end of the expression if a NULL already is being
1830  * returned.
1831  */
1832 
1833  /* adjust jump targets */
1834  foreach(lc, adjust_jumps)
1835  {
1836  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
1837 
1839  Assert(as->d.jump.jumpdone == -1);
1840  as->d.jump.jumpdone = state->steps_len;
1841  }
1842 
1843  break;
1844  }
1845 
1846  case T_MinMaxExpr:
1847  {
1848  MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
1849  int nelems = list_length(minmaxexpr->args);
1850  TypeCacheEntry *typentry;
1851  FmgrInfo *finfo;
1852  FunctionCallInfo fcinfo;
1853  ListCell *lc;
1854  int off;
1855 
1856  /* Look up the btree comparison function for the datatype */
1857  typentry = lookup_type_cache(minmaxexpr->minmaxtype,
1859  if (!OidIsValid(typentry->cmp_proc))
1860  ereport(ERROR,
1861  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1862  errmsg("could not identify a comparison function for type %s",
1863  format_type_be(minmaxexpr->minmaxtype))));
1864 
1865  /*
1866  * If we enforced permissions checks on index support
1867  * functions, we'd need to make a check here. But the index
1868  * support machinery doesn't do that, and thus neither does
1869  * this code.
1870  */
1871 
1872  /* Perform function lookup */
1873  finfo = palloc0(sizeof(FmgrInfo));
1874  fcinfo = palloc0(SizeForFunctionCallInfo(2));
1875  fmgr_info(typentry->cmp_proc, finfo);
1876  fmgr_info_set_expr((Node *) node, finfo);
1877  InitFunctionCallInfoData(*fcinfo, finfo, 2,
1878  minmaxexpr->inputcollid, NULL, NULL);
1879 
1880  scratch.opcode = EEOP_MINMAX;
1881  /* allocate space to store arguments */
1882  scratch.d.minmax.values =
1883  (Datum *) palloc(sizeof(Datum) * nelems);
1884  scratch.d.minmax.nulls =
1885  (bool *) palloc(sizeof(bool) * nelems);
1886  scratch.d.minmax.nelems = nelems;
1887 
1888  scratch.d.minmax.op = minmaxexpr->op;
1889  scratch.d.minmax.finfo = finfo;
1890  scratch.d.minmax.fcinfo_data = fcinfo;
1891 
1892  /* evaluate expressions into minmax->values/nulls */
1893  off = 0;
1894  foreach(lc, minmaxexpr->args)
1895  {
1896  Expr *e = (Expr *) lfirst(lc);
1897 
1898  ExecInitExprRec(e, state,
1899  &scratch.d.minmax.values[off],
1900  &scratch.d.minmax.nulls[off]);
1901  off++;
1902  }
1903 
1904  /* and push the final comparison */
1905  ExprEvalPushStep(state, &scratch);
1906  break;
1907  }
1908 
1909  case T_SQLValueFunction:
1910  {
1911  SQLValueFunction *svf = (SQLValueFunction *) node;
1912 
1913  scratch.opcode = EEOP_SQLVALUEFUNCTION;
1914  scratch.d.sqlvaluefunction.svf = svf;
1915 
1916  ExprEvalPushStep(state, &scratch);
1917  break;
1918  }
1919 
1920  case T_XmlExpr:
1921  {
1922  XmlExpr *xexpr = (XmlExpr *) node;
1923  int nnamed = list_length(xexpr->named_args);
1924  int nargs = list_length(xexpr->args);
1925  int off;
1926  ListCell *arg;
1927 
1928  scratch.opcode = EEOP_XMLEXPR;
1929  scratch.d.xmlexpr.xexpr = xexpr;
1930 
1931  /* allocate space for storing all the arguments */
1932  if (nnamed)
1933  {
1934  scratch.d.xmlexpr.named_argvalue =
1935  (Datum *) palloc(sizeof(Datum) * nnamed);
1936  scratch.d.xmlexpr.named_argnull =
1937  (bool *) palloc(sizeof(bool) * nnamed);
1938  }
1939  else
1940  {
1941  scratch.d.xmlexpr.named_argvalue = NULL;
1942  scratch.d.xmlexpr.named_argnull = NULL;
1943  }
1944 
1945  if (nargs)
1946  {
1947  scratch.d.xmlexpr.argvalue =
1948  (Datum *) palloc(sizeof(Datum) * nargs);
1949  scratch.d.xmlexpr.argnull =
1950  (bool *) palloc(sizeof(bool) * nargs);
1951  }
1952  else
1953  {
1954  scratch.d.xmlexpr.argvalue = NULL;
1955  scratch.d.xmlexpr.argnull = NULL;
1956  }
1957 
1958  /* prepare argument execution */
1959  off = 0;
1960  foreach(arg, xexpr->named_args)
1961  {
1962  Expr *e = (Expr *) lfirst(arg);
1963 
1964  ExecInitExprRec(e, state,
1965  &scratch.d.xmlexpr.named_argvalue[off],
1966  &scratch.d.xmlexpr.named_argnull[off]);
1967  off++;
1968  }
1969 
1970  off = 0;
1971  foreach(arg, xexpr->args)
1972  {
1973  Expr *e = (Expr *) lfirst(arg);
1974 
1975  ExecInitExprRec(e, state,
1976  &scratch.d.xmlexpr.argvalue[off],
1977  &scratch.d.xmlexpr.argnull[off]);
1978  off++;
1979  }
1980 
1981  /* and evaluate the actual XML expression */
1982  ExprEvalPushStep(state, &scratch);
1983  break;
1984  }
1985 
1986  case T_NullTest:
1987  {
1988  NullTest *ntest = (NullTest *) node;
1989 
1990  if (ntest->nulltesttype == IS_NULL)
1991  {
1992  if (ntest->argisrow)
1993  scratch.opcode = EEOP_NULLTEST_ROWISNULL;
1994  else
1995  scratch.opcode = EEOP_NULLTEST_ISNULL;
1996  }
1997  else if (ntest->nulltesttype == IS_NOT_NULL)
1998  {
1999  if (ntest->argisrow)
2001  else
2002  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2003  }
2004  else
2005  {
2006  elog(ERROR, "unrecognized nulltesttype: %d",
2007  (int) ntest->nulltesttype);
2008  }
2009  /* initialize cache in case it's a row test */
2010  scratch.d.nulltest_row.argdesc = NULL;
2011 
2012  /* first evaluate argument into result variable */
2013  ExecInitExprRec(ntest->arg, state,
2014  resv, resnull);
2015 
2016  /* then push the test of that argument */
2017  ExprEvalPushStep(state, &scratch);
2018  break;
2019  }
2020 
2021  case T_BooleanTest:
2022  {
2023  BooleanTest *btest = (BooleanTest *) node;
2024 
2025  /*
2026  * Evaluate argument, directly into result datum. That's ok,
2027  * because resv/resnull is definitely not used anywhere else,
2028  * and will get overwritten by the below EEOP_BOOLTEST_IS_*
2029  * step.
2030  */
2031  ExecInitExprRec(btest->arg, state, resv, resnull);
2032 
2033  switch (btest->booltesttype)
2034  {
2035  case IS_TRUE:
2036  scratch.opcode = EEOP_BOOLTEST_IS_TRUE;
2037  break;
2038  case IS_NOT_TRUE:
2040  break;
2041  case IS_FALSE:
2042  scratch.opcode = EEOP_BOOLTEST_IS_FALSE;
2043  break;
2044  case IS_NOT_FALSE:
2046  break;
2047  case IS_UNKNOWN:
2048  /* Same as scalar IS NULL test */
2049  scratch.opcode = EEOP_NULLTEST_ISNULL;
2050  break;
2051  case IS_NOT_UNKNOWN:
2052  /* Same as scalar IS NOT NULL test */
2053  scratch.opcode = EEOP_NULLTEST_ISNOTNULL;
2054  break;
2055  default:
2056  elog(ERROR, "unrecognized booltesttype: %d",
2057  (int) btest->booltesttype);
2058  }
2059 
2060  ExprEvalPushStep(state, &scratch);
2061  break;
2062  }
2063 
2064  case T_CoerceToDomain:
2065  {
2066  CoerceToDomain *ctest = (CoerceToDomain *) node;
2067 
2068  ExecInitCoerceToDomain(&scratch, ctest, state,
2069  resv, resnull);
2070  break;
2071  }
2072 
2073  case T_CoerceToDomainValue:
2074  {
2075  /*
2076  * Read from location identified by innermost_domainval. Note
2077  * that innermost_domainval could be NULL, if we're compiling
2078  * a standalone domain check rather than one embedded in a
2079  * larger expression. In that case we must read from
2080  * econtext->domainValue_datum. We'll take care of that
2081  * scenario at runtime.
2082  */
2083  scratch.opcode = EEOP_DOMAIN_TESTVAL;
2084  /* we share instruction union variant with case testval */
2085  scratch.d.casetest.value = state->innermost_domainval;
2086  scratch.d.casetest.isnull = state->innermost_domainnull;
2087 
2088  ExprEvalPushStep(state, &scratch);
2089  break;
2090  }
2091 
2092  case T_CurrentOfExpr:
2093  {
2094  scratch.opcode = EEOP_CURRENTOFEXPR;
2095  ExprEvalPushStep(state, &scratch);
2096  break;
2097  }
2098 
2099  case T_NextValueExpr:
2100  {
2101  NextValueExpr *nve = (NextValueExpr *) node;
2102 
2103  scratch.opcode = EEOP_NEXTVALUEEXPR;
2104  scratch.d.nextvalueexpr.seqid = nve->seqid;
2105  scratch.d.nextvalueexpr.seqtypid = nve->typeId;
2106 
2107  ExprEvalPushStep(state, &scratch);
2108  break;
2109  }
2110 
2111  default:
2112  elog(ERROR, "unrecognized node type: %d",
2113  (int) nodeTag(node));
2114  break;
2115  }
2116 }
Datum constvalue
Definition: primnodes.h:214
struct ExprEvalStep::@51::@71 arraycoerce
struct ExprEvalStep::@51::@63 param
Oid minmaxtype
Definition: primnodes.h:1102
bool multidims
Definition: primnodes.h:992
#define NIL
Definition: pg_list.h:65
static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:2780
Definition: fmgr.h:56
struct ExprEvalStep::@51::@86 window_func
List * args
Definition: primnodes.h:1106
List * args
Definition: primnodes.h:1022
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
Definition: execExpr.c:2470
#define BTORDER_PROC
Definition: nbtree.h:575
struct ExprEvalStep::@51::@74 rowcompare_final
struct ExprEvalStep::@51::@70 arrayexpr
Expr * arg
Definition: primnodes.h:791
struct PlanState * parent
Definition: execnodes.h:108
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2784
ExprState * aggfilter
Definition: execnodes.h:765
List * args
Definition: primnodes.h:377
List * args
Definition: primnodes.h:477
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1710
Datum * resvalue
Definition: execExpr.h:253
int numaggs
Definition: execnodes.h:2148
Oid GetUserId(void)
Definition: miscinit.c:448
Oid resulttype
Definition: primnodes.h:764
PGFunction fn_addr
Definition: fmgr.h:58
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2636
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2159
struct ExprEvalStep * steps
Definition: execnodes.h:85
struct ExprEvalStep::@51::@81 convert_rowtype
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool * innermost_casenull
Definition: execnodes.h:112
struct ExprEvalStep::@51::@85 grouping_func
Oid resulttype
Definition: primnodes.h:835
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
struct ExprEvalStep::@51::@57 constval
RowCompareType rctype
Definition: primnodes.h:1070
List * opfamilies
Definition: primnodes.h:1072
bool * resnull
Definition: execExpr.h:254
List * subPlan
Definition: execnodes.h:972
ParamListInfo ext_params
Definition: execnodes.h:109
struct ExprEvalStep::@51::@77 fieldstore
Expr * arg
Definition: primnodes.h:814
ParamKind paramkind
Definition: primnodes.h:262
Definition: nodes.h:529
int errcode(int sqlerrcode)
Definition: elog.c:610
AttrNumber varattno
Definition: primnodes.h:186
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
Expr * arg
Definition: primnodes.h:762
Datum * innermost_domainval
Definition: execnodes.h:114
EState * state
Definition: execnodes.h:947
struct ExprEvalStep::@51::@67 iocoerce
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:644
struct ExprEvalStep::@51::@82 scalararrayop
#define lsecond(l)
Definition: pg_list.h:200
bool * innermost_domainnull
Definition: execnodes.h:115
SubPlanState * ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
Definition: nodeSubplan.c:789
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:335
struct ExprEvalStep::@51::@72 row
static void ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:2543
ParamCompileHook paramCompile
Definition: params.h:114
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
static void convert(const int32 val, char *const buf)
Definition: zic.c:2001
#define linitial(l)
Definition: pg_list.h:195
Oid funcid
Definition: primnodes.h:469
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
struct ExprEvalStep::@51::@87 subplan
List * colnames
Definition: primnodes.h:1038
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:191
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1520
Oid vartype
Definition: primnodes.h:188
List * args
Definition: primnodes.h:1086
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
BoolExprType boolop
Definition: primnodes.h:582
Expr * arg
Definition: primnodes.h:1219
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
Aggref * aggref
Definition: execnodes.h:752
void check_stack_depth(void)
Definition: postgres.c:3312
Expr * arg
Definition: primnodes.h:1242
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:318
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Oid resulttype
Definition: primnodes.h:794
Expr * arg
Definition: primnodes.h:834
List * elements
Definition: primnodes.h:991
Expr * elemexpr
Definition: primnodes.h:859
Definition: type.h:82
Datum * innermost_caseval
Definition: execnodes.h:111
struct ExprEvalStep::@51::@76 fieldselect
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2751
struct ExprEvalStep::@51::@68 sqlvaluefunction
Datum value
Definition: postgres.h:378
List * lappend_int(List *list, int datum)
Definition: list.c:339
List * newvals
Definition: primnodes.h:792
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
List * cols
Definition: primnodes.h:362
union ExprEvalStep::@51 d
Definition: nodes.h:154
List * lappend(List *list, void *datum)
Definition: list.c:321
Index varno
Definition: primnodes.h:184
Definition: nodes.h:153
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
List * args
Definition: primnodes.h:933
void * palloc0(Size size)
Definition: mcxt.c:980
AclResult
Definition: acl.h:177
BoolTestType booltesttype
Definition: primnodes.h:1243
struct ExprEvalStep::@51::@66 make_readonly
uintptr_t Datum
Definition: postgres.h:367
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
Oid opfuncid
Definition: primnodes.h:517
List * groupingSets
Definition: plannodes.h:829
struct ExprEvalStep::@51::@59 boolexpr
struct ExprEvalStep::@51::@53 var
NullTestType nulltesttype
Definition: primnodes.h:1220
struct ExprEvalStep::@51::@69 nextvalueexpr
Plan * plan
Definition: execnodes.h:945
struct ExprEvalStep::@51::@83 xmlexpr
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:331
#define InvalidOid
Definition: postgres_ext.h:36
List * named_args
Definition: primnodes.h:1183
#define ereport(elevel,...)
Definition: elog.h:144
#define INNER_VAR
Definition: primnodes.h:171
struct ExprEvalStep::@51::@62 nulltest_row
List * args
Definition: primnodes.h:1185
#define TYPECACHE_CMP_PROC
Definition: typcache.h:133
#define Max(x, y)
Definition: c.h:914
#define makeNode(_type_)
Definition: nodes.h:577
struct ExprEvalStep::@51::@73 rowcompare_step
AlternativeSubPlanState * ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
Definition: nodeSubplan.c:1314
Oid inputcollid
Definition: primnodes.h:476
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
intptr_t opcode
Definition: execExpr.h:250
Expr * aggfilter
Definition: primnodes.h:378
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:393
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:794
int paramid
Definition: primnodes.h:263
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Oid row_typeid
Definition: primnodes.h:1023
static int list_length(const List *l)
Definition: pg_list.h:169
Oid inputcollid
Definition: primnodes.h:1104
Oid inputcollid
Definition: primnodes.h:521
static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, Oid inputcollid, ExprState *state)
Definition: execExpr.c:2151
struct ExprEvalStep::@51::@65 casetest
List * args
Definition: primnodes.h:583
#define InvalidAttrNumber
Definition: attnum.h:23
#define nodeTag(nodeptr)
Definition: nodes.h:534
Oid element_typeid
Definition: primnodes.h:990
static Datum values[MAXATTR]
Definition: bootstrap.c:167
struct ExprEvalStep::@51::@84 aggref
#define Int32GetDatum(X)
Definition: postgres.h:479
e
Definition: preproc-init.c:82
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:134
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2085
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:1967
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int steps_len
Definition: execnodes.h:104
#define ACL_EXECUTE
Definition: parsenodes.h:81
List * fieldnums
Definition: primnodes.h:793
bool winagg
Definition: primnodes.h:381
#define elog(elevel,...)
Definition: elog.h:214
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5)
Definition: pg_list.h:489
int i
struct ExprEvalStep::@51::@88 alternative_subplan
void * arg
struct ExprEvalStep::@51::@61 jump
ParamListInfo es_param_list_info
Definition: execnodes.h:549
bool argisrow
Definition: primnodes.h:1221
MinMaxOp op
Definition: primnodes.h:1105
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
Expr * arg
Definition: primnodes.h:932
Definition: plannodes.h:816
struct ExprEvalStep::@51::@75 minmax
WindowFunc * wfunc
Definition: execnodes.h:763
List * aggs
Definition: execnodes.h:2147
Expr * result
Definition: primnodes.h:945
List * args
Definition: primnodes.h:522
List * inputcollids
Definition: primnodes.h:1073
Expr * defresult
Definition: primnodes.h:934
Expr * expr
Definition: primnodes.h:944
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:172
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2006
Oid paramtype
Definition: primnodes.h:264
bool constisnull
Definition: primnodes.h:215
#define lfirst_oid(lc)
Definition: pg_list.h:192
TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
Definition: typcache.c:1744
Definition: nodes.h:155
AttrNumber fieldnum
Definition: primnodes.h:763

◆ ExecInitExprSlots()

static void ExecInitExprSlots ( ExprState state,
Node node 
)
static

Definition at line 2256 of file execExpr.c.

References ExecPushExprSlots(), and get_last_attnums_walker().

Referenced by ExecBuildProjectionInfo(), ExecInitExpr(), ExecInitExprWithParams(), and ExecInitQual().

2257 {
2258  LastAttnumInfo info = {0, 0, 0};
2259 
2260  /*
2261  * Figure out which attributes we're going to need.
2262  */
2263  get_last_attnums_walker(node, &info);
2264 
2265  ExecPushExprSlots(state, &info);
2266 }
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
Definition: execExpr.c:2274
static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info)
Definition: execExpr.c:2318

◆ ExecInitExprWithParams()

ExprState* ExecInitExprWithParams ( Expr node,
ParamListInfo  ext_params 
)

Definition at line 160 of file execExpr.c.

References EEOP_DONE, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprState::ext_params, makeNode, ExprEvalStep::opcode, ExprState::parent, ExprState::resnull, and ExprState::resvalue.

Referenced by exec_eval_simple_expr(), and ExecProcNode().

161 {
162  ExprState *state;
163  ExprEvalStep scratch = {0};
164 
165  /* Special case: NULL expression produces a NULL ExprState pointer */
166  if (node == NULL)
167  return NULL;
168 
169  /* Initialize ExprState with empty step list */
170  state = makeNode(ExprState);
171  state->expr = node;
172  state->parent = NULL;
173  state->ext_params = ext_params;
174 
175  /* Insert EEOP_*_FETCHSOME steps as needed */
176  ExecInitExprSlots(state, (Node *) node);
177 
178  /* Compile the expression proper */
179  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
180 
181  /* Finally, append a DONE step */
182  scratch.opcode = EEOP_DONE;
183  ExprEvalPushStep(state, &scratch);
184 
185  ExecReadyExpr(state);
186 
187  return state;
188 }
struct PlanState * parent
Definition: execnodes.h:108
ParamListInfo ext_params
Definition: execnodes.h:109
Definition: nodes.h:529
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
#define makeNode(_type_)
Definition: nodes.h:577
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
Datum resvalue
Definition: execnodes.h:74

◆ ExecInitFunc()

static void ExecInitFunc ( ExprEvalStep scratch,
Expr node,
List args,
Oid  funcid,
Oid  inputcollid,
ExprState state 
)
static

Definition at line 2151 of file execExpr.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, arg, FunctionCallInfoBaseData::args, Const::constisnull, Const::constvalue, ExprEvalStep::d, EEOP_FUNCEXPR, EEOP_FUNCEXPR_FUSAGE, EEOP_FUNCEXPR_STRICT, EEOP_FUNCEXPR_STRICT_FUSAGE, ereport, errcode(), errmsg(), errmsg_plural(), ERROR, ExecInitExprRec(), executor_errposition(), exprLocation(), fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_addr, FmgrInfo::fn_retset, FmgrInfo::fn_strict, ExprEvalStep::func, FUNC_MAX_ARGS, get_func_name(), GetUserId(), InitFunctionCallInfoData, InvokeFunctionExecuteHook, IsA, NullableDatum::isnull, lfirst, list_length(), OBJECT_FUNCTION, ExprEvalStep::opcode, palloc0(), ExprState::parent, pg_proc_aclcheck(), SizeForFunctionCallInfo, PlanState::state, and NullableDatum::value.

Referenced by ExecInitExprRec().

2153 {
2154  int nargs = list_length(args);
2155  AclResult aclresult;
2156  FmgrInfo *flinfo;
2157  FunctionCallInfo fcinfo;
2158  int argno;
2159  ListCell *lc;
2160 
2161  /* Check permission to call function */
2162  aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
2163  if (aclresult != ACLCHECK_OK)
2164  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2165  InvokeFunctionExecuteHook(funcid);
2166 
2167  /*
2168  * Safety check on nargs. Under normal circumstances this should never
2169  * fail, as parser should check sooner. But possibly it might fail if
2170  * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2171  * declared in pg_proc?
2172  */
2173  if (nargs > FUNC_MAX_ARGS)
2174  ereport(ERROR,
2175  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2176  errmsg_plural("cannot pass more than %d argument to a function",
2177  "cannot pass more than %d arguments to a function",
2178  FUNC_MAX_ARGS,
2179  FUNC_MAX_ARGS)));
2180 
2181  /* Allocate function lookup data and parameter workspace for this call */
2182  scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2183  scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2184  flinfo = scratch->d.func.finfo;
2185  fcinfo = scratch->d.func.fcinfo_data;
2186 
2187  /* Set up the primary fmgr lookup information */
2188  fmgr_info(funcid, flinfo);
2189  fmgr_info_set_expr((Node *) node, flinfo);
2190 
2191  /* Initialize function call parameter structure too */
2192  InitFunctionCallInfoData(*fcinfo, flinfo,
2193  nargs, inputcollid, NULL, NULL);
2194 
2195  /* Keep extra copies of this info to save an indirection at runtime */
2196  scratch->d.func.fn_addr = flinfo->fn_addr;
2197  scratch->d.func.nargs = nargs;
2198 
2199  /* We only support non-set functions here */
2200  if (flinfo->fn_retset)
2201  ereport(ERROR,
2202  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2203  errmsg("set-valued function called in context that cannot accept a set"),
2204  state->parent ?
2206  exprLocation((Node *) node)) : 0));
2207 
2208  /* Build code to evaluate arguments directly into the fcinfo struct */
2209  argno = 0;
2210  foreach(lc, args)
2211  {
2212  Expr *arg = (Expr *) lfirst(lc);
2213 
2214  if (IsA(arg, Const))
2215  {
2216  /*
2217  * Don't evaluate const arguments every round; especially
2218  * interesting for constants in comparisons.
2219  */
2220  Const *con = (Const *) arg;
2221 
2222  fcinfo->args[argno].value = con->constvalue;
2223  fcinfo->args[argno].isnull = con->constisnull;
2224  }
2225  else
2226  {
2227  ExecInitExprRec(arg, state,
2228  &fcinfo->args[argno].value,
2229  &fcinfo->args[argno].isnull);
2230  }
2231  argno++;
2232  }
2233 
2234  /* Insert appropriate opcode depending on strictness and stats level */
2235  if (pgstat_track_functions <= flinfo->fn_stats)
2236  {
2237  if (flinfo->fn_strict && nargs > 0)
2238  scratch->opcode = EEOP_FUNCEXPR_STRICT;
2239  else
2240  scratch->opcode = EEOP_FUNCEXPR;
2241  }
2242  else
2243  {
2244  if (flinfo->fn_strict && nargs > 0)
2246  else
2247  scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2248  }
2249 }
Datum constvalue
Definition: primnodes.h:214
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
struct PlanState * parent
Definition: execnodes.h:108
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1191
Oid GetUserId(void)
Definition: miscinit.c:448
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:934
PGFunction fn_addr
Definition: fmgr.h:58
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
Definition: nodes.h:529
int errcode(int sqlerrcode)
Definition: elog.c:610
EState * state
Definition: execnodes.h:947
struct ExprEvalStep::@51::@58 func
#define FUNC_MAX_ARGS
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
bool fn_retset
Definition: fmgr.h:62
#define ERROR
Definition: elog.h:43
bool fn_strict
Definition: fmgr.h:61
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1520
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
Datum value
Definition: postgres.h:378
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
union ExprEvalStep::@51 d
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void * palloc0(Size size)
Definition: mcxt.c:980
AclResult
Definition: acl.h:177
#define ereport(elevel,...)
Definition: elog.h:144
int executor_errposition(EState *estate, int location)
Definition: execUtils.c:877
#define lfirst(lc)
Definition: pg_list.h:190
intptr_t opcode
Definition: execExpr.h:250
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
static int list_length(const List *l)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
void * arg
bool constisnull
Definition: primnodes.h:215

◆ ExecInitQual()

ExprState* ExecInitQual ( List qual,
PlanState parent 
)

Definition at line 209 of file execExpr.c.

References Assert, ExprEvalStep::d, EEO_FLAG_IS_QUAL, EEOP_DONE, EEOP_QUAL, ExecInitExprRec(), ExecInitExprSlots(), ExecReadyExpr(), ExprState::expr, ExprEvalPushStep(), ExprState::ext_params, ExprState::flags, IsA, lappend_int(), lfirst, lfirst_int, makeNode, NIL, ExprEvalStep::opcode, ExprState::parent, ExprEvalStep::qualexpr, ExprState::resnull, ExprEvalStep::resnull, ExprState::resvalue, ExprEvalStep::resvalue, ExprState::steps, and ExprState::steps_len.

Referenced by CopyFrom(), ExecInitAgg(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitCustomScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNamedTuplestoreScan(), ExecInitNestLoop(), ExecInitPartitionInfo(), ExecInitResult(), ExecInitSampleScan(), ExecInitSeqScan(), ExecInitSubqueryScan(), ExecInitTableFuncScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecInitWorkTableScan(), ExecPrepareQual(), and ExecProcNode().

210 {
211  ExprState *state;
212  ExprEvalStep scratch = {0};
213  List *adjust_jumps = NIL;
214  ListCell *lc;
215 
216  /* short-circuit (here and in ExecQual) for empty restriction list */
217  if (qual == NIL)
218  return NULL;
219 
220  Assert(IsA(qual, List));
221 
222  state = makeNode(ExprState);
223  state->expr = (Expr *) qual;
224  state->parent = parent;
225  state->ext_params = NULL;
226 
227  /* mark expression as to be used with ExecQual() */
228  state->flags = EEO_FLAG_IS_QUAL;
229 
230  /* Insert EEOP_*_FETCHSOME steps as needed */
231  ExecInitExprSlots(state, (Node *) qual);
232 
233  /*
234  * ExecQual() needs to return false for an expression returning NULL. That
235  * allows us to short-circuit the evaluation the first time a NULL is
236  * encountered. As qual evaluation is a hot-path this warrants using a
237  * special opcode for qual evaluation that's simpler than BOOL_AND (which
238  * has more complex NULL handling).
239  */
240  scratch.opcode = EEOP_QUAL;
241 
242  /*
243  * We can use ExprState's resvalue/resnull as target for each qual expr.
244  */
245  scratch.resvalue = &state->resvalue;
246  scratch.resnull = &state->resnull;
247 
248  foreach(lc, qual)
249  {
250  Expr *node = (Expr *) lfirst(lc);
251 
252  /* first evaluate expression */
253  ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
254 
255  /* then emit EEOP_QUAL to detect if it's false (or null) */
256  scratch.d.qualexpr.jumpdone = -1;
257  ExprEvalPushStep(state, &scratch);
258  adjust_jumps = lappend_int(adjust_jumps,
259  state->steps_len - 1);
260  }
261 
262  /* adjust jump targets */
263  foreach(lc, adjust_jumps)
264  {
265  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
266 
267  Assert(as->opcode == EEOP_QUAL);
268  Assert(as->d.qualexpr.jumpdone == -1);
269  as->d.qualexpr.jumpdone = state->steps_len;
270  }
271 
272  /*
273  * At the end, we don't need to do anything more. The last qual expr must
274  * have yielded TRUE, and since its result is stored in the desired output
275  * location, we're done.
276  */
277  scratch.opcode = EEOP_DONE;
278  ExprEvalPushStep(state, &scratch);
279 
280  ExecReadyExpr(state);
281 
282  return state;
283 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:253
struct ExprEvalStep * steps
Definition: execnodes.h:85
bool * resnull
Definition: execExpr.h:254
ParamListInfo ext_params
Definition: execnodes.h:109
Definition: nodes.h:529
bool resnull
Definition: execnodes.h:72
Expr * expr
Definition: execnodes.h:94
#define lfirst_int(lc)
Definition: pg_list.h:191
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2256
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:59
List * lappend_int(List *list, int datum)
Definition: list.c:339
union ExprEvalStep::@51 d
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
#define makeNode(_type_)
Definition: nodes.h:577
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
Definition: regguts.h:298
intptr_t opcode
Definition: execExpr.h:250
int steps_len
Definition: execnodes.h:104
uint8 flags
Definition: execnodes.h:65
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:74
struct ExprEvalStep::@51::@60 qualexpr

◆ ExecInitSubscriptingRef()

static void ExecInitSubscriptingRef ( ExprEvalStep scratch,
SubscriptingRef sbsref,
ExprState state,
Datum resv,
bool resnull 
)
static

Definition at line 2543 of file execExpr.c.

References Assert, ExprEvalStep::d, EEOP_JUMP_IF_NULL, EEOP_SBSREF_ASSIGN, EEOP_SBSREF_FETCH, EEOP_SBSREF_OLD, EEOP_SBSREF_SUBSCRIPT, elog, ereport, errcode(), errmsg(), ERROR, ExecInitExprRec(), ExprEvalPushStep(), get_typlen(), get_typlenbyvalalign(), i, ExprState::innermost_casenull, ExprState::innermost_caseval, SubscriptingRefState::isassignment, isAssignmentIndirectionExpr(), ExprEvalStep::jump, lappend_int(), lfirst, lfirst_int, list_length(), SubscriptingRefState::lowerprovided, MAXDIM, NIL, SubscriptingRefState::numlower, SubscriptingRefState::numupper, ExprEvalStep::opcode, palloc0(), SubscriptingRefState::prevnull, SubscriptingRefState::prevvalue, SubscriptingRef::refassgnexpr, SubscriptingRefState::refattrlength, SubscriptingRef::refcontainertype, SubscriptingRefState::refelemalign, SubscriptingRefState::refelembyval, SubscriptingRefState::refelemlength, SubscriptingRef::refelemtype, SubscriptingRefState::refelemtype, SubscriptingRef::refexpr, SubscriptingRef::reflowerindexpr, SubscriptingRef::refupperindexpr, SubscriptingRefState::replacenull, SubscriptingRefState::replacevalue, ExprEvalStep::sbsref, ExprEvalStep::sbsref_subscript, ExprState::steps, ExprState::steps_len, SubscriptingRefState::subscriptnull, SubscriptingRefState::subscriptvalue, and SubscriptingRefState::upperprovided.

Referenced by ExecInitExprRec().

2545 {
2546  bool isAssignment = (sbsref->refassgnexpr != NULL);
2547  SubscriptingRefState *sbsrefstate = palloc0(sizeof(SubscriptingRefState));
2548  List *adjust_jumps = NIL;
2549  ListCell *lc;
2550  int i;
2551 
2552  /* Fill constant fields of SubscriptingRefState */
2553  sbsrefstate->isassignment = isAssignment;
2554  sbsrefstate->refelemtype = sbsref->refelemtype;
2555  sbsrefstate->refattrlength = get_typlen(sbsref->refcontainertype);
2557  &sbsrefstate->refelemlength,
2558  &sbsrefstate->refelembyval,
2559  &sbsrefstate->refelemalign);
2560 
2561  /*
2562  * Evaluate array input. It's safe to do so into resv/resnull, because we
2563  * won't use that as target for any of the other subexpressions, and it'll
2564  * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
2565  * pushed last.
2566  */
2567  ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
2568 
2569  /*
2570  * If refexpr yields NULL, and it's a fetch, then result is NULL. We can
2571  * implement this with just JUMP_IF_NULL, since we evaluated the array
2572  * into the desired target location.
2573  */
2574  if (!isAssignment)
2575  {
2576  scratch->opcode = EEOP_JUMP_IF_NULL;
2577  scratch->d.jump.jumpdone = -1; /* adjust later */
2578  ExprEvalPushStep(state, scratch);
2579  adjust_jumps = lappend_int(adjust_jumps,
2580  state->steps_len - 1);
2581  }
2582 
2583  /* Verify subscript list lengths are within limit */
2584  if (list_length(sbsref->refupperindexpr) > MAXDIM)
2585  ereport(ERROR,
2586  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2587  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2588  list_length(sbsref->refupperindexpr), MAXDIM)));
2589 
2590  if (list_length(sbsref->reflowerindexpr) > MAXDIM)
2591  ereport(ERROR,
2592  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2593  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2594  list_length(sbsref->reflowerindexpr), MAXDIM)));
2595 
2596  /* Evaluate upper subscripts */
2597  i = 0;
2598  foreach(lc, sbsref->refupperindexpr)
2599  {
2600  Expr *e = (Expr *) lfirst(lc);
2601 
2602  /* When slicing, individual subscript bounds can be omitted */
2603  if (!e)
2604  {
2605  sbsrefstate->upperprovided[i] = false;
2606  i++;
2607  continue;
2608  }
2609 
2610  sbsrefstate->upperprovided[i] = true;
2611 
2612  /* Each subscript is evaluated into subscriptvalue/subscriptnull */
2613  ExecInitExprRec(e, state,
2614  &sbsrefstate->subscriptvalue, &sbsrefstate->subscriptnull);
2615 
2616  /* ... and then SBSREF_SUBSCRIPT saves it into step's workspace */
2617  scratch->opcode = EEOP_SBSREF_SUBSCRIPT;
2618  scratch->d.sbsref_subscript.state = sbsrefstate;
2619  scratch->d.sbsref_subscript.off = i;
2620  scratch->d.sbsref_subscript.isupper = true;
2621  scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
2622  ExprEvalPushStep(state, scratch);
2623  adjust_jumps = lappend_int(adjust_jumps,
2624  state->steps_len - 1);
2625  i++;
2626  }
2627  sbsrefstate->numupper = i;
2628 
2629  /* Evaluate lower subscripts similarly */
2630  i = 0;
2631  foreach(lc, sbsref->reflowerindexpr)
2632  {
2633  Expr *e = (Expr *) lfirst(lc);
2634 
2635  /* When slicing, individual subscript bounds can be omitted */
2636  if (!e)
2637  {
2638  sbsrefstate->lowerprovided[i] = false;
2639  i++;
2640  continue;
2641  }
2642 
2643  sbsrefstate->lowerprovided[i] = true;
2644 
2645  /* Each subscript is evaluated into subscriptvalue/subscriptnull */
2646  ExecInitExprRec(e, state,
2647  &sbsrefstate->subscriptvalue, &sbsrefstate->subscriptnull);
2648 
2649  /* ... and then SBSREF_SUBSCRIPT saves it into step's workspace */
2650  scratch->opcode = EEOP_SBSREF_SUBSCRIPT;
2651  scratch->d.sbsref_subscript.state = sbsrefstate;
2652  scratch->d.sbsref_subscript.off = i;
2653  scratch->d.sbsref_subscript.isupper = false;
2654  scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
2655  ExprEvalPushStep(state, scratch);
2656  adjust_jumps = lappend_int(adjust_jumps,
2657  state->steps_len - 1);
2658  i++;
2659  }
2660  sbsrefstate->numlower = i;
2661 
2662  /* Should be impossible if parser is sane, but check anyway: */
2663  if (sbsrefstate->numlower != 0 &&
2664  sbsrefstate->numupper != sbsrefstate->numlower)
2665  elog(ERROR, "upper and lower index lists are not same length");
2666 
2667  if (isAssignment)
2668  {
2669  Datum *save_innermost_caseval;
2670  bool *save_innermost_casenull;
2671 
2672  /*
2673  * We might have a nested-assignment situation, in which the
2674  * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
2675  * to obtain and modify the previous value of the array element or
2676  * slice being replaced. If so, we have to extract that value from
2677  * the array and pass it down via the CaseTestExpr mechanism. It's
2678  * safe to reuse the CASE mechanism because there cannot be a CASE
2679  * between here and where the value would be needed, and an array
2680  * assignment can't be within a CASE either. (So saving and restoring
2681  * innermost_caseval is just paranoia, but let's do it anyway.)
2682  *
2683  * Since fetching the old element might be a nontrivial expense, do it
2684  * only if the argument actually needs it.
2685  */
2687  {
2688  scratch->opcode = EEOP_SBSREF_OLD;
2689  scratch->d.sbsref.state = sbsrefstate;
2690  ExprEvalPushStep(state, scratch);
2691  }
2692 
2693  /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
2694  save_innermost_caseval = state->innermost_caseval;
2695  save_innermost_casenull = state->innermost_casenull;
2696  state->innermost_caseval = &sbsrefstate->prevvalue;
2697  state->innermost_casenull = &sbsrefstate->prevnull;
2698 
2699  /* evaluate replacement value into replacevalue/replacenull */
2700  ExecInitExprRec(sbsref->refassgnexpr, state,
2701  &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
2702 
2703  state->innermost_caseval = save_innermost_caseval;
2704  state->innermost_casenull = save_innermost_casenull;
2705 
2706  /* and perform the assignment */
2707  scratch->opcode = EEOP_SBSREF_ASSIGN;
2708  scratch->d.sbsref.state = sbsrefstate;
2709  ExprEvalPushStep(state, scratch);
2710 
2711  }
2712  else
2713  {
2714  /* array fetch is much simpler */
2715  scratch->opcode = EEOP_SBSREF_FETCH;
2716  scratch->d.sbsref.state = sbsrefstate;
2717  ExprEvalPushStep(state, scratch);
2718 
2719  }
2720 
2721  /* adjust jump targets */
2722  foreach(lc, adjust_jumps)
2723  {
2724  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2725 
2726  if (as->opcode == EEOP_SBSREF_SUBSCRIPT)
2727  {
2728  Assert(as->d.sbsref_subscript.jumpdone == -1);
2729  as->d.sbsref_subscript.jumpdone = state->steps_len;
2730  }
2731  else
2732  {
2734  Assert(as->d.jump.jumpdone == -1);
2735  as->d.jump.jumpdone = state->steps_len;
2736  }
2737  }
2738 }
#define NIL
Definition: pg_list.h:65
struct ExprEvalStep::@51::@79 sbsref
#define MAXDIM
Definition: c.h:535
struct ExprEvalStep::@51::@78 sbsref_subscript
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2159
struct ExprEvalStep * steps
Definition: execnodes.h:85
bool * innermost_casenull
Definition: execnodes.h:112
static bool isAssignmentIndirectionExpr(Expr *expr)
Definition: execExpr.c:2755
int errcode(int sqlerrcode)
Definition: elog.c:610
List * refupperindexpr
Definition: primnodes.h:422
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
bool upperprovided[MAXDIM]
Definition: execExpr.h:661
Datum * innermost_caseval
Definition: execnodes.h:111
List * lappend_int(List *list, int datum)
Definition: list.c:339
union ExprEvalStep::@51 d
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
bool lowerprovided[MAXDIM]
Definition: execExpr.h:666
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
intptr_t opcode
Definition: execExpr.h:250
static int list_length(const List *l)
Definition: pg_list.h:169
Expr * refassgnexpr
Definition: primnodes.h:430
e
Definition: preproc-init.c:82
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2085
int errmsg(const char *fmt,...)
Definition: elog.c:824
int steps_len
Definition: execnodes.h:104
List * reflowerindexpr
Definition: primnodes.h:424
#define elog(elevel,...)
Definition: elog.h:214
int i
struct ExprEvalStep::@51::@61 jump
Oid refcontainertype
Definition: primnodes.h:418
Expr * refexpr
Definition: primnodes.h:427
Definition: pg_list.h:50

◆ ExecInitWholeRowVar()

static void ExecInitWholeRowVar ( ExprEvalStep scratch,
Var variable,
ExprState state 
)
static

Definition at line 2470 of file execExpr.c.

References ExprEvalStep::d, EEOP_WHOLEROW, ExecInitExtraTupleSlot(), ExecInitJunkFilter(), lfirst, nodeTag, ExprEvalStep::opcode, ExprState::parent, PlanState::plan, TargetEntry::resjunk, PlanState::state, T_CteScanState, T_SubqueryScanState, Plan::targetlist, TTSOpsVirtual, and ExprEvalStep::wholerow.

Referenced by ExecInitExprRec().

2471 {
2472  PlanState *parent = state->parent;
2473 
2474  /* fill in all but the target */
2475  scratch->opcode = EEOP_WHOLEROW;
2476  scratch->d.wholerow.var = variable;
2477  scratch->d.wholerow.first = true;
2478  scratch->d.wholerow.slow = false;
2479  scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
2480  scratch->d.wholerow.junkFilter = NULL;
2481 
2482  /*
2483  * If the input tuple came from a subquery, it might contain "resjunk"
2484  * columns (such as GROUP BY or ORDER BY columns), which we don't want to
2485  * keep in the whole-row result. We can get rid of such columns by
2486  * passing the tuple through a JunkFilter --- but to make one, we have to
2487  * lay our hands on the subquery's targetlist. Fortunately, there are not
2488  * very many cases where this can happen, and we can identify all of them
2489  * by examining our parent PlanState. We assume this is not an issue in
2490  * standalone expressions that don't have parent plans. (Whole-row Vars
2491  * can occur in such expressions, but they will always be referencing
2492  * table rows.)
2493  */
2494  if (parent)
2495  {
2496  PlanState *subplan = NULL;
2497 
2498  switch (nodeTag(parent))
2499  {
2500  case T_SubqueryScanState:
2501  subplan = ((SubqueryScanState *) parent)->subplan;
2502  break;
2503  case T_CteScanState:
2504  subplan = ((CteScanState *) parent)->cteplanstate;
2505  break;
2506  default:
2507  break;
2508  }
2509 
2510  if (subplan)
2511  {
2512  bool junk_filter_needed = false;
2513  ListCell *tlist;
2514 
2515  /* Detect whether subplan tlist actually has any junk columns */
2516  foreach(tlist, subplan->plan->targetlist)
2517  {
2518  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
2519 
2520  if (tle->resjunk)
2521  {
2522  junk_filter_needed = true;
2523  break;
2524  }
2525  }
2526 
2527  /* If so, build the junkfilter now */
2528  if (junk_filter_needed)
2529  {
2530  scratch->d.wholerow.junkFilter =
2532  ExecInitExtraTupleSlot(parent->state, NULL,
2533  &TTSOpsVirtual));
2534  }
2535  }
2536  }
2537 }
struct PlanState * parent
Definition: execnodes.h:108
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1801
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
EState * state
Definition: execnodes.h:947
bool resjunk
Definition: primnodes.h:1414
union ExprEvalStep::@51 d
Plan * plan
Definition: execnodes.h:945
#define lfirst(lc)
Definition: pg_list.h:190
intptr_t opcode
Definition: execExpr.h:250
#define nodeTag(nodeptr)
Definition: nodes.h:534
List * targetlist
Definition: plannodes.h:142
struct variable * variable
Definition: type.h:173
struct ExprEvalStep::@51::@54 wholerow
JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
Definition: execJunk.c:60

◆ ExecPrepareCheck()

ExprState* ExecPrepareCheck ( List qual,
EState estate 
)

Definition at line 543 of file execExpr.c.

References EState::es_query_cxt, ExecInitCheck(), expression_planner(), and MemoryContextSwitchTo().

Referenced by ExecPartitionCheck(), and ExecProcNode().

544 {
545  ExprState *result;
546  MemoryContext oldcontext;
547 
548  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
549 
550  qual = (List *) expression_planner((Expr *) qual);
551 
552  result = ExecInitCheck(qual, NULL);
553 
554  MemoryContextSwitchTo(oldcontext);
555 
556  return result;
557 }
ExprState * ExecInitCheck(List *qual, PlanState *parent)
Definition: execExpr.c:298
Expr * expression_planner(Expr *expr)
Definition: planner.c:6156
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:555
Definition: pg_list.h:50

◆ ExecPrepareExpr()

ExprState* ExecPrepareExpr ( Expr node,
EState estate 
)

Definition at line 492 of file execExpr.c.

References EState::es_query_cxt, ExecInitExpr(), expression_planner(), and MemoryContextSwitchTo().

Referenced by ATRewriteTable(), check_default_partition_contents(), ExecComputeStoredGenerated(), ExecPrepareExprList(), ExecProcNode(), ExecRelCheck(), ExecuteCallStmt(), StoreAttrDefault(), validateCheckConstraint(), and validateDomainConstraint().

493 {
494  ExprState *result;
495  MemoryContext oldcontext;
496 
497  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
498 
499  node = expression_planner(node);
500 
501  result = ExecInitExpr(node, NULL);
502 
503  MemoryContextSwitchTo(oldcontext);
504 
505  return result;
506 }
Expr * expression_planner(Expr *expr)
Definition: planner.c:6156
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:555
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123

◆ ExecPrepareExprList()

List* ExecPrepareExprList ( List nodes,
EState estate 
)

Definition at line 566 of file execExpr.c.

References EState::es_query_cxt, ExecPrepareExpr(), lappend(), lfirst, MemoryContextSwitchTo(), and NIL.

Referenced by EvaluateParams(), ExecProcNode(), FormIndexDatum(), and FormPartitionKeyDatum().

567 {
568  List *result = NIL;
569  MemoryContext oldcontext;
570  ListCell *lc;
571 
572  /* Ensure that the list cell nodes are in the right context too */
573  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
574 
575  foreach(lc, nodes)
576  {
577  Expr *e = (Expr *) lfirst(lc);
578 
579  result = lappend(result, ExecPrepareExpr(e, estate));
580  }
581 
582  MemoryContextSwitchTo(oldcontext);
583 
584  return result;
585 }
#define NIL
Definition: pg_list.h:65
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:492
MemoryContext es_query_cxt
Definition: execnodes.h:555
List * lappend(List *list, void *datum)
Definition: list.c:321
#define lfirst(lc)
Definition: pg_list.h:190
e
Definition: preproc-init.c:82
Definition: pg_list.h:50

◆ ExecPrepareQual()

ExprState* ExecPrepareQual ( List qual,
EState estate 
)

Definition at line 520 of file execExpr.c.

References EState::es_query_cxt, ExecInitQual(), expression_planner(), and MemoryContextSwitchTo().

Referenced by compute_index_stats(), ExecCheckIndexConstraints(), ExecInsertIndexTuples(), ExecProcNode(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), and TriggerEnabled().

521 {
522  ExprState *result;
523  MemoryContext oldcontext;
524 
525  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
526 
527  qual = (List *) expression_planner((Expr *) qual);
528 
529  result = ExecInitQual(qual, NULL);
530 
531  MemoryContextSwitchTo(oldcontext);
532 
533  return result;
534 }
Expr * expression_planner(Expr *expr)
Definition: planner.c:6156
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
MemoryContext es_query_cxt
Definition: execnodes.h:555
Definition: pg_list.h:50

◆ ExecPushExprSlots()

static void ExecPushExprSlots ( ExprState state,
LastAttnumInfo info 
)
static

Definition at line 2274 of file execExpr.c.

References ExprEvalStep::d, EEOP_INNER_FETCHSOME, EEOP_OUTER_FETCHSOME, EEOP_SCAN_FETCHSOME, ExecComputeSlotInfo(), ExprEvalPushStep(), ExprEvalStep::fetch, LastAttnumInfo::last_inner, LastAttnumInfo::last_outer, LastAttnumInfo::last_scan, ExprEvalStep::opcode, ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by ExecBuildAggTrans(), and ExecInitExprSlots().

2275 {
2276  ExprEvalStep scratch = {0};
2277 
2278  scratch.resvalue = NULL;
2279  scratch.resnull = NULL;
2280 
2281  /* Emit steps as needed */
2282  if (info->last_inner > 0)
2283  {
2284  scratch.opcode = EEOP_INNER_FETCHSOME;
2285  scratch.d.fetch.last_var = info->last_inner;
2286  scratch.d.fetch.fixed = false;
2287  scratch.d.fetch.kind = NULL;
2288  scratch.d.fetch.known_desc = NULL;
2289  if (ExecComputeSlotInfo(state, &scratch))
2290  ExprEvalPushStep(state, &scratch);
2291  }
2292  if (info->last_outer > 0)
2293  {
2294  scratch.opcode = EEOP_OUTER_FETCHSOME;
2295  scratch.d.fetch.last_var = info->last_outer;
2296  scratch.d.fetch.fixed = false;
2297  scratch.d.fetch.kind = NULL;
2298  scratch.d.fetch.known_desc = NULL;
2299  if (ExecComputeSlotInfo(state, &scratch))
2300  ExprEvalPushStep(state, &scratch);
2301  }
2302  if (info->last_scan > 0)
2303  {
2304  scratch.opcode = EEOP_SCAN_FETCHSOME;
2305  scratch.d.fetch.last_var = info->last_scan;
2306  scratch.d.fetch.fixed = false;
2307  scratch.d.fetch.kind = NULL;
2308  scratch.d.fetch.known_desc = NULL;
2309  if (ExecComputeSlotInfo(state, &scratch))
2310  ExprEvalPushStep(state, &scratch);
2311  }
2312 }
Datum * resvalue
Definition: execExpr.h:253
struct ExprEvalStep::@51::@52 fetch
bool * resnull
Definition: execExpr.h:254
AttrNumber last_scan
Definition: execExpr.c:57
AttrNumber last_inner
Definition: execExpr.c:55
AttrNumber last_outer
Definition: execExpr.c:56
union ExprEvalStep::@51 d
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2372
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2125
intptr_t opcode
Definition: execExpr.h:250

◆ ExecReadyExpr()

static void ExecReadyExpr ( ExprState state)
static

Definition at line 629 of file execExpr.c.

References ExecReadyInterpretedExpr(), and jit_compile_expr().

Referenced by ExecBuildAggTrans(), ExecBuildGroupingEqual(), ExecBuildProjectionInfo(), ExecInitExpr(), ExecInitExprRec(), ExecInitExprWithParams(), and ExecInitQual().

630 {
631  if (jit_compile_expr(state))
632  return;
633 
635 }
void ExecReadyInterpretedExpr(ExprState *state)
bool jit_compile_expr(struct ExprState *state)
Definition: jit.c:153

◆ ExprEvalPushStep()

void ExprEvalPushStep ( ExprState es,
const ExprEvalStep s 
)

Definition at line 2125 of file execExpr.c.

References palloc(), repalloc(), ExprState::steps, ExprState::steps_alloc, and ExprState::steps_len.

Referenced by ExecBuildAggTrans(), ExecBuildAggTransCall(), ExecBuildGroupingEqual(), ExecBuildProjectionInfo(), ExecInitCoerceToDomain(), ExecInitExpr(), ExecInitExprRec(), ExecInitExprWithParams(), ExecInitQual(), ExecInitSubscriptingRef(), ExecPushExprSlots(), and plpgsql_param_compile().

2126 {
2127  if (es->steps_alloc == 0)
2128  {
2129  es->steps_alloc = 16;
2130  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2131  }
2132  else if (es->steps_alloc == es->steps_len)
2133  {
2134  es->steps_alloc *= 2;
2135  es->steps = repalloc(es->steps,
2136  sizeof(ExprEvalStep) * es->steps_alloc);
2137  }
2138 
2139  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2140 }
struct ExprEvalStep * steps
Definition: execnodes.h:85
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
int steps_alloc
Definition: execnodes.h:105
void * palloc(Size size)
Definition: mcxt.c:949
int steps_len
Definition: execnodes.h:104

◆ get_last_attnums_walker()

static bool get_last_attnums_walker ( Node node,
LastAttnumInfo info 
)
static

Definition at line 2318 of file execExpr.c.

References attnum, expression_tree_walker(), INNER_VAR, IsA, LastAttnumInfo::last_inner, LastAttnumInfo::last_outer, LastAttnumInfo::last_scan, Max, OUTER_VAR, Var::varattno, and Var::varno.

Referenced by ExecBuildAggTrans(), and ExecInitExprSlots().

2319 {
2320  if (node == NULL)
2321  return false;
2322  if (IsA(node, Var))
2323  {
2324  Var *variable = (Var *) node;
2325  AttrNumber attnum = variable->varattno;
2326 
2327  switch (variable->varno)
2328  {
2329  case INNER_VAR:
2330  info->last_inner = Max(info->last_inner, attnum);
2331  break;
2332 
2333  case OUTER_VAR:
2334  info->last_outer = Max(info->last_outer, attnum);
2335  break;
2336 
2337  /* INDEX_VAR is handled by default case */
2338 
2339  default:
2340  info->last_scan = Max(info->last_scan, attnum);
2341  break;
2342  }
2343  return false;
2344  }
2345 
2346  /*
2347  * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2348  * because those do not represent expressions to be evaluated within the
2349  * calling expression's econtext. GroupingFunc arguments are never
2350  * evaluated at all.
2351  */
2352  if (IsA(node, Aggref))
2353  return false;
2354  if (IsA(node, WindowFunc))
2355  return false;
2356  if (IsA(node, GroupingFunc))
2357  return false;
2359  (void *) info);
2360 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
AttrNumber last_scan
Definition: execExpr.c:57
AttrNumber last_inner
Definition: execExpr.c:55
AttrNumber last_outer
Definition: execExpr.c:56
Index varno
Definition: primnodes.h:184
int16 attnum
Definition: pg_attribute.h:79
#define INNER_VAR
Definition: primnodes.h:171
#define Max(x, y)
Definition: c.h:914
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nod