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 "nodes/subscripting.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 2941 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().

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

◆ 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 3243 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().

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

◆ 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 3359 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().

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

◆ 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:62
#define IsA(nodeptr, _type_)
Definition: nodes.h:584
struct PlanState * parent
Definition: execnodes.h:107
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
ParamListInfo ext_params
Definition: execnodes.h:108
Definition: nodes.h:533
AttrNumber varattno
Definition: primnodes.h:186
TupleTableSlot * resultslot
Definition: execnodes.h:79
Definition: primnodes.h:181
bool resnull
Definition: execnodes.h:71
union ExprEvalStep::@49 d
Expr * expr
Definition: execnodes.h:93
Oid vartype
Definition: primnodes.h:188
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2236
#define lfirst_node(type, lc)
Definition: pg_list.h:172
AttrNumber resno
Definition: primnodes.h:1432
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Index varno
Definition: primnodes.h:184
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
struct ExprEvalStep::@49::@53 assign_var
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2105
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
int16 attnum
Definition: pg_attribute.h:83
#define INNER_VAR
Definition: primnodes.h:171
#define makeNode(_type_)
Definition: nodes.h:581
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:254
Expr * expr
Definition: primnodes.h:1431
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2144
ExprState pi_state
Definition: execnodes.h:332
struct ExprEvalStep::@49::@54 assign_tmp
ExprContext * pi_exprContext
Definition: execnodes.h:334
Datum resvalue
Definition: execnodes.h:73
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(), and ExecRelCheck().

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:307
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:58
#define DatumGetBool(X)
Definition: postgres.h:393
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:804
uint8 flags
Definition: execnodes.h:64

◆ ExecComputeSlotInfo()

static bool ExecComputeSlotInfo ( ExprState state,
ExprEvalStep op 
)
static

Definition at line 2352 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().

2353 {
2354  PlanState *parent = state->parent;
2355  TupleDesc desc = NULL;
2356  const TupleTableSlotOps *tts_ops = NULL;
2357  bool isfixed = false;
2358  ExprEvalOp opcode = op->opcode;
2359 
2360  Assert(opcode == EEOP_INNER_FETCHSOME ||
2361  opcode == EEOP_OUTER_FETCHSOME ||
2362  opcode == EEOP_SCAN_FETCHSOME);
2363 
2364  if (op->d.fetch.known_desc != NULL)
2365  {
2366  desc = op->d.fetch.known_desc;
2367  tts_ops = op->d.fetch.kind;
2368  isfixed = op->d.fetch.kind != NULL;
2369  }
2370  else if (!parent)
2371  {
2372  isfixed = false;
2373  }
2374  else if (opcode == EEOP_INNER_FETCHSOME)
2375  {
2376  PlanState *is = innerPlanState(parent);
2377 
2378  if (parent->inneropsset && !parent->inneropsfixed)
2379  {
2380  isfixed = false;
2381  }
2382  else if (parent->inneropsset && parent->innerops)
2383  {
2384  isfixed = true;
2385  tts_ops = parent->innerops;
2386  desc = ExecGetResultType(is);
2387  }
2388  else if (is)
2389  {
2390  tts_ops = ExecGetResultSlotOps(is, &isfixed);
2391  desc = ExecGetResultType(is);
2392  }
2393  }
2394  else if (opcode == EEOP_OUTER_FETCHSOME)
2395  {
2396  PlanState *os = outerPlanState(parent);
2397 
2398  if (parent->outeropsset && !parent->outeropsfixed)
2399  {
2400  isfixed = false;
2401  }
2402  else if (parent->outeropsset && parent->outerops)
2403  {
2404  isfixed = true;
2405  tts_ops = parent->outerops;
2406  desc = ExecGetResultType(os);
2407  }
2408  else if (os)
2409  {
2410  tts_ops = ExecGetResultSlotOps(os, &isfixed);
2411  desc = ExecGetResultType(os);
2412  }
2413  }
2414  else if (opcode == EEOP_SCAN_FETCHSOME)
2415  {
2416  desc = parent->scandesc;
2417 
2418  if (parent->scanops)
2419  tts_ops = parent->scanops;
2420 
2421  if (parent->scanopsset)
2422  isfixed = parent->scanopsfixed;
2423  }
2424 
2425  if (isfixed && desc != NULL && tts_ops != NULL)
2426  {
2427  op->d.fetch.fixed = true;
2428  op->d.fetch.kind = tts_ops;
2429  op->d.fetch.known_desc = desc;
2430  }
2431  else
2432  {
2433  op->d.fetch.fixed = false;
2434  op->d.fetch.kind = NULL;
2435  op->d.fetch.known_desc = NULL;
2436  }
2437 
2438  /* if the slot is known to always virtual we never need to deform */
2439  if (op->d.fetch.fixed && op->d.fetch.kind == &TTSOpsVirtual)
2440  return false;
2441 
2442  return true;
2443 }
const TupleTableSlotOps * innerops
Definition: execnodes.h:1015
struct PlanState * parent
Definition: execnodes.h:107
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:499
struct ExprEvalStep::@49::@50 fetch
bool inneropsset
Definition: execnodes.h:1023
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
ExprEvalOp
Definition: execExpr.h:49
bool inneropsfixed
Definition: execnodes.h:1019
union ExprEvalStep::@49 d
#define outerPlanState(node)
Definition: execnodes.h:1035
const TupleTableSlotOps * scanops
Definition: execnodes.h:1013
bool outeropsset
Definition: execnodes.h:1022
TupleDesc scandesc
Definition: execnodes.h:988
bool scanopsfixed
Definition: execnodes.h:1017
#define Assert(condition)
Definition: c.h:804
intptr_t opcode
Definition: execExpr.h:254
bool outeropsfixed
Definition: execnodes.h:1018
bool scanopsset
Definition: execnodes.h:1021
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:490
#define innerPlanState(node)
Definition: execnodes.h:1034
const TupleTableSlotOps * outerops
Definition: execnodes.h:1014

◆ 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:584
Expr * make_ands_explicit(List *andclauses)
Definition: makefuncs.c:708
#define Assert(condition)
Definition: c.h:804
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 2787 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().

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

◆ 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(), MakeTidOpExpr(), 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:107
ParamListInfo ext_params
Definition: execnodes.h:108
Definition: nodes.h:533
bool resnull
Definition: execnodes.h:71
Expr * expr
Definition: execnodes.h:93
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2236
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:2105
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
#define makeNode(_type_)
Definition: nodes.h:581
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:254
Datum resvalue
Definition: execnodes.h:73

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

◆ ExecInitExprSlots()

static void ExecInitExprSlots ( ExprState state,
Node node 
)
static

Definition at line 2236 of file execExpr.c.

References ExecPushExprSlots(), and get_last_attnums_walker().

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

2237 {
2238  LastAttnumInfo info = {0, 0, 0};
2239 
2240  /*
2241  * Figure out which attributes we're going to need.
2242  */
2243  get_last_attnums_walker(node, &info);
2244 
2245  ExecPushExprSlots(state, &info);
2246 }
static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
Definition: execExpr.c:2254
static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info)
Definition: execExpr.c:2298

◆ 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:107
ParamListInfo ext_params
Definition: execnodes.h:108
Definition: nodes.h:533
bool resnull
Definition: execnodes.h:71
Expr * expr
Definition: execnodes.h:93
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2236
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:2105
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
#define makeNode(_type_)
Definition: nodes.h:581
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:254
Datum resvalue
Definition: execnodes.h:73

◆ ExecInitFunc()

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

Definition at line 2131 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().

2133 {
2134  int nargs = list_length(args);
2135  AclResult aclresult;
2136  FmgrInfo *flinfo;
2137  FunctionCallInfo fcinfo;
2138  int argno;
2139  ListCell *lc;
2140 
2141  /* Check permission to call function */
2142  aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE);
2143  if (aclresult != ACLCHECK_OK)
2144  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid));
2145  InvokeFunctionExecuteHook(funcid);
2146 
2147  /*
2148  * Safety check on nargs. Under normal circumstances this should never
2149  * fail, as parser should check sooner. But possibly it might fail if
2150  * server has been compiled with FUNC_MAX_ARGS smaller than some functions
2151  * declared in pg_proc?
2152  */
2153  if (nargs > FUNC_MAX_ARGS)
2154  ereport(ERROR,
2155  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2156  errmsg_plural("cannot pass more than %d argument to a function",
2157  "cannot pass more than %d arguments to a function",
2158  FUNC_MAX_ARGS,
2159  FUNC_MAX_ARGS)));
2160 
2161  /* Allocate function lookup data and parameter workspace for this call */
2162  scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
2163  scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
2164  flinfo = scratch->d.func.finfo;
2165  fcinfo = scratch->d.func.fcinfo_data;
2166 
2167  /* Set up the primary fmgr lookup information */
2168  fmgr_info(funcid, flinfo);
2169  fmgr_info_set_expr((Node *) node, flinfo);
2170 
2171  /* Initialize function call parameter structure too */
2172  InitFunctionCallInfoData(*fcinfo, flinfo,
2173  nargs, inputcollid, NULL, NULL);
2174 
2175  /* Keep extra copies of this info to save an indirection at runtime */
2176  scratch->d.func.fn_addr = flinfo->fn_addr;
2177  scratch->d.func.nargs = nargs;
2178 
2179  /* We only support non-set functions here */
2180  if (flinfo->fn_retset)
2181  ereport(ERROR,
2182  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2183  errmsg("set-valued function called in context that cannot accept a set"),
2184  state->parent ?
2186  exprLocation((Node *) node)) : 0));
2187 
2188  /* Build code to evaluate arguments directly into the fcinfo struct */
2189  argno = 0;
2190  foreach(lc, args)
2191  {
2192  Expr *arg = (Expr *) lfirst(lc);
2193 
2194  if (IsA(arg, Const))
2195  {
2196  /*
2197  * Don't evaluate const arguments every round; especially
2198  * interesting for constants in comparisons.
2199  */
2200  Const *con = (Const *) arg;
2201 
2202  fcinfo->args[argno].value = con->constvalue;
2203  fcinfo->args[argno].isnull = con->constisnull;
2204  }
2205  else
2206  {
2207  ExecInitExprRec(arg, state,
2208  &fcinfo->args[argno].value,
2209  &fcinfo->args[argno].isnull);
2210  }
2211  argno++;
2212  }
2213 
2214  /* Insert appropriate opcode depending on strictness and stats level */
2215  if (pgstat_track_functions <= flinfo->fn_stats)
2216  {
2217  if (flinfo->fn_strict && nargs > 0)
2218  scratch->opcode = EEOP_FUNCEXPR_STRICT;
2219  else
2220  scratch->opcode = EEOP_FUNCEXPR;
2221  }
2222  else
2223  {
2224  if (flinfo->fn_strict && nargs > 0)
2226  else
2227  scratch->opcode = EEOP_FUNCEXPR_FUSAGE;
2228  }
2229 }
Datum constvalue
Definition: primnodes.h:214
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:584
struct PlanState * parent
Definition: execnodes.h:107
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1231
Oid GetUserId(void)
Definition: miscinit.c:478
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1015
PGFunction fn_addr
Definition: fmgr.h:58
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
Definition: nodes.h:533
int errcode(int sqlerrcode)
Definition: elog.c:694
EState * state
Definition: execnodes.h:943
#define FUNC_MAX_ARGS
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
bool fn_retset
Definition: fmgr.h:62
#define ERROR
Definition: elog.h:45
bool fn_strict
Definition: fmgr.h:61
union ExprEvalStep::@49 d
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1579
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
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void * palloc0(Size size)
Definition: mcxt.c:981
AclResult
Definition: acl.h:177
struct ExprEvalStep::@49::@56 func
#define ereport(elevel,...)
Definition: elog.h:155
int executor_errposition(EState *estate, int location)
Definition: execUtils.c:898
#define lfirst(lc)
Definition: pg_list.h:169
intptr_t opcode
Definition: execExpr.h:254
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4606
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(), ExecInitTidRangeScan(), 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:584
struct PlanState * parent
Definition: execnodes.h:107
Datum * resvalue
Definition: execExpr.h:257
struct ExprEvalStep * steps
Definition: execnodes.h:84
struct ExprEvalStep::@49::@58 qualexpr
bool * resnull
Definition: execExpr.h:258
ParamListInfo ext_params
Definition: execnodes.h:108
Definition: nodes.h:533
bool resnull
Definition: execnodes.h:71
union ExprEvalStep::@49 d
Expr * expr
Definition: execnodes.h:93
#define lfirst_int(lc)
Definition: pg_list.h:170
static void ExecInitExprSlots(ExprState *state, Node *node)
Definition: execExpr.c:2236
#define EEO_FLAG_IS_QUAL
Definition: execnodes.h:58
List * lappend_int(List *list, int datum)
Definition: list.c:354
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:2105
static void ExecReadyExpr(ExprState *state)
Definition: execExpr.c:629
#define makeNode(_type_)
Definition: nodes.h:581
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Definition: regguts.h:317
intptr_t opcode
Definition: execExpr.h:254
int steps_len
Definition: execnodes.h:103
uint8 flags
Definition: execnodes.h:64
Definition: pg_list.h:50
Datum resvalue
Definition: execnodes.h:73

◆ ExecInitSubscriptingRef()

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

Definition at line 2523 of file execExpr.c.

References Assert, ExprEvalStep::d, EEOP_JUMP_IF_NULL, EEOP_SBSREF_ASSIGN, EEOP_SBSREF_FETCH, EEOP_SBSREF_OLD, EEOP_SBSREF_SUBSCRIPTS, ereport, errcode(), errmsg(), ERROR, SubscriptRoutines::exec_setup, ExecInitExprRec(), executor_errposition(), ExprEvalPushStep(), exprLocation(), SubscriptRoutines::fetch_strict, format_type_be(), getSubscriptingRoutines(), i, ExprState::innermost_casenull, ExprState::innermost_caseval, SubscriptingRefState::isassignment, isAssignmentIndirectionExpr(), ExprEvalStep::jump, lappend_int(), lfirst, lfirst_int, list_length(), SubscriptingRefState::lowerindex, SubscriptingRefState::lowerindexnull, SubscriptingRefState::lowerprovided, MAXALIGN, NIL, SubscriptingRefState::numlower, SubscriptingRefState::numupper, ExprEvalStep::opcode, palloc0(), ExprState::parent, SubscriptingRefState::prevnull, SubscriptingRefState::prevvalue, SubscriptingRef::refassgnexpr, SubscriptingRef::refcontainertype, SubscriptingRef::reflowerindexpr, SubscriptingRef::refupperindexpr, SubscriptingRefState::replacenull, SubscriptingRefState::replacevalue, SubscriptExecSteps::sbs_assign, SubscriptExecSteps::sbs_check_subscripts, SubscriptExecSteps::sbs_fetch, SubscriptExecSteps::sbs_fetch_old, ExprEvalStep::sbsref, ExprEvalStep::sbsref_subscript, PlanState::state, ExprState::steps, ExprState::steps_len, SubscriptingRefState::upperindex, SubscriptingRefState::upperindexnull, and SubscriptingRefState::upperprovided.

Referenced by ExecInitExprRec().

2525 {
2526  bool isAssignment = (sbsref->refassgnexpr != NULL);
2527  int nupper = list_length(sbsref->refupperindexpr);
2528  int nlower = list_length(sbsref->reflowerindexpr);
2529  const SubscriptRoutines *sbsroutines;
2530  SubscriptingRefState *sbsrefstate;
2531  SubscriptExecSteps methods;
2532  char *ptr;
2533  List *adjust_jumps = NIL;
2534  ListCell *lc;
2535  int i;
2536 
2537  /* Look up the subscripting support methods */
2538  sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL);
2539  if (!sbsroutines)
2540  ereport(ERROR,
2541  (errcode(ERRCODE_DATATYPE_MISMATCH),
2542  errmsg("cannot subscript type %s because it does not support subscripting",
2543  format_type_be(sbsref->refcontainertype)),
2544  state->parent ?
2546  exprLocation((Node *) sbsref)) : 0));
2547 
2548  /* Allocate sbsrefstate, with enough space for per-subscript arrays too */
2549  sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) +
2550  (nupper + nlower) * (sizeof(Datum) +
2551  2 * sizeof(bool)));
2552 
2553  /* Fill constant fields of SubscriptingRefState */
2554  sbsrefstate->isassignment = isAssignment;
2555  sbsrefstate->numupper = nupper;
2556  sbsrefstate->numlower = nlower;
2557  /* Set up per-subscript arrays */
2558  ptr = ((char *) sbsrefstate) + MAXALIGN(sizeof(SubscriptingRefState));
2559  sbsrefstate->upperindex = (Datum *) ptr;
2560  ptr += nupper * sizeof(Datum);
2561  sbsrefstate->lowerindex = (Datum *) ptr;
2562  ptr += nlower * sizeof(Datum);
2563  sbsrefstate->upperprovided = (bool *) ptr;
2564  ptr += nupper * sizeof(bool);
2565  sbsrefstate->lowerprovided = (bool *) ptr;
2566  ptr += nlower * sizeof(bool);
2567  sbsrefstate->upperindexnull = (bool *) ptr;
2568  ptr += nupper * sizeof(bool);
2569  sbsrefstate->lowerindexnull = (bool *) ptr;
2570  /* ptr += nlower * sizeof(bool); */
2571 
2572  /*
2573  * Let the container-type-specific code have a chance. It must fill the
2574  * "methods" struct with function pointers for us to possibly use in
2575  * execution steps below; and it can optionally set up some data pointed
2576  * to by the workspace field.
2577  */
2578  memset(&methods, 0, sizeof(methods));
2579  sbsroutines->exec_setup(sbsref, sbsrefstate, &methods);
2580 
2581  /*
2582  * Evaluate array input. It's safe to do so into resv/resnull, because we
2583  * won't use that as target for any of the other subexpressions, and it'll
2584  * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
2585  * pushed last.
2586  */
2587  ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
2588 
2589  /*
2590  * If refexpr yields NULL, and the operation should be strict, then result
2591  * is NULL. We can implement this with just JUMP_IF_NULL, since we
2592  * evaluated the array into the desired target location.
2593  */
2594  if (!isAssignment && sbsroutines->fetch_strict)
2595  {
2596  scratch->opcode = EEOP_JUMP_IF_NULL;
2597  scratch->d.jump.jumpdone = -1; /* adjust later */
2598  ExprEvalPushStep(state, scratch);
2599  adjust_jumps = lappend_int(adjust_jumps,
2600  state->steps_len - 1);
2601  }
2602 
2603  /* Evaluate upper subscripts */
2604  i = 0;
2605  foreach(lc, sbsref->refupperindexpr)
2606  {
2607  Expr *e = (Expr *) lfirst(lc);
2608 
2609  /* When slicing, individual subscript bounds can be omitted */
2610  if (!e)
2611  {
2612  sbsrefstate->upperprovided[i] = false;
2613  sbsrefstate->upperindexnull[i] = true;
2614  }
2615  else
2616  {
2617  sbsrefstate->upperprovided[i] = true;
2618  /* Each subscript is evaluated into appropriate array entry */
2619  ExecInitExprRec(e, state,
2620  &sbsrefstate->upperindex[i],
2621  &sbsrefstate->upperindexnull[i]);
2622  }
2623  i++;
2624  }
2625 
2626  /* Evaluate lower subscripts similarly */
2627  i = 0;
2628  foreach(lc, sbsref->reflowerindexpr)
2629  {
2630  Expr *e = (Expr *) lfirst(lc);
2631 
2632  /* When slicing, individual subscript bounds can be omitted */
2633  if (!e)
2634  {
2635  sbsrefstate->lowerprovided[i] = false;
2636  sbsrefstate->lowerindexnull[i] = true;
2637  }
2638  else
2639  {
2640  sbsrefstate->lowerprovided[i] = true;
2641  /* Each subscript is evaluated into appropriate array entry */
2642  ExecInitExprRec(e, state,
2643  &sbsrefstate->lowerindex[i],
2644  &sbsrefstate->lowerindexnull[i]);
2645  }
2646  i++;
2647  }
2648 
2649  /* SBSREF_SUBSCRIPTS checks and converts all the subscripts at once */
2650  if (methods.sbs_check_subscripts)
2651  {
2652  scratch->opcode = EEOP_SBSREF_SUBSCRIPTS;
2653  scratch->d.sbsref_subscript.subscriptfunc = methods.sbs_check_subscripts;
2654  scratch->d.sbsref_subscript.state = sbsrefstate;
2655  scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */
2656  ExprEvalPushStep(state, scratch);
2657  adjust_jumps = lappend_int(adjust_jumps,
2658  state->steps_len - 1);
2659  }
2660 
2661  if (isAssignment)
2662  {
2663  Datum *save_innermost_caseval;
2664  bool *save_innermost_casenull;
2665 
2666  /* Check for unimplemented methods */
2667  if (!methods.sbs_assign)
2668  ereport(ERROR,
2669  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2670  errmsg("type %s does not support subscripted assignment",
2671  format_type_be(sbsref->refcontainertype))));
2672 
2673  /*
2674  * We might have a nested-assignment situation, in which the
2675  * refassgnexpr is itself a FieldStore or SubscriptingRef that needs
2676  * to obtain and modify the previous value of the array element or
2677  * slice being replaced. If so, we have to extract that value from
2678  * the array and pass it down via the CaseTestExpr mechanism. It's
2679  * safe to reuse the CASE mechanism because there cannot be a CASE
2680  * between here and where the value would be needed, and an array
2681  * assignment can't be within a CASE either. (So saving and restoring
2682  * innermost_caseval is just paranoia, but let's do it anyway.)
2683  *
2684  * Since fetching the old element might be a nontrivial expense, do it
2685  * only if the argument actually needs it.
2686  */
2688  {
2689  if (!methods.sbs_fetch_old)
2690  ereport(ERROR,
2691  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2692  errmsg("type %s does not support subscripted assignment",
2693  format_type_be(sbsref->refcontainertype))));
2694  scratch->opcode = EEOP_SBSREF_OLD;
2695  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch_old;
2696  scratch->d.sbsref.state = sbsrefstate;
2697  ExprEvalPushStep(state, scratch);
2698  }
2699 
2700  /* SBSREF_OLD puts extracted value into prevvalue/prevnull */
2701  save_innermost_caseval = state->innermost_caseval;
2702  save_innermost_casenull = state->innermost_casenull;
2703  state->innermost_caseval = &sbsrefstate->prevvalue;
2704  state->innermost_casenull = &sbsrefstate->prevnull;
2705 
2706  /* evaluate replacement value into replacevalue/replacenull */
2707  ExecInitExprRec(sbsref->refassgnexpr, state,
2708  &sbsrefstate->replacevalue, &sbsrefstate->replacenull);
2709 
2710  state->innermost_caseval = save_innermost_caseval;
2711  state->innermost_casenull = save_innermost_casenull;
2712 
2713  /* and perform the assignment */
2714  scratch->opcode = EEOP_SBSREF_ASSIGN;
2715  scratch->d.sbsref.subscriptfunc = methods.sbs_assign;
2716  scratch->d.sbsref.state = sbsrefstate;
2717  ExprEvalPushStep(state, scratch);
2718  }
2719  else
2720  {
2721  /* array fetch is much simpler */
2722  scratch->opcode = EEOP_SBSREF_FETCH;
2723  scratch->d.sbsref.subscriptfunc = methods.sbs_fetch;
2724  scratch->d.sbsref.state = sbsrefstate;
2725  ExprEvalPushStep(state, scratch);
2726  }
2727 
2728  /* adjust jump targets */
2729  foreach(lc, adjust_jumps)
2730  {
2731  ExprEvalStep *as = &state->steps[lfirst_int(lc)];
2732 
2733  if (as->opcode == EEOP_SBSREF_SUBSCRIPTS)
2734  {
2735  Assert(as->d.sbsref_subscript.jumpdone == -1);
2736  as->d.sbsref_subscript.jumpdone = state->steps_len;
2737  }
2738  else
2739  {
2741  Assert(as->d.jump.jumpdone == -1);
2742  as->d.jump.jumpdone = state->steps_len;
2743  }
2744  }
2745 }
#define NIL
Definition: pg_list.h:65
struct PlanState * parent
Definition: execnodes.h:107
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1231
struct ExprEvalStep * steps
Definition: execnodes.h:84
SubscriptExecSetup exec_setup
Definition: subscripting.h:161
bool * innermost_casenull
Definition: execnodes.h:111
ExecEvalSubroutine sbs_fetch
Definition: execExpr.h:678
static bool isAssignmentIndirectionExpr(Expr *expr)
Definition: execExpr.c:2762
Definition: nodes.h:533
int errcode(int sqlerrcode)
Definition: elog.c:694
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
ExecEvalSubroutine sbs_fetch_old
Definition: execExpr.h:680
EState * state
Definition: execnodes.h:943
ExecEvalSubroutine sbs_assign
Definition: execExpr.h:679
List * refupperindexpr
Definition: primnodes.h:439
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3077
#define ERROR
Definition: elog.h:45
union ExprEvalStep::@49 d
#define lfirst_int(lc)
Definition: pg_list.h:170
Datum * innermost_caseval
Definition: execnodes.h:110
struct ExprEvalStep::@49::@76 sbsref_subscript
List * lappend_int(List *list, int datum)
Definition: list.c:354
static void ExecInitExprRec(Expr *node, ExprState *state, Datum *resv, bool *resnull)
Definition: execExpr.c:646
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2105
#define ereport(elevel,...)
Definition: elog.h:155
int executor_errposition(EState *estate, int location)
Definition: execUtils.c:898
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
intptr_t opcode
Definition: execExpr.h:254
static int list_length(const List *l)
Definition: pg_list.h:149
#define MAXALIGN(LEN)
Definition: c.h:757
struct ExprEvalStep::@49::@77 sbsref
struct ExprEvalStep::@49::@59 jump
Expr * refassgnexpr
Definition: primnodes.h:446
e
Definition: preproc-init.c:82
int errmsg(const char *fmt,...)
Definition: elog.c:905
int steps_len
Definition: execnodes.h:103
List * reflowerindexpr
Definition: primnodes.h:441
int i
Oid refcontainertype
Definition: primnodes.h:434
Expr * refexpr
Definition: primnodes.h:444
ExecEvalBoolSubroutine sbs_check_subscripts
Definition: execExpr.h:677
Definition: pg_list.h:50
unsigned char bool
Definition: c.h:391

◆ ExecInitWholeRowVar()

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

Definition at line 2450 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().

2451 {
2452  PlanState *parent = state->parent;
2453 
2454  /* fill in all but the target */
2455  scratch->opcode = EEOP_WHOLEROW;
2456  scratch->d.wholerow.var = variable;
2457  scratch->d.wholerow.first = true;
2458  scratch->d.wholerow.slow = false;
2459  scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */
2460  scratch->d.wholerow.junkFilter = NULL;
2461 
2462  /*
2463  * If the input tuple came from a subquery, it might contain "resjunk"
2464  * columns (such as GROUP BY or ORDER BY columns), which we don't want to
2465  * keep in the whole-row result. We can get rid of such columns by
2466  * passing the tuple through a JunkFilter --- but to make one, we have to
2467  * lay our hands on the subquery's targetlist. Fortunately, there are not
2468  * very many cases where this can happen, and we can identify all of them
2469  * by examining our parent PlanState. We assume this is not an issue in
2470  * standalone expressions that don't have parent plans. (Whole-row Vars
2471  * can occur in such expressions, but they will always be referencing
2472  * table rows.)
2473  */
2474  if (parent)
2475  {
2476  PlanState *subplan = NULL;
2477 
2478  switch (nodeTag(parent))
2479  {
2480  case T_SubqueryScanState:
2481  subplan = ((SubqueryScanState *) parent)->subplan;
2482  break;
2483  case T_CteScanState:
2484  subplan = ((CteScanState *) parent)->cteplanstate;
2485  break;
2486  default:
2487  break;
2488  }
2489 
2490  if (subplan)
2491  {
2492  bool junk_filter_needed = false;
2493  ListCell *tlist;
2494 
2495  /* Detect whether subplan tlist actually has any junk columns */
2496  foreach(tlist, subplan->plan->targetlist)
2497  {
2498  TargetEntry *tle = (TargetEntry *) lfirst(tlist);
2499 
2500  if (tle->resjunk)
2501  {
2502  junk_filter_needed = true;
2503  break;
2504  }
2505  }
2506 
2507  /* If so, build the junkfilter now */
2508  if (junk_filter_needed)
2509  {
2510  scratch->d.wholerow.junkFilter =
2512  ExecInitExtraTupleSlot(parent->state, NULL,
2513  &TTSOpsVirtual));
2514  }
2515  }
2516  }
2517 }
struct ExprEvalStep::@49::@52 wholerow
struct PlanState * parent
Definition: execnodes.h:107
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:943
bool resjunk
Definition: primnodes.h:1438
union ExprEvalStep::@49 d
Plan * plan
Definition: execnodes.h:941
#define lfirst(lc)
Definition: pg_list.h:169
intptr_t opcode
Definition: execExpr.h:254
#define nodeTag(nodeptr)
Definition: nodes.h:538
List * targetlist
Definition: plannodes.h:136
struct variable * variable
Definition: type.h:173
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:6165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:572
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(), 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:6165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext es_query_cxt
Definition: execnodes.h:572
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:572
List * lappend(List *list, void *datum)
Definition: list.c:336
#define lfirst(lc)
Definition: pg_list.h:169
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:6165
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:572
Definition: pg_list.h:50

◆ ExecPushExprSlots()

static void ExecPushExprSlots ( ExprState state,
LastAttnumInfo info 
)
static

Definition at line 2254 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().

2255 {
2256  ExprEvalStep scratch = {0};
2257 
2258  scratch.resvalue = NULL;
2259  scratch.resnull = NULL;
2260 
2261  /* Emit steps as needed */
2262  if (info->last_inner > 0)
2263  {
2264  scratch.opcode = EEOP_INNER_FETCHSOME;
2265  scratch.d.fetch.last_var = info->last_inner;
2266  scratch.d.fetch.fixed = false;
2267  scratch.d.fetch.kind = NULL;
2268  scratch.d.fetch.known_desc = NULL;
2269  if (ExecComputeSlotInfo(state, &scratch))
2270  ExprEvalPushStep(state, &scratch);
2271  }
2272  if (info->last_outer > 0)
2273  {
2274  scratch.opcode = EEOP_OUTER_FETCHSOME;
2275  scratch.d.fetch.last_var = info->last_outer;
2276  scratch.d.fetch.fixed = false;
2277  scratch.d.fetch.kind = NULL;
2278  scratch.d.fetch.known_desc = NULL;
2279  if (ExecComputeSlotInfo(state, &scratch))
2280  ExprEvalPushStep(state, &scratch);
2281  }
2282  if (info->last_scan > 0)
2283  {
2284  scratch.opcode = EEOP_SCAN_FETCHSOME;
2285  scratch.d.fetch.last_var = info->last_scan;
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 }
Datum * resvalue
Definition: execExpr.h:257
struct ExprEvalStep::@49::@50 fetch
bool * resnull
Definition: execExpr.h:258
union ExprEvalStep::@49 d
AttrNumber last_scan
Definition: execExpr.c:58
AttrNumber last_inner
Definition: execExpr.c:56
AttrNumber last_outer
Definition: execExpr.c:57
static bool ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
Definition: execExpr.c:2352
void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s)
Definition: execExpr.c:2105
intptr_t opcode
Definition: execExpr.h:254

◆ 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 2105 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().

2106 {
2107  if (es->steps_alloc == 0)
2108  {
2109  es->steps_alloc = 16;
2110  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2111  }
2112  else if (es->steps_alloc == es->steps_len)
2113  {
2114  es->steps_alloc *= 2;
2115  es->steps = repalloc(es->steps,
2116  sizeof(ExprEvalStep) * es->steps_alloc);
2117  }
2118 
2119  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2120 }
struct ExprEvalStep * steps
Definition: execnodes.h:84
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
int steps_alloc
Definition: execnodes.h:104
void * palloc(Size size)
Definition: mcxt.c:950
int steps_len
Definition: execnodes.h:103

◆ get_last_attnums_walker()

static bool get_last_attnums_walker ( Node node,
LastAttnumInfo info 
)
static

Definition at line 2298 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().

2299 {
2300  if (node == NULL)
2301  return false;
2302  if (IsA(node, Var))
2303  {
2304  Var *variable = (Var *) node;
2305  AttrNumber attnum = variable->varattno;
2306 
2307  switch (variable->varno)
2308  {
2309  case INNER_VAR:
2310  info->last_inner = Max(info->last_inner, attnum);
2311  break;
2312 
2313  case OUTER_VAR:
2314  info->last_outer = Max(info->last_outer, attnum);
2315  break;
2316 
2317  /* INDEX_VAR is handled by default case */
2318 
2319  default:
2320  info->last_scan = Max(info->last_scan, attnum);
2321  break;
2322  }
2323  return false;
2324  }
2325 
2326  /*
2327  * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2328  * because those do not represent expressions to be evaluated within the
2329  * calling expression's econtext. GroupingFunc arguments are never
2330  * evaluated at all.
2331  */
2332  if (IsA(node, Aggref))
2333  return false;
2334  if (IsA(node, WindowFunc))
2335  return false;
2336  if (IsA(node, GroupingFunc))
2337  return false;
2339  (void *) info);
2340 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:584
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
AttrNumber last_scan<