PostgreSQL Source Code  git master
execExpr.h File Reference
#include "executor/nodeAgg.h"
#include "nodes/execnodes.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
 

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
 

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_CASE_TESTVAL, EEOP_MAKE_READONLY, EEOP_IOCOERCE, 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_CONVERT_ROWTYPE, EEOP_SCALARARRAYOP, EEOP_HASHED_SCALARARRAYOP,
  EEOP_XMLEXPR, EEOP_AGGREF, EEOP_GROUPING_FUNC, EEOP_WINDOW_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_ORDERED_TRANS_DATUM, EEOP_AGG_ORDERED_TRANS_TUPLE, EEOP_LAST
}
 

Functions

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 ExecEvalParamExtern (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
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 ExecEvalGroupingFunc (ExprState *state, ExprEvalStep *op)
 
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 ExecAggTransReparent (AggState *aggstate, AggStatePerTrans pertrans, Datum newValue, bool newValueIsNull, Datum oldValue, bool oldValueIsNull)
 
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 29 of file execExpr.h.

Referenced by ExecEvalStepOp(), and ExecReadyInterpretedExpr().

◆ EEO_FLAG_INTERPRETER_INITIALIZED

#define EEO_FLAG_INTERPRETER_INITIALIZED   (1 << 1)

Definition at line 27 of file execExpr.h.

Referenced by ExecReadyInterpretedExpr().

Typedef Documentation

◆ ExecEvalBoolSubroutine

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

Definition at line 37 of file execExpr.h.

◆ ExecEvalSubroutine

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

Definition at line 32 of file execExpr.h.

◆ ExprEvalOp

typedef enum ExprEvalOp ExprEvalOp

◆ ExprEvalRowtypeCache

◆ ExprEvalStep

typedef struct ExprEvalStep ExprEvalStep

◆ 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_CASE_TESTVAL 
EEOP_MAKE_READONLY 
EEOP_IOCOERCE 
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_CONVERT_ROWTYPE 
EEOP_SCALARARRAYOP 
EEOP_HASHED_SCALARARRAYOP 
EEOP_XMLEXPR 
EEOP_AGGREF 
EEOP_GROUPING_FUNC 
EEOP_WINDOW_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_ORDERED_TRANS_DATUM 
EEOP_AGG_ORDERED_TRANS_TUPLE 
EEOP_LAST 

Definition at line 64 of file execExpr.h.

65 {
66  /* entire expression has been evaluated completely, return */
67  EEOP_DONE,
68 
69  /* apply slot_getsomeattrs on corresponding tuple slot */
73 
74  /* compute non-system Var value */
78 
79  /* compute system Var value */
83 
84  /* compute wholerow Var */
86 
87  /*
88  * Compute non-system Var value, assign it into ExprState's resultslot.
89  * These are not used if a CheckVarSlotCompatibility() check would be
90  * needed.
91  */
95 
96  /* assign ExprState's resvalue/resnull to a column of its resultslot */
98  /* ditto, applying MakeExpandedObjectReadOnly() */
100 
101  /* evaluate Const value */
102  EEOP_CONST,
103 
104  /*
105  * Evaluate function call (including OpExprs etc). For speed, we
106  * distinguish in the opcode whether the function is strict and/or
107  * requires usage stats tracking.
108  */
113 
114  /*
115  * Evaluate boolean AND expression, one step per subexpression. FIRST/LAST
116  * subexpressions are special-cased for performance. Since AND always has
117  * at least two subexpressions, FIRST and LAST never apply to the same
118  * subexpression.
119  */
123 
124  /* similarly for boolean OR expression */
128 
129  /* evaluate boolean NOT expression */
131 
132  /* simplified version of BOOL_AND_STEP for use by ExecQual() */
133  EEOP_QUAL,
134 
135  /* unconditional jump to another step */
136  EEOP_JUMP,
137 
138  /* conditional jumps based on current result value */
142 
143  /* perform NULL tests for scalar values */
146 
147  /* perform NULL tests for row values */
150 
151  /* evaluate a BooleanTest expression */
156 
157  /* evaluate PARAM_EXEC/EXTERN parameters */
161 
162  /* return CaseTestExpr value */
164 
165  /* apply MakeExpandedObjectReadOnly() to target value */
167 
168  /* evaluate assorted special-purpose expression types */
172  EEOP_NULLIF,
178  EEOP_ROW,
179 
180  /*
181  * Compare two individual elements of each of two compared ROW()
182  * expressions. Skip to ROWCOMPARE_FINAL if elements are not equal.
183  */
185 
186  /* evaluate boolean value based on previous ROWCOMPARE_STEP operations */
188 
189  /* evaluate GREATEST() or LEAST() */
190  EEOP_MINMAX,
191 
192  /* evaluate FieldSelect expression */
194 
195  /*
196  * Deform tuple before evaluating new values for individual fields in a
197  * FieldStore expression.
198  */
200 
201  /*
202  * Form the new tuple for a FieldStore expression. Individual fields will
203  * have been evaluated into columns of the tuple deformed by the preceding
204  * DEFORM step.
205  */
207 
208  /* Process container subscripts; possibly short-circuit result to NULL */
210 
211  /*
212  * Compute old container element/slice when a SubscriptingRef assignment
213  * expression contains SubscriptingRef/FieldStore subexpressions. Value is
214  * accessed using the CaseTest mechanism.
215  */
217 
218  /* compute new value for SubscriptingRef assignment expression */
220 
221  /* compute element/slice for SubscriptingRef fetch expression */
223 
224  /* evaluate value for CoerceToDomainValue */
226 
227  /* evaluate a domain's NOT NULL constraint */
229 
230  /* evaluate a single domain CHECK constraint */
232 
233  /* evaluate assorted special-purpose expression types */
237  EEOP_XMLEXPR,
238  EEOP_AGGREF,
241  EEOP_SUBPLAN,
242 
243  /* aggregation related nodes */
257 
258  /* non-existent operation, used e.g. to check array lengths */
259  EEOP_LAST
260 } ExprEvalOp;
ExprEvalOp
Definition: execExpr.h:64

Function Documentation

◆ CheckExprStillValid()

void CheckExprStillValid ( ExprState state,
ExprContext econtext 
)

Definition at line 1832 of file execExprInterp.c.

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

Referenced by ExecInterpExprStillValid(), and ExecRunCompiledExpr().

1833 {
1834  TupleTableSlot *innerslot;
1835  TupleTableSlot *outerslot;
1836  TupleTableSlot *scanslot;
1837 
1838  innerslot = econtext->ecxt_innertuple;
1839  outerslot = econtext->ecxt_outertuple;
1840  scanslot = econtext->ecxt_scantuple;
1841 
1842  for (int i = 0; i < state->steps_len; i++)
1843  {
1844  ExprEvalStep *op = &state->steps[i];
1845 
1846  switch (ExecEvalStepOp(state, op))
1847  {
1848  case EEOP_INNER_VAR:
1849  {
1850  int attnum = op->d.var.attnum;
1851 
1852  CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
1853  break;
1854  }
1855 
1856  case EEOP_OUTER_VAR:
1857  {
1858  int attnum = op->d.var.attnum;
1859 
1860  CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
1861  break;
1862  }
1863 
1864  case EEOP_SCAN_VAR:
1865  {
1866  int attnum = op->d.var.attnum;
1867 
1868  CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
1869  break;
1870  }
1871  default:
1872  break;
1873  }
1874  }
1875 }
struct ExprEvalStep * steps
Definition: execnodes.h:85
struct ExprEvalStep::@49::@51 var
static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
union ExprEvalStep::@49 d
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:228
int16 attnum
Definition: pg_attribute.h:83
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:230
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
int steps_len
Definition: execnodes.h:104
int i

◆ ExecAggInitGroup()

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

Definition at line 4191 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

4193 {
4194  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4195  MemoryContext oldContext;
4196 
4197  /*
4198  * We must copy the datum into aggcontext if it is pass-by-ref. We do not
4199  * need to pfree the old transValue, since it's NULL. (We already checked
4200  * that the agg's input type is binary-compatible with its transtype, so
4201  * straight copy here is OK.)
4202  */
4203  oldContext = MemoryContextSwitchTo(aggcontext->ecxt_per_tuple_memory);
4204  pergroup->transValue = datumCopy(fcinfo->args[1].value,
4205  pertrans->transtypeByVal,
4206  pertrans->transtypeLen);
4207  pergroup->transValueIsNull = false;
4208  pergroup->noTransValue = false;
4209  MemoryContextSwitchTo(oldContext);
4210 }
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:234
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:162
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Datum value
Definition: postgres.h:422
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131

◆ ExecAggTransReparent()

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

Definition at line 4219 of file execExprInterp.c.

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

Referenced by advance_transition_function(), and ExecAggPlainTransByRef().

4222 {
4223  Assert(newValue != oldValue);
4224 
4225  if (!newValueIsNull)
4226  {
4228  if (DatumIsReadWriteExpandedObject(newValue,
4229  false,
4230  pertrans->transtypeLen) &&
4231  MemoryContextGetParent(DatumGetEOHP(newValue)->eoh_context) == CurrentMemoryContext)
4232  /* do nothing */ ;
4233  else
4234  newValue = datumCopy(newValue,
4235  pertrans->transtypeByVal,
4236  pertrans->transtypeLen);
4237  }
4238  else
4239  {
4240  /*
4241  * Ensure that AggStatePerGroup->transValue ends up being 0, so
4242  * callers can safely compare newValue/oldValue without having to
4243  * check their respective nullness.
4244  */
4245  newValue = (Datum) 0;
4246  }
4247 
4248  if (!oldValueIsNull)
4249  {
4250  if (DatumIsReadWriteExpandedObject(oldValue,
4251  false,
4252  pertrans->transtypeLen))
4253  DeleteExpandedObject(oldValue);
4254  else
4255  pfree(DatumGetPointer(oldValue));
4256  }
4257 
4258  return newValue;
4259 }
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:446
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:234
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void pfree(void *pointer)
Definition: mcxt.c:1169
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
ExprContext * curaggcontext
Definition: execnodes.h:2289
uintptr_t Datum
Definition: postgres.h:411
void DeleteExpandedObject(Datum d)
#define Assert(condition)
Definition: c.h:804
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
#define DatumGetPointer(X)
Definition: postgres.h:593

◆ ExecEvalAggOrderedTransDatum()

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

Definition at line 4265 of file execExprInterp.c.

References ExprEvalStep::agg_trans, ExprEvalStep::d, ExprEvalStep::pertrans, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::setno, AggStatePerTransData::sortstates, and tuplesort_putdatum().

Referenced by ExecInterpExpr().

4267 {
4268  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
4269  int setno = op->d.agg_trans.setno;
4270 
4271  tuplesort_putdatum(pertrans->sortstates[setno],
4272  *op->resvalue, *op->resnull);
4273 }
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
Definition: tuplesort.c:1805
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
union ExprEvalStep::@49 d
struct ExprEvalStep::@49::@90 agg_trans
Tuplesortstate ** sortstates
Definition: nodeAgg.h:154

◆ ExecEvalAggOrderedTransTuple()

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

Definition at line 4279 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

4281 {
4282  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
4283  int setno = op->d.agg_trans.setno;
4284 
4285  ExecClearTuple(pertrans->sortslot);
4286  pertrans->sortslot->tts_nvalid = pertrans->numInputs;
4287  ExecStoreVirtualTuple(pertrans->sortslot);
4288  tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
4289 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
union ExprEvalStep::@49 d
struct ExprEvalStep::@49::@90 agg_trans
Tuplesortstate ** sortstates
Definition: nodeAgg.h:154
AttrNumber tts_nvalid
Definition: tuptable.h:121
TupleTableSlot * sortslot
Definition: nodeAgg.h:136
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1684

◆ ExecEvalArrayCoerce()

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

Definition at line 2885 of file execExprInterp.c.

References ARR_ELEMTYPE, array_map(), ExprEvalStep::arraycoerce, ExprEvalStep::d, DatumGetArrayTypePCopy, PointerGetDatum, ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by ExecInterpExpr().

2886 {
2887  Datum arraydatum;
2888 
2889  /* NULL array -> NULL result */
2890  if (*op->resnull)
2891  return;
2892 
2893  arraydatum = *op->resvalue;
2894 
2895  /*
2896  * If it's binary-compatible, modify the element type in the array header,
2897  * but otherwise leave the array as we received it.
2898  */
2899  if (op->d.arraycoerce.elemexprstate == NULL)
2900  {
2901  /* Detoast input array if necessary, and copy in any case */
2902  ArrayType *array = DatumGetArrayTypePCopy(arraydatum);
2903 
2904  ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
2905  *op->resvalue = PointerGetDatum(array);
2906  return;
2907  }
2908 
2909  /*
2910  * Use array_map to apply the sub-expression to each array element.
2911  */
2912  *op->resvalue = array_map(arraydatum,
2913  op->d.arraycoerce.elemexprstate,
2914  econtext,
2915  op->d.arraycoerce.resultelemtype,
2916  op->d.arraycoerce.amstate);
2917 }
Datum * resvalue
Definition: execExpr.h:273
#define PointerGetDatum(X)
Definition: postgres.h:600
bool * resnull
Definition: execExpr.h:274
union ExprEvalStep::@49 d
struct ExprEvalStep::@49::@69 arraycoerce
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
Datum array_map(Datum arrayd, ExprState *exprstate, ExprContext *econtext, Oid retType, ArrayMapState *amstate)
Definition: arrayfuncs.c:3158
#define ARR_ELEMTYPE(a)
Definition: array.h:285

◆ ExecEvalArrayExpr()

void ExecEvalArrayExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2676 of file execExprInterp.c.

References 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(), ExprEvalStep::arrayexpr, ArrayGetNItems(), construct_empty_array(), construct_md_array(), ExprEvalStep::d, ArrayType::dataoffset, DatumGetArrayTypeP, ExprEvalStep::element_type, ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, format_type_be(), i, MAXDIM, ArrayType::ndim, ExprEvalStep::nelems, palloc(), PointerGetDatum, ExprEvalStep::resnull, ExprEvalStep::resvalue, and SET_VARSIZE.

Referenced by ExecInterpExpr().

2677 {
2678  ArrayType *result;
2679  Oid element_type = op->d.arrayexpr.elemtype;
2680  int nelems = op->d.arrayexpr.nelems;
2681  int ndims = 0;
2682  int dims[MAXDIM];
2683  int lbs[MAXDIM];
2684 
2685  /* Set non-null as default */
2686  *op->resnull = false;
2687 
2688  if (!op->d.arrayexpr.multidims)
2689  {
2690  /* Elements are presumably of scalar type */
2691  Datum *dvalues = op->d.arrayexpr.elemvalues;
2692  bool *dnulls = op->d.arrayexpr.elemnulls;
2693 
2694  /* setup for 1-D array of the given length */
2695  ndims = 1;
2696  dims[0] = nelems;
2697  lbs[0] = 1;
2698 
2699  result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2700  element_type,
2701  op->d.arrayexpr.elemlength,
2702  op->d.arrayexpr.elembyval,
2703  op->d.arrayexpr.elemalign);
2704  }
2705  else
2706  {
2707  /* Must be nested array expressions */
2708  int nbytes = 0;
2709  int nitems = 0;
2710  int outer_nelems = 0;
2711  int elem_ndims = 0;
2712  int *elem_dims = NULL;
2713  int *elem_lbs = NULL;
2714  bool firstone = true;
2715  bool havenulls = false;
2716  bool haveempty = false;
2717  char **subdata;
2718  bits8 **subbitmaps;
2719  int *subbytes;
2720  int *subnitems;
2721  int32 dataoffset;
2722  char *dat;
2723  int iitem;
2724 
2725  subdata = (char **) palloc(nelems * sizeof(char *));
2726  subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
2727  subbytes = (int *) palloc(nelems * sizeof(int));
2728  subnitems = (int *) palloc(nelems * sizeof(int));
2729 
2730  /* loop through and get data area from each element */
2731  for (int elemoff = 0; elemoff < nelems; elemoff++)
2732  {
2733  Datum arraydatum;
2734  bool eisnull;
2735  ArrayType *array;
2736  int this_ndims;
2737 
2738  arraydatum = op->d.arrayexpr.elemvalues[elemoff];
2739  eisnull = op->d.arrayexpr.elemnulls[elemoff];
2740 
2741  /* temporarily ignore null subarrays */
2742  if (eisnull)
2743  {
2744  haveempty = true;
2745  continue;
2746  }
2747 
2748  array = DatumGetArrayTypeP(arraydatum);
2749 
2750  /* run-time double-check on element type */
2751  if (element_type != ARR_ELEMTYPE(array))
2752  ereport(ERROR,
2753  (errcode(ERRCODE_DATATYPE_MISMATCH),
2754  errmsg("cannot merge incompatible arrays"),
2755  errdetail("Array with element type %s cannot be "
2756  "included in ARRAY construct with element type %s.",
2757  format_type_be(ARR_ELEMTYPE(array)),
2758  format_type_be(element_type))));
2759 
2760  this_ndims = ARR_NDIM(array);
2761  /* temporarily ignore zero-dimensional subarrays */
2762  if (this_ndims <= 0)
2763  {
2764  haveempty = true;
2765  continue;
2766  }
2767 
2768  if (firstone)
2769  {
2770  /* Get sub-array details from first member */
2771  elem_ndims = this_ndims;
2772  ndims = elem_ndims + 1;
2773  if (ndims <= 0 || ndims > MAXDIM)
2774  ereport(ERROR,
2775  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2776  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2777  ndims, MAXDIM)));
2778 
2779  elem_dims = (int *) palloc(elem_ndims * sizeof(int));
2780  memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
2781  elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
2782  memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
2783 
2784  firstone = false;
2785  }
2786  else
2787  {
2788  /* Check other sub-arrays are compatible */
2789  if (elem_ndims != this_ndims ||
2790  memcmp(elem_dims, ARR_DIMS(array),
2791  elem_ndims * sizeof(int)) != 0 ||
2792  memcmp(elem_lbs, ARR_LBOUND(array),
2793  elem_ndims * sizeof(int)) != 0)
2794  ereport(ERROR,
2795  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2796  errmsg("multidimensional arrays must have array "
2797  "expressions with matching dimensions")));
2798  }
2799 
2800  subdata[outer_nelems] = ARR_DATA_PTR(array);
2801  subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
2802  subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
2803  nbytes += subbytes[outer_nelems];
2804  subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
2805  ARR_DIMS(array));
2806  nitems += subnitems[outer_nelems];
2807  havenulls |= ARR_HASNULL(array);
2808  outer_nelems++;
2809  }
2810 
2811  /*
2812  * If all items were null or empty arrays, return an empty array;
2813  * otherwise, if some were and some weren't, raise error. (Note: we
2814  * must special-case this somehow to avoid trying to generate a 1-D
2815  * array formed from empty arrays. It's not ideal...)
2816  */
2817  if (haveempty)
2818  {
2819  if (ndims == 0) /* didn't find any nonempty array */
2820  {
2821  *op->resvalue = PointerGetDatum(construct_empty_array(element_type));
2822  return;
2823  }
2824  ereport(ERROR,
2825  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2826  errmsg("multidimensional arrays must have array "
2827  "expressions with matching dimensions")));
2828  }
2829 
2830  /* setup for multi-D array */
2831  dims[0] = outer_nelems;
2832  lbs[0] = 1;
2833  for (int i = 1; i < ndims; i++)
2834  {
2835  dims[i] = elem_dims[i - 1];
2836  lbs[i] = elem_lbs[i - 1];
2837  }
2838 
2839  /* check for subscript overflow */
2840  (void) ArrayGetNItems(ndims, dims);
2841  ArrayCheckBounds(ndims, dims, lbs);
2842 
2843  if (havenulls)
2844  {
2845  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
2846  nbytes += dataoffset;
2847  }
2848  else
2849  {
2850  dataoffset = 0; /* marker for no null bitmap */
2851  nbytes += ARR_OVERHEAD_NONULLS(ndims);
2852  }
2853 
2854  result = (ArrayType *) palloc(nbytes);
2855  SET_VARSIZE(result, nbytes);
2856  result->ndim = ndims;
2857  result->dataoffset = dataoffset;
2858  result->elemtype = element_type;
2859  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
2860  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
2861 
2862  dat = ARR_DATA_PTR(result);
2863  iitem = 0;
2864  for (int i = 0; i < outer_nelems; i++)
2865  {
2866  memcpy(dat, subdata[i], subbytes[i]);
2867  dat += subbytes[i];
2868  if (havenulls)
2869  array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
2870  subbitmaps[i], 0,
2871  subnitems[i]);
2872  iitem += subnitems[i];
2873  }
2874  }
2875 
2876  *op->resvalue = PointerGetDatum(result);
2877 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define ARR_SIZE(a)
Definition: array.h:282
Datum * resvalue
Definition: execExpr.h:273
#define PointerGetDatum(X)
Definition: postgres.h:600
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4721
int32 dataoffset
Definition: array.h:89
bool * resnull
Definition: execExpr.h:274
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3439
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:429
#define ARR_DATA_OFFSET(a)
Definition: array.h:309
#define ARR_LBOUND(a)
Definition: array.h:289
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define ARR_HASNULL(a)
Definition: array.h:284
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:128
uint8 bits8
Definition: c.h:448
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
#define ARR_NDIM(a)
Definition: array.h:283
struct ExprEvalStep::@49::@68 arrayexpr
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342
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:3353
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
int ndim
Definition: array.h:88
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ ExecEvalConstraintCheck()

void ExecEvalConstraintCheck ( ExprState state,
ExprEvalStep op 
)

Definition at line 3661 of file execExprInterp.c.

References ExprEvalStep::d, DatumGetBool, ExprEvalStep::domaincheck, ereport, errcode(), errdomainconstraint(), errmsg(), ERROR, and format_type_be().

Referenced by ExecInterpExpr().

3662 {
3663  if (!*op->d.domaincheck.checknull &&
3664  !DatumGetBool(*op->d.domaincheck.checkvalue))
3665  ereport(ERROR,
3666  (errcode(ERRCODE_CHECK_VIOLATION),
3667  errmsg("value for domain %s violates check constraint \"%s\"",
3668  format_type_be(op->d.domaincheck.resulttype),
3669  op->d.domaincheck.constraintname),
3670  errdomainconstraint(op->d.domaincheck.resulttype,
3671  op->d.domaincheck.constraintname)));
3672 }
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define ERROR
Definition: elog.h:46
int errdomainconstraint(Oid datatypeOid, const char *conname)
Definition: domains.c:384
union ExprEvalStep::@49 d
#define DatumGetBool(X)
Definition: postgres.h:437
struct ExprEvalStep::@49::@78 domaincheck
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ ExecEvalConstraintNotNull()

void ExecEvalConstraintNotNull ( ExprState state,
ExprEvalStep op 
)

Definition at line 3647 of file execExprInterp.c.

References ExprEvalStep::d, ExprEvalStep::domaincheck, ereport, errcode(), errdatatype(), errmsg(), ERROR, format_type_be(), and ExprEvalStep::resnull.

Referenced by ExecInterpExpr().

3648 {
3649  if (*op->resnull)
3650  ereport(ERROR,
3651  (errcode(ERRCODE_NOT_NULL_VIOLATION),
3652  errmsg("domain %s does not allow null values",
3653  format_type_be(op->d.domaincheck.resulttype)),
3654  errdatatype(op->d.domaincheck.resulttype)));
3655 }
bool * resnull
Definition: execExpr.h:274
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
struct ExprEvalStep::@49::@78 domaincheck
int errdatatype(Oid datatypeOid)
Definition: domains.c:360
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ ExecEvalConvertRowtype()

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

Definition at line 3194 of file execExprInterp.c.

References Assert, ExprEvalStep::convert_rowtype, convert_tuples_by_name(), ExprEvalStep::d, 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::resnull, ExprEvalStep::resvalue, HeapTupleData::t_data, HeapTupleData::t_len, and TupleDescData::tdtypeid.

Referenced by ExecInterpExpr().

3195 {
3196  HeapTuple result;
3197  Datum tupDatum;
3198  HeapTupleHeader tuple;
3199  HeapTupleData tmptup;
3200  TupleDesc indesc,
3201  outdesc;
3202  bool changed = false;
3203 
3204  /* NULL in -> NULL out */
3205  if (*op->resnull)
3206  return;
3207 
3208  tupDatum = *op->resvalue;
3209  tuple = DatumGetHeapTupleHeader(tupDatum);
3210 
3211  /*
3212  * Lookup tupdescs if first time through or if type changes. We'd better
3213  * pin them since type conversion functions could do catalog lookups and
3214  * hence cause cache invalidation.
3215  */
3216  indesc = get_cached_rowtype(op->d.convert_rowtype.inputtype, -1,
3217  op->d.convert_rowtype.incache,
3218  &changed);
3219  IncrTupleDescRefCount(indesc);
3220  outdesc = get_cached_rowtype(op->d.convert_rowtype.outputtype, -1,
3221  op->d.convert_rowtype.outcache,
3222  &changed);
3223  IncrTupleDescRefCount(outdesc);
3224 
3225  /*
3226  * We used to be able to assert that incoming tuples are marked with
3227  * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
3228  * might change the tuples' marking to plain RECORD due to inserting
3229  * aliases, we can only make this weak test:
3230  */
3231  Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
3232  HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
3233 
3234  /* if first time through, or after change, initialize conversion map */
3235  if (changed)
3236  {
3237  MemoryContext old_cxt;
3238 
3239  /* allocate map in long-lived memory context */
3240  old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3241 
3242  /* prepare map from old to new attribute numbers */
3243  op->d.convert_rowtype.map = convert_tuples_by_name(indesc, outdesc);
3244 
3245  MemoryContextSwitchTo(old_cxt);
3246  }
3247 
3248  /* Following steps need a HeapTuple not a bare HeapTupleHeader */
3249  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3250  tmptup.t_data = tuple;
3251 
3252  if (op->d.convert_rowtype.map != NULL)
3253  {
3254  /* Full conversion with attribute rearrangement needed */
3255  result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map);
3256  /* Result already has appropriate composite-datum header fields */
3257  *op->resvalue = HeapTupleGetDatum(result);
3258  }
3259  else
3260  {
3261  /*
3262  * The tuple is physically compatible as-is, but we need to insert the
3263  * destination rowtype OID in its composite-datum header field, so we
3264  * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
3265  * for this since it will both make the physical copy and insert the
3266  * correct composite header fields. Note that we aren't expecting to
3267  * have to flatten any toasted fields: the input was a composite
3268  * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
3269  * is overkill here, but its check for external fields is cheap.
3270  */
3271  *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
3272  }
3273 
3274  DecrTupleDescRefCount(indesc);
3275  DecrTupleDescRefCount(outdesc);
3276 }
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:366
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
HeapTupleHeader t_data
Definition: htup.h:68
union ExprEvalStep::@49 d
static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod, ExprEvalRowtypeCache *rowcache, bool *changed)
uint32 t_len
Definition: htup.h:64
struct ExprEvalStep::@49::@79 convert_rowtype
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:139
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:984
uintptr_t Datum
Definition: postgres.h:411
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:457
#define Assert(condition)
Definition: c.h:804
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:384
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Oid tdtypeid
Definition: tupdesc.h:82
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

◆ ExecEvalCurrentOfExpr()

void ExecEvalCurrentOfExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2537 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

2538 {
2539  ereport(ERROR,
2540  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2541  errmsg("WHERE CURRENT OF is not supported for this table type")));
2542 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ ExecEvalFieldSelect()

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

Definition at line 2999 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

3000 {
3001  AttrNumber fieldnum = op->d.fieldselect.fieldnum;
3002  Datum tupDatum;
3003  HeapTupleHeader tuple;
3004  Oid tupType;
3005  int32 tupTypmod;
3006  TupleDesc tupDesc;
3007  Form_pg_attribute attr;
3008  HeapTupleData tmptup;
3009 
3010  /* NULL record -> NULL result */
3011  if (*op->resnull)
3012  return;
3013 
3014  tupDatum = *op->resvalue;
3015 
3016  /* We can special-case expanded records for speed */
3018  {
3020 
3021  Assert(erh->er_magic == ER_MAGIC);
3022 
3023  /* Extract record's TupleDesc */
3024  tupDesc = expanded_record_get_tupdesc(erh);
3025 
3026  /*
3027  * Find field's attr record. Note we don't support system columns
3028  * here: a datum tuple doesn't have valid values for most of the
3029  * interesting system columns anyway.
3030  */
3031  if (fieldnum <= 0) /* should never happen */
3032  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3033  fieldnum);
3034  if (fieldnum > tupDesc->natts) /* should never happen */
3035  elog(ERROR, "attribute number %d exceeds number of columns %d",
3036  fieldnum, tupDesc->natts);
3037  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3038 
3039  /* Check for dropped column, and force a NULL result if so */
3040  if (attr->attisdropped)
3041  {
3042  *op->resnull = true;
3043  return;
3044  }
3045 
3046  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3047  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3048  if (op->d.fieldselect.resulttype != attr->atttypid)
3049  ereport(ERROR,
3050  (errcode(ERRCODE_DATATYPE_MISMATCH),
3051  errmsg("attribute %d has wrong type", fieldnum),
3052  errdetail("Table has type %s, but query expects %s.",
3053  format_type_be(attr->atttypid),
3054  format_type_be(op->d.fieldselect.resulttype))));
3055 
3056  /* extract the field */
3057  *op->resvalue = expanded_record_get_field(erh, fieldnum,
3058  op->resnull);
3059  }
3060  else
3061  {
3062  /* Get the composite datum and extract its type fields */
3063  tuple = DatumGetHeapTupleHeader(tupDatum);
3064 
3065  tupType = HeapTupleHeaderGetTypeId(tuple);
3066  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
3067 
3068  /* Lookup tupdesc if first time through or if type changes */
3069  tupDesc = get_cached_rowtype(tupType, tupTypmod,
3070  &op->d.fieldselect.rowcache, NULL);
3071 
3072  /*
3073  * Find field's attr record. Note we don't support system columns
3074  * here: a datum tuple doesn't have valid values for most of the
3075  * interesting system columns anyway.
3076  */
3077  if (fieldnum <= 0) /* should never happen */
3078  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3079  fieldnum);
3080  if (fieldnum > tupDesc->natts) /* should never happen */
3081  elog(ERROR, "attribute number %d exceeds number of columns %d",
3082  fieldnum, tupDesc->natts);
3083  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3084 
3085  /* Check for dropped column, and force a NULL result if so */
3086  if (attr->attisdropped)
3087  {
3088  *op->resnull = true;
3089  return;
3090  }
3091 
3092  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3093  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3094  if (op->d.fieldselect.resulttype != attr->atttypid)
3095  ereport(ERROR,
3096  (errcode(ERRCODE_DATATYPE_MISMATCH),
3097  errmsg("attribute %d has wrong type", fieldnum),
3098  errdetail("Table has type %s, but query expects %s.",
3099  format_type_be(attr->atttypid),
3100  format_type_be(op->d.fieldselect.resulttype))));
3101 
3102  /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
3103  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3104  tmptup.t_data = tuple;
3105 
3106  /* extract the field */
3107  *op->resvalue = heap_getattr(&tmptup,
3108  fieldnum,
3109  tupDesc,
3110  op->resnull);
3111  }
3112 }
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:335
Datum * resvalue
Definition: execExpr.h:273
static Datum expanded_record_get_field(ExpandedRecordHeader *erh, int fnumber, bool *isnull)
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool * resnull
Definition: execExpr.h:274
int errcode(int sqlerrcode)
Definition: elog.c:698
struct ExprEvalStep::@49::@74 fieldselect
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
signed int int32
Definition: c.h:429
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:467
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod, ExprEvalRowtypeCache *rowcache, bool *changed)
uint32 t_len
Definition: htup.h:64
int errdetail(const char *fmt,...)
Definition: elog.c:1042
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
static TupleDesc expanded_record_get_tupdesc(ExpandedRecordHeader *erh)
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
uintptr_t Datum
Definition: postgres.h:411
#define ER_MAGIC
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:457
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define DatumGetPointer(X)
Definition: postgres.h:593
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
int16 AttrNumber
Definition: attnum.h:21
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

◆ ExecEvalFieldStoreDeForm()

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

Definition at line 3124 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

3125 {
3126  TupleDesc tupDesc;
3127 
3128  /* Lookup tupdesc if first time through or if type changes */
3129  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3130  op->d.fieldstore.rowcache, NULL);
3131 
3132  /* Check that current tupdesc doesn't have more fields than we allocated */
3133  if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
3134  elog(ERROR, "too many columns in composite type %u",
3135  op->d.fieldstore.fstore->resulttype);
3136 
3137  if (*op->resnull)
3138  {
3139  /* Convert null input tuple into an all-nulls row */
3140  memset(op->d.fieldstore.nulls, true,
3141  op->d.fieldstore.ncolumns * sizeof(bool));
3142  }
3143  else
3144  {
3145  /*
3146  * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
3147  * set all the fields in the struct just in case.
3148  */
3149  Datum tupDatum = *op->resvalue;
3150  HeapTupleHeader tuphdr;
3151  HeapTupleData tmptup;
3152 
3153  tuphdr = DatumGetHeapTupleHeader(tupDatum);
3154  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
3155  ItemPointerSetInvalid(&(tmptup.t_self));
3156  tmptup.t_tableOid = InvalidOid;
3157  tmptup.t_data = tuphdr;
3158 
3159  heap_deform_tuple(&tmptup, tupDesc,
3160  op->d.fieldstore.values,
3161  op->d.fieldstore.nulls);
3162  }
3163 }
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
HeapTupleHeader t_data
Definition: htup.h:68
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
ItemPointerData t_self
Definition: htup.h:65
static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod, ExprEvalRowtypeCache *rowcache, bool *changed)
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
struct ExprEvalStep::@49::@75 fieldstore
uintptr_t Datum
Definition: postgres.h:411
#define InvalidOid
Definition: postgres_ext.h:36
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1249
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define elog(elevel,...)
Definition: elog.h:232
#define unlikely(x)
Definition: c.h:273
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

◆ ExecEvalFieldStoreForm()

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

Definition at line 3170 of file execExprInterp.c.

References ExprEvalStep::d, ExprEvalStep::fieldstore, get_cached_rowtype(), heap_form_tuple(), HeapTupleGetDatum, ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by ExecInterpExpr().

3171 {
3172  TupleDesc tupDesc;
3173  HeapTuple tuple;
3174 
3175  /* Lookup tupdesc (should be valid already) */
3176  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3177  op->d.fieldstore.rowcache, NULL);
3178 
3179  tuple = heap_form_tuple(tupDesc,
3180  op->d.fieldstore.values,
3181  op->d.fieldstore.nulls);
3182 
3183  *op->resvalue = HeapTupleGetDatum(tuple);
3184  *op->resnull = false;
3185 }
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
union ExprEvalStep::@49 d
static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod, ExprEvalRowtypeCache *rowcache, bool *changed)
struct ExprEvalStep::@49::@75 fieldstore
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221

◆ ExecEvalFuncExprFusage()

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

Definition at line 2348 of file execExprInterp.c.

References ExprEvalStep::d, ExprEvalStep::func, FunctionCallInfoBaseData::isnull, pgstat_end_function_usage(), pgstat_init_function_usage(), ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by ExecInterpExpr().

2350 {
2351  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2352  PgStat_FunctionCallUsage fcusage;
2353  Datum d;
2354 
2355  pgstat_init_function_usage(fcinfo, &fcusage);
2356 
2357  fcinfo->isnull = false;
2358  d = op->d.func.fn_addr(fcinfo);
2359  *op->resvalue = d;
2360  *op->resnull = fcinfo->isnull;
2361 
2362  pgstat_end_function_usage(&fcusage, true);
2363 }
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
Definition: pgstat.c:1898
union ExprEvalStep::@49 d
uintptr_t Datum
Definition: postgres.h:411
struct ExprEvalStep::@49::@56 func
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
Definition: pgstat.c:1969

◆ ExecEvalFuncExprStrictFusage()

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

Definition at line 2369 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

2371 {
2372 
2373  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2374  PgStat_FunctionCallUsage fcusage;
2375  NullableDatum *args = fcinfo->args;
2376  int nargs = op->d.func.nargs;
2377  Datum d;
2378 
2379  /* strict function, so check for NULL args */
2380  for (int argno = 0; argno < nargs; argno++)
2381  {
2382  if (args[argno].isnull)
2383  {
2384  *op->resnull = true;
2385  return;
2386  }
2387  }
2388 
2389  pgstat_init_function_usage(fcinfo, &fcusage);
2390 
2391  fcinfo->isnull = false;
2392  d = op->d.func.fn_addr(fcinfo);
2393  *op->resvalue = d;
2394  *op->resnull = fcinfo->isnull;
2395 
2396  pgstat_end_function_usage(&fcusage, true);
2397 }
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
Definition: pgstat.c:1898
union ExprEvalStep::@49 d
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
uintptr_t Datum
Definition: postgres.h:411
struct ExprEvalStep::@49::@56 func
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
Definition: pgstat.c:1969

◆ ExecEvalGroupingFunc()

void ExecEvalGroupingFunc ( ExprState state,
ExprEvalStep op 
)

Definition at line 3900 of file execExprInterp.c.

References attnum, bms_is_member(), castNode, ExprEvalStep::d, AggState::grouped_cols, ExprEvalStep::grouping_func, Int32GetDatum, lfirst_int, ExprState::parent, ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by ExecInterpExpr().

3901 {
3902  AggState *aggstate = castNode(AggState, state->parent);
3903  int result = 0;
3904  Bitmapset *grouped_cols = aggstate->grouped_cols;
3905  ListCell *lc;
3906 
3907  foreach(lc, op->d.grouping_func.clauses)
3908  {
3909  int attnum = lfirst_int(lc);
3910 
3911  result <<= 1;
3912 
3913  if (!bms_is_member(attnum, grouped_cols))
3914  result |= 1;
3915  }
3916 
3917  *op->resvalue = Int32GetDatum(result);
3918  *op->resnull = false;
3919 }
struct PlanState * parent
Definition: execnodes.h:108
Datum * resvalue
Definition: execExpr.h:273
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
bool * resnull
Definition: execExpr.h:274
union ExprEvalStep::@49 d
#define lfirst_int(lc)
Definition: pg_list.h:170
Bitmapset * grouped_cols
Definition: execnodes.h:2298
struct ExprEvalStep::@49::@84 grouping_func
int16 attnum
Definition: pg_attribute.h:83
#define Int32GetDatum(X)
Definition: postgres.h:523
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427

◆ ExecEvalHashedScalarArrayOp()

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

Definition at line 3492 of file execExprInterp.c.

References FunctionCallInfoBaseData::args, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, att_addlength_pointer, att_align_nominal, BoolGetDatum, CurrentMemoryContext, ExprEvalStep::d, DatumGetArrayTypeP, DatumGetBool, ExprContext::ecxt_per_query_memory, element(), ExprEvalStep::elements_tab, fetch_att, get_typlenbyvalalign(), ExprEvalStep::has_nulls, ExprEvalStep::hashedscalararrayop, ScalarArrayOpExprHashTable::hashtab, i, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, MemoryContextSwitchTo(), ScalarArrayOpExprHashTable::op, ExprEvalStep::op, palloc(), ExprEvalStep::resnull, ExprEvalStep::resvalue, typalign, ExprEvalStep::typbyval, ExprEvalStep::typlen, and NullableDatum::value.

Referenced by ExecInterpExpr().

3493 {
3494  ScalarArrayOpExprHashTable *elements_tab = op->d.hashedscalararrayop.elements_tab;
3495  FunctionCallInfo fcinfo = op->d.hashedscalararrayop.fcinfo_data;
3496  bool strictfunc = op->d.hashedscalararrayop.finfo->fn_strict;
3497  Datum scalar = fcinfo->args[0].value;
3498  bool scalar_isnull = fcinfo->args[0].isnull;
3499  Datum result;
3500  bool resultnull;
3501  bool hashfound;
3502 
3503  /* We don't setup a hashed scalar array op if the array const is null. */
3504  Assert(!*op->resnull);
3505 
3506  /*
3507  * If the scalar is NULL, and the function is strict, return NULL; no
3508  * point in executing the search.
3509  */
3510  if (fcinfo->args[0].isnull && strictfunc)
3511  {
3512  *op->resnull = true;
3513  return;
3514  }
3515 
3516  /* Build the hash table on first evaluation */
3517  if (elements_tab == NULL)
3518  {
3519  int16 typlen;
3520  bool typbyval;
3521  char typalign;
3522  int nitems;
3523  bool has_nulls = false;
3524  char *s;
3525  bits8 *bitmap;
3526  int bitmask;
3527  MemoryContext oldcontext;
3528  ArrayType *arr;
3529 
3530  arr = DatumGetArrayTypeP(*op->resvalue);
3531  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3532 
3534  &typlen,
3535  &typbyval,
3536  &typalign);
3537 
3538  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3539 
3540  elements_tab = (ScalarArrayOpExprHashTable *)
3542  op->d.hashedscalararrayop.elements_tab = elements_tab;
3543  elements_tab->op = op;
3544 
3545  /*
3546  * Create the hash table sizing it according to the number of elements
3547  * in the array. This does assume that the array has no duplicates.
3548  * If the array happens to contain many duplicate values then it'll
3549  * just mean that we sized the table a bit on the large side.
3550  */
3551  elements_tab->hashtab = saophash_create(CurrentMemoryContext, nitems,
3552  elements_tab);
3553 
3554  MemoryContextSwitchTo(oldcontext);
3555 
3556  s = (char *) ARR_DATA_PTR(arr);
3557  bitmap = ARR_NULLBITMAP(arr);
3558  bitmask = 1;
3559  for (int i = 0; i < nitems; i++)
3560  {
3561  /* Get array element, checking for NULL. */
3562  if (bitmap && (*bitmap & bitmask) == 0)
3563  {
3564  has_nulls = true;
3565  }
3566  else
3567  {
3568  Datum element;
3569 
3570  element = fetch_att(s, typbyval, typlen);
3571  s = att_addlength_pointer(s, typlen, s);
3572  s = (char *) att_align_nominal(s, typalign);
3573 
3574  saophash_insert(elements_tab->hashtab, element, &hashfound);
3575  }
3576 
3577  /* Advance bitmap pointer if any. */
3578  if (bitmap)
3579  {
3580  bitmask <<= 1;
3581  if (bitmask == 0x100)
3582  {
3583  bitmap++;
3584  bitmask = 1;
3585  }
3586  }
3587  }
3588 
3589  /*
3590  * Remember if we had any nulls so that we know if we need to execute
3591  * non-strict functions with a null lhs value if no match is found.
3592  */
3593  op->d.hashedscalararrayop.has_nulls = has_nulls;
3594  }
3595 
3596  /* Check the hash to see if we have a match. */
3597  hashfound = NULL != saophash_lookup(elements_tab->hashtab, scalar);
3598 
3599  result = BoolGetDatum(hashfound);
3600  resultnull = false;
3601 
3602  /*
3603  * If we didn't find a match in the array, we still might need to handle
3604  * the possibility of null values. We didn't put any NULLs into the
3605  * hashtable, but instead marked if we found any when building the table
3606  * in has_nulls.
3607  */
3608  if (!DatumGetBool(result) && op->d.hashedscalararrayop.has_nulls)
3609  {
3610  if (strictfunc)
3611  {
3612 
3613  /*
3614  * We have nulls in the array so a non-null lhs and no match must
3615  * yield NULL.
3616  */
3617  result = (Datum) 0;
3618  resultnull = true;
3619  }
3620  else
3621  {
3622  /*
3623  * Execute function will null rhs just once.
3624  *
3625  * The hash lookup path will have scribbled on the lhs argument so
3626  * we need to set it up also (even though we entered this function
3627  * with it already set).
3628  */
3629  fcinfo->args[0].value = scalar;
3630  fcinfo->args[0].isnull = scalar_isnull;
3631  fcinfo->args[1].value = (Datum) 0;
3632  fcinfo->args[1].isnull = true;
3633 
3634  result = op->d.hashedscalararrayop.fn_addr(fcinfo);
3635  resultnull = fcinfo->isnull;
3636  }
3637  }
3638 
3639  *op->resvalue = result;
3640  *op->resnull = resultnull;
3641 }
signed short int16
Definition: c.h:428
struct ExprEvalStep * op
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
Datum * resvalue
Definition: execExpr.h:273
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2218
bool * resnull
Definition: execExpr.h:274
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char typalign
Definition: pg_type.h:176
union ExprEvalStep::@49 d
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetBool(X)
Definition: postgres.h:437
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
Datum value
Definition: postgres.h:422
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
uint8 bits8
Definition: c.h:448
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define Assert(condition)
Definition: c.h:804
struct ExprEvalStep::@49::@81 hashedscalararrayop
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
#define ARR_NDIM(a)
Definition: array.h:283
void * palloc(Size size)
Definition: mcxt.c:1062
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ ExecEvalMinMax()

void ExecEvalMinMax ( ExprState state,
ExprEvalStep op 
)

Definition at line 2946 of file execExprInterp.c.

References FunctionCallInfoBaseData::args, Assert, ExprEvalStep::d, DatumGetInt32, FunctionCallInvoke, IS_GREATEST, IS_LEAST, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, ExprEvalStep::minmax, ExprEvalStep::nulls, ExprEvalStep::resnull, ExprEvalStep::resvalue, NullableDatum::value, and values.

Referenced by ExecInterpExpr().

2947 {
2948  Datum *values = op->d.minmax.values;
2949  bool *nulls = op->d.minmax.nulls;
2950  FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
2951  MinMaxOp operator = op->d.minmax.op;
2952 
2953  /* set at initialization */
2954  Assert(fcinfo->args[0].isnull == false);
2955  Assert(fcinfo->args[1].isnull == false);
2956 
2957  /* default to null result */
2958  *op->resnull = true;
2959 
2960  for (int off = 0; off < op->d.minmax.nelems; off++)
2961  {
2962  /* ignore NULL inputs */
2963  if (nulls[off])
2964  continue;
2965 
2966  if (*op->resnull)
2967  {
2968  /* first nonnull input, adopt value */
2969  *op->resvalue = values[off];
2970  *op->resnull = false;
2971  }
2972  else
2973  {
2974  int cmpresult;
2975 
2976  /* apply comparison function */
2977  fcinfo->args[0].value = *op->resvalue;
2978  fcinfo->args[1].value = values[off];
2979 
2980  fcinfo->isnull = false;
2981  cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
2982  if (fcinfo->isnull) /* probably should not happen */
2983  continue;
2984 
2985  if (cmpresult > 0 && operator == IS_LEAST)
2986  *op->resvalue = values[off];
2987  else if (cmpresult < 0 && operator == IS_GREATEST)
2988  *op->resvalue = values[off];
2989  }
2990  }
2991 }
Datum * resvalue
Definition: execExpr.h:273
#define DatumGetInt32(X)
Definition: postgres.h:516
bool * resnull
Definition: execExpr.h:274
MinMaxOp
Definition: primnodes.h:1129
union ExprEvalStep::@49 d
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
Datum value
Definition: postgres.h:422
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
static Datum values[MAXATTR]
Definition: bootstrap.c:166
struct ExprEvalStep::@49::@73 minmax

◆ ExecEvalNextValueExpr()

void ExecEvalNextValueExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2548 of file execExprInterp.c.

References ExprEvalStep::d, elog, ERROR, Int16GetDatum, Int32GetDatum, Int64GetDatum(), newval, nextval_internal(), ExprEvalStep::nextvalueexpr, ExprEvalStep::resnull, and ExprEvalStep::resvalue.

Referenced by ExecInterpExpr().

2549 {
2550  int64 newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
2551 
2552  switch (op->d.nextvalueexpr.seqtypid)
2553  {
2554  case INT2OID:
2555  *op->resvalue = Int16GetDatum((int16) newval);
2556  break;
2557  case INT4OID:
2558  *op->resvalue = Int32GetDatum((int32) newval);
2559  break;
2560  case INT8OID:
2561  *op->resvalue = Int64GetDatum((int64) newval);
2562  break;
2563  default:
2564  elog(ERROR, "unsupported sequence type %u",
2565  op->d.nextvalueexpr.seqtypid);
2566  }
2567  *op->resnull = false;
2568 }
signed short int16
Definition: c.h:428
Datum * resvalue
Definition: execExpr.h:273
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:579
bool * resnull
Definition: execExpr.h:274
#define Int16GetDatum(X)
Definition: postgres.h:495
struct ExprEvalStep::@49::@67 nextvalueexpr
signed int int32
Definition: c.h:429
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1697
#define newval
#define Int32GetDatum(X)
Definition: postgres.h:523
#define elog(elevel,...)
Definition: elog.h:232

◆ ExecEvalParamExec()

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

Definition at line 2406 of file execExprInterp.c.

References Assert, ExprEvalStep::d, ExprContext::ecxt_param_exec_vals, ParamExecData::execPlan, ExecSetParamPlan(), ParamExecData::isnull, ExprEvalStep::param, ExprEvalStep::resnull, ExprEvalStep::resvalue, unlikely, and ParamExecData::value.

Referenced by ExecInterpExpr().

2407 {
2408  ParamExecData *prm;
2409 
2410  prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2411  if (unlikely(prm->execPlan != NULL))
2412  {
2413  /* Parameter not evaluated yet, so go do it */
2414  ExecSetParamPlan(prm->execPlan, econtext);
2415  /* ExecSetParamPlan should have processed this param... */
2416  Assert(prm->execPlan == NULL);
2417  }
2418  *op->resvalue = prm->value;
2419  *op->resnull = prm->isnull;
2420 }
void * execPlan
Definition: params.h:148
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
union ExprEvalStep::@49 d
void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
Definition: nodeSubplan.c:1058
bool isnull
Definition: params.h:150
struct ExprEvalStep::@49::@61 param
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:237
#define Assert(condition)
Definition: c.h:804
Datum value
Definition: params.h:149
#define unlikely(x)
Definition: c.h:273

◆ ExecEvalParamExtern()

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

Definition at line 2428 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

2429 {
2430  ParamListInfo paramInfo = econtext->ecxt_param_list_info;
2431  int paramId = op->d.param.paramid;
2432 
2433  if (likely(paramInfo &&
2434  paramId > 0 && paramId <= paramInfo->numParams))
2435  {
2436  ParamExternData *prm;
2437  ParamExternData prmdata;
2438 
2439  /* give hook a chance in case parameter is dynamic */
2440  if (paramInfo->paramFetch != NULL)
2441  prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
2442  else
2443  prm = &paramInfo->params[paramId - 1];
2444 
2445  if (likely(OidIsValid(prm->ptype)))
2446  {
2447  /* safety check in case hook did something unexpected */
2448  if (unlikely(prm->ptype != op->d.param.paramtype))
2449  ereport(ERROR,
2450  (errcode(ERRCODE_DATATYPE_MISMATCH),
2451  errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
2452  paramId,
2453  format_type_be(prm->ptype),
2454  format_type_be(op->d.param.paramtype))));
2455  *op->resvalue = prm->value;
2456  *op->resnull = prm->isnull;
2457  return;
2458  }
2459  }
2460 
2461  ereport(ERROR,
2462  (errcode(ERRCODE_UNDEFINED_OBJECT),
2463  errmsg("no value found for parameter %d", paramId)));
2464 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125
Datum value
Definition: params.h:92
#define likely(x)
Definition: c.h:272
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define OidIsValid(objectId)
Definition: c.h:710
ParamFetchHook paramFetch
Definition: params.h:112
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
struct ExprEvalStep::@49::@61 param
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define unlikely(x)
Definition: c.h:273
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:238
bool isnull
Definition: params.h:93

◆ ExecEvalRow()

void ExecEvalRow ( ExprState state,
ExprEvalStep op 
)

Definition at line 2926 of file execExprInterp.c.

References ExprEvalStep::d, heap_form_tuple(), HeapTupleGetDatum, ExprEvalStep::resnull, ExprEvalStep::resvalue, and ExprEvalStep::row.

Referenced by ExecInterpExpr().

2927 {
2928  HeapTuple tuple;
2929 
2930  /* build tuple from evaluated field values */
2931  tuple = heap_form_tuple(op->d.row.tupdesc,
2932  op->d.row.elemvalues,
2933  op->d.row.elemnulls);
2934 
2935  *op->resvalue = HeapTupleGetDatum(tuple);
2936  *op->resnull = false;
2937 }
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
union ExprEvalStep::@49 d
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
struct ExprEvalStep::@49::@70 row

◆ ExecEvalRowNotNull()

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

Definition at line 2583 of file execExprInterp.c.

References ExecEvalRowNullInt().

Referenced by ExecInterpExpr().

2584 {
2585  ExecEvalRowNullInt(state, op, econtext, false);
2586 }
static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, ExprContext *econtext, bool checkisnull)

◆ ExecEvalRowNull()

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

Definition at line 2574 of file execExprInterp.c.

References ExecEvalRowNullInt().

Referenced by ExecInterpExpr().

2575 {
2576  ExecEvalRowNullInt(state, op, econtext, true);
2577 }
static void ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, ExprContext *econtext, bool checkisnull)

◆ ExecEvalScalarArrayOp()

void ExecEvalScalarArrayOp ( ExprState state,
ExprEvalStep op 
)

Definition at line 3289 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

3290 {
3291  FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
3292  bool useOr = op->d.scalararrayop.useOr;
3293  bool strictfunc = op->d.scalararrayop.finfo->fn_strict;
3294  ArrayType *arr;
3295  int nitems;
3296  Datum result;
3297  bool resultnull;
3298  int16 typlen;
3299  bool typbyval;
3300  char typalign;
3301  char *s;
3302  bits8 *bitmap;
3303  int bitmask;
3304 
3305  /*
3306  * If the array is NULL then we return NULL --- it's not very meaningful
3307  * to do anything else, even if the operator isn't strict.
3308  */
3309  if (*op->resnull)
3310  return;
3311 
3312  /* Else okay to fetch and detoast the array */
3313  arr = DatumGetArrayTypeP(*op->resvalue);
3314 
3315  /*
3316  * If the array is empty, we return either FALSE or TRUE per the useOr
3317  * flag. This is correct even if the scalar is NULL; since we would
3318  * evaluate the operator zero times, it matters not whether it would want
3319  * to return NULL.
3320  */
3321  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3322  if (nitems <= 0)
3323  {
3324  *op->resvalue = BoolGetDatum(!useOr);
3325  *op->resnull = false;
3326  return;
3327  }
3328 
3329  /*
3330  * If the scalar is NULL, and the function is strict, return NULL; no
3331  * point in iterating the loop.
3332  */
3333  if (fcinfo->args[0].isnull && strictfunc)
3334  {
3335  *op->resnull = true;
3336  return;
3337  }
3338 
3339  /*
3340  * We arrange to look up info about the element type only once per series
3341  * of calls, assuming the element type doesn't change underneath us.
3342  */
3343  if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
3344  {
3346  &op->d.scalararrayop.typlen,
3347  &op->d.scalararrayop.typbyval,
3348  &op->d.scalararrayop.typalign);
3349  op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
3350  }
3351 
3352  typlen = op->d.scalararrayop.typlen;
3353  typbyval = op->d.scalararrayop.typbyval;
3354  typalign = op->d.scalararrayop.typalign;
3355 
3356  /* Initialize result appropriately depending on useOr */
3357  result = BoolGetDatum(!useOr);
3358  resultnull = false;
3359 
3360  /* Loop over the array elements */
3361  s = (char *) ARR_DATA_PTR(arr);
3362  bitmap = ARR_NULLBITMAP(arr);
3363  bitmask = 1;
3364 
3365  for (int i = 0; i < nitems; i++)
3366  {
3367  Datum elt;
3368  Datum thisresult;
3369 
3370  /* Get array element, checking for NULL */
3371  if (bitmap && (*bitmap & bitmask) == 0)
3372  {
3373  fcinfo->args[1].value = (Datum) 0;
3374  fcinfo->args[1].isnull = true;
3375  }
3376  else
3377  {
3378  elt = fetch_att(s, typbyval, typlen);
3379  s = att_addlength_pointer(s, typlen, s);
3380  s = (char *) att_align_nominal(s, typalign);
3381  fcinfo->args[1].value = elt;
3382  fcinfo->args[1].isnull = false;
3383  }
3384 
3385  /* Call comparison function */
3386  if (fcinfo->args[1].isnull && strictfunc)
3387  {
3388  fcinfo->isnull = true;
3389  thisresult = (Datum) 0;
3390  }
3391  else
3392  {
3393  fcinfo->isnull = false;
3394  thisresult = op->d.scalararrayop.fn_addr(fcinfo);
3395  }
3396 
3397  /* Combine results per OR or AND semantics */
3398  if (fcinfo->isnull)
3399  resultnull = true;
3400  else if (useOr)
3401  {
3402  if (DatumGetBool(thisresult))
3403  {
3404  result = BoolGetDatum(true);
3405  resultnull = false;
3406  break; /* needn't look at any more elements */
3407  }
3408  }
3409  else
3410  {
3411  if (!DatumGetBool(thisresult))
3412  {
3413  result = BoolGetDatum(false);
3414  resultnull = false;
3415  break; /* needn't look at any more elements */
3416  }
3417  }
3418 
3419  /* advance bitmap pointer if any */
3420  if (bitmap)
3421  {
3422  bitmask <<= 1;
3423  if (bitmask == 0x100)
3424  {
3425  bitmap++;
3426  bitmask = 1;
3427  }
3428  }
3429  }
3430 
3431  *op->resvalue = result;
3432  *op->resnull = resultnull;
3433 }
signed short int16
Definition: c.h:428
struct ExprEvalStep::@49::@80 scalararrayop
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
Datum * resvalue
Definition: execExpr.h:273
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2218
bool * resnull
Definition: execExpr.h:274
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
char typalign
Definition: pg_type.h:176
union ExprEvalStep::@49 d
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetBool(X)
Definition: postgres.h:437
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
Datum value
Definition: postgres.h:422
uint8 bits8
Definition: c.h:448
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ARR_NDIM(a)
Definition: array.h:283
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ ExecEvalSQLValueFunction()

void ExecEvalSQLValueFunction ( ExprState state,
ExprEvalStep op 
)

Definition at line 2470 of file execExprInterp.c.

References current_database(), current_schema(), current_user(), ExprEvalStep::d, DateADTGetDatum, GetSQLCurrentDate(), GetSQLCurrentTime(), GetSQLCurrentTimestamp(), GetSQLLocalTime(), GetSQLLocalTimestamp(), InitFunctionCallInfoData, InvalidOid, LOCAL_FCINFO, SQLValueFunction::op, ExprEvalStep::resnull, ExprEvalStep::resvalue, session_user(), ExprEvalStep::sqlvaluefunction, 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().

2471 {
2472  LOCAL_FCINFO(fcinfo, 0);
2473  SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
2474 
2475  *op->resnull = false;
2476 
2477  /*
2478  * Note: current_schema() can return NULL. current_user() etc currently
2479  * cannot, but might as well code those cases the same way for safety.
2480  */
2481  switch (svf->op)
2482  {
2483  case SVFOP_CURRENT_DATE:
2485  break;
2486  case SVFOP_CURRENT_TIME:
2487  case SVFOP_CURRENT_TIME_N:
2489  break;
2493  break;
2494  case SVFOP_LOCALTIME:
2495  case SVFOP_LOCALTIME_N:
2497  break;
2498  case SVFOP_LOCALTIMESTAMP:
2501  break;
2502  case SVFOP_CURRENT_ROLE:
2503  case SVFOP_CURRENT_USER:
2504  case SVFOP_USER:
2505  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2506  *op->resvalue = current_user(fcinfo);
2507  *op->resnull = fcinfo->isnull;
2508  break;
2509  case SVFOP_SESSION_USER:
2510  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2511  *op->resvalue = session_user(fcinfo);
2512  *op->resnull = fcinfo->isnull;
2513  break;
2514  case SVFOP_CURRENT_CATALOG:
2515  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2516  *op->resvalue = current_database(fcinfo);
2517  *op->resnull = fcinfo->isnull;
2518  break;
2519  case SVFOP_CURRENT_SCHEMA:
2520  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2521  *op->resvalue = current_schema(fcinfo);
2522  *op->resnull = fcinfo->isnull;
2523  break;
2524  }
2525 }
Datum current_schema(PG_FUNCTION_ARGS)
Definition: name.c:279
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
#define TimeTzADTPGetDatum(X)
Definition: date.h:59
TimestampTz GetSQLCurrentTimestamp(int32 typmod)
Definition: timestamp.c:1598
#define DateADTGetDatum(X)
Definition: date.h:57
DateADT GetSQLCurrentDate(void)
Definition: date.c:301
SQLValueFunctionOp op
Definition: primnodes.h:1179
Datum current_database(PG_FUNCTION_ARGS)
Definition: misc.c:173
union ExprEvalStep::@49 d
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:334
Datum current_user(PG_FUNCTION_ARGS)
Definition: name.c:263
#define TimestampGetDatum(X)
Definition: timestamp.h:31
TimeADT GetSQLLocalTime(int32 typmod)
Definition: date.c:354
Datum session_user(PG_FUNCTION_ARGS)
Definition: name.c:269
#define TimeADTGetDatum(X)
Definition: date.h:58
Timestamp GetSQLLocalTimestamp(int32 typmod)
Definition: timestamp.c:1612
#define InvalidOid
Definition: postgres_ext.h:36
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
struct ExprEvalStep::@49::@66 sqlvaluefunction

◆ ExecEvalStepOp()

ExprEvalOp ExecEvalStepOp ( ExprState state,
ExprEvalStep op 
)

Definition at line 2318 of file execExprInterp.c.

References Assert, EEO_FLAG_DIRECT_THREADED, EEOP_LAST, ExprState::flags, sort-test::key, and ExprEvalStep::opcode.

Referenced by CheckExprStillValid(), and llvm_compile_expr().

2319 {
2320 #if defined(EEO_USE_COMPUTED_GOTO)
2321  if (state->flags & EEO_FLAG_DIRECT_THREADED)
2322  {
2323  ExprEvalOpLookup key;
2324  ExprEvalOpLookup *res;
2325 
2326  key.opcode = (void *) op->opcode;
2327  res = bsearch(&key,
2328  reverse_dispatch_table,
2329  EEOP_LAST /* nmembers */ ,
2330  sizeof(ExprEvalOpLookup),
2331  dispatch_compare_ptr);
2332  Assert(res); /* unknown ops shouldn't get looked up */
2333  return res->op;
2334  }
2335 #endif
2336  return (ExprEvalOp) op->opcode;
2337 }
ExprEvalOp
Definition: execExpr.h:64
#define Assert(condition)
Definition: c.h:804
intptr_t opcode
Definition: execExpr.h:270
uint8 flags
Definition: execnodes.h:65
#define EEO_FLAG_DIRECT_THREADED
Definition: execExpr.h:29

◆ ExecEvalSubPlan()

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

Definition at line 3925 of file execExprInterp.c.

References check_stack_depth(), ExprEvalStep::d, ExecSubPlan(), ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sstate, and ExprEvalStep::subplan.

Referenced by ExecInterpExpr().

3926 {
3927  SubPlanState *sstate = op->d.subplan.sstate;
3928 
3929  /* could potentially be nested, so make sure there's enough stack */
3931 
3932  *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
3933 }
struct ExprEvalStep::@49::@86 subplan
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
union ExprEvalStep::@49 d
void check_stack_depth(void)
Definition: postgres.c:3469
Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:62

◆ ExecEvalSysVar()

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

Definition at line 4171 of file execExprInterp.c.

References ExprEvalStep::d, elog, ERROR, ExprEvalStep::resnull, ExprEvalStep::resvalue, slot_getsysattr(), unlikely, and ExprEvalStep::var.

Referenced by ExecInterpExpr().

4173 {
4174  Datum d;
4175 
4176  /* slot_getsysattr has sufficient defenses against bad attnums */
4177  d = slot_getsysattr(slot,
4178  op->d.var.attnum,
4179  op->resnull);
4180  *op->resvalue = d;
4181  /* this ought to be unreachable, but it's cheap enough to check */
4182  if (unlikely(*op->resnull))
4183  elog(ERROR, "failed to fetch attribute from slot");
4184 }
Datum * resvalue
Definition: execExpr.h:273
bool * resnull
Definition: execExpr.h:274
struct ExprEvalStep::@49::@51 var
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
uintptr_t Datum
Definition: postgres.h:411
#define elog(elevel,...)
Definition: elog.h:232
#define unlikely(x)
Definition: c.h:273
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:402

◆ ExecEvalWholeRowVar()

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

Definition at line 3942 of file execExprInterp.c.

References Assert, BlessTupleDesc(), Alias::colnames, CreateTupleDescCopy(), ExprEvalStep::d, ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_scantuple, RangeTblEntry::eref, 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, OUTER_VAR, PointerGetDatum, ReleaseTupleDesc, ExprEvalStep::resnull, ExprEvalStep::resvalue, slot_getallattrs(), HeapTupleData::t_data, toast_build_flattened_tuple(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, TupleTableSlot::tts_values, TupleDescAttr, Var::varattno, Var::varno, Var::vartype, and ExprEvalStep::wholerow.

Referenced by ExecInterpExpr().

3943 {
3944  Var *variable = op->d.wholerow.var;
3945  TupleTableSlot *slot;
3946  TupleDesc output_tupdesc;
3947  MemoryContext oldcontext;
3948  HeapTupleHeader dtuple;
3949  HeapTuple tuple;
3950 
3951  /* This was checked by ExecInitExpr */
3952  Assert(variable->varattno == InvalidAttrNumber);
3953 
3954  /* Get the input slot we want */
3955  switch (variable->varno)
3956  {
3957  case INNER_VAR:
3958  /* get the tuple from the inner node */
3959  slot = econtext->ecxt_innertuple;
3960  break;
3961 
3962  case OUTER_VAR:
3963  /* get the tuple from the outer node */
3964  slot = econtext->ecxt_outertuple;
3965  break;
3966 
3967  /* INDEX_VAR is handled by default case */
3968 
3969  default:
3970  /* get the tuple from the relation being scanned */
3971  slot = econtext->ecxt_scantuple;
3972  break;
3973  }
3974 
3975  /* Apply the junkfilter if any */
3976  if (op->d.wholerow.junkFilter != NULL)
3977  slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
3978 
3979  /*
3980  * If first time through, obtain tuple descriptor and check compatibility.
3981  *
3982  * XXX: It'd be great if this could be moved to the expression
3983  * initialization phase, but due to using slots that's currently not
3984  * feasible.
3985  */
3986  if (op->d.wholerow.first)
3987  {
3988  /* optimistically assume we don't need slow path */
3989  op->d.wholerow.slow = false;
3990 
3991  /*
3992  * If the Var identifies a named composite type, we must check that
3993  * the actual tuple type is compatible with it.
3994  */
3995  if (variable->vartype != RECORDOID)
3996  {
3997  TupleDesc var_tupdesc;
3998  TupleDesc slot_tupdesc;
3999 
4000  /*
4001  * We really only care about numbers of attributes and data types.
4002  * Also, we can ignore type mismatch on columns that are dropped
4003  * in the destination type, so long as (1) the physical storage
4004  * matches or (2) the actual column value is NULL. Case (1) is
4005  * helpful in some cases involving out-of-date cached plans, while
4006  * case (2) is expected behavior in situations such as an INSERT
4007  * into a table with dropped columns (the planner typically
4008  * generates an INT4 NULL regardless of the dropped column type).
4009  * If we find a dropped column and cannot verify that case (1)
4010  * holds, we have to use the slow path to check (2) for each row.
4011  *
4012  * If vartype is a domain over composite, just look through that
4013  * to the base composite type.
4014  */
4015  var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
4016  -1, false);
4017 
4018  slot_tupdesc = slot->tts_tupleDescriptor;
4019 
4020  if (var_tupdesc->natts != slot_tupdesc->natts)
4021  ereport(ERROR,
4022  (errcode(ERRCODE_DATATYPE_MISMATCH),
4023  errmsg("table row type and query-specified row type do not match"),
4024  errdetail_plural("Table row contains %d attribute, but query expects %d.",
4025  "Table row contains %d attributes, but query expects %d.",
4026  slot_tupdesc->natts,
4027  slot_tupdesc->natts,
4028  var_tupdesc->natts)));
4029 
4030  for (int i = 0; i < var_tupdesc->natts; i++)
4031  {
4032  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4033  Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i);
4034 
4035  if (vattr->atttypid == sattr->atttypid)
4036  continue; /* no worries */
4037  if (!vattr->attisdropped)
4038  ereport(ERROR,
4039  (errcode(ERRCODE_DATATYPE_MISMATCH),
4040  errmsg("table row type and query-specified row type do not match"),
4041  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
4042  format_type_be(sattr->atttypid),
4043  i + 1,
4044  format_type_be(vattr->atttypid))));
4045 
4046  if (vattr->attlen != sattr->attlen ||
4047  vattr->attalign != sattr->attalign)
4048  op->d.wholerow.slow = true; /* need to check for nulls */
4049  }
4050 
4051  /*
4052  * Use the variable's declared rowtype as the descriptor for the
4053  * output values, modulo possibly assigning new column names
4054  * below. In particular, we *must* absorb any attisdropped
4055  * markings.
4056  */
4057  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
4058  output_tupdesc = CreateTupleDescCopy(var_tupdesc);
4059  MemoryContextSwitchTo(oldcontext);
4060 
4061  ReleaseTupleDesc(var_tupdesc);
4062  }
4063  else
4064  {
4065  /*
4066  * In the RECORD case, we use the input slot's rowtype as the
4067  * descriptor for the output values, modulo possibly assigning new
4068  * column names below.
4069  */
4070  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
4071  output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
4072  MemoryContextSwitchTo(oldcontext);
4073  }
4074 
4075  /*
4076  * Construct a tuple descriptor for the composite values we'll
4077  * produce, and make sure its record type is "blessed". The main
4078  * reason to do this is to be sure that operations such as
4079  * row_to_json() will see the desired column names when they look up
4080  * the descriptor from the type information embedded in the composite
4081  * values.
4082  *
4083  * We already got the correct physical datatype info above, but now we
4084  * should try to find the source RTE and adopt its column aliases, in
4085  * case they are different from the original rowtype's names. For
4086  * example, in "SELECT foo(t) FROM tab t(x,y)", the first two columns
4087  * in the composite output should be named "x" and "y" regardless of
4088  * tab's column names.
4089  *
4090  * If we can't locate the RTE, assume the column names we've got are
4091  * OK. (As of this writing, the only cases where we can't locate the
4092  * RTE are in execution of trigger WHEN clauses, and then the Var will
4093  * have the trigger's relation's rowtype, so its names are fine.)
4094  * Also, if the creator of the RTE didn't bother to fill in an eref
4095  * field, assume our column names are OK. (This happens in COPY, and
4096  * perhaps other places.)
4097  */
4098  if (econtext->ecxt_estate &&
4099  variable->varno <= econtext->ecxt_estate->es_range_table_size)
4100  {
4101  RangeTblEntry *rte = exec_rt_fetch(variable->varno,
4102  econtext->ecxt_estate);
4103 
4104  if (rte->eref)
4105  ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
4106  }
4107 
4108  /* Bless the tupdesc if needed, and save it in the execution state */
4109  op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
4110 
4111  op->d.wholerow.first = false;
4112  }
4113 
4114  /*
4115  * Make sure all columns of the slot are accessible in the slot's
4116  * Datum/isnull arrays.
4117  */
4118  slot_getallattrs(slot);
4119 
4120  if (op->d.wholerow.slow)
4121  {
4122  /* Check to see if any dropped attributes are non-null */
4123  TupleDesc tupleDesc = slot->tts_tupleDescriptor;
4124  TupleDesc var_tupdesc = op->d.wholerow.tupdesc;
4125 
4126  Assert(var_tupdesc->natts == tupleDesc->natts);
4127 
4128  for (int i = 0; i < var_tupdesc->natts; i++)
4129  {
4130  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4131  Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i);
4132 
4133  if (!vattr->attisdropped)
4134  continue; /* already checked non-dropped cols */
4135  if (slot->tts_isnull[i])
4136  continue; /* null is always okay */
4137  if (vattr->attlen != sattr->attlen ||
4138  vattr->attalign != sattr->attalign)
4139  ereport(ERROR,
4140  (errcode(ERRCODE_DATATYPE_MISMATCH),
4141  errmsg("table row type and query-specified row type do not match"),
4142  errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
4143  i + 1)));
4144  }
4145  }
4146 
4147  /*
4148  * Build a composite datum, making sure any toasted fields get detoasted.
4149  *
4150  * (Note: it is critical that we not change the slot's state here.)
4151  */
4153  slot->tts_values,
4154  slot->tts_isnull);
4155  dtuple = tuple->t_data;
4156 
4157  /*
4158  * Label the datum with the composite type info we identified before.
4159  *
4160  * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
4161  * the tuple build step; but that seems a tad risky so let's not.)
4162  */
4163  HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
4164  HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
4165 
4166  *op->resvalue = PointerGetDatum(dtuple);
4167  *op->resnull = false;
4168 }
struct ExprEvalStep::@49::@52 wholerow
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define HeapTupleHeaderSetTypeId(tup, typeid)
Definition: htup_details.h:462
Datum * resvalue
Definition: execExpr.h:273
List * colnames
Definition: primnodes.h:43
#define PointerGetDatum(X)
Definition: postgres.h:600
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool * resnull
Definition: execExpr.h:274
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
AttrNumber varattno
Definition: primnodes.h:191
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Datum * tts_values
Definition: tuptable.h:126
Definition: primnodes.h:186
TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1882
HeapTupleHeader t_data
Definition: htup.h:68
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
Oid vartype
Definition: primnodes.h:193
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:354
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptoast.c:563
bool * tts_isnull
Definition: tuptable.h:128
int errdetail(const char *fmt,...)
Definition: elog.c:1042
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:228
struct EState * ecxt_estate
Definition: execnodes.h:262
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:571
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
Index varno
Definition: primnodes.h:189
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:247
#define HeapTupleHeaderSetTypMod(tup, typmod)
Definition: htup_details.h:472
#define ereport(elevel,...)
Definition: elog.h:157
#define INNER_VAR
Definition: primnodes.h:175
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:230
#define Assert(condition)
Definition: c.h:804
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1134
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:226
Index es_range_table_size
Definition: execnodes.h:560
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
Alias * eref
Definition: parsenodes.h:1141
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define OUTER_VAR
Definition: primnodes.h:176
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2036

◆ ExecEvalXmlExpr()

void ExecEvalXmlExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 3681 of file execExprInterp.c.

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

Referenced by ExecInterpExpr().

3682 {
3683  XmlExpr *xexpr = op->d.xmlexpr.xexpr;
3684  Datum value;
3685 
3686  *op->resnull = true; /* until we get a result */
3687  *op->resvalue = (Datum) 0;
3688 
3689  switch (xexpr->op)
3690  {
3691  case IS_XMLCONCAT:
3692  {
3693  Datum *argvalue = op->d.xmlexpr.argvalue;
3694  bool *argnull = op->d.xmlexpr.argnull;
3695  List *values = NIL;
3696 
3697  for (int i = 0; i < list_length(xexpr->args); i++)
3698  {
3699  if (!argnull[i])
3700  values = lappend(values, DatumGetPointer(argvalue[i]));
3701  }
3702 
3703  if (values != NIL)
3704  {
3705  *op->resvalue = PointerGetDatum(xmlconcat(values));
3706  *op->resnull = false;
3707  }
3708  }
3709  break;
3710 
3711  case IS_XMLFOREST:
3712  {
3713  Datum *argvalue = op->d.xmlexpr.named_argvalue;
3714  bool *argnull = op->d.xmlexpr.named_argnull;
3716  ListCell *lc;
3717  ListCell *lc2;
3718  int i;
3719 
3720  initStringInfo(&buf);
3721 
3722  i = 0;
3723  forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
3724  {
3725  Expr *e = (Expr *) lfirst(lc);
3726  char *argname = strVal(lfirst(lc2));
3727 
3728  if (!argnull[i])
3729  {
3730  value = argvalue[i];
3731  appendStringInfo(&buf, "<%s>%s</%s>",
3732  argname,
3734  exprType((Node *) e), true),
3735  argname);
3736  *op->resnull = false;
3737  }
3738  i++;
3739  }
3740 
3741  if (!*op->resnull)
3742  {
3743  text *result;
3744 
3745  result = cstring_to_text_with_len(buf.data, buf.len);
3746  *op->resvalue = PointerGetDatum(result);
3747  }
3748 
3749  pfree(buf.data);
3750  }
3751  break;
3752 
3753  case IS_XMLELEMENT:
3754  *op->resvalue = PointerGetDatum(xmlelement(xexpr,
3755  op->d.xmlexpr.named_argvalue,
3756  op->d.xmlexpr.named_argnull,
3757  op->d.xmlexpr.argvalue,
3758  op->d.xmlexpr.argnull));
3759  *op->resnull = false;
3760  break;
3761 
3762  case IS_XMLPARSE:
3763  {
3764  Datum *argvalue = op->d.xmlexpr.argvalue;
3765  bool *argnull = op->d.xmlexpr.argnull;
3766  text *data;
3767  bool preserve_whitespace;
3768 
3769  /* arguments are known to be text, bool */
3770  Assert(list_length(xexpr->args) == 2);
3771 
3772  if (argnull[0])
3773  return;
3774  value = argvalue[0];
3775  data = DatumGetTextPP(value);
3776 
3777  if (argnull[1]) /* probably can't happen */
3778  return;
3779  value = argvalue[1];
3780  preserve_whitespace = DatumGetBool(value);
3781 
3782  *op->resvalue = PointerGetDatum(xmlparse(data,
3783  xexpr->xmloption,
3784  preserve_whitespace));
3785  *op->resnull = false;
3786  }
3787  break;
3788 
3789  case IS_XMLPI:
3790  {
3791  text *arg;
3792  bool isnull;
3793 
3794  /* optional argument is known to be text */
3795  Assert(list_length(xexpr->args) <= 1);
3796 
3797  if (xexpr->args)
3798  {
3799  isnull = op->d.xmlexpr.argnull[0];
3800  if (isnull)
3801  arg = NULL;
3802  else
3803  arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
3804  }
3805  else
3806  {
3807  arg = NULL;
3808  isnull = false;
3809  }
3810 
3811  *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
3812  arg,
3813  isnull,
3814  op->resnull));
3815  }
3816  break;
3817 
3818  case IS_XMLROOT:
3819  {
3820  Datum *argvalue = op->d.xmlexpr.argvalue;
3821  bool *argnull = op->d.xmlexpr.argnull;
3822  xmltype *data;
3823  text *version;
3824  int standalone;
3825 
3826  /* arguments are known to be xml, text, int */
3827  Assert(list_length(xexpr->args) == 3);
3828 
3829  if (argnull[0])
3830  return;
3831  data = DatumGetXmlP(argvalue[0]);
3832 
3833  if (argnull[1])
3834  version = NULL;
3835  else
3836  version = DatumGetTextPP(argvalue[1]);
3837 
3838  Assert(!argnull[2]); /* always present */
3839  standalone = DatumGetInt32(argvalue[2]);
3840 
3841  *op->resvalue = PointerGetDatum(xmlroot(data,
3842  version,
3843  standalone));
3844  *op->resnull = false;
3845  }
3846  break;
3847 
3848  case IS_XMLSERIALIZE:
3849  {
3850  Datum *argvalue = op->d.xmlexpr.argvalue;
3851  bool *argnull = op->d.xmlexpr.argnull;
3852 
3853  /* argument type is known to be xml */
3854  Assert(list_length(xexpr->args) == 1);
3855 
3856  if (argnull[0])
3857  return;
3858  value = argvalue[0];
3859 
3861  xexpr->xmloption));
3862  *op->resnull = false;
3863  }
3864  break;
3865 
3866  case IS_DOCUMENT:
3867  {
3868  Datum *argvalue = op->d.xmlexpr.argvalue;
3869  bool *argnull = op->d.xmlexpr.argnull;
3870 
3871  /* optional argument is known to be xml */
3872  Assert(list_length(xexpr->args) == 1);
3873 
3874  if (argnull[0])
3875  return;
3876  value = argvalue[0];
3877 
3878  *op->resvalue =
3880  *op->resnull = false;
3881  }
3882  break;
3883 
3884  default:
3885  elog(ERROR, "unrecognized XML operation");
3886  break;
3887  }
3888 }
#define NIL
Definition: pg_list.h:65
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
char * name
Definition: primnodes.h:1218
static struct @142 value
Datum * resvalue
Definition: execExpr.h:273
#define DatumGetInt32(X)
Definition: postgres.h:516
#define PointerGetDatum(X)
Definition: postgres.h:600
#define DatumGetTextPP(X)
Definition: fmgr.h:292
bool * resnull
Definition: execExpr.h:274
xmltype * xmlconcat(List *args)
Definition: xml.c:512
Definition: nodes.h:539
#define strVal(v)
Definition: value.h:54
List * arg_names
Definition: primnodes.h:1220
#define DatumGetXmlP(X)
Definition: xml.h:50
xmltype * xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null)
Definition: xml.c:770
void pfree(void *pointer)
Definition: mcxt.c:1169
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:46
union ExprEvalStep::@49 d
text * xmltotext_with_xmloption(xmltype *data, XmlOptionType xmloption_arg)
Definition: xml.c:615
static char * buf
Definition: pg_test_fsync.c:68
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
xmltype * xmlroot(xmltype *data, text *version, int standalone)
Definition: xml.c:822
#define DatumGetBool(X)
Definition: postgres.h:437
List * lappend(List *list, void *datum)
Definition: list.c:336
bool xml_is_document(xmltype *arg)
Definition: xml.c:888
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
XmlExprOp op
Definition: primnodes.h:1217
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
List * named_args
Definition: primnodes.h:1219
List * args
Definition: primnodes.h:1221
struct ExprEvalStep::@49::@82 xmlexpr
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
XmlOptionType xmloption
Definition: primnodes.h:1222
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static int list_length(const List *l)
Definition: pg_list.h:149
#define DatumGetPointer(X)
Definition: postgres.h:593
static Datum values[MAXATTR]
Definition: bootstrap.c:166
e
Definition: preproc-init.c:82
#define elog(elevel,...)
Definition: elog.h:232
int i
xmltype * xmlelement(XmlExpr *xexpr, Datum *named_argvalue, bool *named_argnull, Datum *argvalue, bool *argnull)
Definition: xml.c:628
void * arg
Definition: c.h:621
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2134
Definition: pg_list.h:50
xmltype * xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
Definition: xml.c:752

◆ ExecInterpExprStillValid()

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

Definition at line 1812 of file execExprInterp.c.

References CheckExprStillValid(), ExprState::evalfunc, and ExprState::evalfunc_private.

Referenced by ExecReadyInterpretedExpr().

1813 {
1814  /*
1815  * First time through, check whether attribute matches Var. Might not be
1816  * ok anymore, due to schema changes.
1817  */
1818  CheckExprStillValid(state, econtext);
1819 
1820  /* skip the check during further executions */
1821  state->evalfunc = (ExprStateEvalFunc) state->evalfunc_private;
1822 
1823  /* and actually execute */
1824  return state->evalfunc(state, econtext, isNull);
1825 }
Datum(* ExprStateEvalFunc)(struct ExprState *expression, struct ExprContext *econtext, bool *isNull)
Definition: execnodes.h:53
ExprStateEvalFunc evalfunc
Definition: execnodes.h:91
void * evalfunc_private
Definition: execnodes.h:97
void CheckExprStillValid(ExprState *state, ExprContext *econtext)

◆ ExecReadyInterpretedExpr()

void ExecReadyInterpretedExpr ( ExprState state)

Definition at line 230 of file execExprInterp.c.

References Assert, ExprEvalStep::casetest, ExprEvalStep::d, 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, ExprState::evalfunc, ExprState::evalfunc_private, ExecInitInterpreter(), ExecInterpExpr(), ExecInterpExprStillValid(), ExecJustApplyFuncToCase(), ExecJustAssignInnerVar(), ExecJustAssignInnerVarVirt(), ExecJustAssignOuterVar(), ExecJustAssignOuterVarVirt(), ExecJustAssignScanVar(), ExecJustAssignScanVarVirt(), ExecJustConst(), ExecJustInnerVar(), ExecJustInnerVarVirt(), ExecJustOuterVar(), ExecJustOuterVarVirt(), ExecJustScanVar(), ExecJustScanVarVirt(), ExprState::flags, ExprEvalStep::op, ExprEvalStep::opcode, ExprState::steps, and ExprState::steps_len.

Referenced by ExecReadyExpr().

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

◆ ExprEvalPushStep()

void ExprEvalPushStep ( ExprState es,
const ExprEvalStep s 
)

Definition at line 2429 of file execExpr.c.

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

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

2430 {
2431  if (es->steps_alloc == 0)
2432  {
2433  es->steps_alloc = 16;
2434  es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
2435  }
2436  else if (es->steps_alloc == es->steps_len)
2437  {
2438  es->steps_alloc *= 2;
2439  es->steps = repalloc(es->steps,
2440  sizeof(ExprEvalStep) * es->steps_alloc);
2441  }
2442 
2443  memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
2444 }
struct ExprEvalStep * steps
Definition: execnodes.h:85
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
int steps_alloc
Definition: execnodes.h:105
void * palloc(Size size)
Definition: mcxt.c:1062
int steps_len
Definition: execnodes.h:104