PostgreSQL Source Code  git master
execExpr.h File Reference
#include "executor/nodeAgg.h"
#include "nodes/execnodes.h"
#include "nodes/miscnodes.h"
Include dependency graph for execExpr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ExprEvalRowtypeCache
 
struct  ExprEvalStep
 
struct  SubscriptingRefState
 
struct  SubscriptExecSteps
 
struct  JsonConstructorExprState
 

Macros

#define EEO_FLAG_INTERPRETER_INITIALIZED   (1 << 1)
 
#define EEO_FLAG_DIRECT_THREADED   (1 << 2)
 

Typedefs

typedef void(* ExecEvalSubroutine) (ExprState *state, struct ExprEvalStep *op, ExprContext *econtext)
 
typedef bool(* ExecEvalBoolSubroutine) (ExprState *state, struct ExprEvalStep *op, ExprContext *econtext)
 
typedef struct ExprEvalRowtypeCache ExprEvalRowtypeCache
 
typedef enum ExprEvalOp ExprEvalOp
 
typedef struct ExprEvalStep ExprEvalStep
 
typedef struct SubscriptingRefState SubscriptingRefState
 
typedef struct SubscriptExecSteps SubscriptExecSteps
 
typedef struct JsonConstructorExprState JsonConstructorExprState
 

Enumerations

enum  ExprEvalOp {
  EEOP_DONE , EEOP_INNER_FETCHSOME , EEOP_OUTER_FETCHSOME , EEOP_SCAN_FETCHSOME ,
  EEOP_INNER_VAR , EEOP_OUTER_VAR , EEOP_SCAN_VAR , EEOP_INNER_SYSVAR ,
  EEOP_OUTER_SYSVAR , EEOP_SCAN_SYSVAR , EEOP_WHOLEROW , EEOP_ASSIGN_INNER_VAR ,
  EEOP_ASSIGN_OUTER_VAR , EEOP_ASSIGN_SCAN_VAR , EEOP_ASSIGN_TMP , EEOP_ASSIGN_TMP_MAKE_RO ,
  EEOP_CONST , EEOP_FUNCEXPR , EEOP_FUNCEXPR_STRICT , EEOP_FUNCEXPR_FUSAGE ,
  EEOP_FUNCEXPR_STRICT_FUSAGE , EEOP_BOOL_AND_STEP_FIRST , EEOP_BOOL_AND_STEP , EEOP_BOOL_AND_STEP_LAST ,
  EEOP_BOOL_OR_STEP_FIRST , EEOP_BOOL_OR_STEP , EEOP_BOOL_OR_STEP_LAST , EEOP_BOOL_NOT_STEP ,
  EEOP_QUAL , EEOP_JUMP , EEOP_JUMP_IF_NULL , EEOP_JUMP_IF_NOT_NULL ,
  EEOP_JUMP_IF_NOT_TRUE , EEOP_NULLTEST_ISNULL , EEOP_NULLTEST_ISNOTNULL , EEOP_NULLTEST_ROWISNULL ,
  EEOP_NULLTEST_ROWISNOTNULL , EEOP_BOOLTEST_IS_TRUE , EEOP_BOOLTEST_IS_NOT_TRUE , EEOP_BOOLTEST_IS_FALSE ,
  EEOP_BOOLTEST_IS_NOT_FALSE , EEOP_PARAM_EXEC , EEOP_PARAM_EXTERN , EEOP_PARAM_CALLBACK ,
  EEOP_PARAM_SET , EEOP_CASE_TESTVAL , EEOP_MAKE_READONLY , EEOP_IOCOERCE ,
  EEOP_IOCOERCE_SAFE , EEOP_DISTINCT , EEOP_NOT_DISTINCT , EEOP_NULLIF ,
  EEOP_SQLVALUEFUNCTION , EEOP_CURRENTOFEXPR , EEOP_NEXTVALUEEXPR , EEOP_ARRAYEXPR ,
  EEOP_ARRAYCOERCE , EEOP_ROW , EEOP_ROWCOMPARE_STEP , EEOP_ROWCOMPARE_FINAL ,
  EEOP_MINMAX , EEOP_FIELDSELECT , EEOP_FIELDSTORE_DEFORM , EEOP_FIELDSTORE_FORM ,
  EEOP_SBSREF_SUBSCRIPTS , EEOP_SBSREF_OLD , EEOP_SBSREF_ASSIGN , EEOP_SBSREF_FETCH ,
  EEOP_DOMAIN_TESTVAL , EEOP_DOMAIN_NOTNULL , EEOP_DOMAIN_CHECK , EEOP_HASHDATUM_SET_INITVAL ,
  EEOP_HASHDATUM_FIRST , EEOP_HASHDATUM_FIRST_STRICT , EEOP_HASHDATUM_NEXT32 , EEOP_HASHDATUM_NEXT32_STRICT ,
  EEOP_CONVERT_ROWTYPE , EEOP_SCALARARRAYOP , EEOP_HASHED_SCALARARRAYOP , EEOP_XMLEXPR ,
  EEOP_JSON_CONSTRUCTOR , EEOP_IS_JSON , EEOP_JSONEXPR_PATH , EEOP_JSONEXPR_COERCION ,
  EEOP_JSONEXPR_COERCION_FINISH , EEOP_AGGREF , EEOP_GROUPING_FUNC , EEOP_WINDOW_FUNC ,
  EEOP_MERGE_SUPPORT_FUNC , EEOP_SUBPLAN , EEOP_AGG_STRICT_DESERIALIZE , EEOP_AGG_DESERIALIZE ,
  EEOP_AGG_STRICT_INPUT_CHECK_ARGS , EEOP_AGG_STRICT_INPUT_CHECK_NULLS , EEOP_AGG_PLAIN_PERGROUP_NULLCHECK , EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ,
  EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL , EEOP_AGG_PLAIN_TRANS_BYVAL , EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF , EEOP_AGG_PLAIN_TRANS_STRICT_BYREF ,
  EEOP_AGG_PLAIN_TRANS_BYREF , EEOP_AGG_PRESORTED_DISTINCT_SINGLE , EEOP_AGG_PRESORTED_DISTINCT_MULTI , EEOP_AGG_ORDERED_TRANS_DATUM ,
  EEOP_AGG_ORDERED_TRANS_TUPLE , EEOP_LAST
}
 

Functions

 StaticAssertDecl (sizeof(ExprEvalStep)<=64, "size of ExprEvalStep exceeds 64 bytes")
 
void ExprEvalPushStep (ExprState *es, const ExprEvalStep *s)
 
void ExecReadyInterpretedExpr (ExprState *state)
 
ExprEvalOp ExecEvalStepOp (ExprState *state, ExprEvalStep *op)
 
Datum ExecInterpExprStillValid (ExprState *state, ExprContext *econtext, bool *isNull)
 
void CheckExprStillValid (ExprState *state, ExprContext *econtext)
 
void ExecEvalFuncExprFusage (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalFuncExprStrictFusage (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalParamExec (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalParamSet (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalParamExtern (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalCoerceViaIOSafe (ExprState *state, ExprEvalStep *op)
 
void ExecEvalSQLValueFunction (ExprState *state, ExprEvalStep *op)
 
void ExecEvalCurrentOfExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalNextValueExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalRowNull (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalRowNotNull (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalArrayExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalArrayCoerce (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalRow (ExprState *state, ExprEvalStep *op)
 
void ExecEvalMinMax (ExprState *state, ExprEvalStep *op)
 
void ExecEvalFieldSelect (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalFieldStoreDeForm (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalFieldStoreForm (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalConvertRowtype (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalScalarArrayOp (ExprState *state, ExprEvalStep *op)
 
void ExecEvalHashedScalarArrayOp (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalConstraintNotNull (ExprState *state, ExprEvalStep *op)
 
void ExecEvalConstraintCheck (ExprState *state, ExprEvalStep *op)
 
void ExecEvalXmlExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalJsonConstructor (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalJsonIsPredicate (ExprState *state, ExprEvalStep *op)
 
int ExecEvalJsonExprPath (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalJsonCoercion (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalJsonCoercionFinish (ExprState *state, ExprEvalStep *op)
 
void ExecEvalGroupingFunc (ExprState *state, ExprEvalStep *op)
 
void ExecEvalMergeSupportFunc (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalSubPlan (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalWholeRowVar (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalSysVar (ExprState *state, ExprEvalStep *op, ExprContext *econtext, TupleTableSlot *slot)
 
void ExecAggInitGroup (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext)
 
Datum ExecAggCopyTransValue (AggState *aggstate, AggStatePerTrans pertrans, Datum newValue, bool newValueIsNull, Datum oldValue, bool oldValueIsNull)
 
bool ExecEvalPreOrderedDistinctSingle (AggState *aggstate, AggStatePerTrans pertrans)
 
bool ExecEvalPreOrderedDistinctMulti (AggState *aggstate, AggStatePerTrans pertrans)
 
void ExecEvalAggOrderedTransDatum (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalAggOrderedTransTuple (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 

Macro Definition Documentation

◆ EEO_FLAG_DIRECT_THREADED

#define EEO_FLAG_DIRECT_THREADED   (1 << 2)

Definition at line 31 of file execExpr.h.

◆ EEO_FLAG_INTERPRETER_INITIALIZED

#define EEO_FLAG_INTERPRETER_INITIALIZED   (1 << 1)

Definition at line 29 of file execExpr.h.

Typedef Documentation

◆ ExecEvalBoolSubroutine

typedef bool(* ExecEvalBoolSubroutine) (ExprState *state, struct ExprEvalStep *op, ExprContext *econtext)

Definition at line 39 of file execExpr.h.

◆ ExecEvalSubroutine

typedef void(* ExecEvalSubroutine) (ExprState *state, struct ExprEvalStep *op, ExprContext *econtext)

Definition at line 34 of file execExpr.h.

◆ ExprEvalOp

typedef enum ExprEvalOp ExprEvalOp

◆ ExprEvalRowtypeCache

◆ ExprEvalStep

typedef struct ExprEvalStep ExprEvalStep

◆ JsonConstructorExprState

◆ SubscriptExecSteps

◆ SubscriptingRefState

Enumeration Type Documentation

◆ ExprEvalOp

enum ExprEvalOp
Enumerator
EEOP_DONE 
EEOP_INNER_FETCHSOME 
EEOP_OUTER_FETCHSOME 
EEOP_SCAN_FETCHSOME 
EEOP_INNER_VAR 
EEOP_OUTER_VAR 
EEOP_SCAN_VAR 
EEOP_INNER_SYSVAR 
EEOP_OUTER_SYSVAR 
EEOP_SCAN_SYSVAR 
EEOP_WHOLEROW 
EEOP_ASSIGN_INNER_VAR 
EEOP_ASSIGN_OUTER_VAR 
EEOP_ASSIGN_SCAN_VAR 
EEOP_ASSIGN_TMP 
EEOP_ASSIGN_TMP_MAKE_RO 
EEOP_CONST 
EEOP_FUNCEXPR 
EEOP_FUNCEXPR_STRICT 
EEOP_FUNCEXPR_FUSAGE 
EEOP_FUNCEXPR_STRICT_FUSAGE 
EEOP_BOOL_AND_STEP_FIRST 
EEOP_BOOL_AND_STEP 
EEOP_BOOL_AND_STEP_LAST 
EEOP_BOOL_OR_STEP_FIRST 
EEOP_BOOL_OR_STEP 
EEOP_BOOL_OR_STEP_LAST 
EEOP_BOOL_NOT_STEP 
EEOP_QUAL 
EEOP_JUMP 
EEOP_JUMP_IF_NULL 
EEOP_JUMP_IF_NOT_NULL 
EEOP_JUMP_IF_NOT_TRUE 
EEOP_NULLTEST_ISNULL 
EEOP_NULLTEST_ISNOTNULL 
EEOP_NULLTEST_ROWISNULL 
EEOP_NULLTEST_ROWISNOTNULL 
EEOP_BOOLTEST_IS_TRUE 
EEOP_BOOLTEST_IS_NOT_TRUE 
EEOP_BOOLTEST_IS_FALSE 
EEOP_BOOLTEST_IS_NOT_FALSE 
EEOP_PARAM_EXEC 
EEOP_PARAM_EXTERN 
EEOP_PARAM_CALLBACK 
EEOP_PARAM_SET 
EEOP_CASE_TESTVAL 
EEOP_MAKE_READONLY 
EEOP_IOCOERCE 
EEOP_IOCOERCE_SAFE 
EEOP_DISTINCT 
EEOP_NOT_DISTINCT 
EEOP_NULLIF 
EEOP_SQLVALUEFUNCTION 
EEOP_CURRENTOFEXPR 
EEOP_NEXTVALUEEXPR 
EEOP_ARRAYEXPR 
EEOP_ARRAYCOERCE 
EEOP_ROW 
EEOP_ROWCOMPARE_STEP 
EEOP_ROWCOMPARE_FINAL 
EEOP_MINMAX 
EEOP_FIELDSELECT 
EEOP_FIELDSTORE_DEFORM 
EEOP_FIELDSTORE_FORM 
EEOP_SBSREF_SUBSCRIPTS 
EEOP_SBSREF_OLD 
EEOP_SBSREF_ASSIGN 
EEOP_SBSREF_FETCH 
EEOP_DOMAIN_TESTVAL 
EEOP_DOMAIN_NOTNULL 
EEOP_DOMAIN_CHECK 
EEOP_HASHDATUM_SET_INITVAL 
EEOP_HASHDATUM_FIRST 
EEOP_HASHDATUM_FIRST_STRICT 
EEOP_HASHDATUM_NEXT32 
EEOP_HASHDATUM_NEXT32_STRICT 
EEOP_CONVERT_ROWTYPE 
EEOP_SCALARARRAYOP 
EEOP_HASHED_SCALARARRAYOP 
EEOP_XMLEXPR 
EEOP_JSON_CONSTRUCTOR 
EEOP_IS_JSON 
EEOP_JSONEXPR_PATH 
EEOP_JSONEXPR_COERCION 
EEOP_JSONEXPR_COERCION_FINISH 
EEOP_AGGREF 
EEOP_GROUPING_FUNC 
EEOP_WINDOW_FUNC 
EEOP_MERGE_SUPPORT_FUNC 
EEOP_SUBPLAN 
EEOP_AGG_STRICT_DESERIALIZE 
EEOP_AGG_DESERIALIZE 
EEOP_AGG_STRICT_INPUT_CHECK_ARGS 
EEOP_AGG_STRICT_INPUT_CHECK_NULLS 
EEOP_AGG_PLAIN_PERGROUP_NULLCHECK 
EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL 
EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL 
EEOP_AGG_PLAIN_TRANS_BYVAL 
EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF 
EEOP_AGG_PLAIN_TRANS_STRICT_BYREF 
EEOP_AGG_PLAIN_TRANS_BYREF 
EEOP_AGG_PRESORTED_DISTINCT_SINGLE 
EEOP_AGG_PRESORTED_DISTINCT_MULTI 
EEOP_AGG_ORDERED_TRANS_DATUM 
EEOP_AGG_ORDERED_TRANS_TUPLE 
EEOP_LAST 

Definition at line 66 of file execExpr.h.

67 {
68  /* entire expression has been evaluated completely, return */
69  EEOP_DONE,
70 
71  /* apply slot_getsomeattrs on corresponding tuple slot */
75 
76  /* compute non-system Var value */
80 
81  /* compute system Var value */
85 
86  /* compute wholerow Var */
88 
89  /*
90  * Compute non-system Var value, assign it into ExprState's resultslot.
91  * These are not used if a CheckVarSlotCompatibility() check would be
92  * needed.
93  */
97 
98  /* assign ExprState's resvalue/resnull to a column of its resultslot */
100  /* ditto, applying MakeExpandedObjectReadOnly() */
102 
103  /* evaluate Const value */
104  EEOP_CONST,
105 
106  /*
107  * Evaluate function call (including OpExprs etc). For speed, we
108  * distinguish in the opcode whether the function is strict and/or
109  * requires usage stats tracking.
110  */
115 
116  /*
117  * Evaluate boolean AND expression, one step per subexpression. FIRST/LAST
118  * subexpressions are special-cased for performance. Since AND always has
119  * at least two subexpressions, FIRST and LAST never apply to the same
120  * subexpression.
121  */
125 
126  /* similarly for boolean OR expression */
130 
131  /* evaluate boolean NOT expression */
133 
134  /* simplified version of BOOL_AND_STEP for use by ExecQual() */
135  EEOP_QUAL,
136 
137  /* unconditional jump to another step */
138  EEOP_JUMP,
139 
140  /* conditional jumps based on current result value */
144 
145  /* perform NULL tests for scalar values */
148 
149  /* perform NULL tests for row values */
152 
153  /* evaluate a BooleanTest expression */
158 
159  /* evaluate PARAM_EXEC/EXTERN parameters */
163  /* set PARAM_EXEC value */
165 
166  /* return CaseTestExpr value */
168 
169  /* apply MakeExpandedObjectReadOnly() to target value */
171 
172  /* evaluate assorted special-purpose expression types */
177  EEOP_NULLIF,
183  EEOP_ROW,
184 
185  /*
186  * Compare two individual elements of each of two compared ROW()
187  * expressions. Skip to ROWCOMPARE_FINAL if elements are not equal.
188  */
190 
191  /* evaluate boolean value based on previous ROWCOMPARE_STEP operations */
193 
194  /* evaluate GREATEST() or LEAST() */
195  EEOP_MINMAX,
196 
197  /* evaluate FieldSelect expression */
199 
200  /*
201  * Deform tuple before evaluating new values for individual fields in a
202  * FieldStore expression.
203  */
205 
206  /*
207  * Form the new tuple for a FieldStore expression. Individual fields will
208  * have been evaluated into columns of the tuple deformed by the preceding
209  * DEFORM step.
210  */
212 
213  /* Process container subscripts; possibly short-circuit result to NULL */
215 
216  /*
217  * Compute old container element/slice when a SubscriptingRef assignment
218  * expression contains SubscriptingRef/FieldStore subexpressions. Value is
219  * accessed using the CaseTest mechanism.
220  */
222 
223  /* compute new value for SubscriptingRef assignment expression */
225 
226  /* compute element/slice for SubscriptingRef fetch expression */
228 
229  /* evaluate value for CoerceToDomainValue */
231 
232  /* evaluate a domain's NOT NULL constraint */
234 
235  /* evaluate a single domain CHECK constraint */
237 
238  /* evaluation steps for hashing */
244 
245  /* evaluate assorted special-purpose expression types */
249  EEOP_XMLEXPR,
251  EEOP_IS_JSON,
255  EEOP_AGGREF,
259  EEOP_SUBPLAN,
260 
261  /* aggregation related nodes */
277 
278  /* non-existent operation, used e.g. to check array lengths */
279  EEOP_LAST
280 } ExprEvalOp;
ExprEvalOp
Definition: execExpr.h:67
@ EEOP_ASSIGN_TMP
Definition: execExpr.h:99
@ EEOP_SUBPLAN
Definition: execExpr.h:259
@ EEOP_CONVERT_ROWTYPE
Definition: execExpr.h:246
@ EEOP_FUNCEXPR_STRICT_FUSAGE
Definition: execExpr.h:114
@ EEOP_ARRAYEXPR
Definition: execExpr.h:181
@ EEOP_JSONEXPR_PATH
Definition: execExpr.h:252
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:176
@ EEOP_DOMAIN_TESTVAL
Definition: execExpr.h:230
@ EEOP_PARAM_EXTERN
Definition: execExpr.h:161
@ EEOP_HASHDATUM_NEXT32_STRICT
Definition: execExpr.h:243
@ EEOP_IOCOERCE_SAFE
Definition: execExpr.h:174
@ EEOP_BOOL_AND_STEP
Definition: execExpr.h:123
@ EEOP_WHOLEROW
Definition: execExpr.h:87
@ EEOP_JSONEXPR_COERCION_FINISH
Definition: execExpr.h:254
@ EEOP_HASHDATUM_FIRST_STRICT
Definition: execExpr.h:241
@ EEOP_AGGREF
Definition: execExpr.h:255
@ EEOP_INNER_VAR
Definition: execExpr.h:77
@ EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
Definition: execExpr.h:266
@ EEOP_HASHDATUM_NEXT32
Definition: execExpr.h:242
@ EEOP_ROWCOMPARE_FINAL
Definition: execExpr.h:192
@ EEOP_AGG_STRICT_DESERIALIZE
Definition: execExpr.h:262
@ EEOP_IOCOERCE
Definition: execExpr.h:173
@ EEOP_GROUPING_FUNC
Definition: execExpr.h:256
@ EEOP_DOMAIN_CHECK
Definition: execExpr.h:236
@ EEOP_BOOLTEST_IS_NOT_FALSE
Definition: execExpr.h:157
@ EEOP_PARAM_SET
Definition: execExpr.h:164
@ EEOP_NEXTVALUEEXPR
Definition: execExpr.h:180
@ EEOP_DONE
Definition: execExpr.h:69
@ EEOP_AGG_PLAIN_TRANS_BYREF
Definition: execExpr.h:272
@ EEOP_QUAL
Definition: execExpr.h:135
@ EEOP_AGG_PRESORTED_DISTINCT_MULTI
Definition: execExpr.h:274
@ EEOP_AGG_PLAIN_TRANS_BYVAL
Definition: execExpr.h:269
@ EEOP_SCAN_VAR
Definition: execExpr.h:79
@ EEOP_BOOL_NOT_STEP
Definition: execExpr.h:132
@ EEOP_ASSIGN_SCAN_VAR
Definition: execExpr.h:96
@ EEOP_SCAN_SYSVAR
Definition: execExpr.h:84
@ EEOP_SCALARARRAYOP
Definition: execExpr.h:247
@ EEOP_DOMAIN_NOTNULL
Definition: execExpr.h:233
@ EEOP_WINDOW_FUNC
Definition: execExpr.h:257
@ EEOP_INNER_FETCHSOME
Definition: execExpr.h:72
@ EEOP_NULLTEST_ROWISNOTNULL
Definition: execExpr.h:151
@ EEOP_ASSIGN_OUTER_VAR
Definition: execExpr.h:95
@ EEOP_ROW
Definition: execExpr.h:183
@ EEOP_MAKE_READONLY
Definition: execExpr.h:170
@ EEOP_FIELDSTORE_FORM
Definition: execExpr.h:211
@ EEOP_SBSREF_SUBSCRIPTS
Definition: execExpr.h:214
@ EEOP_SBSREF_FETCH
Definition: execExpr.h:227
@ EEOP_FUNCEXPR_STRICT
Definition: execExpr.h:112
@ EEOP_NULLIF
Definition: execExpr.h:177
@ EEOP_CURRENTOFEXPR
Definition: execExpr.h:179
@ EEOP_INNER_SYSVAR
Definition: execExpr.h:82
@ EEOP_ASSIGN_TMP_MAKE_RO
Definition: execExpr.h:101
@ EEOP_CONST
Definition: execExpr.h:104
@ EEOP_BOOL_OR_STEP_LAST
Definition: execExpr.h:129
@ EEOP_JSONEXPR_COERCION
Definition: execExpr.h:253
@ EEOP_BOOL_OR_STEP_FIRST
Definition: execExpr.h:127
@ EEOP_XMLEXPR
Definition: execExpr.h:249
@ EEOP_AGG_STRICT_INPUT_CHECK_NULLS
Definition: execExpr.h:265
@ EEOP_SBSREF_ASSIGN
Definition: execExpr.h:224
@ EEOP_OUTER_SYSVAR
Definition: execExpr.h:83
@ EEOP_ASSIGN_INNER_VAR
Definition: execExpr.h:94
@ EEOP_BOOL_OR_STEP
Definition: execExpr.h:128
@ EEOP_OUTER_FETCHSOME
Definition: execExpr.h:73
@ EEOP_AGG_STRICT_INPUT_CHECK_ARGS
Definition: execExpr.h:264
@ EEOP_NULLTEST_ROWISNULL
Definition: execExpr.h:150
@ EEOP_BOOLTEST_IS_TRUE
Definition: execExpr.h:154
@ EEOP_FUNCEXPR
Definition: execExpr.h:111
@ EEOP_NULLTEST_ISNOTNULL
Definition: execExpr.h:147
@ EEOP_ROWCOMPARE_STEP
Definition: execExpr.h:189
@ EEOP_MERGE_SUPPORT_FUNC
Definition: execExpr.h:258
@ EEOP_AGG_DESERIALIZE
Definition: execExpr.h:263
@ EEOP_LAST
Definition: execExpr.h:279
@ EEOP_HASHDATUM_FIRST
Definition: execExpr.h:240
@ EEOP_DISTINCT
Definition: execExpr.h:175
@ EEOP_JUMP_IF_NOT_TRUE
Definition: execExpr.h:143
@ EEOP_FUNCEXPR_FUSAGE
Definition: execExpr.h:113
@ EEOP_AGG_PRESORTED_DISTINCT_SINGLE
Definition: execExpr.h:273
@ EEOP_BOOL_AND_STEP_FIRST
Definition: execExpr.h:122
@ EEOP_JUMP
Definition: execExpr.h:138
@ EEOP_PARAM_CALLBACK
Definition: execExpr.h:162
@ EEOP_BOOL_AND_STEP_LAST
Definition: execExpr.h:124
@ EEOP_AGG_ORDERED_TRANS_DATUM
Definition: execExpr.h:275
@ EEOP_SBSREF_OLD
Definition: execExpr.h:221
@ EEOP_SQLVALUEFUNCTION
Definition: execExpr.h:178
@ EEOP_HASHDATUM_SET_INITVAL
Definition: execExpr.h:239
@ EEOP_JUMP_IF_NOT_NULL
Definition: execExpr.h:142
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
Definition: execExpr.h:271
@ EEOP_FIELDSTORE_DEFORM
Definition: execExpr.h:204
@ EEOP_BOOLTEST_IS_FALSE
Definition: execExpr.h:156
@ EEOP_BOOLTEST_IS_NOT_TRUE
Definition: execExpr.h:155
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
Definition: execExpr.h:267
@ EEOP_PARAM_EXEC
Definition: execExpr.h:160
@ EEOP_JSON_CONSTRUCTOR
Definition: execExpr.h:250
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
Definition: execExpr.h:268
@ EEOP_NULLTEST_ISNULL
Definition: execExpr.h:146
@ EEOP_MINMAX
Definition: execExpr.h:195
@ EEOP_JUMP_IF_NULL
Definition: execExpr.h:141
@ EEOP_ARRAYCOERCE
Definition: execExpr.h:182
@ EEOP_FIELDSELECT
Definition: execExpr.h:198
@ EEOP_CASE_TESTVAL
Definition: execExpr.h:167
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
Definition: execExpr.h:270
@ EEOP_HASHED_SCALARARRAYOP
Definition: execExpr.h:248
@ EEOP_OUTER_VAR
Definition: execExpr.h:78
@ EEOP_AGG_ORDERED_TRANS_TUPLE
Definition: execExpr.h:276
@ EEOP_SCAN_FETCHSOME
Definition: execExpr.h:74
@ EEOP_IS_JSON
Definition: execExpr.h:251

Function Documentation

◆ CheckExprStillValid()

void CheckExprStillValid ( ExprState state,
ExprContext econtext 
)

Definition at line 2041 of file execExprInterp.c.

2042 {
2043  TupleTableSlot *innerslot;
2044  TupleTableSlot *outerslot;
2045  TupleTableSlot *scanslot;
2046 
2047  innerslot = econtext->ecxt_innertuple;
2048  outerslot = econtext->ecxt_outertuple;
2049  scanslot = econtext->ecxt_scantuple;
2050 
2051  for (int i = 0; i < state->steps_len; i++)
2052  {
2053  ExprEvalStep *op = &state->steps[i];
2054 
2055  switch (ExecEvalStepOp(state, op))
2056  {
2057  case EEOP_INNER_VAR:
2058  {
2059  int attnum = op->d.var.attnum;
2060 
2061  CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
2062  break;
2063  }
2064 
2065  case EEOP_OUTER_VAR:
2066  {
2067  int attnum = op->d.var.attnum;
2068 
2069  CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
2070  break;
2071  }
2072 
2073  case EEOP_SCAN_VAR:
2074  {
2075  int attnum = op->d.var.attnum;
2076 
2077  CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
2078  break;
2079  }
2080  default:
2081  break;
2082  }
2083  }
2084 }
static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
int i
Definition: isn.c:73
int16 attnum
Definition: pg_attribute.h:74
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:259
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:257
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:261
union ExprEvalStep::@54 d
struct ExprEvalStep::@54::@56 var
Definition: regguts.h:323

References attnum, CheckVarSlotCompatibility(), ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_scantuple, EEOP_INNER_VAR, EEOP_OUTER_VAR, EEOP_SCAN_VAR, ExecEvalStepOp(), i, and ExprEvalStep::op.

Referenced by ExecInterpExprStillValid(), and ExecRunCompiledExpr().

◆ ExecAggCopyTransValue()

Datum ExecAggCopyTransValue ( AggState aggstate,
AggStatePerTrans  pertrans,
Datum  newValue,
bool  newValueIsNull,
Datum  oldValue,
bool  oldValueIsNull 
)

Definition at line 5195 of file execExprInterp.c.

5198 {
5199  Assert(newValue != oldValue);
5200 
5201  if (!newValueIsNull)
5202  {
5204  if (DatumIsReadWriteExpandedObject(newValue,
5205  false,
5206  pertrans->transtypeLen) &&
5207  MemoryContextGetParent(DatumGetEOHP(newValue)->eoh_context) == CurrentMemoryContext)
5208  /* do nothing */ ;
5209  else
5210  newValue = datumCopy(newValue,
5211  pertrans->transtypeByVal,
5212  pertrans->transtypeLen);
5213  }
5214  else
5215  {
5216  /*
5217  * Ensure that AggStatePerGroup->transValue ends up being 0, so
5218  * callers can safely compare newValue/oldValue without having to
5219  * check their respective nullness.
5220  */
5221  newValue = (Datum) 0;
5222  }
5223 
5224  if (!oldValueIsNull)
5225  {
5226  if (DatumIsReadWriteExpandedObject(oldValue,
5227  false,
5228  pertrans->transtypeLen))
5229  DeleteExpandedObject(oldValue);
5230  else
5231  pfree(DatumGetPointer(oldValue));
5232  }
5233 
5234  return newValue;
5235 }
#define Assert(condition)
Definition: c.h:858
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
void DeleteExpandedObject(Datum d)
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
void pfree(void *pointer)
Definition: mcxt.c:1521
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:731
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
MemoryContextSwitchTo(old_ctx)
ExprContext * curaggcontext
Definition: execnodes.h:2504
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:265

References Assert, AggState::curaggcontext, CurrentMemoryContext, datumCopy(), DatumGetEOHP(), DatumGetPointer(), DatumIsReadWriteExpandedObject, DeleteExpandedObject(), ExprContext::ecxt_per_tuple_memory, MemoryContextGetParent(), MemoryContextSwitchTo(), ExprEvalStep::pertrans, pfree(), AggStatePerTransData::transtypeByVal, and AggStatePerTransData::transtypeLen.

Referenced by advance_transition_function(), and ExecAggPlainTransByRef().

◆ ExecAggInitGroup()

void ExecAggInitGroup ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroup,
ExprContext aggcontext 
)

Definition at line 5142 of file execExprInterp.c.

5144 {
5145  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
5146  MemoryContext oldContext;
5147 
5148  /*
5149  * We must copy the datum into aggcontext if it is pass-by-ref. We do not
5150  * need to pfree the old transValue, since it's NULL. (We already checked
5151  * that the agg's input type is binary-compatible with its transtype, so
5152  * straight copy here is OK.)
5153  */
5154  oldContext = MemoryContextSwitchTo(aggcontext->ecxt_per_tuple_memory);
5155  pergroup->transValue = datumCopy(fcinfo->args[1].value,
5156  pertrans->transtypeByVal,
5157  pertrans->transtypeLen);
5158  pergroup->transValueIsNull = false;
5159  pergroup->noTransValue = false;
5160  MemoryContextSwitchTo(oldContext);
5161 }
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:170
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Datum value
Definition: postgres.h:75

References ExprEvalStep::aggcontext, FunctionCallInfoBaseData::args, datumCopy(), ExprContext::ecxt_per_tuple_memory, MemoryContextSwitchTo(), AggStatePerGroupData::noTransValue, ExprEvalStep::pertrans, AggStatePerTransData::transfn_fcinfo, AggStatePerTransData::transtypeByVal, AggStatePerTransData::transtypeLen, AggStatePerGroupData::transValue, AggStatePerGroupData::transValueIsNull, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalAggOrderedTransDatum()

void ExecEvalAggOrderedTransDatum ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 5334 of file execExprInterp.c.

5336 {
5337  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
5338  int setno = op->d.agg_trans.setno;
5339 
5340  tuplesort_putdatum(pertrans->sortstates[setno],
5341  *op->resvalue, *op->resnull);
5342 }
Tuplesortstate ** sortstates
Definition: nodeAgg.h:162
struct ExprEvalStep::@54::@99 agg_trans
Datum * resvalue
Definition: execExpr.h:293
bool * resnull
Definition: execExpr.h:294
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)

References ExprEvalStep::op, ExprEvalStep::pertrans, ExprEvalStep::setno, AggStatePerTransData::sortstates, and tuplesort_putdatum().

Referenced by ExecInterpExpr().

◆ ExecEvalAggOrderedTransTuple()

void ExecEvalAggOrderedTransTuple ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 5348 of file execExprInterp.c.

5350 {
5351  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
5352  int setno = op->d.agg_trans.setno;
5353 
5354  ExecClearTuple(pertrans->sortslot);
5355  pertrans->sortslot->tts_nvalid = pertrans->numInputs;
5356  ExecStoreVirtualTuple(pertrans->sortslot);
5357  tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
5358 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1639
TupleTableSlot * sortslot
Definition: nodeAgg.h:141
AttrNumber tts_nvalid
Definition: tuptable.h:120
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References ExecClearTuple(), ExecStoreVirtualTuple(), AggStatePerTransData::numInputs, ExprEvalStep::op, ExprEvalStep::pertrans, ExprEvalStep::setno, AggStatePerTransData::sortslot, AggStatePerTransData::sortstates, TupleTableSlot::tts_nvalid, and tuplesort_puttupleslot().

Referenced by ExecInterpExpr().

◆ ExecEvalArrayCoerce()

void ExecEvalArrayCoerce ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 3183 of file execExprInterp.c.

3184 {
3185  Datum arraydatum;
3186 
3187  /* NULL array -> NULL result */
3188  if (*op->resnull)
3189  return;
3190 
3191  arraydatum = *op->resvalue;
3192 
3193  /*
3194  * If it's binary-compatible, modify the element type in the array header,
3195  * but otherwise leave the array as we received it.
3196  */
3197  if (op->d.arraycoerce.elemexprstate == NULL)
3198  {
3199  /* Detoast input array if necessary, and copy in any case */
3200  ArrayType *array = DatumGetArrayTypePCopy(arraydatum);
3201 
3202  ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
3203  *op->resvalue = PointerGetDatum(array);
3204  return;
3205  }
3206 
3207  /*
3208  * Use array_map to apply the sub-expression to each array element.
3209  */
3210  *op->resvalue = array_map(arraydatum,
3211  op->d.arraycoerce.elemexprstate,
3212  econtext,
3213  op->d.arraycoerce.resultelemtype,
3214  op->d.arraycoerce.amstate);
3215 }
#define DatumGetArrayTypePCopy(X)
Definition: array.h:262
#define ARR_ELEMTYPE(a)
Definition: array.h:292
Datum array_map(Datum arrayd, ExprState *exprstate, ExprContext *econtext, Oid retType, ArrayMapState *amstate)
Definition: arrayfuncs.c:3201
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
struct ExprEvalStep::@54::@74 arraycoerce

References ARR_ELEMTYPE, array_map(), DatumGetArrayTypePCopy, ExprEvalStep::op, and PointerGetDatum().

Referenced by ExecInterpExpr().

◆ ExecEvalArrayExpr()

void ExecEvalArrayExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2969 of file execExprInterp.c.

2970 {
2971  ArrayType *result;
2972  Oid element_type = op->d.arrayexpr.elemtype;
2973  int nelems = op->d.arrayexpr.nelems;
2974  int ndims = 0;
2975  int dims[MAXDIM];
2976  int lbs[MAXDIM];
2977 
2978  /* Set non-null as default */
2979  *op->resnull = false;
2980 
2981  if (!op->d.arrayexpr.multidims)
2982  {
2983  /* Elements are presumably of scalar type */
2984  Datum *dvalues = op->d.arrayexpr.elemvalues;
2985  bool *dnulls = op->d.arrayexpr.elemnulls;
2986 
2987  /* setup for 1-D array of the given length */
2988  ndims = 1;
2989  dims[0] = nelems;
2990  lbs[0] = 1;
2991 
2992  result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2993  element_type,
2994  op->d.arrayexpr.elemlength,
2995  op->d.arrayexpr.elembyval,
2996  op->d.arrayexpr.elemalign);
2997  }
2998  else
2999  {
3000  /* Must be nested array expressions */
3001  int nbytes = 0;
3002  int nitems;
3003  int outer_nelems = 0;
3004  int elem_ndims = 0;
3005  int *elem_dims = NULL;
3006  int *elem_lbs = NULL;
3007  bool firstone = true;
3008  bool havenulls = false;
3009  bool haveempty = false;
3010  char **subdata;
3011  bits8 **subbitmaps;
3012  int *subbytes;
3013  int *subnitems;
3014  int32 dataoffset;
3015  char *dat;
3016  int iitem;
3017 
3018  subdata = (char **) palloc(nelems * sizeof(char *));
3019  subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
3020  subbytes = (int *) palloc(nelems * sizeof(int));
3021  subnitems = (int *) palloc(nelems * sizeof(int));
3022 
3023  /* loop through and get data area from each element */
3024  for (int elemoff = 0; elemoff < nelems; elemoff++)
3025  {
3026  Datum arraydatum;
3027  bool eisnull;
3028  ArrayType *array;
3029  int this_ndims;
3030 
3031  arraydatum = op->d.arrayexpr.elemvalues[elemoff];
3032  eisnull = op->d.arrayexpr.elemnulls[elemoff];
3033 
3034  /* temporarily ignore null subarrays */
3035  if (eisnull)
3036  {
3037  haveempty = true;
3038  continue;
3039  }
3040 
3041  array = DatumGetArrayTypeP(arraydatum);
3042 
3043  /* run-time double-check on element type */
3044  if (element_type != ARR_ELEMTYPE(array))
3045  ereport(ERROR,
3046  (errcode(ERRCODE_DATATYPE_MISMATCH),
3047  errmsg("cannot merge incompatible arrays"),
3048  errdetail("Array with element type %s cannot be "
3049  "included in ARRAY construct with element type %s.",
3050  format_type_be(ARR_ELEMTYPE(array)),
3051  format_type_be(element_type))));
3052 
3053  this_ndims = ARR_NDIM(array);
3054  /* temporarily ignore zero-dimensional subarrays */
3055  if (this_ndims <= 0)
3056  {
3057  haveempty = true;
3058  continue;
3059  }
3060 
3061  if (firstone)
3062  {
3063  /* Get sub-array details from first member */
3064  elem_ndims = this_ndims;
3065  ndims = elem_ndims + 1;
3066  if (ndims <= 0 || ndims > MAXDIM)
3067  ereport(ERROR,
3068  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3069  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3070  ndims, MAXDIM)));
3071 
3072  elem_dims = (int *) palloc(elem_ndims * sizeof(int));
3073  memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
3074  elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
3075  memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
3076 
3077  firstone = false;
3078  }
3079  else
3080  {
3081  /* Check other sub-arrays are compatible */
3082  if (elem_ndims != this_ndims ||
3083  memcmp(elem_dims, ARR_DIMS(array),
3084  elem_ndims * sizeof(int)) != 0 ||
3085  memcmp(elem_lbs, ARR_LBOUND(array),
3086  elem_ndims * sizeof(int)) != 0)
3087  ereport(ERROR,
3088  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3089  errmsg("multidimensional arrays must have array "
3090  "expressions with matching dimensions")));
3091  }
3092 
3093  subdata[outer_nelems] = ARR_DATA_PTR(array);
3094  subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
3095  subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
3096  nbytes += subbytes[outer_nelems];
3097  /* check for overflow of total request */
3098  if (!AllocSizeIsValid(nbytes))
3099  ereport(ERROR,
3100  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3101  errmsg("array size exceeds the maximum allowed (%d)",
3102  (int) MaxAllocSize)));
3103  subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
3104  ARR_DIMS(array));
3105  havenulls |= ARR_HASNULL(array);
3106  outer_nelems++;
3107  }
3108 
3109  /*
3110  * If all items were null or empty arrays, return an empty array;
3111  * otherwise, if some were and some weren't, raise error. (Note: we
3112  * must special-case this somehow to avoid trying to generate a 1-D
3113  * array formed from empty arrays. It's not ideal...)
3114  */
3115  if (haveempty)
3116  {
3117  if (ndims == 0) /* didn't find any nonempty array */
3118  {
3119  *op->resvalue = PointerGetDatum(construct_empty_array(element_type));
3120  return;
3121  }
3122  ereport(ERROR,
3123  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3124  errmsg("multidimensional arrays must have array "
3125  "expressions with matching dimensions")));
3126  }
3127 
3128  /* setup for multi-D array */
3129  dims[0] = outer_nelems;
3130  lbs[0] = 1;
3131  for (int i = 1; i < ndims; i++)
3132  {
3133  dims[i] = elem_dims[i - 1];
3134  lbs[i] = elem_lbs[i - 1];
3135  }
3136 
3137  /* check for subscript overflow */
3138  nitems = ArrayGetNItems(ndims, dims);
3139  ArrayCheckBounds(ndims, dims, lbs);
3140 
3141  if (havenulls)
3142  {
3143  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
3144  nbytes += dataoffset;
3145  }
3146  else
3147  {
3148  dataoffset = 0; /* marker for no null bitmap */
3149  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3150  }
3151 
3152  result = (ArrayType *) palloc0(nbytes);
3153  SET_VARSIZE(result, nbytes);
3154  result->ndim = ndims;
3155  result->dataoffset = dataoffset;
3156  result->elemtype = element_type;
3157  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3158  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3159 
3160  dat = ARR_DATA_PTR(result);
3161  iitem = 0;
3162  for (int i = 0; i < outer_nelems; i++)
3163  {
3164  memcpy(dat, subdata[i], subbytes[i]);
3165  dat += subbytes[i];
3166  if (havenulls)
3167  array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
3168  subbitmaps[i], 0,
3169  subnitems[i]);
3170  iitem += subnitems[i];
3171  }
3172  }
3173 
3174  *op->resvalue = PointerGetDatum(result);
3175 }
#define ARR_NDIM(a)
Definition: array.h:290
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define MAXDIM
Definition: array.h:75
#define ARR_NULLBITMAP(a)
Definition: array.h:300
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:312
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_SIZE(a)
Definition: array.h:289
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:310
#define ARR_DATA_OFFSET(a)
Definition: array.h:316
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_HASNULL(a)
Definition: array.h:291
#define ARR_LBOUND(a)
Definition: array.h:296
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3568
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3482
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4954
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:117
signed int int32
Definition: c.h:494
uint8 bits8
Definition: c.h:513
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define nitems(x)
Definition: indent.h:31
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
unsigned int Oid
Definition: postgres_ext.h:31
Oid elemtype
Definition: array.h:97
int ndim
Definition: array.h:95
int32 dataoffset
Definition: array.h:96
struct ExprEvalStep::@54::@73 arrayexpr
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References AllocSizeIsValid, ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ARR_SIZE, array_bitmap_copy(), ArrayCheckBounds(), ArrayGetNItems(), construct_empty_array(), construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, ExprEvalStep::element_type, ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, format_type_be(), i, MaxAllocSize, MAXDIM, ArrayType::ndim, ExprEvalStep::nelems, nitems, ExprEvalStep::op, palloc(), palloc0(), PointerGetDatum(), and SET_VARSIZE.

Referenced by ExecInterpExpr().

◆ ExecEvalCoerceViaIOSafe()

void ExecEvalCoerceViaIOSafe ( ExprState state,
ExprEvalStep op 
)

Definition at line 2703 of file execExprInterp.c.

2704 {
2705  char *str;
2706 
2707  /* call output function (similar to OutputFunctionCall) */
2708  if (*op->resnull)
2709  {
2710  /* output functions are not called on nulls */
2711  str = NULL;
2712  }
2713  else
2714  {
2715  FunctionCallInfo fcinfo_out;
2716 
2717  fcinfo_out = op->d.iocoerce.fcinfo_data_out;
2718  fcinfo_out->args[0].value = *op->resvalue;
2719  fcinfo_out->args[0].isnull = false;
2720 
2721  fcinfo_out->isnull = false;
2722  str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
2723 
2724  /* OutputFunctionCall assumes result isn't null */
2725  Assert(!fcinfo_out->isnull);
2726  }
2727 
2728  /* call input function (similar to InputFunctionCallSafe) */
2729  if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
2730  {
2731  FunctionCallInfo fcinfo_in;
2732 
2733  fcinfo_in = op->d.iocoerce.fcinfo_data_in;
2734  fcinfo_in->args[0].value = PointerGetDatum(str);
2735  fcinfo_in->args[0].isnull = *op->resnull;
2736  /* second and third arguments are already set up */
2737 
2738  /* ErrorSaveContext must be present. */
2739  Assert(IsA(fcinfo_in->context, ErrorSaveContext));
2740 
2741  fcinfo_in->isnull = false;
2742  *op->resvalue = FunctionCallInvoke(fcinfo_in);
2743 
2744  if (SOFT_ERROR_OCCURRED(fcinfo_in->context))
2745  {
2746  *op->resnull = true;
2747  *op->resvalue = (Datum) 0;
2748  return;
2749  }
2750 
2751  /* Should get null result if and only if str is NULL */
2752  if (str == NULL)
2753  Assert(*op->resnull);
2754  else
2755  Assert(!*op->resnull);
2756  }
2757 }
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
const char * str
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:52
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
struct ExprEvalStep::@54::@70 iocoerce
fmNodePtr context
Definition: fmgr.h:88
bool isnull
Definition: postgres.h:77

References FunctionCallInfoBaseData::args, Assert, FunctionCallInfoBaseData::context, DatumGetCString(), FunctionCallInvoke, IsA, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, ExprEvalStep::op, PointerGetDatum(), SOFT_ERROR_OCCURRED, str, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalConstraintCheck()

void ExecEvalConstraintCheck ( ExprState state,
ExprEvalStep op 
)

Definition at line 3990 of file execExprInterp.c.

3991 {
3992  if (!*op->d.domaincheck.checknull &&
3993  !DatumGetBool(*op->d.domaincheck.checkvalue))
3994  errsave((Node *) op->d.domaincheck.escontext,
3995  (errcode(ERRCODE_CHECK_VIOLATION),
3996  errmsg("value for domain %s violates check constraint \"%s\"",
3997  format_type_be(op->d.domaincheck.resulttype),
3998  op->d.domaincheck.constraintname),
3999  errdomainconstraint(op->d.domaincheck.resulttype,
4000  op->d.domaincheck.constraintname)));
4001 }
int errdomainconstraint(Oid datatypeOid, const char *conname)
Definition: domains.c:431
#define errsave(context,...)
Definition: elog.h:261
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
struct ExprEvalStep::@54::@83 domaincheck
Definition: nodes.h:129

References DatumGetBool(), errcode(), errdomainconstraint(), errmsg(), errsave, format_type_be(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalConstraintNotNull()

void ExecEvalConstraintNotNull ( ExprState state,
ExprEvalStep op 
)

Definition at line 3976 of file execExprInterp.c.

3977 {
3978  if (*op->resnull)
3979  errsave((Node *) op->d.domaincheck.escontext,
3980  (errcode(ERRCODE_NOT_NULL_VIOLATION),
3981  errmsg("domain %s does not allow null values",
3982  format_type_be(op->d.domaincheck.resulttype)),
3983  errdatatype(op->d.domaincheck.resulttype)));
3984 }
int errdatatype(Oid datatypeOid)
Definition: domains.c:407

References errcode(), errdatatype(), errmsg(), errsave, format_type_be(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalConvertRowtype()

void ExecEvalConvertRowtype ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 3496 of file execExprInterp.c.

3497 {
3498  HeapTuple result;
3499  Datum tupDatum;
3500  HeapTupleHeader tuple;
3501  HeapTupleData tmptup;
3502  TupleDesc indesc,
3503  outdesc;
3504  bool changed = false;
3505 
3506  /* NULL in -> NULL out */
3507  if (*op->resnull)
3508  return;
3509 
3510  tupDatum = *op->resvalue;
3511  tuple = DatumGetHeapTupleHeader(tupDatum);
3512 
3513  /*
3514  * Lookup tupdescs if first time through or if type changes. We'd better
3515  * pin them since type conversion functions could do catalog lookups and
3516  * hence cause cache invalidation.
3517  */
3518  indesc = get_cached_rowtype(op->d.convert_rowtype.inputtype, -1,
3519  op->d.convert_rowtype.incache,
3520  &changed);
3521  IncrTupleDescRefCount(indesc);
3522  outdesc = get_cached_rowtype(op->d.convert_rowtype.outputtype, -1,
3523  op->d.convert_rowtype.outcache,
3524  &changed);
3525  IncrTupleDescRefCount(outdesc);
3526 
3527  /*
3528  * We used to be able to assert that incoming tuples are marked with
3529  * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
3530  * might change the tuples' marking to plain RECORD due to inserting
3531  * aliases, we can only make this weak test:
3532  */
3533  Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
3534  HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
3535 
3536  /* if first time through, or after change, initialize conversion map */
3537  if (changed)
3538  {
3539  MemoryContext old_cxt;
3540 
3541  /* allocate map in long-lived memory context */
3542  old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3543 
3544  /* prepare map from old to new attribute numbers */
3545  op->d.convert_rowtype.map = convert_tuples_by_name(indesc, outdesc);
3546 
3547  MemoryContextSwitchTo(old_cxt);
3548  }
3549 
3550  /* Following steps need a HeapTuple not a bare HeapTupleHeader */
3551  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3552  tmptup.t_data = tuple;
3553 
3554  if (op->d.convert_rowtype.map != NULL)
3555  {
3556  /* Full conversion with attribute rearrangement needed */
3557  result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map);
3558  /* Result already has appropriate composite-datum header fields */
3559  *op->resvalue = HeapTupleGetDatum(result);
3560  }
3561  else
3562  {
3563  /*
3564  * The tuple is physically compatible as-is, but we need to insert the
3565  * destination rowtype OID in its composite-datum header field, so we
3566  * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
3567  * for this since it will both make the physical copy and insert the
3568  * correct composite header fields. Note that we aren't expecting to
3569  * have to flatten any toasted fields: the input was a composite
3570  * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
3571  * is overkill here, but its check for external fields is cheap.
3572  */
3573  *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
3574  }
3575 
3576  DecrTupleDescRefCount(indesc);
3577  DecrTupleDescRefCount(outdesc);
3578 }
static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod, ExprEvalRowtypeCache *rowcache, bool *changed)
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:1080
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:264
struct ExprEvalStep::@54::@86 convert_rowtype
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid tdtypeid
Definition: tupdesc.h:82
TupleConversionMap * convert_tuples_by_name(TupleDesc indesc, TupleDesc outdesc)
Definition: tupconvert.c:102
HeapTuple execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:154
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:406
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:388

References Assert, convert_tuples_by_name(), DatumGetHeapTupleHeader, DecrTupleDescRefCount(), ExprContext::ecxt_per_query_memory, execute_attr_map_tuple(), get_cached_rowtype(), heap_copy_tuple_as_datum(), HeapTupleGetDatum(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, IncrTupleDescRefCount(), MemoryContextSwitchTo(), ExprEvalStep::op, HeapTupleData::t_data, HeapTupleData::t_len, and TupleDescData::tdtypeid.

Referenced by ExecInterpExpr().

◆ ExecEvalCurrentOfExpr()

void ExecEvalCurrentOfExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2830 of file execExprInterp.c.

2831 {
2832  ereport(ERROR,
2833  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2834  errmsg("WHERE CURRENT OF is not supported for this table type")));
2835 }

References ereport, errcode(), errmsg(), and ERROR.

Referenced by ExecInterpExpr().

◆ ExecEvalFieldSelect()

void ExecEvalFieldSelect ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 3297 of file execExprInterp.c.

3298 {
3299  AttrNumber fieldnum = op->d.fieldselect.fieldnum;
3300  Datum tupDatum;
3301  HeapTupleHeader tuple;
3302  Oid tupType;
3303  int32 tupTypmod;
3304  TupleDesc tupDesc;
3305  Form_pg_attribute attr;
3306  HeapTupleData tmptup;
3307 
3308  /* NULL record -> NULL result */
3309  if (*op->resnull)
3310  return;
3311 
3312  tupDatum = *op->resvalue;
3313 
3314  /* We can special-case expanded records for speed */
3316  {
3318 
3319  Assert(erh->er_magic == ER_MAGIC);
3320 
3321  /* Extract record's TupleDesc */
3322  tupDesc = expanded_record_get_tupdesc(erh);
3323 
3324  /*
3325  * Find field's attr record. Note we don't support system columns
3326  * here: a datum tuple doesn't have valid values for most of the
3327  * interesting system columns anyway.
3328  */
3329  if (fieldnum <= 0) /* should never happen */
3330  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3331  fieldnum);
3332  if (fieldnum > tupDesc->natts) /* should never happen */
3333  elog(ERROR, "attribute number %d exceeds number of columns %d",
3334  fieldnum, tupDesc->natts);
3335  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3336 
3337  /* Check for dropped column, and force a NULL result if so */
3338  if (attr->attisdropped)
3339  {
3340  *op->resnull = true;
3341  return;
3342  }
3343 
3344  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3345  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3346  if (op->d.fieldselect.resulttype != attr->atttypid)
3347  ereport(ERROR,
3348  (errcode(ERRCODE_DATATYPE_MISMATCH),
3349  errmsg("attribute %d has wrong type", fieldnum),
3350  errdetail("Table has type %s, but query expects %s.",
3351  format_type_be(attr->atttypid),
3352  format_type_be(op->d.fieldselect.resulttype))));
3353 
3354  /* extract the field */
3355  *op->resvalue = expanded_record_get_field(erh, fieldnum,
3356  op->resnull);
3357  }
3358  else
3359  {
3360  /* Get the composite datum and extract its type fields */
3361  tuple = DatumGetHeapTupleHeader(tupDatum);
3362 
3363  tupType = HeapTupleHeaderGetTypeId(tuple);
3364  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
3365 
3366  /* Lookup tupdesc if first time through or if type changes */
3367  tupDesc = get_cached_rowtype(tupType, tupTypmod,
3368  &op->d.fieldselect.rowcache, NULL);
3369 
3370  /*
3371  * Find field's attr record. Note we don't support system columns
3372  * here: a datum tuple doesn't have valid values for most of the
3373  * interesting system columns anyway.
3374  */
3375  if (fieldnum <= 0) /* should never happen */
3376  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3377  fieldnum);
3378  if (fieldnum > tupDesc->natts) /* should never happen */
3379  elog(ERROR, "attribute number %d exceeds number of columns %d",
3380  fieldnum, tupDesc->natts);
3381  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3382 
3383  /* Check for dropped column, and force a NULL result if so */
3384  if (attr->attisdropped)
3385  {
3386  *op->resnull = true;
3387  return;
3388  }
3389 
3390  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3391  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3392  if (op->d.fieldselect.resulttype != attr->atttypid)
3393  ereport(ERROR,
3394  (errcode(ERRCODE_DATATYPE_MISMATCH),
3395  errmsg("attribute %d has wrong type", fieldnum),
3396  errdetail("Table has type %s, but query expects %s.",
3397  format_type_be(attr->atttypid),
3398  format_type_be(op->d.fieldselect.resulttype))));
3399 
3400  /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
3401  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3402  tmptup.t_data = tuple;
3403 
3404  /* extract the field */
3405  *op->resvalue = heap_getattr(&tmptup,
3406  fieldnum,
3407  tupDesc,
3408  op->resnull);
3409  }
3410 }
int16 AttrNumber
Definition: attnum.h:21
#define elog(elevel,...)
Definition: elog.h:225
static Datum expanded_record_get_field(ExpandedRecordHeader *erh, int fnumber, bool *isnull)
#define ER_MAGIC
static TupleDesc expanded_record_get_tupdesc(ExpandedRecordHeader *erh)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
struct ExprEvalStep::@54::@79 fieldselect
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: varatt.h:298

References Assert, DatumGetEOHP(), DatumGetHeapTupleHeader, DatumGetPointer(), elog, ER_MAGIC, ExpandedRecordHeader::er_magic, ereport, errcode(), errdetail(), errmsg(), ERROR, expanded_record_get_field(), expanded_record_get_tupdesc(), ExprEvalStep::fieldnum, format_type_be(), get_cached_rowtype(), heap_getattr(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, TupleDescData::natts, ExprEvalStep::op, HeapTupleData::t_data, HeapTupleData::t_len, TupleDescAttr, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by ExecInterpExpr().

◆ ExecEvalFieldStoreDeForm()

void ExecEvalFieldStoreDeForm ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 3422 of file execExprInterp.c.

3423 {
3424  if (*op->resnull)
3425  {
3426  /* Convert null input tuple into an all-nulls row */
3427  memset(op->d.fieldstore.nulls, true,
3428  op->d.fieldstore.ncolumns * sizeof(bool));
3429  }
3430  else
3431  {
3432  /*
3433  * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
3434  * set all the fields in the struct just in case.
3435  */
3436  Datum tupDatum = *op->resvalue;
3437  HeapTupleHeader tuphdr;
3438  HeapTupleData tmptup;
3439  TupleDesc tupDesc;
3440 
3441  tuphdr = DatumGetHeapTupleHeader(tupDatum);
3442  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
3443  ItemPointerSetInvalid(&(tmptup.t_self));
3444  tmptup.t_tableOid = InvalidOid;
3445  tmptup.t_data = tuphdr;
3446 
3447  /*
3448  * Lookup tupdesc if first time through or if type changes. Because
3449  * we don't pin the tupdesc, we must not do this lookup until after
3450  * doing DatumGetHeapTupleHeader: that could do database access while
3451  * detoasting the datum.
3452  */
3453  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3454  op->d.fieldstore.rowcache, NULL);
3455 
3456  /* Check that current tupdesc doesn't have more fields than allocated */
3457  if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
3458  elog(ERROR, "too many columns in composite type %u",
3459  op->d.fieldstore.fstore->resulttype);
3460 
3461  heap_deform_tuple(&tmptup, tupDesc,
3462  op->d.fieldstore.values,
3463  op->d.fieldstore.nulls);
3464  }
3465 }
#define unlikely(x)
Definition: c.h:311
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1345
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
#define InvalidOid
Definition: postgres_ext.h:36
struct ExprEvalStep::@54::@80 fieldstore
ItemPointerData t_self
Definition: htup.h:65
Oid t_tableOid
Definition: htup.h:66

References DatumGetHeapTupleHeader, elog, ERROR, get_cached_rowtype(), heap_deform_tuple(), HeapTupleHeaderGetDatumLength, InvalidOid, ItemPointerSetInvalid(), TupleDescData::natts, ExprEvalStep::op, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, and unlikely.

Referenced by ExecInterpExpr().

◆ ExecEvalFieldStoreForm()

void ExecEvalFieldStoreForm ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 3472 of file execExprInterp.c.

3473 {
3474  TupleDesc tupDesc;
3475  HeapTuple tuple;
3476 
3477  /* Lookup tupdesc (should be valid already) */
3478  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3479  op->d.fieldstore.rowcache, NULL);
3480 
3481  tuple = heap_form_tuple(tupDesc,
3482  op->d.fieldstore.values,
3483  op->d.fieldstore.nulls);
3484 
3485  *op->resvalue = HeapTupleGetDatum(tuple);
3486  *op->resnull = false;
3487 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116

References get_cached_rowtype(), heap_form_tuple(), HeapTupleGetDatum(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalFuncExprFusage()

void ExecEvalFuncExprFusage ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2558 of file execExprInterp.c.

2560 {
2561  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2562  PgStat_FunctionCallUsage fcusage;
2563  Datum d;
2564 
2565  pgstat_init_function_usage(fcinfo, &fcusage);
2566 
2567  fcinfo->isnull = false;
2568  d = op->d.func.fn_addr(fcinfo);
2569  *op->resvalue = d;
2570  *op->resnull = fcinfo->isnull;
2571 
2572  pgstat_end_function_usage(&fcusage, true);
2573 }
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
struct ExprEvalStep::@54::@61 func

References ExprEvalStep::d, FunctionCallInfoBaseData::isnull, ExprEvalStep::op, pgstat_end_function_usage(), and pgstat_init_function_usage().

Referenced by ExecInterpExpr().

◆ ExecEvalFuncExprStrictFusage()

void ExecEvalFuncExprStrictFusage ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2579 of file execExprInterp.c.

2581 {
2582 
2583  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2584  PgStat_FunctionCallUsage fcusage;
2585  NullableDatum *args = fcinfo->args;
2586  int nargs = op->d.func.nargs;
2587  Datum d;
2588 
2589  /* strict function, so check for NULL args */
2590  for (int argno = 0; argno < nargs; argno++)
2591  {
2592  if (args[argno].isnull)
2593  {
2594  *op->resnull = true;
2595  return;
2596  }
2597  }
2598 
2599  pgstat_init_function_usage(fcinfo, &fcusage);
2600 
2601  fcinfo->isnull = false;
2602  d = op->d.func.fn_addr(fcinfo);
2603  *op->resvalue = d;
2604  *op->resnull = fcinfo->isnull;
2605 
2606  pgstat_end_function_usage(&fcusage, true);
2607 }

References generate_unaccent_rules::args, FunctionCallInfoBaseData::args, ExprEvalStep::d, ExprEvalStep::isnull, FunctionCallInfoBaseData::isnull, ExprEvalStep::nargs, ExprEvalStep::op, pgstat_end_function_usage(), and pgstat_init_function_usage().

Referenced by ExecInterpExpr().

◆ ExecEvalGroupingFunc()

void ExecEvalGroupingFunc ( ExprState state,
ExprEvalStep op 
)

Definition at line 4814 of file execExprInterp.c.

4815 {
4816  AggState *aggstate = castNode(AggState, state->parent);
4817  int result = 0;
4818  Bitmapset *grouped_cols = aggstate->grouped_cols;
4819  ListCell *lc;
4820 
4821  foreach(lc, op->d.grouping_func.clauses)
4822  {
4823  int attnum = lfirst_int(lc);
4824 
4825  result <<= 1;
4826 
4827  if (!bms_is_member(attnum, grouped_cols))
4828  result |= 1;
4829  }
4830 
4831  *op->resvalue = Int32GetDatum(result);
4832  *op->resnull = false;
4833 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define lfirst_int(lc)
Definition: pg_list.h:173
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
Bitmapset * grouped_cols
Definition: execnodes.h:2513
struct ExprEvalStep::@54::@92 grouping_func

References attnum, bms_is_member(), castNode, AggState::grouped_cols, Int32GetDatum(), lfirst_int, and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalHashedScalarArrayOp()

void ExecEvalHashedScalarArrayOp ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 3794 of file execExprInterp.c.

3795 {
3796  ScalarArrayOpExprHashTable *elements_tab = op->d.hashedscalararrayop.elements_tab;
3797  FunctionCallInfo fcinfo = op->d.hashedscalararrayop.fcinfo_data;
3798  bool inclause = op->d.hashedscalararrayop.inclause;
3799  bool strictfunc = op->d.hashedscalararrayop.finfo->fn_strict;
3800  Datum scalar = fcinfo->args[0].value;
3801  bool scalar_isnull = fcinfo->args[0].isnull;
3802  Datum result;
3803  bool resultnull;
3804  bool hashfound;
3805 
3806  /* We don't setup a hashed scalar array op if the array const is null. */
3807  Assert(!*op->resnull);
3808 
3809  /*
3810  * If the scalar is NULL, and the function is strict, return NULL; no
3811  * point in executing the search.
3812  */
3813  if (fcinfo->args[0].isnull && strictfunc)
3814  {
3815  *op->resnull = true;
3816  return;
3817  }
3818 
3819  /* Build the hash table on first evaluation */
3820  if (elements_tab == NULL)
3821  {
3822  ScalarArrayOpExpr *saop;
3823  int16 typlen;
3824  bool typbyval;
3825  char typalign;
3826  int nitems;
3827  bool has_nulls = false;
3828  char *s;
3829  bits8 *bitmap;
3830  int bitmask;
3831  MemoryContext oldcontext;
3832  ArrayType *arr;
3833 
3834  saop = op->d.hashedscalararrayop.saop;
3835 
3836  arr = DatumGetArrayTypeP(*op->resvalue);
3837  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3838 
3840  &typlen,
3841  &typbyval,
3842  &typalign);
3843 
3844  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3845 
3846  elements_tab = (ScalarArrayOpExprHashTable *)
3847  palloc0(offsetof(ScalarArrayOpExprHashTable, hash_fcinfo_data) +
3849  op->d.hashedscalararrayop.elements_tab = elements_tab;
3850  elements_tab->op = op;
3851 
3852  fmgr_info(saop->hashfuncid, &elements_tab->hash_finfo);
3853  fmgr_info_set_expr((Node *) saop, &elements_tab->hash_finfo);
3854 
3856  &elements_tab->hash_finfo,
3857  1,
3858  saop->inputcollid,
3859  NULL,
3860  NULL);
3861 
3862  /*
3863  * Create the hash table sizing it according to the number of elements
3864  * in the array. This does assume that the array has no duplicates.
3865  * If the array happens to contain many duplicate values then it'll
3866  * just mean that we sized the table a bit on the large side.
3867  */
3868  elements_tab->hashtab = saophash_create(CurrentMemoryContext, nitems,
3869  elements_tab);
3870 
3871  MemoryContextSwitchTo(oldcontext);
3872 
3873  s = (char *) ARR_DATA_PTR(arr);
3874  bitmap = ARR_NULLBITMAP(arr);
3875  bitmask = 1;
3876  for (int i = 0; i < nitems; i++)
3877  {
3878  /* Get array element, checking for NULL. */
3879  if (bitmap && (*bitmap & bitmask) == 0)
3880  {
3881  has_nulls = true;
3882  }
3883  else
3884  {
3885  Datum element;
3886 
3887  element = fetch_att(s, typbyval, typlen);
3888  s = att_addlength_pointer(s, typlen, s);
3889  s = (char *) att_align_nominal(s, typalign);
3890 
3891  saophash_insert(elements_tab->hashtab, element, &hashfound);
3892  }
3893 
3894  /* Advance bitmap pointer if any. */
3895  if (bitmap)
3896  {
3897  bitmask <<= 1;
3898  if (bitmask == 0x100)
3899  {
3900  bitmap++;
3901  bitmask = 1;
3902  }
3903  }
3904  }
3905 
3906  /*
3907  * Remember if we had any nulls so that we know if we need to execute
3908  * non-strict functions with a null lhs value if no match is found.
3909  */
3910  op->d.hashedscalararrayop.has_nulls = has_nulls;
3911  }
3912 
3913  /* Check the hash to see if we have a match. */
3914  hashfound = NULL != saophash_lookup(elements_tab->hashtab, scalar);
3915 
3916  /* the result depends on if the clause is an IN or NOT IN clause */
3917  if (inclause)
3918  result = BoolGetDatum(hashfound); /* IN */
3919  else
3920  result = BoolGetDatum(!hashfound); /* NOT IN */
3921 
3922  resultnull = false;
3923 
3924  /*
3925  * If we didn't find a match in the array, we still might need to handle
3926  * the possibility of null values. We didn't put any NULLs into the
3927  * hashtable, but instead marked if we found any when building the table
3928  * in has_nulls.
3929  */
3930  if (!hashfound && op->d.hashedscalararrayop.has_nulls)
3931  {
3932  if (strictfunc)
3933  {
3934 
3935  /*
3936  * We have nulls in the array so a non-null lhs and no match must
3937  * yield NULL.
3938  */
3939  result = (Datum) 0;
3940  resultnull = true;
3941  }
3942  else
3943  {
3944  /*
3945  * Execute function will null rhs just once.
3946  *
3947  * The hash lookup path will have scribbled on the lhs argument so
3948  * we need to set it up also (even though we entered this function
3949  * with it already set).
3950  */
3951  fcinfo->args[0].value = scalar;
3952  fcinfo->args[0].isnull = scalar_isnull;
3953  fcinfo->args[1].value = (Datum) 0;
3954  fcinfo->args[1].isnull = true;
3955 
3956  result = op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
3957  resultnull = fcinfo->isnull;
3958 
3959  /*
3960  * Reverse the result for NOT IN clauses since the above function
3961  * is the equality function and we need not-equals.
3962  */
3963  if (!inclause)
3964  result = !result;
3965  }
3966  }
3967 
3968  *op->resvalue = result;
3969  *op->resnull = resultnull;
3970 }
signed short int16
Definition: c.h:493
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define SizeForFunctionCallInfo(nargs)
Definition: fmgr.h:102
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
char typalign
Definition: pg_type.h:176
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
struct ExprEvalStep::@54::@88 hashedscalararrayop
FunctionCallInfoBaseData hash_fcinfo_data
struct ExprEvalStep * op
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:129
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:157
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:52

References FunctionCallInfoBaseData::args, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, att_addlength_pointer, att_align_nominal, BoolGetDatum(), CurrentMemoryContext, DatumGetArrayTypeP, ExprContext::ecxt_per_query_memory, element(), ExprEvalStep::elements_tab, fetch_att(), fmgr_info(), fmgr_info_set_expr, get_typlenbyvalalign(), ExprEvalStep::has_nulls, ScalarArrayOpExprHashTable::hash_fcinfo_data, ScalarArrayOpExprHashTable::hash_finfo, ScalarArrayOpExprHashTable::hashtab, i, ExprEvalStep::inclause, InitFunctionCallInfoData, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, MemoryContextSwitchTo(), nitems, ScalarArrayOpExprHashTable::op, ExprEvalStep::op, palloc0(), ExprEvalStep::saop, SizeForFunctionCallInfo, typalign, ExprEvalStep::typbyval, ExprEvalStep::typlen, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalJsonCoercion()

void ExecEvalJsonCoercion ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 4680 of file execExprInterp.c.

4682 {
4683  ErrorSaveContext *escontext = op->d.jsonexpr_coercion.escontext;
4684 
4685  /*
4686  * Prepare to call json_populate_type() to coerce the boolean result of
4687  * JSON_EXISTS_OP to the target type. If the the target type is integer
4688  * or a domain over integer, call the boolean-to-integer cast function
4689  * instead, because the integer's input function (which is what
4690  * json_populate_type() calls to coerce to scalar target types) doesn't
4691  * accept boolean literals as valid input. We only have a special case
4692  * for integer and domains thereof as it seems common to use those types
4693  * for EXISTS columns in JSON_TABLE().
4694  */
4695  if (op->d.jsonexpr_coercion.exists_coerce)
4696  {
4697  if (op->d.jsonexpr_coercion.exists_cast_to_int)
4698  {
4699  /* Check domain constraints if any. */
4700  if (op->d.jsonexpr_coercion.exists_check_domain &&
4701  !domain_check_safe(*op->resvalue, *op->resnull,
4702  op->d.jsonexpr_coercion.targettype,
4703  &op->d.jsonexpr_coercion.json_coercion_cache,
4704  econtext->ecxt_per_query_memory,
4705  (Node *) escontext))
4706  {
4707  *op->resnull = true;
4708  *op->resvalue = (Datum) 0;
4709  }
4710  else
4712  return;
4713  }
4714 
4716  DatumGetBool(*op->resvalue) ?
4717  CStringGetDatum("true") :
4718  CStringGetDatum("false"));
4719  }
4720 
4721  *op->resvalue = json_populate_type(*op->resvalue, JSONBOID,
4722  op->d.jsonexpr_coercion.targettype,
4723  op->d.jsonexpr_coercion.targettypmod,
4724  &op->d.jsonexpr_coercion.json_coercion_cache,
4725  econtext->ecxt_per_query_memory,
4726  op->resnull,
4727  op->d.jsonexpr_coercion.omit_quotes,
4728  (Node *) escontext);
4729 }
bool domain_check_safe(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt, Node *escontext)
Definition: domains.c:355
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
Datum bool_int4(PG_FUNCTION_ARGS)
Definition: int.c:372
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:73
Datum json_populate_type(Datum json_val, Oid json_type, Oid typid, int32 typmod, void **cache, MemoryContext mcxt, bool *isnull, bool omit_quotes, Node *escontext)
Definition: jsonfuncs.c:3344
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
struct ExprEvalStep::@54::@102 jsonexpr_coercion

References bool_int4(), CStringGetDatum(), DatumGetBool(), DirectFunctionCall1, domain_check_safe(), ExprContext::ecxt_per_query_memory, ExprEvalStep::escontext, json_populate_type(), jsonb_in(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalJsonCoercionFinish()

void ExecEvalJsonCoercionFinish ( ExprState state,
ExprEvalStep op 
)

Definition at line 4760 of file execExprInterp.c.

4761 {
4762  JsonExprState *jsestate = op->d.jsonexpr.jsestate;
4763 
4764  if (SOFT_ERROR_OCCURRED(&jsestate->escontext))
4765  {
4766  /*
4767  * jsestate->error or jsestate->empty being set means that the error
4768  * occurred when coercing the JsonBehavior value. Throw the error in
4769  * that case with the actual coercion error message shown in the
4770  * DETAIL part.
4771  */
4772  if (DatumGetBool(jsestate->error.value))
4773  ereport(ERROR,
4774  (errcode(ERRCODE_DATATYPE_MISMATCH),
4775  /*- translator: first %s is a SQL/JSON clause (e.g. ON ERROR) */
4776  errmsg("could not coerce %s expression (%s) to the RETURNING type",
4777  "ON ERROR",
4779  errdetail("%s", jsestate->escontext.error_data->message)));
4780  else if (DatumGetBool(jsestate->empty.value))
4781  ereport(ERROR,
4782  (errcode(ERRCODE_DATATYPE_MISMATCH),
4783  /*- translator: first %s is a SQL/JSON clause (e.g. ON ERROR) */
4784  errmsg("could not coerce %s expression (%s) to the RETURNING type",
4785  "ON EMPTY",
4787  errdetail("%s", jsestate->escontext.error_data->message)));
4788 
4789  *op->resvalue = (Datum) 0;
4790  *op->resnull = true;
4791 
4792  jsestate->error.value = BoolGetDatum(true);
4793 
4794  /*
4795  * Reset for next use such as for catching errors when coercing a
4796  * JsonBehavior expression.
4797  */
4798  jsestate->escontext.error_occurred = false;
4799  jsestate->escontext.error_occurred = false;
4800  jsestate->escontext.details_wanted = true;
4801  }
4802 }
static char * GetJsonBehaviorValueString(JsonBehavior *behavior)
char * message
Definition: elog.h:440
bool details_wanted
Definition: miscnodes.h:47
ErrorData * error_data
Definition: miscnodes.h:48
bool error_occurred
Definition: miscnodes.h:46
struct ExprEvalStep::@54::@101 jsonexpr
NullableDatum empty
Definition: execnodes.h:1047
JsonExpr * jsexpr
Definition: execnodes.h:1025
NullableDatum error
Definition: execnodes.h:1044
ErrorSaveContext escontext
Definition: execnodes.h:1084
JsonBehavior * on_empty
Definition: primnodes.h:1835
JsonBehavior * on_error
Definition: primnodes.h:1836

References BoolGetDatum(), DatumGetBool(), ErrorSaveContext::details_wanted, JsonExprState::empty, ereport, errcode(), errdetail(), errmsg(), JsonExprState::error, ERROR, ErrorSaveContext::error_data, ErrorSaveContext::error_occurred, JsonExprState::escontext, GetJsonBehaviorValueString(), ExprEvalStep::jsestate, JsonExprState::jsexpr, ErrorData::message, JsonExpr::on_empty, JsonExpr::on_error, ExprEvalStep::op, SOFT_ERROR_OCCURRED, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalJsonConstructor()

void ExecEvalJsonConstructor ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 4225 of file execExprInterp.c.

4227 {
4228  Datum res;
4229  JsonConstructorExprState *jcstate = op->d.json_constructor.jcstate;
4230  JsonConstructorExpr *ctor = jcstate->constructor;
4231  bool is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
4232  bool isnull = false;
4233 
4234  if (ctor->type == JSCTOR_JSON_ARRAY)
4235  res = (is_jsonb ?
4237  json_build_array_worker) (jcstate->nargs,
4238  jcstate->arg_values,
4239  jcstate->arg_nulls,
4240  jcstate->arg_types,
4241  jcstate->constructor->absent_on_null);
4242  else if (ctor->type == JSCTOR_JSON_OBJECT)
4243  res = (is_jsonb ?
4245  json_build_object_worker) (jcstate->nargs,
4246  jcstate->arg_values,
4247  jcstate->arg_nulls,
4248  jcstate->arg_types,
4249  jcstate->constructor->absent_on_null,
4250  jcstate->constructor->unique);
4251  else if (ctor->type == JSCTOR_JSON_SCALAR)
4252  {
4253  if (jcstate->arg_nulls[0])
4254  {
4255  res = (Datum) 0;
4256  isnull = true;
4257  }
4258  else
4259  {
4260  Datum value = jcstate->arg_values[0];
4261  Oid outfuncid = jcstate->arg_type_cache[0].outfuncid;
4262  JsonTypeCategory category = (JsonTypeCategory)
4263  jcstate->arg_type_cache[0].category;
4264 
4265  if (is_jsonb)
4266  res = datum_to_jsonb(value, category, outfuncid);
4267  else
4268  res = datum_to_json(value, category, outfuncid);
4269  }
4270  }
4271  else if (ctor->type == JSCTOR_JSON_PARSE)
4272  {
4273  if (jcstate->arg_nulls[0])
4274  {
4275  res = (Datum) 0;
4276  isnull = true;
4277  }
4278  else
4279  {
4280  Datum value = jcstate->arg_values[0];
4281  text *js = DatumGetTextP(value);
4282 
4283  if (is_jsonb)
4284  res = jsonb_from_text(js, true);
4285  else
4286  {
4287  (void) json_validate(js, true, true);
4288  res = value;
4289  }
4290  }
4291  }
4292  else
4293  elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type);
4294 
4295  *op->resvalue = res;
4296  *op->resnull = isnull;
4297 }
#define DatumGetTextP(X)
Definition: fmgr.h:332
static struct @157 value
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Datum json_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Definition: json.c:1344
Datum json_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1224
Datum datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: json.c:763
bool json_validate(text *json, bool check_unique_keys, bool throw_error)
Definition: json.c:1812
Datum jsonb_from_text(text *js, bool unique_keys)
Definition: jsonb.c:147
Datum jsonb_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Definition: jsonb.c:1210
Datum jsonb_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1125
Datum datum_to_jsonb(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:1112
JsonTypeCategory
Definition: jsonfuncs.h:69
@ JS_FORMAT_JSONB
Definition: primnodes.h:1640
@ JSCTOR_JSON_PARSE
Definition: primnodes.h:1690
@ JSCTOR_JSON_OBJECT
Definition: primnodes.h:1686
@ JSCTOR_JSON_SCALAR
Definition: primnodes.h:1691
@ JSCTOR_JSON_ARRAY
Definition: primnodes.h:1687
struct ExprEvalStep::@54::@90 json_constructor
JsonConstructorExpr * constructor
Definition: execExpr.h:795
struct JsonConstructorExprState::@103 * arg_type_cache
JsonReturning * returning
Definition: primnodes.h:1706
JsonConstructorType type
Definition: primnodes.h:1702
JsonFormatType format_type
Definition: primnodes.h:1651
JsonFormat * format
Definition: primnodes.h:1663
Definition: c.h:687

References JsonConstructorExpr::absent_on_null, JsonConstructorExprState::arg_nulls, JsonConstructorExprState::arg_type_cache, JsonConstructorExprState::arg_types, JsonConstructorExprState::arg_values, JsonConstructorExprState::category, JsonConstructorExprState::constructor, datum_to_json(), datum_to_jsonb(), DatumGetTextP, elog, ERROR, JsonReturning::format, JsonFormat::format_type, if(), ExprEvalStep::isnull, ExprEvalStep::jcstate, JS_FORMAT_JSONB, JSCTOR_JSON_ARRAY, JSCTOR_JSON_OBJECT, JSCTOR_JSON_PARSE, JSCTOR_JSON_SCALAR, json_build_array_worker(), json_build_object_worker(), json_validate(), jsonb_build_array_worker(), jsonb_build_object_worker(), jsonb_from_text(), JsonConstructorExprState::nargs, ExprEvalStep::op, JsonConstructorExprState::outfuncid, res, JsonConstructorExpr::returning, JsonConstructorExpr::type, JsonConstructorExpr::unique, and value.

Referenced by ExecInterpExpr().

◆ ExecEvalJsonExprPath()

int ExecEvalJsonExprPath ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 4403 of file execExprInterp.c.

4405 {
4406  JsonExprState *jsestate = op->d.jsonexpr.jsestate;
4407  JsonExpr *jsexpr = jsestate->jsexpr;
4408  Datum item;
4409  JsonPath *path;
4410  bool throw_error = jsexpr->on_error->btype == JSON_BEHAVIOR_ERROR;
4411  bool error = false,
4412  empty = false;
4413  int jump_eval_coercion = jsestate->jump_eval_coercion;
4414  char *val_string = NULL;
4415 
4416  item = jsestate->formatted_expr.value;
4417  path = DatumGetJsonPathP(jsestate->pathspec.value);
4418 
4419  /* Set error/empty to false. */
4420  memset(&jsestate->error, 0, sizeof(NullableDatum));
4421  memset(&jsestate->empty, 0, sizeof(NullableDatum));
4422 
4423  /* Also reset ErrorSaveContext contents for the next row. */
4424  if (jsestate->escontext.details_wanted)
4425  {
4426  jsestate->escontext.error_data = NULL;
4427  jsestate->escontext.details_wanted = false;
4428  }
4429  jsestate->escontext.error_occurred = false;
4430 
4431  switch (jsexpr->op)
4432  {
4433  case JSON_EXISTS_OP:
4434  {
4435  bool exists = JsonPathExists(item, path,
4436  !throw_error ? &error : NULL,
4437  jsestate->args);
4438 
4439  if (!error)
4440  {
4441  *op->resnull = false;
4442  *op->resvalue = BoolGetDatum(exists);
4443  }
4444  }
4445  break;
4446 
4447  case JSON_QUERY_OP:
4448  *op->resvalue = JsonPathQuery(item, path, jsexpr->wrapper, &empty,
4449  !throw_error ? &error : NULL,
4450  jsestate->args,
4451  jsexpr->column_name);
4452 
4453  *op->resnull = (DatumGetPointer(*op->resvalue) == NULL);
4454  break;
4455 
4456  case JSON_VALUE_OP:
4457  {
4458  JsonbValue *jbv = JsonPathValue(item, path, &empty,
4459  !throw_error ? &error : NULL,
4460  jsestate->args,
4461  jsexpr->column_name);
4462 
4463  if (jbv == NULL)
4464  {
4465  /* Will be coerced with json_populate_type(), if needed. */
4466  *op->resvalue = (Datum) 0;
4467  *op->resnull = true;
4468  }
4469  else if (!error && !empty)
4470  {
4471  if (jsexpr->returning->typid == JSONOID ||
4472  jsexpr->returning->typid == JSONBOID)
4473  {
4476  }
4477  else if (jsexpr->use_json_coercion)
4478  {
4480  *op->resnull = false;
4481  }
4482  else
4483  {
4485 
4486  /*
4487  * Simply convert to the default RETURNING type (text)
4488  * if no coercion needed.
4489  */
4490  if (!jsexpr->use_io_coercion)
4493  }
4494  }
4495  break;
4496  }
4497 
4498  /* JSON_TABLE_OP can't happen here */
4499 
4500  default:
4501  elog(ERROR, "unrecognized SQL/JSON expression op %d",
4502  (int) jsexpr->op);
4503  return false;
4504  }
4505 
4506  /*
4507  * Coerce the result value to the RETURNING type by calling its input
4508  * function.
4509  */
4510  if (!*op->resnull && jsexpr->use_io_coercion)
4511  {
4512  FunctionCallInfo fcinfo;
4513 
4514  Assert(jump_eval_coercion == -1);
4515  fcinfo = jsestate->input_fcinfo;
4516  Assert(fcinfo != NULL);
4517  Assert(val_string != NULL);
4518  fcinfo->args[0].value = PointerGetDatum(val_string);
4519  fcinfo->args[0].isnull = *op->resnull;
4520 
4521  /*
4522  * Second and third arguments are already set up in
4523  * ExecInitJsonExpr().
4524  */
4525 
4526  fcinfo->isnull = false;
4527  *op->resvalue = FunctionCallInvoke(fcinfo);
4528  if (SOFT_ERROR_OCCURRED(&jsestate->escontext))
4529  error = true;
4530  }
4531 
4532  /*
4533  * When setting up the ErrorSaveContext (if needed) for capturing the
4534  * errors that occur when coercing the JsonBehavior expression, set
4535  * details_wanted to be able to show the actual error message as the
4536  * DETAIL of the error message that tells that it is the JsonBehavior
4537  * expression that caused the error; see ExecEvalJsonCoercionFinish().
4538  */
4539 
4540  /* Handle ON EMPTY. */
4541  if (empty)
4542  {
4543  *op->resvalue = (Datum) 0;
4544  *op->resnull = true;
4545  if (jsexpr->on_empty)
4546  {
4547  if (jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR)
4548  {
4549  jsestate->empty.value = BoolGetDatum(true);
4550  /* Set up to catch coercion errors of the ON EMPTY value. */
4551  jsestate->escontext.error_occurred = false;
4552  jsestate->escontext.details_wanted = true;
4553  /* Jump to end if the ON EMPTY behavior is to return NULL */
4554  return jsestate->jump_empty >= 0 ? jsestate->jump_empty : jsestate->jump_end;
4555  }
4556  }
4557  else if (jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR)
4558  {
4559  jsestate->error.value = BoolGetDatum(true);
4560  /* Set up to catch coercion errors of the ON ERROR value. */
4561  jsestate->escontext.error_occurred = false;
4562  jsestate->escontext.details_wanted = true;
4563  Assert(!throw_error);
4564  /* Jump to end if the ON ERROR behavior is to return NULL */
4565  return jsestate->jump_error >= 0 ? jsestate->jump_error : jsestate->jump_end;
4566  }
4567 
4568  if (jsexpr->column_name)
4569  ereport(ERROR,
4570  errcode(ERRCODE_NO_SQL_JSON_ITEM),
4571  errmsg("no SQL/JSON item found for specified path of column \"%s\"",
4572  jsexpr->column_name));
4573  else
4574  ereport(ERROR,
4575  errcode(ERRCODE_NO_SQL_JSON_ITEM),
4576  errmsg("no SQL/JSON item found for specified path"));
4577  }
4578 
4579  /*
4580  * ON ERROR. Wouldn't get here if the behavior is ERROR, because they
4581  * would have already been thrown.
4582  */
4583  if (error)
4584  {
4585  Assert(!throw_error);
4586  *op->resvalue = (Datum) 0;
4587  *op->resnull = true;
4588  jsestate->error.value = BoolGetDatum(true);
4589  /* Set up to catch coercion errors of the ON ERROR value. */
4590  jsestate->escontext.error_occurred = false;
4591  jsestate->escontext.details_wanted = true;
4592  /* Jump to end if the ON ERROR behavior is to return NULL */
4593  return jsestate->jump_error >= 0 ? jsestate->jump_error : jsestate->jump_end;
4594  }
4595 
4596  return jump_eval_coercion >= 0 ? jump_eval_coercion : jsestate->jump_end;
4597 }
static char * ExecGetJsonValueItemString(JsonbValue *item, bool *resnull)
char * val_string
Definition: informix.c:694
Datum jsonb_out(PG_FUNCTION_ARGS)
Definition: jsonb.c:108
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:386
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
static JsonPath * DatumGetJsonPathP(Datum d)
Definition: jsonpath.h:35
bool JsonPathExists(Datum jb, JsonPath *jp, bool *error, List *vars)
Datum JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, bool *error, List *vars, const char *column_name)
JsonbValue * JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars, const char *column_name)
@ JSON_BEHAVIOR_ERROR
Definition: primnodes.h:1762
@ JSON_QUERY_OP
Definition: primnodes.h:1799
@ JSON_EXISTS_OP
Definition: primnodes.h:1798
@ JSON_VALUE_OP
Definition: primnodes.h:1800
static void error(void)
Definition: sql-dyntest.c:147
JsonBehaviorType btype
Definition: primnodes.h:1786
int jump_eval_coercion
Definition: execnodes.h:1061
FunctionCallInfo input_fcinfo
Definition: execnodes.h:1075
NullableDatum pathspec
Definition: execnodes.h:1031
NullableDatum formatted_expr
Definition: execnodes.h:1028
char * column_name
Definition: primnodes.h:1815
bool use_io_coercion
Definition: primnodes.h:1842
JsonReturning * returning
Definition: primnodes.h:1828
bool use_json_coercion
Definition: primnodes.h:1843
JsonWrapper wrapper
Definition: primnodes.h:1846
JsonExprOp op
Definition: primnodes.h:1813
Datum textin(PG_FUNCTION_ARGS)
Definition: varlena.c:579

References FunctionCallInfoBaseData::args, JsonExprState::args, Assert, BoolGetDatum(), JsonBehavior::btype, JsonExpr::column_name, CStringGetDatum(), DatumGetCString(), DatumGetJsonPathP(), DatumGetPointer(), ErrorSaveContext::details_wanted, DirectFunctionCall1, elog, JsonExprState::empty, ereport, errcode(), errmsg(), JsonExprState::error, ERROR, error(), ErrorSaveContext::error_data, ErrorSaveContext::error_occurred, JsonExprState::escontext, ExecGetJsonValueItemString(), JsonExprState::formatted_expr, FunctionCallInvoke, JsonExprState::input_fcinfo, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, ExprEvalStep::jsestate, JsonExprState::jsexpr, JSON_BEHAVIOR_ERROR, JSON_EXISTS_OP, JSON_QUERY_OP, JSON_VALUE_OP, jsonb_out(), JsonbPGetDatum(), JsonbValueToJsonb(), JsonPathExists(), JsonPathQuery(), JsonPathValue(), JsonExprState::jump_empty, JsonExprState::jump_end, JsonExprState::jump_error, JsonExprState::jump_eval_coercion, JsonExpr::on_empty, JsonExpr::on_error, ExprEvalStep::op, JsonExpr::op, JsonExprState::pathspec, PointerGetDatum(), JsonExpr::returning, SOFT_ERROR_OCCURRED, textin(), JsonReturning::typid, JsonExpr::use_io_coercion, JsonExpr::use_json_coercion, val_string, NullableDatum::value, and JsonExpr::wrapper.

Referenced by ExecInterpExpr().

◆ ExecEvalJsonIsPredicate()

void ExecEvalJsonIsPredicate ( ExprState state,
ExprEvalStep op 
)

Definition at line 4303 of file execExprInterp.c.

4304 {
4305  JsonIsPredicate *pred = op->d.is_json.pred;
4306  Datum js = *op->resvalue;
4307  Oid exprtype;
4308  bool res;
4309 
4310  if (*op->resnull)
4311  {
4312  *op->resvalue = BoolGetDatum(false);
4313  return;
4314  }
4315 
4316  exprtype = exprType(pred->expr);
4317 
4318  if (exprtype == TEXTOID || exprtype == JSONOID)
4319  {
4320  text *json = DatumGetTextP(js);
4321 
4322  if (pred->item_type == JS_TYPE_ANY)
4323  res = true;
4324  else
4325  {
4326  switch (json_get_first_token(json, false))
4327  {
4329  res = pred->item_type == JS_TYPE_OBJECT;
4330  break;
4332  res = pred->item_type == JS_TYPE_ARRAY;
4333  break;
4334  case JSON_TOKEN_STRING:
4335  case JSON_TOKEN_NUMBER:
4336  case JSON_TOKEN_TRUE:
4337  case JSON_TOKEN_FALSE:
4338  case JSON_TOKEN_NULL:
4339  res = pred->item_type == JS_TYPE_SCALAR;
4340  break;
4341  default:
4342  res = false;
4343  break;
4344  }
4345  }
4346 
4347  /*
4348  * Do full parsing pass only for uniqueness check or for JSON text
4349  * validation.
4350  */
4351  if (res && (pred->unique_keys || exprtype == TEXTOID))
4352  res = json_validate(json, pred->unique_keys, false);
4353  }
4354  else if (exprtype == JSONBOID)
4355  {
4356  if (pred->item_type == JS_TYPE_ANY)
4357  res = true;
4358  else
4359  {
4360  Jsonb *jb = DatumGetJsonbP(js);
4361 
4362  switch (pred->item_type)
4363  {
4364  case JS_TYPE_OBJECT:
4365  res = JB_ROOT_IS_OBJECT(jb);
4366  break;
4367  case JS_TYPE_ARRAY:
4368  res = JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb);
4369  break;
4370  case JS_TYPE_SCALAR:
4371  res = JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb);
4372  break;
4373  default:
4374  res = false;
4375  break;
4376  }
4377  }
4378 
4379  /* Key uniqueness check is redundant for jsonb */
4380  }
4381  else
4382  res = false;
4383 
4384  *op->resvalue = BoolGetDatum(res);
4385 }
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:29
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:28
@ JSON_TOKEN_NULL
Definition: jsonapi.h:30
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:22
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:21
@ JSON_TOKEN_STRING
Definition: jsonapi.h:20
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:24
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:221
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:222
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:220
JsonTokenType json_get_first_token(text *json, bool throw_error)
Definition: jsonfuncs.c:5949
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
@ JS_TYPE_ANY
Definition: primnodes.h:1718
@ JS_TYPE_ARRAY
Definition: primnodes.h:1720
@ JS_TYPE_OBJECT
Definition: primnodes.h:1719
@ JS_TYPE_SCALAR
Definition: primnodes.h:1721
struct ExprEvalStep::@54::@100 is_json
JsonValueType item_type
Definition: primnodes.h:1733
Definition: jsonb.h:213

References BoolGetDatum(), DatumGetJsonbP(), DatumGetTextP, JsonIsPredicate::expr, exprType(), JsonIsPredicate::item_type, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JS_TYPE_ANY, JS_TYPE_ARRAY, JS_TYPE_OBJECT, JS_TYPE_SCALAR, json_get_first_token(), JSON_TOKEN_ARRAY_START, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_OBJECT_START, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, json_validate(), ExprEvalStep::op, ExprEvalStep::pred, res, and JsonIsPredicate::unique_keys.

Referenced by ExecInterpExpr().

◆ ExecEvalMergeSupportFunc()

void ExecEvalMergeSupportFunc ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 4841 of file execExprInterp.c.

4843 {
4844  ModifyTableState *mtstate = castNode(ModifyTableState, state->parent);
4845  MergeActionState *relaction = mtstate->mt_merge_action;
4846 
4847  if (!relaction)
4848  elog(ERROR, "no merge action in progress");
4849 
4850  /* Return the MERGE action ("INSERT", "UPDATE", or "DELETE") */
4851  switch (relaction->mas_action->commandType)
4852  {
4853  case CMD_INSERT:
4854  *op->resvalue = PointerGetDatum(cstring_to_text_with_len("INSERT", 6));
4855  *op->resnull = false;
4856  break;
4857  case CMD_UPDATE:
4858  *op->resvalue = PointerGetDatum(cstring_to_text_with_len("UPDATE", 6));
4859  *op->resnull = false;
4860  break;
4861  case CMD_DELETE:
4862  *op->resvalue = PointerGetDatum(cstring_to_text_with_len("DELETE", 6));
4863  *op->resnull = false;
4864  break;
4865  case CMD_NOTHING:
4866  elog(ERROR, "unexpected merge action: DO NOTHING");
4867  break;
4868  default:
4869  elog(ERROR, "unrecognized commandType: %d",
4870  (int) relaction->mas_action->commandType);
4871  }
4872 }
@ CMD_INSERT
Definition: nodes.h:267
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
@ CMD_NOTHING
Definition: nodes.h:272
MergeAction * mas_action
Definition: execnodes.h:427
CmdType commandType
Definition: primnodes.h:2003
MergeActionState * mt_merge_action
Definition: execnodes.h:1405
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

References castNode, CMD_DELETE, CMD_INSERT, CMD_NOTHING, CMD_UPDATE, MergeAction::commandType, cstring_to_text_with_len(), elog, ERROR, MergeActionState::mas_action, ModifyTableState::mt_merge_action, ExprEvalStep::op, and PointerGetDatum().

Referenced by ExecInterpExpr().

◆ ExecEvalMinMax()

void ExecEvalMinMax ( ExprState state,
ExprEvalStep op 
)

Definition at line 3244 of file execExprInterp.c.

3245 {
3246  Datum *values = op->d.minmax.values;
3247  bool *nulls = op->d.minmax.nulls;
3248  FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
3249  MinMaxOp operator = op->d.minmax.op;
3250 
3251  /* set at initialization */
3252  Assert(fcinfo->args[0].isnull == false);
3253  Assert(fcinfo->args[1].isnull == false);
3254 
3255  /* default to null result */
3256  *op->resnull = true;
3257 
3258  for (int off = 0; off < op->d.minmax.nelems; off++)
3259  {
3260  /* ignore NULL inputs */
3261  if (nulls[off])
3262  continue;
3263 
3264  if (*op->resnull)
3265  {
3266  /* first nonnull input, adopt value */
3267  *op->resvalue = values[off];
3268  *op->resnull = false;
3269  }
3270  else
3271  {
3272  int cmpresult;
3273 
3274  /* apply comparison function */
3275  fcinfo->args[0].value = *op->resvalue;
3276  fcinfo->args[1].value = values[off];
3277 
3278  fcinfo->isnull = false;
3279  cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
3280  if (fcinfo->isnull) /* probably should not happen */
3281  continue;
3282 
3283  if (cmpresult > 0 && operator == IS_LEAST)
3284  *op->resvalue = values[off];
3285  else if (cmpresult < 0 && operator == IS_GREATEST)
3286  *op->resvalue = values[off];
3287  }
3288  }
3289 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
MinMaxOp
Definition: primnodes.h:1501
@ IS_LEAST
Definition: primnodes.h:1503
@ IS_GREATEST
Definition: primnodes.h:1502
struct ExprEvalStep::@54::@78 minmax

References FunctionCallInfoBaseData::args, Assert, DatumGetInt32(), FunctionCallInvoke, IS_GREATEST, IS_LEAST, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, ExprEvalStep::nulls, ExprEvalStep::op, NullableDatum::value, and values.

Referenced by ExecInterpExpr().

◆ ExecEvalNextValueExpr()

void ExecEvalNextValueExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2841 of file execExprInterp.c.

2842 {
2843  int64 newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
2844 
2845  switch (op->d.nextvalueexpr.seqtypid)
2846  {
2847  case INT2OID:
2848  *op->resvalue = Int16GetDatum((int16) newval);
2849  break;
2850  case INT4OID:
2851  *op->resvalue = Int32GetDatum((int32) newval);
2852  break;
2853  case INT8OID:
2854  *op->resvalue = Int64GetDatum((int64) newval);
2855  break;
2856  default:
2857  elog(ERROR, "unsupported sequence type %u",
2858  op->d.nextvalueexpr.seqtypid);
2859  }
2860  *op->resnull = false;
2861 }
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:623
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807
#define newval
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
struct ExprEvalStep::@54::@72 nextvalueexpr

References elog, ERROR, Int16GetDatum(), Int32GetDatum(), Int64GetDatum(), newval, nextval_internal(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalParamExec()

void ExecEvalParamExec ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2616 of file execExprInterp.c.

2617 {
2618  ParamExecData *prm;
2619 
2620  prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2621  if (unlikely(prm->execPlan != NULL))
2622  {
2623  /* Parameter not evaluated yet, so go do it */
2624  ExecSetParamPlan(prm->execPlan, econtext);
2625  /* ExecSetParamPlan should have processed this param... */
2626  Assert(prm->execPlan == NULL);
2627  }
2628  *op->resvalue = prm->value;
2629  *op->resnull = prm->isnull;
2630 }
void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
Definition: nodeSubplan.c:1087
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:268
struct ExprEvalStep::@54::@66 param
bool isnull
Definition: params.h:150
Datum value
Definition: params.h:149
void * execPlan
Definition: params.h:148

References Assert, ExprContext::ecxt_param_exec_vals, ParamExecData::execPlan, ExecSetParamPlan(), ParamExecData::isnull, ExprEvalStep::op, unlikely, and ParamExecData::value.

Referenced by ExecInterpExpr().

◆ ExecEvalParamExtern()

void ExecEvalParamExtern ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2638 of file execExprInterp.c.

2639 {
2640  ParamListInfo paramInfo = econtext->ecxt_param_list_info;
2641  int paramId = op->d.param.paramid;
2642 
2643  if (likely(paramInfo &&
2644  paramId > 0 && paramId <= paramInfo->numParams))
2645  {
2646  ParamExternData *prm;
2647  ParamExternData prmdata;
2648 
2649  /* give hook a chance in case parameter is dynamic */
2650  if (paramInfo->paramFetch != NULL)
2651  prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
2652  else
2653  prm = &paramInfo->params[paramId - 1];
2654 
2655  if (likely(OidIsValid(prm->ptype)))
2656  {
2657  /* safety check in case hook did something unexpected */
2658  if (unlikely(prm->ptype != op->d.param.paramtype))
2659  ereport(ERROR,
2660  (errcode(ERRCODE_DATATYPE_MISMATCH),
2661  errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
2662  paramId,
2663  format_type_be(prm->ptype),
2664  format_type_be(op->d.param.paramtype))));
2665  *op->resvalue = prm->value;
2666  *op->resnull = prm->isnull;
2667  return;
2668  }
2669  }
2670 
2671  ereport(ERROR,
2672  (errcode(ERRCODE_UNDEFINED_OBJECT),
2673  errmsg("no value found for parameter %d", paramId)));
2674 }
#define likely(x)
Definition: c.h:310
#define OidIsValid(objectId)
Definition: c.h:775
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:269
bool isnull
Definition: params.h:93
Datum value
Definition: params.h:92
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125
ParamFetchHook paramFetch
Definition: params.h:112

References ExprContext::ecxt_param_list_info, ereport, errcode(), errmsg(), ERROR, format_type_be(), ParamExternData::isnull, likely, OidIsValid, ExprEvalStep::op, ParamListInfoData::paramFetch, ParamListInfoData::params, ParamExternData::ptype, unlikely, and ParamExternData::value.

Referenced by ExecInterpExpr().

◆ ExecEvalParamSet()

void ExecEvalParamSet ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2681 of file execExprInterp.c.

2682 {
2683  ParamExecData *prm;
2684 
2685  prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2686 
2687  /* Shouldn't have a pending evaluation anymore */
2688  Assert(prm->execPlan == NULL);
2689 
2690  prm->value = state->resvalue;
2691  prm->isnull = state->resnull;
2692 }

References Assert, ExprContext::ecxt_param_exec_vals, ParamExecData::execPlan, ParamExecData::isnull, ExprEvalStep::op, and ParamExecData::value.

Referenced by ExecInterpExpr().

◆ ExecEvalPreOrderedDistinctMulti()

bool ExecEvalPreOrderedDistinctMulti ( AggState aggstate,
AggStatePerTrans  pertrans 
)

Definition at line 5287 of file execExprInterp.c.

5288 {
5289  ExprContext *tmpcontext = aggstate->tmpcontext;
5290  bool isdistinct = false; /* for now */
5291  TupleTableSlot *save_outer;
5292  TupleTableSlot *save_inner;
5293 
5294  for (int i = 0; i < pertrans->numTransInputs; i++)
5295  {
5296  pertrans->sortslot->tts_values[i] = pertrans->transfn_fcinfo->args[i + 1].value;
5297  pertrans->sortslot->tts_isnull[i] = pertrans->transfn_fcinfo->args[i + 1].isnull;
5298  }
5299 
5300  ExecClearTuple(pertrans->sortslot);
5301  pertrans->sortslot->tts_nvalid = pertrans->numInputs;
5302  ExecStoreVirtualTuple(pertrans->sortslot);
5303 
5304  /* save the previous slots before we overwrite them */
5305  save_outer = tmpcontext->ecxt_outertuple;
5306  save_inner = tmpcontext->ecxt_innertuple;
5307 
5308  tmpcontext->ecxt_outertuple = pertrans->sortslot;
5309  tmpcontext->ecxt_innertuple = pertrans->uniqslot;
5310 
5311  if (!pertrans->haslast ||
5312  !ExecQual(pertrans->equalfnMulti, tmpcontext))
5313  {
5314  if (pertrans->haslast)
5315  ExecClearTuple(pertrans->uniqslot);
5316 
5317  pertrans->haslast = true;
5318  ExecCopySlot(pertrans->uniqslot, pertrans->sortslot);
5319 
5320  isdistinct = true;
5321  }
5322 
5323  /* restore the original slots */
5324  tmpcontext->ecxt_outertuple = save_outer;
5325  tmpcontext->ecxt_innertuple = save_inner;
5326 
5327  return isdistinct;
5328 }
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:424
ExprState * equalfnMulti
Definition: nodeAgg.h:116
TupleTableSlot * uniqslot
Definition: nodeAgg.h:142
ExprContext * tmpcontext
Definition: execnodes.h:2502
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:509

References FunctionCallInfoBaseData::args, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, AggStatePerTransData::equalfnMulti, ExecClearTuple(), ExecCopySlot(), ExecQual(), ExecStoreVirtualTuple(), AggStatePerTransData::haslast, i, NullableDatum::isnull, AggStatePerTransData::numInputs, AggStatePerTransData::numTransInputs, ExprEvalStep::pertrans, AggStatePerTransData::sortslot, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, TupleTableSlot::tts_isnull, TupleTableSlot::tts_nvalid, TupleTableSlot::tts_values, AggStatePerTransData::uniqslot, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalPreOrderedDistinctSingle()

bool ExecEvalPreOrderedDistinctSingle ( AggState aggstate,
AggStatePerTrans  pertrans 
)

Definition at line 5244 of file execExprInterp.c.

5245 {
5246  Datum value = pertrans->transfn_fcinfo->args[1].value;
5247  bool isnull = pertrans->transfn_fcinfo->args[1].isnull;
5248 
5249  if (!pertrans->haslast ||
5250  pertrans->lastisnull != isnull ||
5251  (!isnull && !DatumGetBool(FunctionCall2Coll(&pertrans->equalfnOne,
5252  pertrans->aggCollation,
5253  pertrans->lastdatum, value))))
5254  {
5255  if (pertrans->haslast && !pertrans->inputtypeByVal &&
5256  !pertrans->lastisnull)
5257  pfree(DatumGetPointer(pertrans->lastdatum));
5258 
5259  pertrans->haslast = true;
5260  if (!isnull)
5261  {
5262  MemoryContext oldContext;
5263 
5265 
5266  pertrans->lastdatum = datumCopy(value, pertrans->inputtypeByVal,
5267  pertrans->inputtypeLen);
5268 
5269  MemoryContextSwitchTo(oldContext);
5270  }
5271  else
5272  pertrans->lastdatum = (Datum) 0;
5273  pertrans->lastisnull = isnull;
5274  return true;
5275  }
5276 
5277  return false;
5278 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
FmgrInfo equalfnOne
Definition: nodeAgg.h:115

References AggStatePerTransData::aggCollation, FunctionCallInfoBaseData::args, AggState::curaggcontext, datumCopy(), DatumGetBool(), DatumGetPointer(), ExprContext::ecxt_per_tuple_memory, AggStatePerTransData::equalfnOne, FunctionCall2Coll(), AggStatePerTransData::haslast, AggStatePerTransData::inputtypeByVal, AggStatePerTransData::inputtypeLen, ExprEvalStep::isnull, NullableDatum::isnull, AggStatePerTransData::lastdatum, AggStatePerTransData::lastisnull, MemoryContextSwitchTo(), ExprEvalStep::pertrans, pfree(), AggStatePerTransData::transfn_fcinfo, NullableDatum::value, and value.

Referenced by ExecInterpExpr().

◆ ExecEvalRow()

void ExecEvalRow ( ExprState state,
ExprEvalStep op 
)

Definition at line 3224 of file execExprInterp.c.

3225 {
3226  HeapTuple tuple;
3227 
3228  /* build tuple from evaluated field values */
3229  tuple = heap_form_tuple(op->d.row.tupdesc,
3230  op->d.row.elemvalues,
3231  op->d.row.elemnulls);
3232 
3233  *op->resvalue = HeapTupleGetDatum(tuple);
3234  *op->resnull = false;
3235 }
struct ExprEvalStep::@54::@75 row

References heap_form_tuple(), HeapTupleGetDatum(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalRowNotNull()

void ExecEvalRowNotNull ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2876 of file execExprInterp.c.

2877 {
2878  ExecEvalRowNullInt(state, op, econtext, false);
2879 }
static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, ExprContext *econtext, bool checkisnull)

References ExecEvalRowNullInt(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalRowNull()

void ExecEvalRowNull ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 2867 of file execExprInterp.c.

2868 {
2869  ExecEvalRowNullInt(state, op, econtext, true);
2870 }

References ExecEvalRowNullInt(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalScalarArrayOp()

void ExecEvalScalarArrayOp ( ExprState state,
ExprEvalStep op 
)

Definition at line 3591 of file execExprInterp.c.

3592 {
3593  FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
3594  bool useOr = op->d.scalararrayop.useOr;
3595  bool strictfunc = op->d.scalararrayop.finfo->fn_strict;
3596  ArrayType *arr;
3597  int nitems;
3598  Datum result;
3599  bool resultnull;
3600  int16 typlen;
3601  bool typbyval;
3602  char typalign;
3603  char *s;
3604  bits8 *bitmap;
3605  int bitmask;
3606 
3607  /*
3608  * If the array is NULL then we return NULL --- it's not very meaningful
3609  * to do anything else, even if the operator isn't strict.
3610  */
3611  if (*op->resnull)
3612  return;
3613 
3614  /* Else okay to fetch and detoast the array */
3615  arr = DatumGetArrayTypeP(*op->resvalue);
3616 
3617  /*
3618  * If the array is empty, we return either FALSE or TRUE per the useOr
3619  * flag. This is correct even if the scalar is NULL; since we would
3620  * evaluate the operator zero times, it matters not whether it would want
3621  * to return NULL.
3622  */
3623  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3624  if (nitems <= 0)
3625  {
3626  *op->resvalue = BoolGetDatum(!useOr);
3627  *op->resnull = false;
3628  return;
3629  }
3630 
3631  /*
3632  * If the scalar is NULL, and the function is strict, return NULL; no
3633  * point in iterating the loop.
3634  */
3635  if (fcinfo->args[0].isnull && strictfunc)
3636  {
3637  *op->resnull = true;
3638  return;
3639  }
3640 
3641  /*
3642  * We arrange to look up info about the element type only once per series
3643  * of calls, assuming the element type doesn't change underneath us.
3644  */
3645  if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
3646  {
3648  &op->d.scalararrayop.typlen,
3649  &op->d.scalararrayop.typbyval,
3650  &op->d.scalararrayop.typalign);
3651  op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
3652  }
3653 
3654  typlen = op->d.scalararrayop.typlen;
3655  typbyval = op->d.scalararrayop.typbyval;
3656  typalign = op->d.scalararrayop.typalign;
3657 
3658  /* Initialize result appropriately depending on useOr */
3659  result = BoolGetDatum(!useOr);
3660  resultnull = false;
3661 
3662  /* Loop over the array elements */
3663  s = (char *) ARR_DATA_PTR(arr);
3664  bitmap = ARR_NULLBITMAP(arr);
3665  bitmask = 1;
3666 
3667  for (int i = 0; i < nitems; i++)
3668  {
3669  Datum elt;
3670  Datum thisresult;
3671 
3672  /* Get array element, checking for NULL */
3673  if (bitmap && (*bitmap & bitmask) == 0)
3674  {
3675  fcinfo->args[1].value = (Datum) 0;
3676  fcinfo->args[1].isnull = true;
3677  }
3678  else
3679  {
3680  elt = fetch_att(s, typbyval, typlen);
3681  s = att_addlength_pointer(s, typlen, s);
3682  s = (char *) att_align_nominal(s, typalign);
3683  fcinfo->args[1].value = elt;
3684  fcinfo->args[1].isnull = false;
3685  }
3686 
3687  /* Call comparison function */
3688  if (fcinfo->args[1].isnull && strictfunc)
3689  {
3690  fcinfo->isnull = true;
3691  thisresult = (Datum) 0;
3692  }
3693  else
3694  {
3695  fcinfo->isnull = false;
3696  thisresult = op->d.scalararrayop.fn_addr(fcinfo);
3697  }
3698 
3699  /* Combine results per OR or AND semantics */
3700  if (fcinfo->isnull)
3701  resultnull = true;
3702  else if (useOr)
3703  {
3704  if (DatumGetBool(thisresult))
3705  {
3706  result = BoolGetDatum(true);
3707  resultnull = false;
3708  break; /* needn't look at any more elements */
3709  }
3710  }
3711  else
3712  {
3713  if (!DatumGetBool(thisresult))
3714  {
3715  result = BoolGetDatum(false);
3716  resultnull = false;
3717  break; /* needn't look at any more elements */
3718  }
3719  }
3720 
3721  /* advance bitmap pointer if any */
3722  if (bitmap)
3723  {
3724  bitmask <<= 1;
3725  if (bitmask == 0x100)
3726  {
3727  bitmap++;
3728  bitmask = 1;
3729  }
3730  }
3731  }
3732 
3733  *op->resvalue = result;
3734  *op->resnull = resultnull;
3735 }
struct ExprEvalStep::@54::@87 scalararrayop

References FunctionCallInfoBaseData::args, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), att_addlength_pointer, att_align_nominal, BoolGetDatum(), DatumGetArrayTypeP, DatumGetBool(), fetch_att(), get_typlenbyvalalign(), i, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, nitems, ExprEvalStep::op, typalign, ExprEvalStep::typbyval, ExprEvalStep::typlen, ExprEvalStep::useOr, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalSQLValueFunction()

void ExecEvalSQLValueFunction ( ExprState state,
ExprEvalStep op 
)

Definition at line 2763 of file execExprInterp.c.

2764 {
2765  LOCAL_FCINFO(fcinfo, 0);
2766  SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
2767 
2768  *op->resnull = false;
2769 
2770  /*
2771  * Note: current_schema() can return NULL. current_user() etc currently
2772  * cannot, but might as well code those cases the same way for safety.
2773  */
2774  switch (svf->op)
2775  {
2776  case SVFOP_CURRENT_DATE:
2778  break;
2779  case SVFOP_CURRENT_TIME:
2780  case SVFOP_CURRENT_TIME_N:
2782  break;
2786  break;
2787  case SVFOP_LOCALTIME:
2788  case SVFOP_LOCALTIME_N:
2790  break;
2791  case SVFOP_LOCALTIMESTAMP:
2794  break;
2795  case SVFOP_CURRENT_ROLE:
2796  case SVFOP_CURRENT_USER:
2797  case SVFOP_USER:
2798  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2799  *op->resvalue = current_user(fcinfo);
2800  *op->resnull = fcinfo->isnull;
2801  break;
2802  case SVFOP_SESSION_USER:
2803  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2804  *op->resvalue = session_user(fcinfo);
2805  *op->resnull = fcinfo->isnull;
2806  break;
2807  case SVFOP_CURRENT_CATALOG:
2808  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2809  *op->resvalue = current_database(fcinfo);
2810  *op->resnull = fcinfo->isnull;
2811  break;
2812  case SVFOP_CURRENT_SCHEMA:
2813  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2814  *op->resvalue = current_schema(fcinfo);
2815  *op->resnull = fcinfo->isnull;
2816  break;
2817  }
2818 }
Datum current_database(PG_FUNCTION_ARGS)
Definition: misc.c:195
Timestamp GetSQLLocalTimestamp(int32 typmod)
Definition: timestamp.c:1676
TimestampTz GetSQLCurrentTimestamp(int32 typmod)
Definition: timestamp.c:1662
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:342
TimeADT GetSQLLocalTime(int32 typmod)
Definition: date.c:362
DateADT GetSQLCurrentDate(void)
Definition: date.c:309
static Datum DateADTGetDatum(DateADT X)
Definition: date.h:72
static Datum TimeTzADTPGetDatum(const TimeTzADT *X)
Definition: date.h:84
static Datum TimeADTGetDatum(TimeADT X)
Definition: date.h:78
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
Datum current_user(PG_FUNCTION_ARGS)
Definition: name.c:263
Datum session_user(PG_FUNCTION_ARGS)
Definition: name.c:269
Datum current_schema(PG_FUNCTION_ARGS)
Definition: name.c:279
@ SVFOP_CURRENT_CATALOG
Definition: primnodes.h:1549
@ SVFOP_LOCALTIME_N
Definition: primnodes.h:1542
@ SVFOP_CURRENT_TIMESTAMP
Definition: primnodes.h:1539
@ SVFOP_LOCALTIME
Definition: primnodes.h:1541
@ SVFOP_CURRENT_TIMESTAMP_N
Definition: primnodes.h:1540
@ SVFOP_CURRENT_ROLE
Definition: primnodes.h:1545
@ SVFOP_USER
Definition: primnodes.h:1547
@ SVFOP_CURRENT_SCHEMA
Definition: primnodes.h:1550
@ SVFOP_LOCALTIMESTAMP_N
Definition: primnodes.h:1544
@ SVFOP_CURRENT_DATE
Definition: primnodes.h:1536
@ SVFOP_CURRENT_TIME_N
Definition: primnodes.h:1538
@ SVFOP_CURRENT_TIME
Definition: primnodes.h:1537
@ SVFOP_LOCALTIMESTAMP
Definition: primnodes.h:1543
@ SVFOP_CURRENT_USER
Definition: primnodes.h:1546
@ SVFOP_SESSION_USER
Definition: primnodes.h:1548
struct ExprEvalStep::@54::@71 sqlvaluefunction
SQLValueFunctionOp op
Definition: primnodes.h:1556
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46

References current_database(), current_schema(), current_user(), DateADTGetDatum(), GetSQLCurrentDate(), GetSQLCurrentTime(), GetSQLCurrentTimestamp(), GetSQLLocalTime(), GetSQLLocalTimestamp(), InitFunctionCallInfoData, InvalidOid, LOCAL_FCINFO, ExprEvalStep::op, SQLValueFunction::op, session_user(), ExprEvalStep::svf, SVFOP_CURRENT_CATALOG, SVFOP_CURRENT_DATE, SVFOP_CURRENT_ROLE, SVFOP_CURRENT_SCHEMA, SVFOP_CURRENT_TIME, SVFOP_CURRENT_TIME_N, SVFOP_CURRENT_TIMESTAMP, SVFOP_CURRENT_TIMESTAMP_N, SVFOP_CURRENT_USER, SVFOP_LOCALTIME, SVFOP_LOCALTIME_N, SVFOP_LOCALTIMESTAMP, SVFOP_LOCALTIMESTAMP_N, SVFOP_SESSION_USER, SVFOP_USER, TimeADTGetDatum(), TimestampGetDatum(), TimestampTzGetDatum(), TimeTzADTPGetDatum(), and SQLValueFunction::typmod.

Referenced by ExecInterpExpr().

◆ ExecEvalStepOp()

ExprEvalOp ExecEvalStepOp ( ExprState state,
ExprEvalStep op 
)

Definition at line 2528 of file execExprInterp.c.

2529 {
2530 #if defined(EEO_USE_COMPUTED_GOTO)
2531  if (state->flags & EEO_FLAG_DIRECT_THREADED)
2532  {
2533  ExprEvalOpLookup key;
2534  ExprEvalOpLookup *res;
2535 
2536  key.opcode = (void *) op->opcode;
2537  res = bsearch(&key,
2538  reverse_dispatch_table,
2539  EEOP_LAST /* nmembers */ ,
2540  sizeof(ExprEvalOpLookup),
2541  dispatch_compare_ptr);
2542  Assert(res); /* unknown ops shouldn't get looked up */
2543  return res->op;
2544  }
2545 #endif
2546  return (ExprEvalOp) op->opcode;
2547 }
#define EEO_FLAG_DIRECT_THREADED
Definition: execExpr.h:31
intptr_t opcode
Definition: execExpr.h:290

References Assert, EEO_FLAG_DIRECT_THREADED, EEOP_LAST, sort-test::key, ExprEvalStep::op, and res.

Referenced by CheckExprStillValid().

◆ ExecEvalSubPlan()

void ExecEvalSubPlan ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 4878 of file execExprInterp.c.

4879 {
4880  SubPlanState *sstate = op->d.subplan.sstate;
4881 
4882  /* could potentially be nested, so make sure there's enough stack */
4884 
4885  *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
4886 }
Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:62
void check_stack_depth(void)
Definition: postgres.c:3540
struct ExprEvalStep::@54::@94 subplan

References check_stack_depth(), ExecSubPlan(), ExprEvalStep::op, and ExprEvalStep::sstate.

Referenced by ExecInterpExpr().

◆ ExecEvalSysVar()

void ExecEvalSysVar ( ExprState state,
ExprEvalStep op,
ExprContext econtext,
TupleTableSlot slot 
)

Definition at line 5122 of file execExprInterp.c.

5124 {
5125  Datum d;
5126 
5127  /* slot_getsysattr has sufficient defenses against bad attnums */
5128  d = slot_getsysattr(slot,
5129  op->d.var.attnum,
5130  op->resnull);
5131  *op->resvalue = d;
5132  /* this ought to be unreachable, but it's cheap enough to check */
5133  if (unlikely(*op->resnull))
5134  elog(ERROR, "failed to fetch attribute from slot");
5135 }
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:416

References ExprEvalStep::d, elog, ERROR, ExprEvalStep::op, slot_getsysattr(), and unlikely.

Referenced by ExecInterpExpr().

◆ ExecEvalWholeRowVar()

void ExecEvalWholeRowVar ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)

Definition at line 4895 of file execExprInterp.c.

4896 {
4897  Var *variable = op->d.wholerow.var;
4898  TupleTableSlot *slot;
4899  TupleDesc output_tupdesc;
4900  MemoryContext oldcontext;
4901  HeapTupleHeader dtuple;
4902  HeapTuple tuple;
4903 
4904  /* This was checked by ExecInitExpr */
4905  Assert(variable->varattno == InvalidAttrNumber);
4906 
4907  /* Get the input slot we want */
4908  switch (variable->varno)
4909  {
4910  case INNER_VAR:
4911  /* get the tuple from the inner node */
4912  slot = econtext->ecxt_innertuple;
4913  break;
4914 
4915  case OUTER_VAR:
4916  /* get the tuple from the outer node */
4917  slot = econtext->ecxt_outertuple;
4918  break;
4919 
4920  /* INDEX_VAR is handled by default case */
4921 
4922  default:
4923  /* get the tuple from the relation being scanned */
4924  slot = econtext->ecxt_scantuple;
4925  break;
4926  }
4927 
4928  /* Apply the junkfilter if any */
4929  if (op->d.wholerow.junkFilter != NULL)
4930  slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
4931 
4932  /*
4933  * If first time through, obtain tuple descriptor and check compatibility.
4934  *
4935  * XXX: It'd be great if this could be moved to the expression
4936  * initialization phase, but due to using slots that's currently not
4937  * feasible.
4938  */
4939  if (op->d.wholerow.first)
4940  {
4941  /* optimistically assume we don't need slow path */
4942  op->d.wholerow.slow = false;
4943 
4944  /*
4945  * If the Var identifies a named composite type, we must check that
4946  * the actual tuple type is compatible with it.
4947  */
4948  if (variable->vartype != RECORDOID)
4949  {
4950  TupleDesc var_tupdesc;
4951  TupleDesc slot_tupdesc;
4952 
4953  /*
4954  * We really only care about numbers of attributes and data types.
4955  * Also, we can ignore type mismatch on columns that are dropped
4956  * in the destination type, so long as (1) the physical storage
4957  * matches or (2) the actual column value is NULL. Case (1) is
4958  * helpful in some cases involving out-of-date cached plans, while
4959  * case (2) is expected behavior in situations such as an INSERT
4960  * into a table with dropped columns (the planner typically
4961  * generates an INT4 NULL regardless of the dropped column type).
4962  * If we find a dropped column and cannot verify that case (1)
4963  * holds, we have to use the slow path to check (2) for each row.
4964  *
4965  * If vartype is a domain over composite, just look through that
4966  * to the base composite type.
4967  */
4968  var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
4969  -1, false);
4970 
4971  slot_tupdesc = slot->tts_tupleDescriptor;
4972 
4973  if (var_tupdesc->natts != slot_tupdesc->natts)
4974  ereport(ERROR,
4975  (errcode(ERRCODE_DATATYPE_MISMATCH),
4976  errmsg("table row type and query-specified row type do not match"),
4977  errdetail_plural("Table row contains %d attribute, but query expects %d.",
4978  "Table row contains %d attributes, but query expects %d.",
4979  slot_tupdesc->natts,
4980  slot_tupdesc->natts,
4981  var_tupdesc->natts)));
4982 
4983  for (int i = 0; i < var_tupdesc->natts; i++)
4984  {
4985  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4986  Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i);
4987 
4988  if (vattr->atttypid == sattr->atttypid)
4989  continue; /* no worries */
4990  if (!vattr->attisdropped)
4991  ereport(ERROR,
4992  (errcode(ERRCODE_DATATYPE_MISMATCH),
4993  errmsg("table row type and query-specified row type do not match"),
4994  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
4995  format_type_be(sattr->atttypid),
4996  i + 1,
4997  format_type_be(vattr->atttypid))));
4998 
4999  if (vattr->attlen != sattr->attlen ||
5000  vattr->attalign != sattr->attalign)
5001  op->d.wholerow.slow = true; /* need to check for nulls */
5002  }
5003 
5004  /*
5005  * Use the variable's declared rowtype as the descriptor for the
5006  * output values. In particular, we *must* absorb any
5007  * attisdropped markings.
5008  */
5009  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
5010  output_tupdesc = CreateTupleDescCopy(var_tupdesc);
5011  MemoryContextSwitchTo(oldcontext);
5012 
5013  ReleaseTupleDesc(var_tupdesc);
5014  }
5015  else
5016  {
5017  /*
5018  * In the RECORD case, we use the input slot's rowtype as the
5019  * descriptor for the output values, modulo possibly assigning new
5020  * column names below.
5021  */
5022  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
5023  output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
5024  MemoryContextSwitchTo(oldcontext);
5025 
5026  /*
5027  * It's possible that the input slot is a relation scan slot and
5028  * so is marked with that relation's rowtype. But we're supposed
5029  * to be returning RECORD, so reset to that.
5030  */
5031  output_tupdesc->tdtypeid = RECORDOID;
5032  output_tupdesc->tdtypmod = -1;
5033 
5034  /*
5035  * We already got the correct physical datatype info above, but
5036  * now we should try to find the source RTE and adopt its column
5037  * aliases, since it's unlikely that the input slot has the
5038  * desired names.
5039  *
5040  * If we can't locate the RTE, assume the column names we've got
5041  * are OK. (As of this writing, the only cases where we can't
5042  * locate the RTE are in execution of trigger WHEN clauses, and
5043  * then the Var will have the trigger's relation's rowtype, so its
5044  * names are fine.) Also, if the creator of the RTE didn't bother
5045  * to fill in an eref field, assume our column names are OK. (This
5046  * happens in COPY, and perhaps other places.)
5047  */
5048  if (econtext->ecxt_estate &&
5049  variable->varno <= econtext->ecxt_estate->es_range_table_size)
5050  {
5051  RangeTblEntry *rte = exec_rt_fetch(variable->varno,
5052  econtext->ecxt_estate);
5053 
5054  if (rte->eref)
5055  ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
5056  }
5057  }
5058 
5059  /* Bless the tupdesc if needed, and save it in the execution state */
5060  op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
5061 
5062  op->d.wholerow.first = false;
5063  }
5064 
5065  /*
5066  * Make sure all columns of the slot are accessible in the slot's
5067  * Datum/isnull arrays.
5068  */
5069  slot_getallattrs(slot);
5070 
5071  if (op->d.wholerow.slow)
5072  {
5073  /* Check to see if any dropped attributes are non-null */
5074  TupleDesc tupleDesc = slot->tts_tupleDescriptor;
5075  TupleDesc var_tupdesc = op->d.wholerow.tupdesc;
5076 
5077  Assert(var_tupdesc->natts == tupleDesc->natts);
5078 
5079  for (int i = 0; i < var_tupdesc->natts; i++)
5080  {
5081  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
5082  Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i);
5083 
5084  if (!vattr->attisdropped)
5085  continue; /* already checked non-dropped cols */
5086  if (slot->tts_isnull[i])
5087  continue; /* null is always okay */
5088  if (vattr->attlen != sattr->attlen ||
5089  vattr->attalign != sattr->attalign)
5090  ereport(ERROR,
5091  (errcode(ERRCODE_DATATYPE_MISMATCH),
5092  errmsg("table row type and query-specified row type do not match"),
5093  errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
5094  i + 1)));
5095  }
5096  }
5097 
5098  /*
5099  * Build a composite datum, making sure any toasted fields get detoasted.
5100  *
5101  * (Note: it is critical that we not change the slot's state here.)
5102  */
5104  slot->tts_values,
5105  slot->tts_isnull);
5106  dtuple = tuple->t_data;
5107 
5108  /*
5109  * Label the datum with the composite type info we identified before.
5110  *
5111  * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
5112  * the tuple build step; but that seems a tad risky so let's not.)
5113  */
5114  HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
5115  HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
5116 
5117  *op->resvalue = PointerGetDatum(dtuple);
5118  *op->resnull = false;
5119 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1295
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:247
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2158
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2117
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:598
HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptoast.c:563
#define HeapTupleHeaderSetTypMod(tup, typmod)
Definition: htup_details.h:471
#define HeapTupleHeaderSetTypeId(tup, typeid)
Definition: htup_details.h:461
#define OUTER_VAR
Definition: primnodes.h:237
#define INNER_VAR
Definition: primnodes.h:236
Index es_range_table_size
Definition: execnodes.h:631
struct EState * ecxt_estate
Definition: execnodes.h:293
struct ExprEvalStep::@54::@57 wholerow
int32 tdtypmod
Definition: tupdesc.h:83
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:123
Definition: primnodes.h:248
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:368
TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1906

References Assert, BlessTupleDesc(), CreateTupleDescCopy(), ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_scantuple, ereport, errcode(), errdetail(), errdetail_plural(), errmsg(), ERROR, EState::es_range_table_size, exec_rt_fetch(), ExecFilterJunk(), ExecTypeSetColNames(), format_type_be(), HeapTupleHeaderSetTypeId, HeapTupleHeaderSetTypMod, i, INNER_VAR, InvalidAttrNumber, lookup_rowtype_tupdesc_domain(), MemoryContextSwitchTo(), TupleDescData::natts, ExprEvalStep::op, OUTER_VAR, PointerGetDatum(), ReleaseTupleDesc, slot_getallattrs(), HeapTupleData::t_data, TupleDescData::tdtypeid, TupleDescData::tdtypmod, toast_build_flattened_tuple(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, TupleTableSlot::tts_values, and TupleDescAttr.

Referenced by ExecInterpExpr().

◆ ExecEvalXmlExpr()

void ExecEvalXmlExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 4010 of file execExprInterp.c.

4011 {
4012  XmlExpr *xexpr = op->d.xmlexpr.xexpr;
4013  Datum value;
4014 
4015  *op->resnull = true; /* until we get a result */
4016  *op->resvalue = (Datum) 0;
4017 
4018  switch (xexpr->op)
4019  {
4020  case IS_XMLCONCAT:
4021  {
4022  Datum *argvalue = op->d.xmlexpr.argvalue;
4023  bool *argnull = op->d.xmlexpr.argnull;
4024  List *values = NIL;
4025 
4026  for (int i = 0; i < list_length(xexpr->args); i++)
4027  {
4028  if (!argnull[i])
4029  values = lappend(values, DatumGetPointer(argvalue[i]));
4030  }
4031 
4032  if (values != NIL)
4033  {
4035  *op->resnull = false;
4036  }
4037  }
4038  break;
4039 
4040  case IS_XMLFOREST:
4041  {
4042  Datum *argvalue = op->d.xmlexpr.named_argvalue;
4043  bool *argnull = op->d.xmlexpr.named_argnull;
4045  ListCell *lc;
4046  ListCell *lc2;
4047  int i;
4048 
4049  initStringInfo(&buf);
4050 
4051  i = 0;
4052  forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
4053  {
4054  Expr *e = (Expr *) lfirst(lc);
4055  char *argname = strVal(lfirst(lc2));
4056 
4057  if (!argnull[i])
4058  {
4059  value = argvalue[i];
4060  appendStringInfo(&buf, "<%s>%s</%s>",
4061  argname,
4063  exprType((Node *) e), true),
4064  argname);
4065  *op->resnull = false;
4066  }
4067  i++;
4068  }
4069 
4070  if (!*op->resnull)
4071  {
4072  text *result;
4073 
4074  result = cstring_to_text_with_len(buf.data, buf.len);
4075  *op->resvalue = PointerGetDatum(result);
4076  }
4077 
4078  pfree(buf.data);
4079  }
4080  break;
4081 
4082  case IS_XMLELEMENT:
4083  *op->resvalue = PointerGetDatum(xmlelement(xexpr,
4084  op->d.xmlexpr.named_argvalue,
4085  op->d.xmlexpr.named_argnull,
4086  op->d.xmlexpr.argvalue,
4087  op->d.xmlexpr.argnull));
4088  *op->resnull = false;
4089  break;
4090 
4091  case IS_XMLPARSE:
4092  {
4093  Datum *argvalue = op->d.xmlexpr.argvalue;
4094  bool *argnull = op->d.xmlexpr.argnull;
4095  text *data;
4096  bool preserve_whitespace;
4097 
4098  /* arguments are known to be text, bool */
4099  Assert(list_length(xexpr->args) == 2);
4100 
4101  if (argnull[0])
4102  return;
4103  value = argvalue[0];
4105 
4106  if (argnull[1]) /* probably can't happen */
4107  return;
4108  value = argvalue[1];
4109  preserve_whitespace = DatumGetBool(value);
4110 
4112  xexpr->xmloption,
4113  preserve_whitespace));
4114  *op->resnull = false;
4115  }
4116  break;
4117 
4118  case IS_XMLPI:
4119  {
4120  text *arg;
4121  bool isnull;
4122 
4123  /* optional argument is known to be text */
4124  Assert(list_length(xexpr->args) <= 1);
4125 
4126  if (xexpr->args)
4127  {
4128  isnull = op->d.xmlexpr.argnull[0];
4129  if (isnull)
4130  arg = NULL;
4131  else
4132  arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
4133  }
4134  else
4135  {
4136  arg = NULL;
4137  isnull = false;
4138  }
4139 
4140  *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
4141  arg,
4142  isnull,
4143  op->resnull));
4144  }
4145  break;
4146 
4147  case IS_XMLROOT:
4148  {
4149  Datum *argvalue = op->d.xmlexpr.argvalue;
4150  bool *argnull = op->d.xmlexpr.argnull;
4151  xmltype *data;
4152  text *version;
4153  int standalone;
4154 
4155  /* arguments are known to be xml, text, int */
4156  Assert(list_length(xexpr->args) == 3);
4157 
4158  if (argnull[0])
4159  return;
4160  data = DatumGetXmlP(argvalue[0]);
4161 
4162  if (argnull[1])
4163  version = NULL;
4164  else
4165  version = DatumGetTextPP(argvalue[1]);
4166 
4167  Assert(!argnull[2]); /* always present */
4168  standalone = DatumGetInt32(argvalue[2]);
4169 
4171  version,
4172  standalone));
4173  *op->resnull = false;
4174  }
4175  break;
4176 
4177  case IS_XMLSERIALIZE:
4178  {
4179  Datum *argvalue = op->d.xmlexpr.argvalue;
4180  bool *argnull = op->d.xmlexpr.argnull;
4181 
4182  /* argument type is known to be xml */
4183  Assert(list_length(xexpr->args) == 1);
4184 
4185  if (argnull[0])
4186  return;
4187  value = argvalue[0];
4188 
4189  *op->resvalue =
4191  xexpr->xmloption,
4192  xexpr->indent));
4193  *op->resnull = false;
4194  }
4195  break;
4196 
4197  case IS_DOCUMENT:
4198  {
4199  Datum *argvalue = op->d.xmlexpr.argvalue;
4200  bool *argnull = op->d.xmlexpr.argnull;
4201 
4202  /* optional argument is known to be xml */
4203  Assert(list_length(xexpr->args) == 1);
4204 
4205  if (argnull[0])
4206  return;
4207  value = argvalue[0];
4208 
4209  *op->resvalue =
4211  *op->resnull = false;
4212  }
4213  break;
4214 
4215  default:
4216  elog(ERROR, "unrecognized XML operation");
4217  break;
4218  }
4219 }
#define DatumGetTextPP(X)
Definition: fmgr.h:292
List * lappend(List *list, void *datum)
Definition: list.c:339
void * arg
const void * data
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
static char * buf
Definition: pg_test_fsync.c:73
e
Definition: preproc-init.c:82
@ IS_DOCUMENT
Definition: primnodes.h:1587
@ IS_XMLFOREST
Definition: primnodes.h:1582
@ IS_XMLCONCAT
Definition: primnodes.h:1580
@ IS_XMLPI
Definition: primnodes.h:1584
@ IS_XMLPARSE
Definition: primnodes.h:1583
@ IS_XMLSERIALIZE
Definition: primnodes.h:1586
@ IS_XMLROOT
Definition: primnodes.h:1585
@ IS_XMLELEMENT
Definition: primnodes.h:1581
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
struct ExprEvalStep::@54::@89 xmlexpr
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1608
bool indent
Definition: primnodes.h:1612
List * named_args
Definition: primnodes.h:1604
XmlExprOp op
Definition: primnodes.h:1600
#define strVal(v)
Definition: value.h:82
xmltype * xmlconcat(List *args)
Definition: xml.c:553
text * xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
Definition: xml.c:656
xmltype * xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
Definition: xml.c:981
bool xml_is_document(xmltype *arg)
Definition: xml.c:1117
xmltype * xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null)
Definition: xml.c:999
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2476
xmltype * xmlelement(XmlExpr *xexpr, Datum *named_argvalue, bool *named_argnull, Datum *argvalue, bool *argnull)
Definition: xml.c:857
xmltype * xmlroot(xmltype *data, text *version, int standalone)
Definition: xml.c:1051
static xmltype * DatumGetXmlP(Datum X)
Definition: xml.h:51

References appendStringInfo(), arg, ExprEvalStep::argnull, XmlExpr::args, ExprEvalStep::argvalue, Assert, BoolGetDatum(), buf, cstring_to_text_with_len(), data, DatumGetBool(), DatumGetInt32(), DatumGetPointer(), DatumGetTextPP, DatumGetXmlP(), elog, ERROR, exprType(), forboth, i, XmlExpr::indent, initStringInfo(), IS_DOCUMENT, IS_XMLCONCAT, IS_XMLELEMENT, IS_XMLFOREST, IS_XMLPARSE, IS_XMLPI, IS_XMLROOT, IS_XMLSERIALIZE, ExprEvalStep::isnull, lappend(), lfirst, list_length(), map_sql_value_to_xml_value(), XmlExpr::named_args, NIL, ExprEvalStep::op, XmlExpr::op, pfree(), PointerGetDatum(), strVal, value, values, ExprEvalStep::xexpr, xml_is_document(), xmlconcat(), xmlelement(), xmlparse(), xmlpi(), xmlroot(), and xmltotext_with_options().

Referenced by ExecInterpExpr().

◆ ExecInterpExprStillValid()

Datum ExecInterpExprStillValid ( ExprState state,
ExprContext econtext,
bool isNull 
)

Definition at line 2021 of file execExprInterp.c.

2022 {
2023  /*
2024  * First time through, check whether attribute matches Var. Might not be
2025  * ok anymore, due to schema changes.
2026  */
2027  CheckExprStillValid(state, econtext);
2028 
2029  /* skip the check during further executions */
2030  state->evalfunc = (ExprStateEvalFunc) state->evalfunc_private;
2031 
2032  /* and actually execute */
2033  return state->evalfunc(state, econtext, isNull);
2034 }
void CheckExprStillValid(ExprState *state, ExprContext *econtext)
Datum(* ExprStateEvalFunc)(struct ExprState *expression, struct ExprContext *econtext, bool *isNull)
Definition: execnodes.h:70

References CheckExprStillValid().

Referenced by ExecReadyInterpretedExpr().

◆ ExecReadyInterpretedExpr()

void ExecReadyInterpretedExpr ( ExprState state)

Definition at line 236 of file execExprInterp.c.

237 {
238  /* Ensure one-time interpreter setup has been done */
240 
241  /* Simple validity checks on expression */
242  Assert(state->steps_len >= 1);
243  Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE);
244 
245  /*
246  * Don't perform redundant initialization. This is unreachable in current
247  * cases, but might be hit if there's additional expression evaluation
248  * methods that rely on interpreted execution to work.
249  */
251  return;
252 
253  /*
254  * First time through, check whether attribute matches Var. Might not be
255  * ok anymore, due to schema changes. We do that by setting up a callback
256  * that does checking on the first call, which then sets the evalfunc
257  * callback to the actual method of execution.
258  */
259  state->evalfunc = ExecInterpExprStillValid;
260 
261  /* DIRECT_THREADED should not already be set */
262  Assert((state->flags & EEO_FLAG_DIRECT_THREADED) == 0);
263 
264  /*
265  * There shouldn't be any errors before the expression is fully
266  * initialized, and even if so, it'd lead to the expression being
267  * abandoned. So we can set the flag now and save some code.
268  */
270 
271  /*
272  * Select fast-path evalfuncs for very simple expressions. "Starting up"
273  * the full interpreter is a measurable overhead for these, and these
274  * patterns occur often enough to be worth optimizing.
275  */
276  if (state->steps_len == 3)
277  {
278  ExprEvalOp step0 = state->steps[0].opcode;
279  ExprEvalOp step1 = state->steps[1].opcode;
280 
281  if (step0 == EEOP_INNER_FETCHSOME &&
282  step1 == EEOP_INNER_VAR)
283  {
284  state->evalfunc_private = (void *) ExecJustInnerVar;
285  return;
286  }
287  else if (step0 == EEOP_OUTER_FETCHSOME &&
288  step1 == EEOP_OUTER_VAR)
289  {
290  state->evalfunc_private = (void *) ExecJustOuterVar;
291  return;
292  }
293  else if (step0 == EEOP_SCAN_FETCHSOME &&
294  step1 == EEOP_SCAN_VAR)
295  {
296  state->evalfunc_private = (void *) ExecJustScanVar;
297  return;
298  }
299  else if (step0 == EEOP_INNER_FETCHSOME &&
300  step1 == EEOP_ASSIGN_INNER_VAR)
301  {
302  state->evalfunc_private = (void *) ExecJustAssignInnerVar;
303  return;
304  }
305  else if (step0 == EEOP_OUTER_FETCHSOME &&
306  step1 == EEOP_ASSIGN_OUTER_VAR)
307  {
308  state->evalfunc_private = (void *) ExecJustAssignOuterVar;
309  return;
310  }
311  else if (step0 == EEOP_SCAN_FETCHSOME &&
312  step1 == EEOP_ASSIGN_SCAN_VAR)
313  {
314  state->evalfunc_private = (void *) ExecJustAssignScanVar;
315  return;
316  }
317  else if (step0 == EEOP_CASE_TESTVAL &&
318  step1 == EEOP_FUNCEXPR_STRICT &&
319  state->steps[0].d.casetest.value)
320  {
321  state->evalfunc_private = (void *) ExecJustApplyFuncToCase;
322  return;
323  }
324  }
325  else if (state->steps_len == 2)
326  {
327  ExprEvalOp step0 = state->steps[0].opcode;
328 
329  if (step0 == EEOP_CONST)
330  {
331  state->evalfunc_private = (void *) ExecJustConst;
332  return;
333  }
334  else if (step0 == EEOP_INNER_VAR)
335  {
336  state->evalfunc_private = (void *) ExecJustInnerVarVirt;
337  return;
338  }
339  else if (step0 == EEOP_OUTER_VAR)
340  {
341  state->evalfunc_private = (void *) ExecJustOuterVarVirt;
342  return;
343  }
344  else if (step0 == EEOP_SCAN_VAR)
345  {
346  state->evalfunc_private = (void *) ExecJustScanVarVirt;
347  return;
348  }
349  else if (step0 == EEOP_ASSIGN_INNER_VAR)
350  {
351  state->evalfunc_private = (void *) ExecJustAssignInnerVarVirt;
352  return;
353  }
354  else if (step0 == EEOP_ASSIGN_OUTER_VAR)
355  {
356  state->evalfunc_private = (void *) ExecJustAssignOuterVarVirt;
357  return;
358  }
359  else if (step0 == EEOP_ASSIGN_SCAN_VAR)
360  {
361  state->evalfunc_private = (void *) ExecJustAssignScanVarVirt;
362  return;
363  }
364  }
365 
366 #if defined(EEO_USE_COMPUTED_GOTO)
367 
368  /*
369  * In the direct-threaded implementation, replace each opcode with the
370  * address to jump to. (Use ExecEvalStepOp() to get back the opcode.)
371  */
372  for (int off = 0; off < state->steps_len; off++)
373  {
374  ExprEvalStep *op = &state->steps[off];
375 
376  op->opcode = EEO_OPCODE(op->opcode);
377  }
378 
380 #endif /* EEO_USE_COMPUTED_GOTO */
381 
382  state->evalfunc_private = (void *) ExecInterpExpr;
383 }
static Datum ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
Datum ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull)
static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
static void ExecInitInterpreter(void)
static Datum ExecJustConst(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
#define EEO_OPCODE(opcode)
#define EEO_FLAG_INTERPRETER_INITIALIZED
Definition: execExpr.h:29

References Assert, EEO_FLAG_DIRECT_THREADED, EEO_FLAG_INTERPRETER_INITIALIZED, EEO_OPCODE, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_CASE_TESTVAL, EEOP_CONST, EEOP_DONE, EEOP_FUNCEXPR_STRICT, EEOP_INNER_FETCHSOME, EEOP_INNER_VAR, EEOP_OUTER_FETCHSOME, EEOP_OUTER_VAR, EEOP_SCAN_FETCHSOME, EEOP_SCAN_VAR, ExecInitInterpreter(), ExecInterpExpr(), ExecInterpExprStillValid(), ExecJustApplyFuncToCase(), ExecJustAssignInnerVar(), ExecJustAssignInnerVarVirt(), ExecJustAssignOuterVar(), ExecJustAssignOuterVarVirt(), ExecJustAssignScanVar(), ExecJustAssignScanVarVirt(), ExecJustConst(), ExecJustInnerVar(), ExecJustInnerVarVirt(), ExecJustOuterVar(), ExecJustOuterVarVirt(), ExecJustScanVar(), ExecJustScanVarVirt(), and ExprEvalStep::op.

Referenced by ExecReadyExpr().

◆ ExprEvalPushStep()

void ExprEvalPushStep ( ExprState es,
const ExprEvalStep s 
)

Definition at line 2582 of file execExpr.c.

2583 {
2584  if (es->steps_alloc == 0)
2585  {
2586  es->steps_alloc = 16;
2587  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2588  }
2589  else if (es->steps_alloc == es->steps_len)
2590  {
2591  es->steps_alloc *= 2;
2592  es->steps = repalloc(es->steps,
2593  sizeof(ExprEvalStep) * es->steps_alloc);
2594  }
2595 
2596  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2597 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
struct ExprEvalStep * steps
Definition: execnodes.h:102
int steps_alloc
Definition: execnodes.h:122
int steps_len
Definition: execnodes.h:121

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

Referenced by ExecBuildAggTrans(), ExecBuildAggTransCall(), ExecBuildGroupingEqual(), ExecBuildHash32Expr(), ExecBuildParamSetEqual(), ExecBuildProjectionInfo(), ExecBuildUpdateProjection(), ExecInitCoerceToDomain(), ExecInitExpr(), ExecInitExprRec(), ExecInitExprWithParams(), ExecInitJsonCoercion(), ExecInitJsonExpr(), ExecInitQual(), ExecInitSubPlanExpr(), ExecInitSubscriptingRef(), ExecPushExprSetupSteps(), and plpgsql_param_compile().

◆ StaticAssertDecl()

StaticAssertDecl ( sizeof(ExprEvalStep)<=  64,
"size of ExprEvalStep exceeds 64 bytes"   
)