PostgreSQL Source Code  git master
execExprInterp.c File Reference
#include "postgres.h"
#include "access/heaptoast.h"
#include "catalog/pg_type.h"
#include "commands/sequence.h"
#include "executor/execExpr.h"
#include "executor/nodeSubplan.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "nodes/nodeFuncs.h"
#include "pgstat.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datum.h"
#include "utils/expandedrecord.h"
#include "utils/json.h"
#include "utils/jsonfuncs.h"
#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
#include "utils/typcache.h"
#include "utils/xml.h"
#include "lib/simplehash.h"
Include dependency graph for execExprInterp.c:

Go to the source code of this file.

Data Structures

struct  ScalarArrayOpExprHashEntry
 
struct  ScalarArrayOpExprHashTable
 

Macros

#define EEO_SWITCH()   starteval: switch ((ExprEvalOp) op->opcode)
 
#define EEO_CASE(name)   case name:
 
#define EEO_DISPATCH()   goto starteval
 
#define EEO_OPCODE(opcode)   (opcode)
 
#define EEO_NEXT()
 
#define EEO_JUMP(stepno)
 
#define SH_PREFIX   saophash
 
#define SH_ELEMENT_TYPE   ScalarArrayOpExprHashEntry
 
#define SH_KEY_TYPE   Datum
 
#define SH_SCOPE   static inline
 
#define SH_DECLARE
 
#define SH_PREFIX   saophash
 
#define SH_ELEMENT_TYPE   ScalarArrayOpExprHashEntry
 
#define SH_KEY_TYPE   Datum
 
#define SH_KEY   key
 
#define SH_HASH_KEY(tb, key)   saop_element_hash(tb, key)
 
#define SH_EQUAL(tb, a, b)   saop_hash_element_match(tb, a, b)
 
#define SH_SCOPE   static inline
 
#define SH_STORE_HASH
 
#define SH_GET_HASH(tb, a)   a->hash
 
#define SH_DEFINE
 

Typedefs

typedef struct ScalarArrayOpExprHashEntry ScalarArrayOpExprHashEntry
 
typedef struct ScalarArrayOpExprHashTable ScalarArrayOpExprHashTable
 

Functions

static Datum ExecInterpExpr (ExprState *state, ExprContext *econtext, bool *isnull)
 
static void ExecInitInterpreter (void)
 
static void CheckVarSlotCompatibility (TupleTableSlot *slot, int attnum, Oid vartype)
 
static void CheckOpSlotCompatibility (ExprEvalStep *op, TupleTableSlot *slot)
 
static TupleDesc get_cached_rowtype (Oid type_id, int32 typmod, ExprEvalRowtypeCache *rowcache, bool *changed)
 
static void ExecEvalRowNullInt (ExprState *state, ExprEvalStep *op, ExprContext *econtext, bool checkisnull)
 
static Datum ExecJustInnerVar (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 ExecJustAssignInnerVar (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustAssignOuterVar (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustAssignScanVar (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustApplyFuncToCase (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustConst (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustInnerVarVirt (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustOuterVarVirt (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustScanVarVirt (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustAssignInnerVarVirt (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustAssignOuterVarVirt (ExprState *state, ExprContext *econtext, bool *isnull)
 
static Datum ExecJustAssignScanVarVirt (ExprState *state, ExprContext *econtext, bool *isnull)
 
static pg_attribute_always_inline void ExecAggPlainTransByVal (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext, int setno)
 
static pg_attribute_always_inline void ExecAggPlainTransByRef (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext, int setno)
 
static char * ExecGetJsonValueItemString (JsonbValue *item, bool *resnull)
 
static bool saop_hash_element_match (struct saophash_hash *tb, Datum key1, Datum key2)
 
static uint32 saop_element_hash (struct saophash_hash *tb, Datum key)
 
void ExecReadyInterpretedExpr (ExprState *state)
 
Datum ExecInterpExprStillValid (ExprState *state, ExprContext *econtext, bool *isNull)
 
void CheckExprStillValid (ExprState *state, ExprContext *econtext)
 
static pg_attribute_always_inline Datum ExecJustVarImpl (ExprState *state, TupleTableSlot *slot, bool *isnull)
 
static pg_attribute_always_inline Datum ExecJustAssignVarImpl (ExprState *state, TupleTableSlot *inslot, bool *isnull)
 
static pg_attribute_always_inline Datum ExecJustVarVirtImpl (ExprState *state, TupleTableSlot *slot, bool *isnull)
 
static pg_attribute_always_inline Datum ExecJustAssignVarVirtImpl (ExprState *state, TupleTableSlot *inslot, bool *isnull)
 
ExprEvalOp ExecEvalStepOp (ExprState *state, ExprEvalStep *op)
 
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 ExecEvalParamSet (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalCoerceViaIOSafe (ExprState *state, ExprEvalStep *op)
 
void ExecEvalSQLValueFunction (ExprState *state, ExprEvalStep *op)
 
void ExecEvalCurrentOfExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalNextValueExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalRowNull (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalRowNotNull (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalArrayExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalArrayCoerce (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalRow (ExprState *state, ExprEvalStep *op)
 
void ExecEvalMinMax (ExprState *state, ExprEvalStep *op)
 
void ExecEvalFieldSelect (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalFieldStoreDeForm (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalFieldStoreForm (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalConvertRowtype (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalScalarArrayOp (ExprState *state, ExprEvalStep *op)
 
void ExecEvalHashedScalarArrayOp (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalConstraintNotNull (ExprState *state, ExprEvalStep *op)
 
void ExecEvalConstraintCheck (ExprState *state, ExprEvalStep *op)
 
void ExecEvalXmlExpr (ExprState *state, ExprEvalStep *op)
 
void ExecEvalJsonConstructor (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalJsonIsPredicate (ExprState *state, ExprEvalStep *op)
 
int ExecEvalJsonExprPath (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalJsonCoercion (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static char * GetJsonBehaviorValueString (JsonBehavior *behavior)
 
void ExecEvalJsonCoercionFinish (ExprState *state, ExprEvalStep *op)
 
void ExecEvalGroupingFunc (ExprState *state, ExprEvalStep *op)
 
void ExecEvalMergeSupportFunc (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalSubPlan (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalWholeRowVar (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalSysVar (ExprState *state, ExprEvalStep *op, ExprContext *econtext, TupleTableSlot *slot)
 
void ExecAggInitGroup (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext)
 
Datum ExecAggCopyTransValue (AggState *aggstate, AggStatePerTrans pertrans, Datum newValue, bool newValueIsNull, Datum oldValue, bool oldValueIsNull)
 
bool ExecEvalPreOrderedDistinctSingle (AggState *aggstate, AggStatePerTrans pertrans)
 
bool ExecEvalPreOrderedDistinctMulti (AggState *aggstate, AggStatePerTrans pertrans)
 
void ExecEvalAggOrderedTransDatum (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalAggOrderedTransTuple (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 

Macro Definition Documentation

◆ EEO_CASE

#define EEO_CASE (   name)    case name:

Definition at line 125 of file execExprInterp.c.

◆ EEO_DISPATCH

#define EEO_DISPATCH ( )    goto starteval

Definition at line 126 of file execExprInterp.c.

◆ EEO_JUMP

#define EEO_JUMP (   stepno)
Value:
do { \
op = &state->steps[stepno]; \
EEO_DISPATCH(); \
} while (0)
Definition: regguts.h:323

Definition at line 137 of file execExprInterp.c.

◆ EEO_NEXT

#define EEO_NEXT ( )
Value:
do { \
op++; \
EEO_DISPATCH(); \
} while (0)

Definition at line 131 of file execExprInterp.c.

◆ EEO_OPCODE

#define EEO_OPCODE (   opcode)    (opcode)

Definition at line 127 of file execExprInterp.c.

◆ EEO_SWITCH

#define EEO_SWITCH ( )    starteval: switch ((ExprEvalOp) op->opcode)

Definition at line 124 of file execExprInterp.c.

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 200 of file execExprInterp.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 229 of file execExprInterp.c.

◆ SH_ELEMENT_TYPE [1/2]

#define SH_ELEMENT_TYPE   ScalarArrayOpExprHashEntry

Definition at line 221 of file execExprInterp.c.

◆ SH_ELEMENT_TYPE [2/2]

#define SH_ELEMENT_TYPE   ScalarArrayOpExprHashEntry

Definition at line 221 of file execExprInterp.c.

◆ SH_EQUAL

#define SH_EQUAL (   tb,
  a,
  b 
)    saop_hash_element_match(tb, a, b)

Definition at line 225 of file execExprInterp.c.

◆ SH_GET_HASH

#define SH_GET_HASH (   tb,
  a 
)    a->hash

Definition at line 228 of file execExprInterp.c.

◆ SH_HASH_KEY

#define SH_HASH_KEY (   tb,
  key 
)    saop_element_hash(tb, key)

Definition at line 224 of file execExprInterp.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 223 of file execExprInterp.c.

◆ SH_KEY_TYPE [1/2]

#define SH_KEY_TYPE   Datum

Definition at line 222 of file execExprInterp.c.

◆ SH_KEY_TYPE [2/2]

#define SH_KEY_TYPE   Datum

Definition at line 222 of file execExprInterp.c.

◆ SH_PREFIX [1/2]

#define SH_PREFIX   saophash

Definition at line 220 of file execExprInterp.c.

◆ SH_PREFIX [2/2]

#define SH_PREFIX   saophash

Definition at line 220 of file execExprInterp.c.

◆ SH_SCOPE [1/2]

#define SH_SCOPE   static inline

Definition at line 226 of file execExprInterp.c.

◆ SH_SCOPE [2/2]

#define SH_SCOPE   static inline

Definition at line 226 of file execExprInterp.c.

◆ SH_STORE_HASH

#define SH_STORE_HASH

Definition at line 227 of file execExprInterp.c.

Typedef Documentation

◆ ScalarArrayOpExprHashEntry

◆ ScalarArrayOpExprHashTable

Function Documentation

◆ CheckExprStillValid()

void CheckExprStillValid ( ExprState state,
ExprContext econtext 
)

Definition at line 2041 of file execExprInterp.c.

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

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

Referenced by ExecInterpExprStillValid(), and ExecRunCompiledExpr().

◆ CheckOpSlotCompatibility()

static void CheckOpSlotCompatibility ( ExprEvalStep op,
TupleTableSlot slot 
)
static

Definition at line 2143 of file execExprInterp.c.

2144 {
2145 #ifdef USE_ASSERT_CHECKING
2146  /* there's nothing to check */
2147  if (!op->d.fetch.fixed)
2148  return;
2149 
2150  /*
2151  * Should probably fixed at some point, but for now it's easier to allow
2152  * buffer and heap tuples to be used interchangeably.
2153  */
2154  if (slot->tts_ops == &TTSOpsBufferHeapTuple &&
2155  op->d.fetch.kind == &TTSOpsHeapTuple)
2156  return;
2157  if (slot->tts_ops == &TTSOpsHeapTuple &&
2158  op->d.fetch.kind == &TTSOpsBufferHeapTuple)
2159  return;
2160 
2161  /*
2162  * At the moment we consider it OK if a virtual slot is used instead of a
2163  * specific type of slot, as a virtual slot never needs to be deformed.
2164  */
2165  if (slot->tts_ops == &TTSOpsVirtual)
2166  return;
2167 
2168  Assert(op->d.fetch.kind == slot->tts_ops);
2169 #endif
2170 }
#define Assert(condition)
Definition: c.h:858
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
const TupleTableSlotOps TTSOpsBufferHeapTuple
Definition: execTuples.c:87
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
struct ExprEvalStep::@54::@55 fetch
const TupleTableSlotOps *const tts_ops
Definition: tuptable.h:121

References Assert, ExprEvalStep::op, TupleTableSlot::tts_ops, TTSOpsBufferHeapTuple, TTSOpsHeapTuple, and TTSOpsVirtual.

Referenced by ExecInterpExpr(), ExecJustAssignVarImpl(), and ExecJustVarImpl().

◆ CheckVarSlotCompatibility()

static void CheckVarSlotCompatibility ( TupleTableSlot slot,
int  attnum,
Oid  vartype 
)
static

Definition at line 2092 of file execExprInterp.c.

2093 {
2094  /*
2095  * What we have to check for here is the possibility of an attribute
2096  * having been dropped or changed in type since the plan tree was created.
2097  * Ideally the plan will get invalidated and not re-used, but just in
2098  * case, we keep these defenses. Fortunately it's sufficient to check
2099  * once on the first time through.
2100  *
2101  * Note: ideally we'd check typmod as well as typid, but that seems
2102  * impractical at the moment: in many cases the tupdesc will have been
2103  * generated by ExecTypeFromTL(), and that can't guarantee to generate an
2104  * accurate typmod in all cases, because some expression node types don't
2105  * carry typmod. Fortunately, for precisely that reason, there should be
2106  * no places with a critical dependency on the typmod of a value.
2107  *
2108  * System attributes don't require checking since their types never
2109  * change.
2110  */
2111  if (attnum > 0)
2112  {
2113  TupleDesc slot_tupdesc = slot->tts_tupleDescriptor;
2114  Form_pg_attribute attr;
2115 
2116  if (attnum > slot_tupdesc->natts) /* should never happen */
2117  elog(ERROR, "attribute number %d exceeds number of columns %d",
2118  attnum, slot_tupdesc->natts);
2119 
2120  attr = TupleDescAttr(slot_tupdesc, attnum - 1);
2121 
2122  if (attr->attisdropped)
2123  ereport(ERROR,
2124  (errcode(ERRCODE_UNDEFINED_COLUMN),
2125  errmsg("attribute %d of type %s has been dropped",
2126  attnum, format_type_be(slot_tupdesc->tdtypeid))));
2127 
2128  if (vartype != attr->atttypid)
2129  ereport(ERROR,
2130  (errcode(ERRCODE_DATATYPE_MISMATCH),
2131  errmsg("attribute %d of type %s has wrong type",
2132  attnum, format_type_be(slot_tupdesc->tdtypeid)),
2133  errdetail("Table has type %s, but query expects %s.",
2134  format_type_be(attr->atttypid),
2135  format_type_be(vartype))));
2136  }
2137 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
Oid tdtypeid
Definition: tupdesc.h:82
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:123
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References attnum, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, format_type_be(), TupleDescData::natts, TupleDescData::tdtypeid, TupleTableSlot::tts_tupleDescriptor, TupleDescAttr, and ExprEvalStep::vartype.

Referenced by CheckExprStillValid().

◆ ExecAggCopyTransValue()

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

Definition at line 5195 of file execExprInterp.c.

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

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

Referenced by advance_transition_function(), and ExecAggPlainTransByRef().

◆ ExecAggInitGroup()

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

Definition at line 5142 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecAggPlainTransByRef()

static pg_attribute_always_inline void ExecAggPlainTransByRef ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroup,
ExprContext aggcontext,
int  setno 
)
static

Definition at line 5394 of file execExprInterp.c.

5397 {
5398  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
5399  MemoryContext oldContext;
5400  Datum newVal;
5401 
5402  /* cf. select_current_set() */
5403  aggstate->curaggcontext = aggcontext;
5404  aggstate->current_set = setno;
5405 
5406  /* set up aggstate->curpertrans for AggGetAggref() */
5407  aggstate->curpertrans = pertrans;
5408 
5409  /* invoke transition function in per-tuple context */
5410  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
5411 
5412  fcinfo->args[0].value = pergroup->transValue;
5413  fcinfo->args[0].isnull = pergroup->transValueIsNull;
5414  fcinfo->isnull = false; /* just in case transfn doesn't set it */
5415 
5416  newVal = FunctionCallInvoke(fcinfo);
5417 
5418  /*
5419  * For pass-by-ref datatype, must copy the new value into aggcontext and
5420  * free the prior transValue. But if transfn returned a pointer to its
5421  * first input, we don't need to do anything.
5422  *
5423  * It's safe to compare newVal with pergroup->transValue without regard
5424  * for either being NULL, because ExecAggCopyTransValue takes care to set
5425  * transValue to 0 when NULL. Otherwise we could end up accidentally not
5426  * reparenting, when the transValue has the same numerical value as
5427  * newValue, despite being NULL. This is a somewhat hot path, making it
5428  * undesirable to instead solve this with another branch for the common
5429  * case of the transition function returning its (modified) input
5430  * argument.
5431  */
5432  if (DatumGetPointer(newVal) != DatumGetPointer(pergroup->transValue))
5433  newVal = ExecAggCopyTransValue(aggstate, pertrans,
5434  newVal, fcinfo->isnull,
5435  pergroup->transValue,
5436  pergroup->transValueIsNull);
5437 
5438  pergroup->transValue = newVal;
5439  pergroup->transValueIsNull = fcinfo->isnull;
5440 
5441  MemoryContextSwitchTo(oldContext);
5442 }
Datum ExecAggCopyTransValue(AggState *aggstate, AggStatePerTrans pertrans, Datum newValue, bool newValueIsNull, Datum oldValue, bool oldValueIsNull)
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
ExprContext * tmpcontext
Definition: execnodes.h:2502
AggStatePerTrans curpertrans
Definition: execnodes.h:2507
int current_set
Definition: execnodes.h:2512
bool isnull
Definition: postgres.h:77

References ExprEvalStep::aggcontext, FunctionCallInfoBaseData::args, AggState::curaggcontext, AggState::curpertrans, AggState::current_set, DatumGetPointer(), ExprContext::ecxt_per_tuple_memory, ExecAggCopyTransValue(), FunctionCallInvoke, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, MemoryContextSwitchTo(), ExprEvalStep::pertrans, ExprEvalStep::setno, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, AggStatePerGroupData::transValue, AggStatePerGroupData::transValueIsNull, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecAggPlainTransByVal()

static pg_attribute_always_inline void ExecAggPlainTransByVal ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroup,
ExprContext aggcontext,
int  setno 
)
static

Definition at line 5362 of file execExprInterp.c.

5365 {
5366  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
5367  MemoryContext oldContext;
5368  Datum newVal;
5369 
5370  /* cf. select_current_set() */
5371  aggstate->curaggcontext = aggcontext;
5372  aggstate->current_set = setno;
5373 
5374  /* set up aggstate->curpertrans for AggGetAggref() */
5375  aggstate->curpertrans = pertrans;
5376 
5377  /* invoke transition function in per-tuple context */
5378  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
5379 
5380  fcinfo->args[0].value = pergroup->transValue;
5381  fcinfo->args[0].isnull = pergroup->transValueIsNull;
5382  fcinfo->isnull = false; /* just in case transfn doesn't set it */
5383 
5384  newVal = FunctionCallInvoke(fcinfo);
5385 
5386  pergroup->transValue = newVal;
5387  pergroup->transValueIsNull = fcinfo->isnull;
5388 
5389  MemoryContextSwitchTo(oldContext);
5390 }

References ExprEvalStep::aggcontext, FunctionCallInfoBaseData::args, AggState::curaggcontext, AggState::curpertrans, AggState::current_set, ExprContext::ecxt_per_tuple_memory, FunctionCallInvoke, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, MemoryContextSwitchTo(), ExprEvalStep::pertrans, ExprEvalStep::setno, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, AggStatePerGroupData::transValue, AggStatePerGroupData::transValueIsNull, and NullableDatum::value.

Referenced by ExecInterpExpr().

◆ ExecEvalAggOrderedTransDatum()

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

Definition at line 5334 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalAggOrderedTransTuple()

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

Definition at line 5348 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalArrayCoerce()

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

Definition at line 3183 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalArrayExpr()

void ExecEvalArrayExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2969 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalCoerceViaIOSafe()

void ExecEvalCoerceViaIOSafe ( ExprState state,
ExprEvalStep op 
)

Definition at line 2703 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalConstraintCheck()

void ExecEvalConstraintCheck ( ExprState state,
ExprEvalStep op 
)

Definition at line 3990 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalConstraintNotNull()

void ExecEvalConstraintNotNull ( ExprState state,
ExprEvalStep op 
)

Definition at line 3976 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalConvertRowtype()

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

Definition at line 3496 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalCurrentOfExpr()

void ExecEvalCurrentOfExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2830 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalFieldSelect()

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

Definition at line 3297 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalFieldStoreDeForm()

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

Definition at line 3422 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalFieldStoreForm()

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

Definition at line 3472 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalFuncExprFusage()

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

Definition at line 2558 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalFuncExprStrictFusage()

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

Definition at line 2579 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalGroupingFunc()

void ExecEvalGroupingFunc ( ExprState state,
ExprEvalStep op 
)

Definition at line 4814 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalHashedScalarArrayOp()

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

Definition at line 3794 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalJsonCoercion()

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

Definition at line 4680 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalJsonCoercionFinish()

void ExecEvalJsonCoercionFinish ( ExprState state,
ExprEvalStep op 
)

Definition at line 4760 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalJsonConstructor()

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

Definition at line 4225 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalJsonExprPath()

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

Definition at line 4403 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalJsonIsPredicate()

void ExecEvalJsonIsPredicate ( ExprState state,
ExprEvalStep op 
)

Definition at line 4303 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalMergeSupportFunc()

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

Definition at line 4841 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalMinMax()

void ExecEvalMinMax ( ExprState state,
ExprEvalStep op 
)

Definition at line 3244 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalNextValueExpr()

void ExecEvalNextValueExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2841 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalParamExec()

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

Definition at line 2616 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalParamExtern()

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

Definition at line 2638 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalParamSet()

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

Definition at line 2681 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalPreOrderedDistinctMulti()

bool ExecEvalPreOrderedDistinctMulti ( AggState aggstate,
AggStatePerTrans  pertrans 
)

Definition at line 5287 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalPreOrderedDistinctSingle()

bool ExecEvalPreOrderedDistinctSingle ( AggState aggstate,
AggStatePerTrans  pertrans 
)

Definition at line 5244 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalRow()

void ExecEvalRow ( ExprState state,
ExprEvalStep op 
)

Definition at line 3224 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalRowNotNull()

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

Definition at line 2876 of file execExprInterp.c.

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

References ExecEvalRowNullInt(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalRowNull()

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

Definition at line 2867 of file execExprInterp.c.

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

References ExecEvalRowNullInt(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalRowNullInt()

static void ExecEvalRowNullInt ( ExprState state,
ExprEvalStep op,
ExprContext econtext,
bool  checkisnull 
)
static

Definition at line 2883 of file execExprInterp.c.

2885 {
2886  Datum value = *op->resvalue;
2887  bool isnull = *op->resnull;
2888  HeapTupleHeader tuple;
2889  Oid tupType;
2890  int32 tupTypmod;
2891  TupleDesc tupDesc;
2892  HeapTupleData tmptup;
2893 
2894  *op->resnull = false;
2895 
2896  /* NULL row variables are treated just as NULL scalar columns */
2897  if (isnull)
2898  {
2899  *op->resvalue = BoolGetDatum(checkisnull);
2900  return;
2901  }
2902 
2903  /*
2904  * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
2905  * as:
2906  *
2907  * "R IS NULL" is true if every field is the null value.
2908  *
2909  * "R IS NOT NULL" is true if no field is the null value.
2910  *
2911  * This definition is (apparently intentionally) not recursive; so our
2912  * tests on the fields are primitive attisnull tests, not recursive checks
2913  * to see if they are all-nulls or no-nulls rowtypes.
2914  *
2915  * The standard does not consider the possibility of zero-field rows, but
2916  * here we consider them to vacuously satisfy both predicates.
2917  */
2918 
2919  tuple = DatumGetHeapTupleHeader(value);
2920 
2921  tupType = HeapTupleHeaderGetTypeId(tuple);
2922  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2923 
2924  /* Lookup tupdesc if first time through or if type changes */
2925  tupDesc = get_cached_rowtype(tupType, tupTypmod,
2926  &op->d.nulltest_row.rowcache, NULL);
2927 
2928  /*
2929  * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
2930  */
2931  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2932  tmptup.t_data = tuple;
2933 
2934  for (int att = 1; att <= tupDesc->natts; att++)
2935  {
2936  /* ignore dropped columns */
2937  if (TupleDescAttr(tupDesc, att - 1)->attisdropped)
2938  continue;
2939  if (heap_attisnull(&tmptup, att, tupDesc))
2940  {
2941  /* null field disproves IS NOT NULL */
2942  if (!checkisnull)
2943  {
2944  *op->resvalue = BoolGetDatum(false);
2945  return;
2946  }
2947  }
2948  else
2949  {
2950  /* non-null field disproves IS NULL */
2951  if (checkisnull)
2952  {
2953  *op->resvalue = BoolGetDatum(false);
2954  return;
2955  }
2956  }
2957  }
2958 
2959  *op->resvalue = BoolGetDatum(true);
2960 }
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:455
struct ExprEvalStep::@54::@65 nulltest_row

References BoolGetDatum(), DatumGetHeapTupleHeader, get_cached_rowtype(), heap_attisnull(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, ExprEvalStep::isnull, TupleDescData::natts, ExprEvalStep::op, HeapTupleData::t_data, HeapTupleData::t_len, TupleDescAttr, and value.

Referenced by ExecEvalRowNotNull(), and ExecEvalRowNull().

◆ ExecEvalScalarArrayOp()

void ExecEvalScalarArrayOp ( ExprState state,
ExprEvalStep op 
)

Definition at line 3591 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalSQLValueFunction()

void ExecEvalSQLValueFunction ( ExprState state,
ExprEvalStep op 
)

Definition at line 2763 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalStepOp()

ExprEvalOp ExecEvalStepOp ( ExprState state,
ExprEvalStep op 
)

Definition at line 2528 of file execExprInterp.c.

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

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

Referenced by CheckExprStillValid().

◆ ExecEvalSubPlan()

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

Definition at line 4878 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalSysVar()

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

Definition at line 5122 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalWholeRowVar()

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

Definition at line 4895 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecEvalXmlExpr()

void ExecEvalXmlExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 4010 of file execExprInterp.c.

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

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

Referenced by ExecInterpExpr().

◆ ExecGetJsonValueItemString()

static char * ExecGetJsonValueItemString ( JsonbValue item,
bool resnull 
)
static

Definition at line 4605 of file execExprInterp.c.

4606 {
4607  *resnull = false;
4608 
4609  /* get coercion state reference and datum of the corresponding SQL type */
4610  switch (item->type)
4611  {
4612  case jbvNull:
4613  *resnull = true;
4614  return NULL;
4615 
4616  case jbvString:
4617  {
4618  char *str = palloc(item->val.string.len + 1);
4619 
4620  memcpy(str, item->val.string.val, item->val.string.len);
4621  str[item->val.string.len] = '\0';
4622  return str;
4623  }
4624 
4625  case jbvNumeric:
4627  NumericGetDatum(item->val.numeric)));
4628 
4629  case jbvBool:
4631  BoolGetDatum(item->val.boolean)));
4632 
4633  case jbvDatetime:
4634  switch (item->val.datetime.typid)
4635  {
4636  case DATEOID:
4638  item->val.datetime.value));
4639  case TIMEOID:
4641  item->val.datetime.value));
4642  case TIMETZOID:
4644  item->val.datetime.value));
4645  case TIMESTAMPOID:
4647  item->val.datetime.value));
4648  case TIMESTAMPTZOID:
4650  item->val.datetime.value));
4651  default:
4652  elog(ERROR, "unexpected jsonb datetime type oid %u",
4653  item->val.datetime.typid);
4654  }
4655  break;
4656 
4657  case jbvArray:
4658  case jbvObject:
4659  case jbvBinary:
4662 
4663  default:
4664  elog(ERROR, "unexpected jsonb value type %d", item->type);
4665  }
4666 
4667  Assert(false);
4668  *resnull = true;
4669  return NULL;
4670 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:818
Datum timestamptz_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:775
Datum timestamp_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:233
Datum boolout(PG_FUNCTION_ARGS)
Definition: bool.c:158
Datum date_out(PG_FUNCTION_ARGS)
Definition: date.c:184
Datum time_out(PG_FUNCTION_ARGS)
Definition: date.c:1513
Datum timetz_out(PG_FUNCTION_ARGS)
Definition: date.c:2326
@ jbvObject
Definition: jsonb.h:234
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ jbvArray
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:236
@ jbvNull
Definition: jsonb.h:228
@ jbvDatetime
Definition: jsonb.h:244
@ jbvString
Definition: jsonb.h:229
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264

References Assert, BoolGetDatum(), boolout(), date_out(), DatumGetCString(), DirectFunctionCall1, elog, ERROR, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jsonb_out(), JsonbPGetDatum(), JsonbValueToJsonb(), numeric_out(), NumericGetDatum(), palloc(), ExprEvalStep::resnull, str, time_out(), timestamp_out(), timestamptz_out(), timetz_out(), JsonbValue::type, and JsonbValue::val.

Referenced by ExecEvalJsonExprPath().

◆ ExecInitInterpreter()

static void ExecInitInterpreter ( void  )
static

Definition at line 2496 of file execExprInterp.c.

2497 {
2498 #if defined(EEO_USE_COMPUTED_GOTO)
2499  /* Set up externally-visible pointer to dispatch table */
2500  if (dispatch_table == NULL)
2501  {
2502  dispatch_table = (const void **)
2503  DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
2504 
2505  /* build reverse lookup table */
2506  for (int i = 0; i < EEOP_LAST; i++)
2507  {
2508  reverse_dispatch_table[i].opcode = dispatch_table[i];
2509  reverse_dispatch_table[i].op = (ExprEvalOp) i;
2510  }
2511 
2512  /* make it bsearch()able */
2513  qsort(reverse_dispatch_table,
2514  EEOP_LAST /* nmembers */ ,
2515  sizeof(ExprEvalOpLookup),
2516  dispatch_compare_ptr);
2517  }
2518 #endif
2519 }
static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
#define qsort(a, b, c, d)
Definition: port.h:447

References DatumGetPointer(), EEOP_LAST, ExecInterpExpr(), i, and qsort.

Referenced by ExecReadyInterpretedExpr().

◆ ExecInterpExpr()

static Datum ExecInterpExpr ( ExprState state,
ExprContext econtext,
bool isnull 
)
static

Definition at line 396 of file execExprInterp.c.

397 {
398  ExprEvalStep *op;
399  TupleTableSlot *resultslot;
400  TupleTableSlot *innerslot;
401  TupleTableSlot *outerslot;
402  TupleTableSlot *scanslot;
403 
404  /*
405  * This array has to be in the same order as enum ExprEvalOp.
406  */
407 #if defined(EEO_USE_COMPUTED_GOTO)
408  static const void *const dispatch_table[] = {
409  &&CASE_EEOP_DONE,
410  &&CASE_EEOP_INNER_FETCHSOME,
411  &&CASE_EEOP_OUTER_FETCHSOME,
412  &&CASE_EEOP_SCAN_FETCHSOME,
413  &&CASE_EEOP_INNER_VAR,
414  &&CASE_EEOP_OUTER_VAR,
415  &&CASE_EEOP_SCAN_VAR,
416  &&CASE_EEOP_INNER_SYSVAR,
417  &&CASE_EEOP_OUTER_SYSVAR,
418  &&CASE_EEOP_SCAN_SYSVAR,
419  &&CASE_EEOP_WHOLEROW,
420  &&CASE_EEOP_ASSIGN_INNER_VAR,
421  &&CASE_EEOP_ASSIGN_OUTER_VAR,
422  &&CASE_EEOP_ASSIGN_SCAN_VAR,
423  &&CASE_EEOP_ASSIGN_TMP,
424  &&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
425  &&CASE_EEOP_CONST,
426  &&CASE_EEOP_FUNCEXPR,
427  &&CASE_EEOP_FUNCEXPR_STRICT,
428  &&CASE_EEOP_FUNCEXPR_FUSAGE,
429  &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
430  &&CASE_EEOP_BOOL_AND_STEP_FIRST,
431  &&CASE_EEOP_BOOL_AND_STEP,
432  &&CASE_EEOP_BOOL_AND_STEP_LAST,
433  &&CASE_EEOP_BOOL_OR_STEP_FIRST,
434  &&CASE_EEOP_BOOL_OR_STEP,
435  &&CASE_EEOP_BOOL_OR_STEP_LAST,
436  &&CASE_EEOP_BOOL_NOT_STEP,
437  &&CASE_EEOP_QUAL,
438  &&CASE_EEOP_JUMP,
439  &&CASE_EEOP_JUMP_IF_NULL,
440  &&CASE_EEOP_JUMP_IF_NOT_NULL,
441  &&CASE_EEOP_JUMP_IF_NOT_TRUE,
442  &&CASE_EEOP_NULLTEST_ISNULL,
443  &&CASE_EEOP_NULLTEST_ISNOTNULL,
444  &&CASE_EEOP_NULLTEST_ROWISNULL,
445  &&CASE_EEOP_NULLTEST_ROWISNOTNULL,
446  &&CASE_EEOP_BOOLTEST_IS_TRUE,
447  &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
448  &&CASE_EEOP_BOOLTEST_IS_FALSE,
449  &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
450  &&CASE_EEOP_PARAM_EXEC,
451  &&CASE_EEOP_PARAM_EXTERN,
452  &&CASE_EEOP_PARAM_CALLBACK,
453  &&CASE_EEOP_PARAM_SET,
454  &&CASE_EEOP_CASE_TESTVAL,
455  &&CASE_EEOP_MAKE_READONLY,
456  &&CASE_EEOP_IOCOERCE,
457  &&CASE_EEOP_IOCOERCE_SAFE,
458  &&CASE_EEOP_DISTINCT,
459  &&CASE_EEOP_NOT_DISTINCT,
460  &&CASE_EEOP_NULLIF,
461  &&CASE_EEOP_SQLVALUEFUNCTION,
462  &&CASE_EEOP_CURRENTOFEXPR,
463  &&CASE_EEOP_NEXTVALUEEXPR,
464  &&CASE_EEOP_ARRAYEXPR,
465  &&CASE_EEOP_ARRAYCOERCE,
466  &&CASE_EEOP_ROW,
467  &&CASE_EEOP_ROWCOMPARE_STEP,
468  &&CASE_EEOP_ROWCOMPARE_FINAL,
469  &&CASE_EEOP_MINMAX,
470  &&CASE_EEOP_FIELDSELECT,
471  &&CASE_EEOP_FIELDSTORE_DEFORM,
472  &&CASE_EEOP_FIELDSTORE_FORM,
473  &&CASE_EEOP_SBSREF_SUBSCRIPTS,
474  &&CASE_EEOP_SBSREF_OLD,
475  &&CASE_EEOP_SBSREF_ASSIGN,
476  &&CASE_EEOP_SBSREF_FETCH,
477  &&CASE_EEOP_DOMAIN_TESTVAL,
478  &&CASE_EEOP_DOMAIN_NOTNULL,
479  &&CASE_EEOP_DOMAIN_CHECK,
480  &&CASE_EEOP_HASHDATUM_SET_INITVAL,
481  &&CASE_EEOP_HASHDATUM_FIRST,
482  &&CASE_EEOP_HASHDATUM_FIRST_STRICT,
483  &&CASE_EEOP_HASHDATUM_NEXT32,
484  &&CASE_EEOP_HASHDATUM_NEXT32_STRICT,
485  &&CASE_EEOP_CONVERT_ROWTYPE,
486  &&CASE_EEOP_SCALARARRAYOP,
487  &&CASE_EEOP_HASHED_SCALARARRAYOP,
488  &&CASE_EEOP_XMLEXPR,
489  &&CASE_EEOP_JSON_CONSTRUCTOR,
490  &&CASE_EEOP_IS_JSON,
491  &&CASE_EEOP_JSONEXPR_PATH,
492  &&CASE_EEOP_JSONEXPR_COERCION,
493  &&CASE_EEOP_JSONEXPR_COERCION_FINISH,
494  &&CASE_EEOP_AGGREF,
495  &&CASE_EEOP_GROUPING_FUNC,
496  &&CASE_EEOP_WINDOW_FUNC,
497  &&CASE_EEOP_MERGE_SUPPORT_FUNC,
498  &&CASE_EEOP_SUBPLAN,
499  &&CASE_EEOP_AGG_STRICT_DESERIALIZE,
500  &&CASE_EEOP_AGG_DESERIALIZE,
501  &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
502  &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
503  &&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
504  &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
505  &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL,
506  &&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
507  &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
508  &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
509  &&CASE_EEOP_AGG_PLAIN_TRANS_BYREF,
510  &&CASE_EEOP_AGG_PRESORTED_DISTINCT_SINGLE,
511  &&CASE_EEOP_AGG_PRESORTED_DISTINCT_MULTI,
512  &&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,
513  &&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,
514  &&CASE_EEOP_LAST
515  };
516 
517  StaticAssertDecl(lengthof(dispatch_table) == EEOP_LAST + 1,
518  "dispatch_table out of whack with ExprEvalOp");
519 
520  if (unlikely(state == NULL))
521  return PointerGetDatum(dispatch_table);
522 #else
523  Assert(state != NULL);
524 #endif /* EEO_USE_COMPUTED_GOTO */
525 
526  /* setup state */
527  op = state->steps;
528  resultslot = state->resultslot;
529  innerslot = econtext->ecxt_innertuple;
530  outerslot = econtext->ecxt_outertuple;
531  scanslot = econtext->ecxt_scantuple;
532 
533 #if defined(EEO_USE_COMPUTED_GOTO)
534  EEO_DISPATCH();
535 #endif
536 
537  EEO_SWITCH()
538  {
540  {
541  goto out;
542  }
543 
545  {
546  CheckOpSlotCompatibility(op, innerslot);
547 
548  slot_getsomeattrs(innerslot, op->d.fetch.last_var);
549 
550  EEO_NEXT();
551  }
552 
554  {
555  CheckOpSlotCompatibility(op, outerslot);
556 
557  slot_getsomeattrs(outerslot, op->d.fetch.last_var);
558 
559  EEO_NEXT();
560  }
561 
563  {
564  CheckOpSlotCompatibility(op, scanslot);
565 
566  slot_getsomeattrs(scanslot, op->d.fetch.last_var);
567 
568  EEO_NEXT();
569  }
570 
572  {
573  int attnum = op->d.var.attnum;
574 
575  /*
576  * Since we already extracted all referenced columns from the
577  * tuple with a FETCHSOME step, we can just grab the value
578  * directly out of the slot's decomposed-data arrays. But let's
579  * have an Assert to check that that did happen.
580  */
581  Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
582  *op->resvalue = innerslot->tts_values[attnum];
583  *op->resnull = innerslot->tts_isnull[attnum];
584 
585  EEO_NEXT();
586  }
587 
589  {
590  int attnum = op->d.var.attnum;
591 
592  /* See EEOP_INNER_VAR comments */
593 
594  Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
595  *op->resvalue = outerslot->tts_values[attnum];
596  *op->resnull = outerslot->tts_isnull[attnum];
597 
598  EEO_NEXT();
599  }
600 
602  {
603  int attnum = op->d.var.attnum;
604 
605  /* See EEOP_INNER_VAR comments */
606 
607  Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
608  *op->resvalue = scanslot->tts_values[attnum];
609  *op->resnull = scanslot->tts_isnull[attnum];
610 
611  EEO_NEXT();
612  }
613 
615  {
616  ExecEvalSysVar(state, op, econtext, innerslot);
617  EEO_NEXT();
618  }
619 
621  {
622  ExecEvalSysVar(state, op, econtext, outerslot);
623  EEO_NEXT();
624  }
625 
627  {
628  ExecEvalSysVar(state, op, econtext, scanslot);
629  EEO_NEXT();
630  }
631 
633  {
634  /* too complex for an inline implementation */
635  ExecEvalWholeRowVar(state, op, econtext);
636 
637  EEO_NEXT();
638  }
639 
641  {
642  int resultnum = op->d.assign_var.resultnum;
643  int attnum = op->d.assign_var.attnum;
644 
645  /*
646  * We do not need CheckVarSlotCompatibility here; that was taken
647  * care of at compilation time. But see EEOP_INNER_VAR comments.
648  */
649  Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
650  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
651  resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
652  resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
653 
654  EEO_NEXT();
655  }
656 
658  {
659  int resultnum = op->d.assign_var.resultnum;
660  int attnum = op->d.assign_var.attnum;
661 
662  /*
663  * We do not need CheckVarSlotCompatibility here; that was taken
664  * care of at compilation time. But see EEOP_INNER_VAR comments.
665  */
666  Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
667  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
668  resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
669  resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
670 
671  EEO_NEXT();
672  }
673 
675  {
676  int resultnum = op->d.assign_var.resultnum;
677  int attnum = op->d.assign_var.attnum;
678 
679  /*
680  * We do not need CheckVarSlotCompatibility here; that was taken
681  * care of at compilation time. But see EEOP_INNER_VAR comments.
682  */
683  Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
684  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
685  resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
686  resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
687 
688  EEO_NEXT();
689  }
690 
692  {
693  int resultnum = op->d.assign_tmp.resultnum;
694 
695  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
696  resultslot->tts_values[resultnum] = state->resvalue;
697  resultslot->tts_isnull[resultnum] = state->resnull;
698 
699  EEO_NEXT();
700  }
701 
703  {
704  int resultnum = op->d.assign_tmp.resultnum;
705 
706  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
707  resultslot->tts_isnull[resultnum] = state->resnull;
708  if (!resultslot->tts_isnull[resultnum])
709  resultslot->tts_values[resultnum] =
711  else
712  resultslot->tts_values[resultnum] = state->resvalue;
713 
714  EEO_NEXT();
715  }
716 
718  {
719  *op->resnull = op->d.constval.isnull;
720  *op->resvalue = op->d.constval.value;
721 
722  EEO_NEXT();
723  }
724 
725  /*
726  * Function-call implementations. Arguments have previously been
727  * evaluated directly into fcinfo->args.
728  *
729  * As both STRICT checks and function-usage are noticeable performance
730  * wise, and function calls are a very hot-path (they also back
731  * operators!), it's worth having so many separate opcodes.
732  *
733  * Note: the reason for using a temporary variable "d", here and in
734  * other places, is that some compilers think "*op->resvalue = f();"
735  * requires them to evaluate op->resvalue into a register before
736  * calling f(), just in case f() is able to modify op->resvalue
737  * somehow. The extra line of code can save a useless register spill
738  * and reload across the function call.
739  */
741  {
742  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
743  Datum d;
744 
745  fcinfo->isnull = false;
746  d = op->d.func.fn_addr(fcinfo);
747  *op->resvalue = d;
748  *op->resnull = fcinfo->isnull;
749 
750  EEO_NEXT();
751  }
752 
754  {
755  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
756  NullableDatum *args = fcinfo->args;
757  int nargs = op->d.func.nargs;
758  Datum d;
759 
760  /* strict function, so check for NULL args */
761  for (int argno = 0; argno < nargs; argno++)
762  {
763  if (args[argno].isnull)
764  {
765  *op->resnull = true;
766  goto strictfail;
767  }
768  }
769  fcinfo->isnull = false;
770  d = op->d.func.fn_addr(fcinfo);
771  *op->resvalue = d;
772  *op->resnull = fcinfo->isnull;
773 
774  strictfail:
775  EEO_NEXT();
776  }
777 
779  {
780  /* not common enough to inline */
781  ExecEvalFuncExprFusage(state, op, econtext);
782 
783  EEO_NEXT();
784  }
785 
787  {
788  /* not common enough to inline */
789  ExecEvalFuncExprStrictFusage(state, op, econtext);
790 
791  EEO_NEXT();
792  }
793 
794  /*
795  * If any of its clauses is FALSE, an AND's result is FALSE regardless
796  * of the states of the rest of the clauses, so we can stop evaluating
797  * and return FALSE immediately. If none are FALSE and one or more is
798  * NULL, we return NULL; otherwise we return TRUE. This makes sense
799  * when you interpret NULL as "don't know": perhaps one of the "don't
800  * knows" would have been FALSE if we'd known its value. Only when
801  * all the inputs are known to be TRUE can we state confidently that
802  * the AND's result is TRUE.
803  */
805  {
806  *op->d.boolexpr.anynull = false;
807 
808  /*
809  * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
810  * same as EEOP_BOOL_AND_STEP - so fall through to that.
811  */
812 
813  /* FALL THROUGH */
814  }
815 
817  {
818  if (*op->resnull)
819  {
820  *op->d.boolexpr.anynull = true;
821  }
822  else if (!DatumGetBool(*op->resvalue))
823  {
824  /* result is already set to FALSE, need not change it */
825  /* bail out early */
826  EEO_JUMP(op->d.boolexpr.jumpdone);
827  }
828 
829  EEO_NEXT();
830  }
831 
833  {
834  if (*op->resnull)
835  {
836  /* result is already set to NULL, need not change it */
837  }
838  else if (!DatumGetBool(*op->resvalue))
839  {
840  /* result is already set to FALSE, need not change it */
841 
842  /*
843  * No point jumping early to jumpdone - would be same target
844  * (as this is the last argument to the AND expression),
845  * except more expensive.
846  */
847  }
848  else if (*op->d.boolexpr.anynull)
849  {
850  *op->resvalue = (Datum) 0;
851  *op->resnull = true;
852  }
853  else
854  {
855  /* result is already set to TRUE, need not change it */
856  }
857 
858  EEO_NEXT();
859  }
860 
861  /*
862  * If any of its clauses is TRUE, an OR's result is TRUE regardless of
863  * the states of the rest of the clauses, so we can stop evaluating
864  * and return TRUE immediately. If none are TRUE and one or more is
865  * NULL, we return NULL; otherwise we return FALSE. This makes sense
866  * when you interpret NULL as "don't know": perhaps one of the "don't
867  * knows" would have been TRUE if we'd known its value. Only when all
868  * the inputs are known to be FALSE can we state confidently that the
869  * OR's result is FALSE.
870  */
872  {
873  *op->d.boolexpr.anynull = false;
874 
875  /*
876  * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
877  * as EEOP_BOOL_OR_STEP - so fall through to that.
878  */
879 
880  /* FALL THROUGH */
881  }
882 
884  {
885  if (*op->resnull)
886  {
887  *op->d.boolexpr.anynull = true;
888  }
889  else if (DatumGetBool(*op->resvalue))
890  {
891  /* result is already set to TRUE, need not change it */
892  /* bail out early */
893  EEO_JUMP(op->d.boolexpr.jumpdone);
894  }
895 
896  EEO_NEXT();
897  }
898 
900  {
901  if (*op->resnull)
902  {
903  /* result is already set to NULL, need not change it */
904  }
905  else if (DatumGetBool(*op->resvalue))
906  {
907  /* result is already set to TRUE, need not change it */
908 
909  /*
910  * No point jumping to jumpdone - would be same target (as
911  * this is the last argument to the AND expression), except
912  * more expensive.
913  */
914  }
915  else if (*op->d.boolexpr.anynull)
916  {
917  *op->resvalue = (Datum) 0;
918  *op->resnull = true;
919  }
920  else
921  {
922  /* result is already set to FALSE, need not change it */
923  }
924 
925  EEO_NEXT();
926  }
927 
929  {
930  /*
931  * Evaluation of 'not' is simple... if expr is false, then return
932  * 'true' and vice versa. It's safe to do this even on a
933  * nominally null value, so we ignore resnull; that means that
934  * NULL in produces NULL out, which is what we want.
935  */
937 
938  EEO_NEXT();
939  }
940 
942  {
943  /* simplified version of BOOL_AND_STEP for use by ExecQual() */
944 
945  /* If argument (also result) is false or null ... */
946  if (*op->resnull ||
947  !DatumGetBool(*op->resvalue))
948  {
949  /* ... bail out early, returning FALSE */
950  *op->resnull = false;
951  *op->resvalue = BoolGetDatum(false);
952  EEO_JUMP(op->d.qualexpr.jumpdone);
953  }
954 
955  /*
956  * Otherwise, leave the TRUE value in place, in case this is the
957  * last qual. Then, TRUE is the correct answer.
958  */
959 
960  EEO_NEXT();
961  }
962 
964  {
965  /* Unconditionally jump to target step */
966  EEO_JUMP(op->d.jump.jumpdone);
967  }
968 
970  {
971  /* Transfer control if current result is null */
972  if (*op->resnull)
973  EEO_JUMP(op->d.jump.jumpdone);
974 
975  EEO_NEXT();
976  }
977 
979  {
980  /* Transfer control if current result is non-null */
981  if (!*op->resnull)
982  EEO_JUMP(op->d.jump.jumpdone);
983 
984  EEO_NEXT();
985  }
986 
988  {
989  /* Transfer control if current result is null or false */
990  if (*op->resnull || !DatumGetBool(*op->resvalue))
991  EEO_JUMP(op->d.jump.jumpdone);
992 
993  EEO_NEXT();
994  }
995 
997  {
998  *op->resvalue = BoolGetDatum(*op->resnull);
999  *op->resnull = false;
1000 
1001  EEO_NEXT();
1002  }
1003 
1005  {
1006  *op->resvalue = BoolGetDatum(!*op->resnull);
1007  *op->resnull = false;
1008 
1009  EEO_NEXT();
1010  }
1011 
1013  {
1014  /* out of line implementation: too large */
1015  ExecEvalRowNull(state, op, econtext);
1016 
1017  EEO_NEXT();
1018  }
1019 
1021  {
1022  /* out of line implementation: too large */
1023  ExecEvalRowNotNull(state, op, econtext);
1024 
1025  EEO_NEXT();
1026  }
1027 
1028  /* BooleanTest implementations for all booltesttypes */
1029 
1031  {
1032  if (*op->resnull)
1033  {
1034  *op->resvalue = BoolGetDatum(false);
1035  *op->resnull = false;
1036  }
1037  /* else, input value is the correct output as well */
1038 
1039  EEO_NEXT();
1040  }
1041 
1043  {
1044  if (*op->resnull)
1045  {
1046  *op->resvalue = BoolGetDatum(true);
1047  *op->resnull = false;
1048  }
1049  else
1050  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
1051 
1052  EEO_NEXT();
1053  }
1054 
1056  {
1057  if (*op->resnull)
1058  {
1059  *op->resvalue = BoolGetDatum(false);
1060  *op->resnull = false;
1061  }
1062  else
1063  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
1064 
1065  EEO_NEXT();
1066  }
1067 
1069  {
1070  if (*op->resnull)
1071  {
1072  *op->resvalue = BoolGetDatum(true);
1073  *op->resnull = false;
1074  }
1075  /* else, input value is the correct output as well */
1076 
1077  EEO_NEXT();
1078  }
1079 
1081  {
1082  /* out of line implementation: too large */
1083  ExecEvalParamExec(state, op, econtext);
1084 
1085  EEO_NEXT();
1086  }
1087 
1089  {
1090  /* out of line implementation: too large */
1091  ExecEvalParamExtern(state, op, econtext);
1092  EEO_NEXT();
1093  }
1094 
1096  {
1097  /* allow an extension module to supply a PARAM_EXTERN value */
1098  op->d.cparam.paramfunc(state, op, econtext);
1099  EEO_NEXT();
1100  }
1101 
1103  {
1104  /* out of line, unlikely to matter performance-wise */
1105  ExecEvalParamSet(state, op, econtext);
1106  EEO_NEXT();
1107  }
1108 
1110  {
1111  /*
1112  * Normally upper parts of the expression tree have setup the
1113  * values to be returned here, but some parts of the system
1114  * currently misuse {caseValue,domainValue}_{datum,isNull} to set
1115  * run-time data. So if no values have been set-up, use
1116  * ExprContext's. This isn't pretty, but also not *that* ugly,
1117  * and this is unlikely to be performance sensitive enough to
1118  * worry about an extra branch.
1119  */
1120  if (op->d.casetest.value)
1121  {
1122  *op->resvalue = *op->d.casetest.value;
1123  *op->resnull = *op->d.casetest.isnull;
1124  }
1125  else
1126  {
1127  *op->resvalue = econtext->caseValue_datum;
1128  *op->resnull = econtext->caseValue_isNull;
1129  }
1130 
1131  EEO_NEXT();
1132  }
1133 
1135  {
1136  /*
1137  * See EEOP_CASE_TESTVAL comment.
1138  */
1139  if (op->d.casetest.value)
1140  {
1141  *op->resvalue = *op->d.casetest.value;
1142  *op->resnull = *op->d.casetest.isnull;
1143  }
1144  else
1145  {
1146  *op->resvalue = econtext->domainValue_datum;
1147  *op->resnull = econtext->domainValue_isNull;
1148  }
1149 
1150  EEO_NEXT();
1151  }
1152 
1154  {
1155  /*
1156  * Force a varlena value that might be read multiple times to R/O
1157  */
1158  if (!*op->d.make_readonly.isnull)
1159  *op->resvalue =
1161  *op->resnull = *op->d.make_readonly.isnull;
1162 
1163  EEO_NEXT();
1164  }
1165<