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/nodeFuncs.h"
#include "parser/parsetree.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/jsonb.h"
#include "utils/jsonfuncs.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 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 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)
 
void ExecEvalGroupingFunc (ExprState *state, ExprEvalStep *op)
 
void ExecEvalSubPlan (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalWholeRowVar (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
void ExecEvalSysVar (ExprState *state, ExprEvalStep *op, ExprContext *econtext, TupleTableSlot *slot)
 
void ExecAggInitGroup (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext)
 
Datum 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 199 of file execExprInterp.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 228 of file execExprInterp.c.

◆ SH_ELEMENT_TYPE [1/2]

#define SH_ELEMENT_TYPE   ScalarArrayOpExprHashEntry

Definition at line 220 of file execExprInterp.c.

◆ SH_ELEMENT_TYPE [2/2]

#define SH_ELEMENT_TYPE   ScalarArrayOpExprHashEntry

Definition at line 220 of file execExprInterp.c.

◆ SH_EQUAL

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

Definition at line 224 of file execExprInterp.c.

◆ SH_GET_HASH

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

Definition at line 227 of file execExprInterp.c.

◆ SH_HASH_KEY

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

Definition at line 223 of file execExprInterp.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 222 of file execExprInterp.c.

◆ SH_KEY_TYPE [1/2]

#define SH_KEY_TYPE   Datum

Definition at line 221 of file execExprInterp.c.

◆ SH_KEY_TYPE [2/2]

#define SH_KEY_TYPE   Datum

Definition at line 221 of file execExprInterp.c.

◆ SH_PREFIX [1/2]

#define SH_PREFIX   saophash

Definition at line 219 of file execExprInterp.c.

◆ SH_PREFIX [2/2]

#define SH_PREFIX   saophash

Definition at line 219 of file execExprInterp.c.

◆ SH_SCOPE [1/2]

#define SH_SCOPE   static inline

Definition at line 225 of file execExprInterp.c.

◆ SH_SCOPE [2/2]

#define SH_SCOPE   static inline

Definition at line 225 of file execExprInterp.c.

◆ SH_STORE_HASH

#define SH_STORE_HASH

Definition at line 226 of file execExprInterp.c.

Typedef Documentation

◆ ScalarArrayOpExprHashEntry

◆ ScalarArrayOpExprHashTable

Function Documentation

◆ CheckExprStillValid()

void CheckExprStillValid ( ExprState state,
ExprContext econtext 
)

Definition at line 1878 of file execExprInterp.c.

1879 {
1880  TupleTableSlot *innerslot;
1881  TupleTableSlot *outerslot;
1882  TupleTableSlot *scanslot;
1883 
1884  innerslot = econtext->ecxt_innertuple;
1885  outerslot = econtext->ecxt_outertuple;
1886  scanslot = econtext->ecxt_scantuple;
1887 
1888  for (int i = 0; i < state->steps_len; i++)
1889  {
1890  ExprEvalStep *op = &state->steps[i];
1891 
1892  switch (ExecEvalStepOp(state, op))
1893  {
1894  case EEOP_INNER_VAR:
1895  {
1896  int attnum = op->d.var.attnum;
1897 
1898  CheckVarSlotCompatibility(innerslot, attnum + 1, op->d.var.vartype);
1899  break;
1900  }
1901 
1902  case EEOP_OUTER_VAR:
1903  {
1904  int attnum = op->d.var.attnum;
1905 
1906  CheckVarSlotCompatibility(outerslot, attnum + 1, op->d.var.vartype);
1907  break;
1908  }
1909 
1910  case EEOP_SCAN_VAR:
1911  {
1912  int attnum = op->d.var.attnum;
1913 
1914  CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype);
1915  break;
1916  }
1917  default:
1918  break;
1919  }
1920  }
1921 }
static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
@ EEOP_INNER_VAR
Definition: execExpr.h:76
@ EEOP_SCAN_VAR
Definition: execExpr.h:78
@ EEOP_OUTER_VAR
Definition: execExpr.h:77
int i
Definition: isn.c:73
int16 attnum
Definition: pg_attribute.h:74
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:251
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:249
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:253
union ExprEvalStep::@51 d
struct ExprEvalStep::@51::@53 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 1980 of file execExprInterp.c.

1981 {
1982 #ifdef USE_ASSERT_CHECKING
1983  /* there's nothing to check */
1984  if (!op->d.fetch.fixed)
1985  return;
1986 
1987  /*
1988  * Should probably fixed at some point, but for now it's easier to allow
1989  * buffer and heap tuples to be used interchangeably.
1990  */
1991  if (slot->tts_ops == &TTSOpsBufferHeapTuple &&
1992  op->d.fetch.kind == &TTSOpsHeapTuple)
1993  return;
1994  if (slot->tts_ops == &TTSOpsHeapTuple &&
1995  op->d.fetch.kind == &TTSOpsBufferHeapTuple)
1996  return;
1997 
1998  /*
1999  * At the moment we consider it OK if a virtual slot is used instead of a
2000  * specific type of slot, as a virtual slot never needs to be deformed.
2001  */
2002  if (slot->tts_ops == &TTSOpsVirtual)
2003  return;
2004 
2005  Assert(op->d.fetch.kind == slot->tts_ops);
2006 #endif
2007 }
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
const TupleTableSlotOps TTSOpsBufferHeapTuple
Definition: execTuples.c:86
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
Assert(fmt[strlen(fmt) - 1] !='\n')
struct ExprEvalStep::@51::@52 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 1929 of file execExprInterp.c.

1930 {
1931  /*
1932  * What we have to check for here is the possibility of an attribute
1933  * having been dropped or changed in type since the plan tree was created.
1934  * Ideally the plan will get invalidated and not re-used, but just in
1935  * case, we keep these defenses. Fortunately it's sufficient to check
1936  * once on the first time through.
1937  *
1938  * Note: ideally we'd check typmod as well as typid, but that seems
1939  * impractical at the moment: in many cases the tupdesc will have been
1940  * generated by ExecTypeFromTL(), and that can't guarantee to generate an
1941  * accurate typmod in all cases, because some expression node types don't
1942  * carry typmod. Fortunately, for precisely that reason, there should be
1943  * no places with a critical dependency on the typmod of a value.
1944  *
1945  * System attributes don't require checking since their types never
1946  * change.
1947  */
1948  if (attnum > 0)
1949  {
1950  TupleDesc slot_tupdesc = slot->tts_tupleDescriptor;
1951  Form_pg_attribute attr;
1952 
1953  if (attnum > slot_tupdesc->natts) /* should never happen */
1954  elog(ERROR, "attribute number %d exceeds number of columns %d",
1955  attnum, slot_tupdesc->natts);
1956 
1957  attr = TupleDescAttr(slot_tupdesc, attnum - 1);
1958 
1959  if (attr->attisdropped)
1960  ereport(ERROR,
1961  (errcode(ERRCODE_UNDEFINED_COLUMN),
1962  errmsg("attribute %d of type %s has been dropped",
1963  attnum, format_type_be(slot_tupdesc->tdtypeid))));
1964 
1965  if (vartype != attr->atttypid)
1966  ereport(ERROR,
1967  (errcode(ERRCODE_DATATYPE_MISMATCH),
1968  errmsg("attribute %d of type %s has wrong type",
1969  attnum, format_type_be(slot_tupdesc->tdtypeid)),
1970  errdetail("Table has type %s, but query expects %s.",
1971  format_type_be(attr->atttypid),
1972  format_type_be(vartype))));
1973  }
1974 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
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 4494 of file execExprInterp.c.

4497 {
4498  Assert(newValue != oldValue);
4499 
4500  if (!newValueIsNull)
4501  {
4503  if (DatumIsReadWriteExpandedObject(newValue,
4504  false,
4505  pertrans->transtypeLen) &&
4506  MemoryContextGetParent(DatumGetEOHP(newValue)->eoh_context) == CurrentMemoryContext)
4507  /* do nothing */ ;
4508  else
4509  newValue = datumCopy(newValue,
4510  pertrans->transtypeByVal,
4511  pertrans->transtypeLen);
4512  }
4513  else
4514  {
4515  /*
4516  * Ensure that AggStatePerGroup->transValue ends up being 0, so
4517  * callers can safely compare newValue/oldValue without having to
4518  * check their respective nullness.
4519  */
4520  newValue = (Datum) 0;
4521  }
4522 
4523  if (!oldValueIsNull)
4524  {
4525  if (DatumIsReadWriteExpandedObject(oldValue,
4526  false,
4527  pertrans->transtypeLen))
4528  DeleteExpandedObject(oldValue);
4529  else
4530  pfree(DatumGetPointer(oldValue));
4531  }
4532 
4533  return newValue;
4534 }
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:1456
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:640
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
ExprContext * curaggcontext
Definition: execnodes.h:2394
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:257

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 4441 of file execExprInterp.c.

4443 {
4444  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4445  MemoryContext oldContext;
4446 
4447  /*
4448  * We must copy the datum into aggcontext if it is pass-by-ref. We do not
4449  * need to pfree the old transValue, since it's NULL. (We already checked
4450  * that the agg's input type is binary-compatible with its transtype, so
4451  * straight copy here is OK.)
4452  */
4453  oldContext = MemoryContextSwitchTo(aggcontext->ecxt_per_tuple_memory);
4454  pergroup->transValue = datumCopy(fcinfo->args[1].value,
4455  pertrans->transtypeByVal,
4456  pertrans->transtypeLen);
4457  pergroup->transValueIsNull = false;
4458  pergroup->noTransValue = false;
4459  MemoryContextSwitchTo(oldContext);
4460 }
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 4679 of file execExprInterp.c.

4682 {
4683  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4684  MemoryContext oldContext;
4685  Datum newVal;
4686 
4687  /* cf. select_current_set() */
4688  aggstate->curaggcontext = aggcontext;
4689  aggstate->current_set = setno;
4690 
4691  /* set up aggstate->curpertrans for AggGetAggref() */
4692  aggstate->curpertrans = pertrans;
4693 
4694  /* invoke transition function in per-tuple context */
4695  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
4696 
4697  fcinfo->args[0].value = pergroup->transValue;
4698  fcinfo->args[0].isnull = pergroup->transValueIsNull;
4699  fcinfo->isnull = false; /* just in case transfn doesn't set it */
4700 
4701  newVal = FunctionCallInvoke(fcinfo);
4702 
4703  /*
4704  * For pass-by-ref datatype, must copy the new value into aggcontext and
4705  * free the prior transValue. But if transfn returned a pointer to its
4706  * first input, we don't need to do anything.
4707  *
4708  * It's safe to compare newVal with pergroup->transValue without regard
4709  * for either being NULL, because ExecAggCopyTransValue takes care to set
4710  * transValue to 0 when NULL. Otherwise we could end up accidentally not
4711  * reparenting, when the transValue has the same numerical value as
4712  * newValue, despite being NULL. This is a somewhat hot path, making it
4713  * undesirable to instead solve this with another branch for the common
4714  * case of the transition function returning its (modified) input
4715  * argument.
4716  */
4717  if (DatumGetPointer(newVal) != DatumGetPointer(pergroup->transValue))
4718  newVal = ExecAggCopyTransValue(aggstate, pertrans,
4719  newVal, fcinfo->isnull,
4720  pergroup->transValue,
4721  pergroup->transValueIsNull);
4722 
4723  pergroup->transValue = newVal;
4724  pergroup->transValueIsNull = fcinfo->isnull;
4725 
4726  MemoryContextSwitchTo(oldContext);
4727 }
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:2392
AggStatePerTrans curpertrans
Definition: execnodes.h:2397
int current_set
Definition: execnodes.h:2402
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 4647 of file execExprInterp.c.

4650 {
4651  FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
4652  MemoryContext oldContext;
4653  Datum newVal;
4654 
4655  /* cf. select_current_set() */
4656  aggstate->curaggcontext = aggcontext;
4657  aggstate->current_set = setno;
4658 
4659  /* set up aggstate->curpertrans for AggGetAggref() */
4660  aggstate->curpertrans = pertrans;
4661 
4662  /* invoke transition function in per-tuple context */
4663  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
4664 
4665  fcinfo->args[0].value = pergroup->transValue;
4666  fcinfo->args[0].isnull = pergroup->transValueIsNull;
4667  fcinfo->isnull = false; /* just in case transfn doesn't set it */
4668 
4669  newVal = FunctionCallInvoke(fcinfo);
4670 
4671  pergroup->transValue = newVal;
4672  pergroup->transValueIsNull = fcinfo->isnull;
4673 
4674  MemoryContextSwitchTo(oldContext);
4675 }

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 4619 of file execExprInterp.c.

4621 {
4622  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
4623  int setno = op->d.agg_trans.setno;
4624 
4625  tuplesort_putdatum(pertrans->sortstates[setno],
4626  *op->resvalue, *op->resnull);
4627 }
Tuplesortstate ** sortstates
Definition: nodeAgg.h:162
Datum * resvalue
Definition: execExpr.h:278
struct ExprEvalStep::@51::@94 agg_trans
bool * resnull
Definition: execExpr.h:279
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 4633 of file execExprInterp.c.

4635 {
4636  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
4637  int setno = op->d.agg_trans.setno;
4638 
4639  ExecClearTuple(pertrans->sortslot);
4640  pertrans->sortslot->tts_nvalid = pertrans->numInputs;
4641  ExecStoreVirtualTuple(pertrans->sortslot);
4642  tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
4643 }
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1553
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:432

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 2937 of file execExprInterp.c.

2938 {
2939  Datum arraydatum;
2940 
2941  /* NULL array -> NULL result */
2942  if (*op->resnull)
2943  return;
2944 
2945  arraydatum = *op->resvalue;
2946 
2947  /*
2948  * If it's binary-compatible, modify the element type in the array header,
2949  * but otherwise leave the array as we received it.
2950  */
2951  if (op->d.arraycoerce.elemexprstate == NULL)
2952  {
2953  /* Detoast input array if necessary, and copy in any case */
2954  ArrayType *array = DatumGetArrayTypePCopy(arraydatum);
2955 
2956  ARR_ELEMTYPE(array) = op->d.arraycoerce.resultelemtype;
2957  *op->resvalue = PointerGetDatum(array);
2958  return;
2959  }
2960 
2961  /*
2962  * Use array_map to apply the sub-expression to each array element.
2963  */
2964  *op->resvalue = array_map(arraydatum,
2965  op->d.arraycoerce.elemexprstate,
2966  econtext,
2967  op->d.arraycoerce.resultelemtype,
2968  op->d.arraycoerce.amstate);
2969 }
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
#define ARR_ELEMTYPE(a)
Definition: array.h:285
Datum array_map(Datum arrayd, ExprState *exprstate, ExprContext *econtext, Oid retType, ArrayMapState *amstate)
Definition: arrayfuncs.c:3160
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
struct ExprEvalStep::@51::@71 arraycoerce

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

Referenced by ExecInterpExpr().

◆ ExecEvalArrayExpr()

void ExecEvalArrayExpr ( ExprState state,
ExprEvalStep op 
)

Definition at line 2723 of file execExprInterp.c.

2724 {
2725  ArrayType *result;
2726  Oid element_type = op->d.arrayexpr.elemtype;
2727  int nelems = op->d.arrayexpr.nelems;
2728  int ndims = 0;
2729  int dims[MAXDIM];
2730  int lbs[MAXDIM];
2731 
2732  /* Set non-null as default */
2733  *op->resnull = false;
2734 
2735  if (!op->d.arrayexpr.multidims)
2736  {
2737  /* Elements are presumably of scalar type */
2738  Datum *dvalues = op->d.arrayexpr.elemvalues;
2739  bool *dnulls = op->d.arrayexpr.elemnulls;
2740 
2741  /* setup for 1-D array of the given length */
2742  ndims = 1;
2743  dims[0] = nelems;
2744  lbs[0] = 1;
2745 
2746  result = construct_md_array(dvalues, dnulls, ndims, dims, lbs,
2747  element_type,
2748  op->d.arrayexpr.elemlength,
2749  op->d.arrayexpr.elembyval,
2750  op->d.arrayexpr.elemalign);
2751  }
2752  else
2753  {
2754  /* Must be nested array expressions */
2755  int nbytes = 0;
2756  int nitems;
2757  int outer_nelems = 0;
2758  int elem_ndims = 0;
2759  int *elem_dims = NULL;
2760  int *elem_lbs = NULL;
2761  bool firstone = true;
2762  bool havenulls = false;
2763  bool haveempty = false;
2764  char **subdata;
2765  bits8 **subbitmaps;
2766  int *subbytes;
2767  int *subnitems;
2768  int32 dataoffset;
2769  char *dat;
2770  int iitem;
2771 
2772  subdata = (char **) palloc(nelems * sizeof(char *));
2773  subbitmaps = (bits8 **) palloc(nelems * sizeof(bits8 *));
2774  subbytes = (int *) palloc(nelems * sizeof(int));
2775  subnitems = (int *) palloc(nelems * sizeof(int));
2776 
2777  /* loop through and get data area from each element */
2778  for (int elemoff = 0; elemoff < nelems; elemoff++)
2779  {
2780  Datum arraydatum;
2781  bool eisnull;
2782  ArrayType *array;
2783  int this_ndims;
2784 
2785  arraydatum = op->d.arrayexpr.elemvalues[elemoff];
2786  eisnull = op->d.arrayexpr.elemnulls[elemoff];
2787 
2788  /* temporarily ignore null subarrays */
2789  if (eisnull)
2790  {
2791  haveempty = true;
2792  continue;
2793  }
2794 
2795  array = DatumGetArrayTypeP(arraydatum);
2796 
2797  /* run-time double-check on element type */
2798  if (element_type != ARR_ELEMTYPE(array))
2799  ereport(ERROR,
2800  (errcode(ERRCODE_DATATYPE_MISMATCH),
2801  errmsg("cannot merge incompatible arrays"),
2802  errdetail("Array with element type %s cannot be "
2803  "included in ARRAY construct with element type %s.",
2804  format_type_be(ARR_ELEMTYPE(array)),
2805  format_type_be(element_type))));
2806 
2807  this_ndims = ARR_NDIM(array);
2808  /* temporarily ignore zero-dimensional subarrays */
2809  if (this_ndims <= 0)
2810  {
2811  haveempty = true;
2812  continue;
2813  }
2814 
2815  if (firstone)
2816  {
2817  /* Get sub-array details from first member */
2818  elem_ndims = this_ndims;
2819  ndims = elem_ndims + 1;
2820  if (ndims <= 0 || ndims > MAXDIM)
2821  ereport(ERROR,
2822  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2823  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
2824  ndims, MAXDIM)));
2825 
2826  elem_dims = (int *) palloc(elem_ndims * sizeof(int));
2827  memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
2828  elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
2829  memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
2830 
2831  firstone = false;
2832  }
2833  else
2834  {
2835  /* Check other sub-arrays are compatible */
2836  if (elem_ndims != this_ndims ||
2837  memcmp(elem_dims, ARR_DIMS(array),
2838  elem_ndims * sizeof(int)) != 0 ||
2839  memcmp(elem_lbs, ARR_LBOUND(array),
2840  elem_ndims * sizeof(int)) != 0)
2841  ereport(ERROR,
2842  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2843  errmsg("multidimensional arrays must have array "
2844  "expressions with matching dimensions")));
2845  }
2846 
2847  subdata[outer_nelems] = ARR_DATA_PTR(array);
2848  subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
2849  subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
2850  nbytes += subbytes[outer_nelems];
2851  /* check for overflow of total request */
2852  if (!AllocSizeIsValid(nbytes))
2853  ereport(ERROR,
2854  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2855  errmsg("array size exceeds the maximum allowed (%d)",
2856  (int) MaxAllocSize)));
2857  subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
2858  ARR_DIMS(array));
2859  havenulls |= ARR_HASNULL(array);
2860  outer_nelems++;
2861  }
2862 
2863  /*
2864  * If all items were null or empty arrays, return an empty array;
2865  * otherwise, if some were and some weren't, raise error. (Note: we
2866  * must special-case this somehow to avoid trying to generate a 1-D
2867  * array formed from empty arrays. It's not ideal...)
2868  */
2869  if (haveempty)
2870  {
2871  if (ndims == 0) /* didn't find any nonempty array */
2872  {
2873  *op->resvalue = PointerGetDatum(construct_empty_array(element_type));
2874  return;
2875  }
2876  ereport(ERROR,
2877  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2878  errmsg("multidimensional arrays must have array "
2879  "expressions with matching dimensions")));
2880  }
2881 
2882  /* setup for multi-D array */
2883  dims[0] = outer_nelems;
2884  lbs[0] = 1;
2885  for (int i = 1; i < ndims; i++)
2886  {
2887  dims[i] = elem_dims[i - 1];
2888  lbs[i] = elem_lbs[i - 1];
2889  }
2890 
2891  /* check for subscript overflow */
2892  nitems = ArrayGetNItems(ndims, dims);
2893  ArrayCheckBounds(ndims, dims, lbs);
2894 
2895  if (havenulls)
2896  {
2897  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
2898  nbytes += dataoffset;
2899  }
2900  else
2901  {
2902  dataoffset = 0; /* marker for no null bitmap */
2903  nbytes += ARR_OVERHEAD_NONULLS(ndims);
2904  }
2905 
2906  result = (ArrayType *) palloc0(nbytes);
2907  SET_VARSIZE(result, nbytes);
2908  result->ndim = ndims;
2909  result->dataoffset = dataoffset;
2910  result->elemtype = element_type;
2911  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
2912  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
2913 
2914  dat = ARR_DATA_PTR(result);
2915  iitem = 0;
2916  for (int i = 0; i < outer_nelems; i++)
2917  {
2918  memcpy(dat, subdata[i], subbytes[i]);
2919  dat += subbytes[i];
2920  if (havenulls)
2921  array_bitmap_copy(ARR_NULLBITMAP(result), iitem,
2922  subbitmaps[i], 0,
2923  subnitems[i]);
2924  iitem += subnitems[i];
2925  }
2926  }
2927 
2928  *op->resvalue = PointerGetDatum(result);
2929 }
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
#define ARR_NULLBITMAP(a)
Definition: array.h:293
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_SIZE(a)
Definition: array.h:282
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define ARR_DATA_OFFSET(a)
Definition: array.h:309
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
#define ARR_LBOUND(a)
Definition: array.h:289
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3527
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:3441
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4913
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:138
signed int int32
Definition: c.h:483
uint8 bits8
Definition: c.h:502
#define nitems(x)
Definition: indent.h:31
void * palloc0(Size size)
Definition: mcxt.c:1257
void * palloc(Size size)
Definition: mcxt.c:1226
#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:90
int ndim
Definition: array.h:88
int32 dataoffset
Definition: array.h:89
struct ExprEvalStep::@51::@70 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().

◆ ExecEvalConstraintCheck()

void ExecEvalConstraintCheck ( ExprState state,
ExprEvalStep op 
)

Definition at line 3744 of file execExprInterp.c.

3745 {
3746  if (!*op->d.domaincheck.checknull &&
3747  !DatumGetBool(*op->d.domaincheck.checkvalue))
3748  ereport(ERROR,
3749  (errcode(ERRCODE_CHECK_VIOLATION),
3750  errmsg("value for domain %s violates check constraint \"%s\"",
3751  format_type_be(op->d.domaincheck.resulttype),
3752  op->d.domaincheck.constraintname),
3753  errdomainconstraint(op->d.domaincheck.resulttype,
3754  op->d.domaincheck.constraintname)));
3755 }
int errdomainconstraint(Oid datatypeOid, const char *conname)
Definition: domains.c:400
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
struct ExprEvalStep::@51::@80 domaincheck

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

Referenced by ExecInterpExpr().

◆ ExecEvalConstraintNotNull()

void ExecEvalConstraintNotNull ( ExprState state,
ExprEvalStep op 
)

Definition at line 3730 of file execExprInterp.c.

3731 {
3732  if (*op->resnull)
3733  ereport(ERROR,
3734  (errcode(ERRCODE_NOT_NULL_VIOLATION),
3735  errmsg("domain %s does not allow null values",
3736  format_type_be(op->d.domaincheck.resulttype)),
3737  errdatatype(op->d.domaincheck.resulttype)));
3738 }
int errdatatype(Oid datatypeOid)
Definition: domains.c:376

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

Referenced by ExecInterpExpr().

◆ ExecEvalConvertRowtype()

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

Definition at line 3250 of file execExprInterp.c.

3251 {
3252  HeapTuple result;
3253  Datum tupDatum;
3254  HeapTupleHeader tuple;
3255  HeapTupleData tmptup;
3256  TupleDesc indesc,
3257  outdesc;
3258  bool changed = false;
3259 
3260  /* NULL in -> NULL out */
3261  if (*op->resnull)
3262  return;
3263 
3264  tupDatum = *op->resvalue;
3265  tuple = DatumGetHeapTupleHeader(tupDatum);
3266 
3267  /*
3268  * Lookup tupdescs if first time through or if type changes. We'd better
3269  * pin them since type conversion functions could do catalog lookups and
3270  * hence cause cache invalidation.
3271  */
3272  indesc = get_cached_rowtype(op->d.convert_rowtype.inputtype, -1,
3273  op->d.convert_rowtype.incache,
3274  &changed);
3275  IncrTupleDescRefCount(indesc);
3276  outdesc = get_cached_rowtype(op->d.convert_rowtype.outputtype, -1,
3277  op->d.convert_rowtype.outcache,
3278  &changed);
3279  IncrTupleDescRefCount(outdesc);
3280 
3281  /*
3282  * We used to be able to assert that incoming tuples are marked with
3283  * exactly the rowtype of indesc. However, now that ExecEvalWholeRowVar
3284  * might change the tuples' marking to plain RECORD due to inserting
3285  * aliases, we can only make this weak test:
3286  */
3287  Assert(HeapTupleHeaderGetTypeId(tuple) == indesc->tdtypeid ||
3288  HeapTupleHeaderGetTypeId(tuple) == RECORDOID);
3289 
3290  /* if first time through, or after change, initialize conversion map */
3291  if (changed)
3292  {
3293  MemoryContext old_cxt;
3294 
3295  /* allocate map in long-lived memory context */
3296  old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3297 
3298  /* prepare map from old to new attribute numbers */
3299  op->d.convert_rowtype.map = convert_tuples_by_name(indesc, outdesc);
3300 
3301  MemoryContextSwitchTo(old_cxt);
3302  }
3303 
3304  /* Following steps need a HeapTuple not a bare HeapTupleHeader */
3305  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3306  tmptup.t_data = tuple;
3307 
3308  if (op->d.convert_rowtype.map != NULL)
3309  {
3310  /* Full conversion with attribute rearrangement needed */
3311  result = execute_attr_map_tuple(&tmptup, op->d.convert_rowtype.map);
3312  /* Result already has appropriate composite-datum header fields */
3313  *op->resvalue = HeapTupleGetDatum(result);
3314  }
3315  else
3316  {
3317  /*
3318  * The tuple is physically compatible as-is, but we need to insert the
3319  * destination rowtype OID in its composite-datum header field, so we
3320  * have to copy it anyway. heap_copy_tuple_as_datum() is convenient
3321  * for this since it will both make the physical copy and insert the
3322  * correct composite header fields. Note that we aren't expecting to
3323  * have to flatten any toasted fields: the input was a composite
3324  * datum, so it shouldn't contain any. So heap_copy_tuple_as_datum()
3325  * is overkill here, but its check for external fields is cheap.
3326  */
3327  *op->resvalue = heap_copy_tuple_as_datum(&tmptup, outdesc);
3328  }
3329 
3330  DecrTupleDescRefCount(indesc);
3331  DecrTupleDescRefCount(outdesc);
3332 }
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:1072
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:256
struct ExprEvalStep::@51::@81 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:384
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:366

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 2584 of file execExprInterp.c.

2585 {
2586  ereport(ERROR,
2587  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2588  errmsg("WHERE CURRENT OF is not supported for this table type")));
2589 }

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

Referenced by ExecInterpExpr().

◆ ExecEvalFieldSelect()

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

Definition at line 3051 of file execExprInterp.c.

3052 {
3053  AttrNumber fieldnum = op->d.fieldselect.fieldnum;
3054  Datum tupDatum;
3055  HeapTupleHeader tuple;
3056  Oid tupType;
3057  int32 tupTypmod;
3058  TupleDesc tupDesc;
3059  Form_pg_attribute attr;
3060  HeapTupleData tmptup;
3061 
3062  /* NULL record -> NULL result */
3063  if (*op->resnull)
3064  return;
3065 
3066  tupDatum = *op->resvalue;
3067 
3068  /* We can special-case expanded records for speed */
3070  {
3072 
3073  Assert(erh->er_magic == ER_MAGIC);
3074 
3075  /* Extract record's TupleDesc */
3076  tupDesc = expanded_record_get_tupdesc(erh);
3077 
3078  /*
3079  * Find field's attr record. Note we don't support system columns
3080  * here: a datum tuple doesn't have valid values for most of the
3081  * interesting system columns anyway.
3082  */
3083  if (fieldnum <= 0) /* should never happen */
3084  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3085  fieldnum);
3086  if (fieldnum > tupDesc->natts) /* should never happen */
3087  elog(ERROR, "attribute number %d exceeds number of columns %d",
3088  fieldnum, tupDesc->natts);
3089  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3090 
3091  /* Check for dropped column, and force a NULL result if so */
3092  if (attr->attisdropped)
3093  {
3094  *op->resnull = true;
3095  return;
3096  }
3097 
3098  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3099  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3100  if (op->d.fieldselect.resulttype != attr->atttypid)
3101  ereport(ERROR,
3102  (errcode(ERRCODE_DATATYPE_MISMATCH),
3103  errmsg("attribute %d has wrong type", fieldnum),
3104  errdetail("Table has type %s, but query expects %s.",
3105  format_type_be(attr->atttypid),
3106  format_type_be(op->d.fieldselect.resulttype))));
3107 
3108  /* extract the field */
3109  *op->resvalue = expanded_record_get_field(erh, fieldnum,
3110  op->resnull);
3111  }
3112  else
3113  {
3114  /* Get the composite datum and extract its type fields */
3115  tuple = DatumGetHeapTupleHeader(tupDatum);
3116 
3117  tupType = HeapTupleHeaderGetTypeId(tuple);
3118  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
3119 
3120  /* Lookup tupdesc if first time through or if type changes */
3121  tupDesc = get_cached_rowtype(tupType, tupTypmod,
3122  &op->d.fieldselect.rowcache, NULL);
3123 
3124  /*
3125  * Find field's attr record. Note we don't support system columns
3126  * here: a datum tuple doesn't have valid values for most of the
3127  * interesting system columns anyway.
3128  */
3129  if (fieldnum <= 0) /* should never happen */
3130  elog(ERROR, "unsupported reference to system column %d in FieldSelect",
3131  fieldnum);
3132  if (fieldnum > tupDesc->natts) /* should never happen */
3133  elog(ERROR, "attribute number %d exceeds number of columns %d",
3134  fieldnum, tupDesc->natts);
3135  attr = TupleDescAttr(tupDesc, fieldnum - 1);
3136 
3137  /* Check for dropped column, and force a NULL result if so */
3138  if (attr->attisdropped)
3139  {
3140  *op->resnull = true;
3141  return;
3142  }
3143 
3144  /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */
3145  /* As in CheckVarSlotCompatibility, we should but can't check typmod */
3146  if (op->d.fieldselect.resulttype != attr->atttypid)
3147  ereport(ERROR,
3148  (errcode(ERRCODE_DATATYPE_MISMATCH),
3149  errmsg("attribute %d has wrong type", fieldnum),
3150  errdetail("Table has type %s, but query expects %s.",
3151  format_type_be(attr->atttypid),
3152  format_type_be(op->d.fieldselect.resulttype))));
3153 
3154  /* heap_getattr needs a HeapTuple not a bare HeapTupleHeader */
3155  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
3156  tmptup.t_data = tuple;
3157 
3158  /* extract the field */
3159  *op->resvalue = heap_getattr(&tmptup,
3160  fieldnum,
3161  tupDesc,
3162  op->resnull);
3163  }
3164 }
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::@51::@76 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 3176 of file execExprInterp.c.

3177 {
3178  if (*op->resnull)
3179  {
3180  /* Convert null input tuple into an all-nulls row */
3181  memset(op->d.fieldstore.nulls, true,
3182  op->d.fieldstore.ncolumns * sizeof(bool));
3183  }
3184  else
3185  {
3186  /*
3187  * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. We
3188  * set all the fields in the struct just in case.
3189  */
3190  Datum tupDatum = *op->resvalue;
3191  HeapTupleHeader tuphdr;
3192  HeapTupleData tmptup;
3193  TupleDesc tupDesc;
3194 
3195  tuphdr = DatumGetHeapTupleHeader(tupDatum);
3196  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
3197  ItemPointerSetInvalid(&(tmptup.t_self));
3198  tmptup.t_tableOid = InvalidOid;
3199  tmptup.t_data = tuphdr;
3200 
3201  /*
3202  * Lookup tupdesc if first time through or if type changes. Because
3203  * we don't pin the tupdesc, we must not do this lookup until after
3204  * doing DatumGetHeapTupleHeader: that could do database access while
3205  * detoasting the datum.
3206  */
3207  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3208  op->d.fieldstore.rowcache, NULL);
3209 
3210  /* Check that current tupdesc doesn't have more fields than allocated */
3211  if (unlikely(tupDesc->natts > op->d.fieldstore.ncolumns))
3212  elog(ERROR, "too many columns in composite type %u",
3213  op->d.fieldstore.fstore->resulttype);
3214 
3215  heap_deform_tuple(&tmptup, tupDesc,
3216  op->d.fieldstore.values,
3217  op->d.fieldstore.nulls);
3218  }
3219 }
#define unlikely(x)
Definition: c.h:300
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1337
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
#define InvalidOid
Definition: postgres_ext.h:36
struct ExprEvalStep::@51::@77 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 3226 of file execExprInterp.c.

3227 {
3228  TupleDesc tupDesc;
3229  HeapTuple tuple;
3230 
3231  /* Lookup tupdesc (should be valid already) */
3232  tupDesc = get_cached_rowtype(op->d.fieldstore.fstore->resulttype, -1,
3233  op->d.fieldstore.rowcache, NULL);
3234 
3235  tuple = heap_form_tuple(tupDesc,
3236  op->d.fieldstore.values,
3237  op->d.fieldstore.nulls);
3238 
3239  *op->resvalue = HeapTupleGetDatum(tuple);
3240  *op->resnull = false;
3241 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108

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 2395 of file execExprInterp.c.

2397 {
2398  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2399  PgStat_FunctionCallUsage fcusage;
2400  Datum d;
2401 
2402  pgstat_init_function_usage(fcinfo, &fcusage);
2403 
2404  fcinfo->isnull = false;
2405  d = op->d.func.fn_addr(fcinfo);
2406  *op->resvalue = d;
2407  *op->resnull = fcinfo->isnull;
2408 
2409  pgstat_end_function_usage(&fcusage, true);
2410 }
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
struct ExprEvalStep::@51::@58 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 2416 of file execExprInterp.c.

2418 {
2419 
2420  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
2421  PgStat_FunctionCallUsage fcusage;
2422  NullableDatum *args = fcinfo->args;
2423  int nargs = op->d.func.nargs;
2424  Datum d;
2425 
2426  /* strict function, so check for NULL args */
2427  for (int argno = 0; argno < nargs; argno++)
2428  {
2429  if (args[argno].isnull)
2430  {
2431  *op->resnull = true;
2432  return;
2433  }
2434  }
2435 
2436  pgstat_init_function_usage(fcinfo, &fcusage);
2437 
2438  fcinfo->isnull = false;
2439  d = op->d.func.fn_addr(fcinfo);
2440  *op->resvalue = d;
2441  *op->resnull = fcinfo->isnull;
2442 
2443  pgstat_end_function_usage(&fcusage, true);
2444 }

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 4152 of file execExprInterp.c.

4153 {
4154  AggState *aggstate = castNode(AggState, state->parent);
4155  int result = 0;
4156  Bitmapset *grouped_cols = aggstate->grouped_cols;
4157  ListCell *lc;
4158 
4159  foreach(lc, op->d.grouping_func.clauses)
4160  {
4161  int attnum = lfirst_int(lc);
4162 
4163  result <<= 1;
4164 
4165  if (!bms_is_member(attnum, grouped_cols))
4166  result |= 1;
4167  }
4168 
4169  *op->resvalue = Int32GetDatum(result);
4170  *op->resnull = false;
4171 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:460
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
#define lfirst_int(lc)
Definition: pg_list.h:173
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
Bitmapset * grouped_cols
Definition: execnodes.h:2403
struct ExprEvalStep::@51::@87 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 3548 of file execExprInterp.c.

3549 {
3550  ScalarArrayOpExprHashTable *elements_tab = op->d.hashedscalararrayop.elements_tab;
3551  FunctionCallInfo fcinfo = op->d.hashedscalararrayop.fcinfo_data;
3552  bool inclause = op->d.hashedscalararrayop.inclause;
3553  bool strictfunc = op->d.hashedscalararrayop.finfo->fn_strict;
3554  Datum scalar = fcinfo->args[0].value;
3555  bool scalar_isnull = fcinfo->args[0].isnull;
3556  Datum result;
3557  bool resultnull;
3558  bool hashfound;
3559 
3560  /* We don't setup a hashed scalar array op if the array const is null. */
3561  Assert(!*op->resnull);
3562 
3563  /*
3564  * If the scalar is NULL, and the function is strict, return NULL; no
3565  * point in executing the search.
3566  */
3567  if (fcinfo->args[0].isnull && strictfunc)
3568  {
3569  *op->resnull = true;
3570  return;
3571  }
3572 
3573  /* Build the hash table on first evaluation */
3574  if (elements_tab == NULL)
3575  {
3576  ScalarArrayOpExpr *saop;
3577  int16 typlen;
3578  bool typbyval;
3579  char typalign;
3580  int nitems;
3581  bool has_nulls = false;
3582  char *s;
3583  bits8 *bitmap;
3584  int bitmask;
3585  MemoryContext oldcontext;
3586  ArrayType *arr;
3587 
3588  saop = op->d.hashedscalararrayop.saop;
3589 
3590  arr = DatumGetArrayTypeP(*op->resvalue);
3591  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3592 
3594  &typlen,
3595  &typbyval,
3596  &typalign);
3597 
3598  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
3599 
3600  elements_tab = (ScalarArrayOpExprHashTable *)
3601  palloc0(offsetof(ScalarArrayOpExprHashTable, hash_fcinfo_data) +
3603  op->d.hashedscalararrayop.elements_tab = elements_tab;
3604  elements_tab->op = op;
3605 
3606  fmgr_info(saop->hashfuncid, &elements_tab->hash_finfo);
3607  fmgr_info_set_expr((Node *) saop, &elements_tab->hash_finfo);
3608 
3610  &elements_tab->hash_finfo,
3611  1,
3612  saop->inputcollid,
3613  NULL,
3614  NULL);
3615 
3616  /*
3617  * Create the hash table sizing it according to the number of elements
3618  * in the array. This does assume that the array has no duplicates.
3619  * If the array happens to contain many duplicate values then it'll
3620  * just mean that we sized the table a bit on the large side.
3621  */
3622  elements_tab->hashtab = saophash_create(CurrentMemoryContext, nitems,
3623  elements_tab);
3624 
3625  MemoryContextSwitchTo(oldcontext);
3626 
3627  s = (char *) ARR_DATA_PTR(arr);
3628  bitmap = ARR_NULLBITMAP(arr);
3629  bitmask = 1;
3630  for (int i = 0; i < nitems; i++)
3631  {
3632  /* Get array element, checking for NULL. */
3633  if (bitmap && (*bitmap & bitmask) == 0)
3634  {
3635  has_nulls = true;
3636  }
3637  else
3638  {
3639  Datum element;
3640 
3641  element = fetch_att(s, typbyval, typlen);
3642  s = att_addlength_pointer(s, typlen, s);
3643  s = (char *) att_align_nominal(s, typalign);
3644 
3645  saophash_insert(elements_tab->hashtab, element, &hashfound);
3646  }
3647 
3648  /* Advance bitmap pointer if any. */
3649  if (bitmap)
3650  {
3651  bitmask <<= 1;
3652  if (bitmask == 0x100)
3653  {
3654  bitmap++;
3655  bitmask = 1;
3656  }
3657  }
3658  }
3659 
3660  /*
3661  * Remember if we had any nulls so that we know if we need to execute
3662  * non-strict functions with a null lhs value if no match is found.
3663  */
3664  op->d.hashedscalararrayop.has_nulls = has_nulls;
3665  }
3666 
3667  /* Check the hash to see if we have a match. */
3668  hashfound = NULL != saophash_lookup(elements_tab->hashtab, scalar);
3669 
3670  /* the result depends on if the clause is an IN or NOT IN clause */
3671  if (inclause)
3672  result = BoolGetDatum(hashfound); /* IN */
3673  else
3674  result = BoolGetDatum(!hashfound); /* NOT IN */
3675 
3676  resultnull = false;
3677 
3678  /*
3679  * If we didn't find a match in the array, we still might need to handle
3680  * the possibility of null values. We didn't put any NULLs into the
3681  * hashtable, but instead marked if we found any when building the table
3682  * in has_nulls.
3683  */
3684  if (!hashfound && op->d.hashedscalararrayop.has_nulls)
3685  {
3686  if (strictfunc)
3687  {
3688 
3689  /*
3690  * We have nulls in the array so a non-null lhs and no match must
3691  * yield NULL.
3692  */
3693  result = (Datum) 0;
3694  resultnull = true;
3695  }
3696  else
3697  {
3698  /*
3699  * Execute function will null rhs just once.
3700  *
3701  * The hash lookup path will have scribbled on the lhs argument so
3702  * we need to set it up also (even though we entered this function
3703  * with it already set).
3704  */
3705  fcinfo->args[0].value = scalar;
3706  fcinfo->args[0].isnull = scalar_isnull;
3707  fcinfo->args[1].value = (Datum) 0;
3708  fcinfo->args[1].isnull = true;
3709 
3710  result = op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
3711  resultnull = fcinfo->isnull;
3712 
3713  /*
3714  * Reverse the result for NOT IN clauses since the above function
3715  * is the equality function and we need not-equals.
3716  */
3717  if (!inclause)
3718  result = !result;
3719  }
3720  }
3721 
3722  *op->resvalue = result;
3723  *op->resnull = resultnull;
3724 }
signed short int16
Definition: c.h:482
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:2253
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::@51::@83 hashedscalararrayop
Definition: nodes.h:129
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().

◆ ExecEvalJsonConstructor()

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

Definition at line 3979 of file execExprInterp.c.

3981 {
3982  Datum res;
3983  JsonConstructorExprState *jcstate = op->d.json_constructor.jcstate;
3984  JsonConstructorExpr *ctor = jcstate->constructor;
3985  bool is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
3986  bool isnull = false;
3987 
3988  if (ctor->type == JSCTOR_JSON_ARRAY)
3989  res = (is_jsonb ?
3991  json_build_array_worker) (jcstate->nargs,
3992  jcstate->arg_values,
3993  jcstate->arg_nulls,
3994  jcstate->arg_types,
3995  jcstate->constructor->absent_on_null);
3996  else if (ctor->type == JSCTOR_JSON_OBJECT)
3997  res = (is_jsonb ?
3999  json_build_object_worker) (jcstate->nargs,
4000  jcstate->arg_values,
4001  jcstate->arg_nulls,
4002  jcstate->arg_types,
4003  jcstate->constructor->absent_on_null,
4004  jcstate->constructor->unique);
4005  else if (ctor->type == JSCTOR_JSON_SCALAR)
4006  {
4007  if (jcstate->arg_nulls[0])
4008  {
4009  res = (Datum) 0;
4010  isnull = true;
4011  }
4012  else
4013  {
4014  Datum value = jcstate->arg_values[0];
4015  Oid outfuncid = jcstate->arg_type_cache[0].outfuncid;
4016  JsonTypeCategory category = (JsonTypeCategory)
4017  jcstate->arg_type_cache[0].category;
4018 
4019  if (is_jsonb)
4020  res = datum_to_jsonb(value, category, outfuncid);
4021  else
4022  res = datum_to_json(value, category, outfuncid);
4023  }
4024  }
4025  else if (ctor->type == JSCTOR_JSON_PARSE)
4026  {
4027  if (jcstate->arg_nulls[0])
4028  {
4029  res = (Datum) 0;
4030  isnull = true;
4031  }
4032  else
4033  {
4034  Datum value = jcstate->arg_values[0];
4035  text *js = DatumGetTextP(value);
4036 
4037  if (is_jsonb)
4038  res = jsonb_from_text(js, true);
4039  else
4040  {
4041  (void) json_validate(js, true, true);
4042  res = value;
4043  }
4044  }
4045  }
4046  else
4047  elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type);
4048 
4049  *op->resvalue = res;
4050  *op->resnull = isnull;
4051 }
#define DatumGetTextP(X)
Definition: fmgr.h:332
static struct @148 value
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Datum json_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null)
Definition: json.c:1297
Datum json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null, bool unique_keys)
Definition: json.c:1184
Datum datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: json.c:730
bool json_validate(text *json, bool check_unique_keys, bool throw_error)
Definition: json.c:1626
Datum jsonb_from_text(text *js, bool unique_keys)
Definition: jsonb.c:152
Datum jsonb_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null)
Definition: jsonb.c:1214
Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1129
Datum datum_to_jsonb(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:1116
JsonTypeCategory
Definition: jsonfuncs.h:68
@ JS_FORMAT_JSONB
Definition: primnodes.h:1567
@ JSCTOR_JSON_PARSE
Definition: primnodes.h:1617
@ JSCTOR_JSON_OBJECT
Definition: primnodes.h:1613
@ JSCTOR_JSON_SCALAR
Definition: primnodes.h:1618
@ JSCTOR_JSON_ARRAY
Definition: primnodes.h:1614
struct ExprEvalStep::@51::@85 json_constructor
JsonConstructorExpr * constructor
Definition: execExpr.h:743
struct JsonConstructorExprState::@96 * arg_type_cache
JsonReturning * returning
Definition: primnodes.h:1633
JsonConstructorType type
Definition: primnodes.h:1629
JsonFormatType format_type
Definition: primnodes.h:1578
JsonFormat * format
Definition: primnodes.h:1590
Definition: c.h:676

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

◆ ExecEvalJsonIsPredicate()

void ExecEvalJsonIsPredicate ( ExprState state,
ExprEvalStep op 
)

Definition at line 4057 of file execExprInterp.c.

4058 {
4059  JsonIsPredicate *pred = op->d.is_json.pred;
4060  Datum js = *op->resvalue;
4061  Oid exprtype;
4062  bool res;
4063 
4064  if (*op->resnull)
4065  {
4066  *op->resvalue = BoolGetDatum(false);
4067  return;
4068  }
4069 
4070  exprtype = exprType(pred->expr);
4071 
4072  if (exprtype == TEXTOID || exprtype == JSONOID)
4073  {
4074  text *json = DatumGetTextP(js);
4075 
4076  if (pred->item_type == JS_TYPE_ANY)
4077  res = true;
4078  else
4079  {
4080  switch (json_get_first_token(json, false))
4081  {
4083  res = pred->item_type == JS_TYPE_OBJECT;
4084  break;
4086  res = pred->item_type == JS_TYPE_ARRAY;
4087  break;
4088  case JSON_TOKEN_STRING:
4089  case JSON_TOKEN_NUMBER:
4090  case JSON_TOKEN_TRUE:
4091  case JSON_TOKEN_FALSE:
4092  case JSON_TOKEN_NULL:
4093  res = pred->item_type == JS_TYPE_SCALAR;
4094  break;
4095  default:
4096  res = false;
4097  break;
4098  }
4099  }
4100 
4101  /*
4102  * Do full parsing pass only for uniqueness check or for JSON text
4103  * validation.
4104  */
4105  if (res && (pred->unique_keys || exprtype == TEXTOID))
4106  res = json_validate(json, pred->unique_keys, false);
4107  }
4108  else if (exprtype == JSONBOID)
4109  {
4110  if (pred->item_type == JS_TYPE_ANY)
4111  res = true;
4112  else
4113  {
4114  Jsonb *jb = DatumGetJsonbP(js);
4115 
4116  switch (pred->item_type)
4117  {
4118  case JS_TYPE_OBJECT:
4119  res = JB_ROOT_IS_OBJECT(jb);
4120  break;
4121  case JS_TYPE_ARRAY:
4122  res = JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb);
4123  break;
4124  case JS_TYPE_SCALAR:
4125  res = JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb);
4126  break;
4127  default:
4128  res = false;
4129  break;
4130  }
4131  }
4132 
4133  /* Key uniqueness check is redundant for jsonb */
4134  }
4135  else
4136  res = false;
4137 
4138  *op->resvalue = BoolGetDatum(res);
4139 }
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26
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:5671
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:43
@ JS_TYPE_ANY
Definition: primnodes.h:1645
@ JS_TYPE_ARRAY
Definition: primnodes.h:1647
@ JS_TYPE_OBJECT
Definition: primnodes.h:1646
@ JS_TYPE_SCALAR
Definition: primnodes.h:1648
struct ExprEvalStep::@51::@95 is_json
JsonValueType item_type
Definition: primnodes.h:1660
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().

◆ ExecEvalMinMax()

void ExecEvalMinMax ( ExprState state,
ExprEvalStep op 
)

Definition at line 2998 of file execExprInterp.c.

2999 {
3000  Datum *values = op->d.minmax.values;
3001  bool *nulls = op->d.minmax.nulls;
3002  FunctionCallInfo fcinfo = op->d.minmax.fcinfo_data;
3003  MinMaxOp operator = op->d.minmax.op;
3004 
3005  /* set at initialization */
3006  Assert(fcinfo->args[0].isnull == false);
3007  Assert(fcinfo->args[1].isnull == false);
3008 
3009  /* default to null result */
3010  *op->resnull = true;
3011 
3012  for (int off = 0; off < op->d.minmax.nelems; off++)
3013  {
3014  /* ignore NULL inputs */
3015  if (nulls[off])
3016  continue;
3017 
3018  if (*op->resnull)
3019  {
3020  /* first nonnull input, adopt value */
3021  *op->resvalue = values[off];
3022  *op->resnull = false;
3023  }
3024  else
3025  {
3026  int cmpresult;
3027 
3028  /* apply comparison function */
3029  fcinfo->args[0].value = *op->resvalue;
3030  fcinfo->args[1].value = values[off];
3031 
3032  fcinfo->isnull = false;
3033  cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
3034  if (fcinfo->isnull) /* probably should not happen */
3035  continue;
3036 
3037  if (cmpresult > 0 && operator == IS_LEAST)
3038  *op->resvalue = values[off];
3039  else if (cmpresult < 0 && operator == IS_GREATEST)
3040  *op->resvalue = values[off];
3041  }
3042  }
3043 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
MinMaxOp
Definition: primnodes.h:1428
@ IS_LEAST
Definition: primnodes.h:1430
@ IS_GREATEST
Definition: primnodes.h:1429
struct ExprEvalStep::@51::@75 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 2595 of file execExprInterp.c.

2596 {
2597  int64 newval = nextval_internal(op->d.nextvalueexpr.seqid, false);
2598 
2599  switch (op->d.nextvalueexpr.seqtypid)
2600  {
2601  case INT2OID:
2602  *op->resvalue = Int16GetDatum((int16) newval);
2603  break;
2604  case INT4OID:
2605  *op->resvalue = Int32GetDatum((int32) newval);
2606  break;
2607  case INT8OID:
2608  *op->resvalue = Int64GetDatum((int64) newval);
2609  break;
2610  default:
2611  elog(ERROR, "unsupported sequence type %u",
2612  op->d.nextvalueexpr.seqtypid);
2613  }
2614  *op->resnull = false;
2615 }
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1790
#define newval
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:615
struct ExprEvalStep::@51::@69 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 2453 of file execExprInterp.c.

2454 {
2455  ParamExecData *prm;
2456 
2457  prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]);
2458  if (unlikely(prm->execPlan != NULL))
2459  {
2460  /* Parameter not evaluated yet, so go do it */
2461  ExecSetParamPlan(prm->execPlan, econtext);
2462  /* ExecSetParamPlan should have processed this param... */
2463  Assert(prm->execPlan == NULL);
2464  }
2465  *op->resvalue = prm->value;
2466  *op->resnull = prm->isnull;
2467 }
void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
Definition: nodeSubplan.c:1092
ParamExecData * ecxt_param_exec_vals
Definition: execnodes.h:260
struct ExprEvalStep::@51::@63 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 2475 of file execExprInterp.c.

2476 {
2477  ParamListInfo paramInfo = econtext->ecxt_param_list_info;
2478  int paramId = op->d.param.paramid;
2479 
2480  if (likely(paramInfo &&
2481  paramId > 0 && paramId <= paramInfo->numParams))
2482  {
2483  ParamExternData *prm;
2484  ParamExternData prmdata;
2485 
2486  /* give hook a chance in case parameter is dynamic */
2487  if (paramInfo->paramFetch != NULL)
2488  prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
2489  else
2490  prm = &paramInfo->params[paramId - 1];
2491 
2492  if (likely(OidIsValid(prm->ptype)))
2493  {
2494  /* safety check in case hook did something unexpected */
2495  if (unlikely(prm->ptype != op->d.param.paramtype))
2496  ereport(ERROR,
2497  (errcode(ERRCODE_DATATYPE_MISMATCH),
2498  errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
2499  paramId,
2500  format_type_be(prm->ptype),
2501  format_type_be(op->d.param.paramtype))));
2502  *op->resvalue = prm->value;
2503  *op->resnull = prm->isnull;
2504  return;
2505  }
2506  }
2507 
2508  ereport(ERROR,
2509  (errcode(ERRCODE_UNDEFINED_OBJECT),
2510  errmsg("no value found for parameter %d", paramId)));
2511 }
#define likely(x)
Definition: c.h:299
#define OidIsValid(objectId)
Definition: c.h:764
ParamListInfo ecxt_param_list_info
Definition: execnodes.h:261
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().

◆ ExecEvalPreOrderedDistinctMulti()

bool ExecEvalPreOrderedDistinctMulti ( AggState aggstate,
AggStatePerTrans  pertrans 
)

Definition at line 4585 of file execExprInterp.c.

4586 {
4587  ExprContext *tmpcontext = aggstate->tmpcontext;
4588 
4589  for (int i = 0; i < pertrans->numTransInputs; i++)
4590  {
4591  pertrans->sortslot->tts_values[i] = pertrans->transfn_fcinfo->args[i + 1].value;
4592  pertrans->sortslot->tts_isnull[i] = pertrans->transfn_fcinfo->args[i + 1].isnull;
4593  }
4594 
4595  ExecClearTuple(pertrans->sortslot);
4596  pertrans->sortslot->tts_nvalid = pertrans->numInputs;
4597  ExecStoreVirtualTuple(pertrans->sortslot);
4598 
4599  tmpcontext->ecxt_outertuple = pertrans->sortslot;
4600  tmpcontext->ecxt_innertuple = pertrans->uniqslot;
4601 
4602  if (!pertrans->haslast ||
4603  !ExecQual(pertrans->equalfnMulti, tmpcontext))
4604  {
4605  if (pertrans->haslast)
4606  ExecClearTuple(pertrans->uniqslot);
4607 
4608  pertrans->haslast = true;
4609  ExecCopySlot(pertrans->uniqslot, pertrans->sortslot);
4610  return true;
4611  }
4612  return false;
4613 }
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:412
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:482

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 4543 of file execExprInterp.c.

4544 {
4545  Datum value = pertrans->transfn_fcinfo->args[1].value;
4546  bool isnull = pertrans->transfn_fcinfo->args[1].isnull;
4547 
4548  if (!pertrans->haslast ||
4549  pertrans->lastisnull != isnull ||
4550  (!isnull && !DatumGetBool(FunctionCall2Coll(&pertrans->equalfnOne,
4551  pertrans->aggCollation,
4552  pertrans->lastdatum, value))))
4553  {
4554  if (pertrans->haslast && !pertrans->inputtypeByVal &&
4555  !pertrans->lastisnull)
4556  pfree(DatumGetPointer(pertrans->lastdatum));
4557 
4558  pertrans->haslast = true;
4559  if (!isnull)
4560  {
4561  MemoryContext oldContext;
4562 
4564 
4565  pertrans->lastdatum = datumCopy(value, pertrans->inputtypeByVal,
4566  pertrans->inputtypeLen);
4567 
4568  MemoryContextSwitchTo(oldContext);
4569  }
4570  else
4571  pertrans->lastdatum = (Datum) 0;
4572  pertrans->lastisnull = isnull;
4573  return true;
4574  }
4575 
4576  return false;
4577 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1132
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 2978 of file execExprInterp.c.

2979 {
2980  HeapTuple tuple;
2981 
2982  /* build tuple from evaluated field values */
2983  tuple = heap_form_tuple(op->d.row.tupdesc,
2984  op->d.row.elemvalues,
2985  op->d.row.elemnulls);
2986 
2987  *op->resvalue = HeapTupleGetDatum(tuple);
2988  *op->resnull = false;
2989 }
struct ExprEvalStep::@51::@72 row

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

Referenced by ExecInterpExpr().

◆ ExecEvalRowNotNull()

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

Definition at line 2630 of file execExprInterp.c.

2631 {
2632  ExecEvalRowNullInt(state, op, econtext, false);
2633 }
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 2621 of file execExprInterp.c.

2622 {
2623  ExecEvalRowNullInt(state, op, econtext, true);
2624 }

References ExecEvalRowNullInt(), and ExprEvalStep::op.

Referenced by ExecInterpExpr().

◆ ExecEvalRowNullInt()

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

Definition at line 2637 of file execExprInterp.c.

2639 {
2640  Datum value = *op->resvalue;
2641  bool isnull = *op->resnull;
2642  HeapTupleHeader tuple;
2643  Oid tupType;
2644  int32 tupTypmod;
2645  TupleDesc tupDesc;
2646  HeapTupleData tmptup;
2647 
2648  *op->resnull = false;
2649 
2650  /* NULL row variables are treated just as NULL scalar columns */
2651  if (isnull)
2652  {
2653  *op->resvalue = BoolGetDatum(checkisnull);
2654  return;
2655  }
2656 
2657  /*
2658  * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument
2659  * as:
2660  *
2661  * "R IS NULL" is true if every field is the null value.
2662  *
2663  * "R IS NOT NULL" is true if no field is the null value.
2664  *
2665  * This definition is (apparently intentionally) not recursive; so our
2666  * tests on the fields are primitive attisnull tests, not recursive checks
2667  * to see if they are all-nulls or no-nulls rowtypes.
2668  *
2669  * The standard does not consider the possibility of zero-field rows, but
2670  * here we consider them to vacuously satisfy both predicates.
2671  */
2672 
2673  tuple = DatumGetHeapTupleHeader(value);
2674 
2675  tupType = HeapTupleHeaderGetTypeId(tuple);
2676  tupTypmod = HeapTupleHeaderGetTypMod(tuple);
2677 
2678  /* Lookup tupdesc if first time through or if type changes */
2679  tupDesc = get_cached_rowtype(tupType, tupTypmod,
2680  &op->d.nulltest_row.rowcache, NULL);
2681 
2682  /*
2683  * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader.
2684  */
2685  tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
2686  tmptup.t_data = tuple;
2687 
2688  for (int att = 1; att <= tupDesc->natts; att++)
2689  {
2690  /* ignore dropped columns */
2691  if (TupleDescAttr(tupDesc, att - 1)->attisdropped)
2692  continue;
2693  if (heap_attisnull(&tmptup, att, tupDesc))
2694  {
2695  /* null field disproves IS NOT NULL */
2696  if (!checkisnull)
2697  {
2698  *op->resvalue = BoolGetDatum(false);
2699  return;
2700  }
2701  }
2702  else
2703  {
2704  /* non-null field disproves IS NULL */
2705  if (checkisnull)
2706  {
2707  *op->resvalue = BoolGetDatum(false);
2708  return;
2709  }
2710  }
2711  }
2712 
2713  *op->resvalue = BoolGetDatum(true);
2714 }
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:447
struct ExprEvalStep::@51::@62 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 3345 of file execExprInterp.c.

3346 {
3347  FunctionCallInfo fcinfo = op->d.scalararrayop.fcinfo_data;
3348  bool useOr = op->d.scalararrayop.useOr;
3349  bool strictfunc = op->d.scalararrayop.finfo->fn_strict;
3350  ArrayType *arr;
3351  int nitems;
3352  Datum result;
3353  bool resultnull;
3354  int16 typlen;
3355  bool typbyval;
3356  char typalign;
3357  char *s;
3358  bits8 *bitmap;
3359  int bitmask;
3360 
3361  /*
3362  * If the array is NULL then we return NULL --- it's not very meaningful
3363  * to do anything else, even if the operator isn't strict.
3364  */
3365  if (*op->resnull)
3366  return;
3367 
3368  /* Else okay to fetch and detoast the array */
3369  arr = DatumGetArrayTypeP(*op->resvalue);
3370 
3371  /*
3372  * If the array is empty, we return either FALSE or TRUE per the useOr
3373  * flag. This is correct even if the scalar is NULL; since we would
3374  * evaluate the operator zero times, it matters not whether it would want
3375  * to return NULL.
3376  */
3377  nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
3378  if (nitems <= 0)
3379  {
3380  *op->resvalue = BoolGetDatum(!useOr);
3381  *op->resnull = false;
3382  return;
3383  }
3384 
3385  /*
3386  * If the scalar is NULL, and the function is strict, return NULL; no
3387  * point in iterating the loop.
3388  */
3389  if (fcinfo->args[0].isnull && strictfunc)
3390  {
3391  *op->resnull = true;
3392  return;
3393  }
3394 
3395  /*
3396  * We arrange to look up info about the element type only once per series
3397  * of calls, assuming the element type doesn't change underneath us.
3398  */
3399  if (op->d.scalararrayop.element_type != ARR_ELEMTYPE(arr))
3400  {
3402  &op->d.scalararrayop.typlen,
3403  &op->d.scalararrayop.typbyval,
3404  &op->d.scalararrayop.typalign);
3405  op->d.scalararrayop.element_type = ARR_ELEMTYPE(arr);
3406  }
3407 
3408  typlen = op->d.scalararrayop.typlen;
3409  typbyval = op->d.scalararrayop.typbyval;
3410  typalign = op->d.scalararrayop.typalign;
3411 
3412  /* Initialize result appropriately depending on useOr */
3413  result = BoolGetDatum(!useOr);
3414  resultnull = false;
3415 
3416  /* Loop over the array elements */
3417  s = (char *) ARR_DATA_PTR(arr);
3418  bitmap = ARR_NULLBITMAP(arr);
3419  bitmask = 1;
3420 
3421  for (int i = 0; i < nitems; i++)
3422  {
3423  Datum elt;
3424  Datum thisresult;
3425 
3426  /* Get array element, checking for NULL */
3427  if (bitmap && (*bitmap & bitmask) == 0)
3428  {
3429  fcinfo->args[1].value = (Datum) 0;
3430  fcinfo->args[1].isnull = true;
3431  }
3432  else
3433  {
3434  elt = fetch_att(s, typbyval, typlen);
3435  s = att_addlength_pointer(s, typlen, s);
3436  s = (char *) att_align_nominal(s, typalign);
3437  fcinfo->args[1].value = elt;
3438  fcinfo->args[1].isnull = false;
3439  }
3440 
3441  /* Call comparison function */
3442  if (fcinfo->args[1].isnull && strictfunc)
3443  {
3444  fcinfo->isnull = true;
3445  thisresult = (Datum) 0;
3446  }
3447  else
3448  {
3449  fcinfo->isnull = false;
3450  thisresult = op->d.scalararrayop.fn_addr(fcinfo);
3451  }
3452 
3453  /* Combine results per OR or AND semantics */
3454  if (fcinfo->isnull)
3455  resultnull = true;
3456  else if (useOr)
3457  {
3458  if (DatumGetBool(thisresult))
3459  {
3460  result = BoolGetDatum(true);
3461  resultnull = false;
3462  break; /* needn't look at any more elements */
3463  }
3464  }
3465  else
3466  {
3467  if (!DatumGetBool(thisresult))
3468  {
3469  result = BoolGetDatum(false);
3470  resultnull = false;
3471  break; /* needn't look at any more elements */
3472  }
3473  }
3474 
3475  /* advance bitmap pointer if any */
3476  if (bitmap)
3477  {
3478  bitmask <<= 1;
3479  if (bitmask == 0x100)
3480  {
3481  bitmap++;
3482  bitmask = 1;
3483  }
3484  }
3485  }
3486 
3487  *op->resvalue = result;
3488  *op->resnull = resultnull;
3489 }
struct ExprEvalStep::@51::@82 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 2517 of file execExprInterp.c.

2518 {
2519  LOCAL_FCINFO(fcinfo, 0);
2520  SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
2521 
2522  *op->resnull = false;
2523 
2524  /*
2525  * Note: current_schema() can return NULL. current_user() etc currently
2526  * cannot, but might as well code those cases the same way for safety.
2527  */
2528  switch (svf->op)
2529  {
2530  case SVFOP_CURRENT_DATE:
2532  break;
2533  case SVFOP_CURRENT_TIME:
2534  case SVFOP_CURRENT_TIME_N:
2536  break;
2540  break;
2541  case SVFOP_LOCALTIME:
2542  case SVFOP_LOCALTIME_N:
2544  break;
2545  case SVFOP_LOCALTIMESTAMP:
2548  break;
2549  case SVFOP_CURRENT_ROLE:
2550  case SVFOP_CURRENT_USER:
2551  case SVFOP_USER:
2552  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2553  *op->resvalue = current_user(fcinfo);
2554  *op->resnull = fcinfo->isnull;
2555  break;
2556  case SVFOP_SESSION_USER:
2557  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2558  *op->resvalue = session_user(fcinfo);
2559  *op->resnull = fcinfo->isnull;
2560  break;
2561  case SVFOP_CURRENT_CATALOG:
2562  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2563  *op->resvalue = current_database(fcinfo);
2564  *op->resnull = fcinfo->isnull;
2565  break;
2566  case SVFOP_CURRENT_SCHEMA:
2567  InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
2568  *op->resvalue = current_schema(fcinfo);
2569  *op->resnull = fcinfo->isnull;
2570  break;
2571  }
2572 }
Datum current_database(PG_FUNCTION_ARGS)
Definition: misc.c:195
Timestamp GetSQLLocalTimestamp(int32 typmod)
Definition: timestamp.c:1615
TimestampTz GetSQLCurrentTimestamp(int32 typmod)
Definition: timestamp.c:1601
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:341
TimeADT GetSQLLocalTime(int32 typmod)
Definition: date.c:361
DateADT GetSQLCurrentDate(void)
Definition: date.c:308
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:1476
@ SVFOP_LOCALTIME_N
Definition: primnodes.h:1469
@ SVFOP_CURRENT_TIMESTAMP
Definition: primnodes.h:1466
@ SVFOP_LOCALTIME
Definition: primnodes.h:1468
@ SVFOP_CURRENT_TIMESTAMP_N
Definition: primnodes.h:1467
@ SVFOP_CURRENT_ROLE
Definition: primnodes.h:1472
@ SVFOP_USER
Definition: primnodes.h:1474
@ SVFOP_CURRENT_SCHEMA
Definition: primnodes.h:1477
@ SVFOP_LOCALTIMESTAMP_N
Definition: primnodes.h:1471
@ SVFOP_CURRENT_DATE
Definition: primnodes.h:1463
@ SVFOP_CURRENT_TIME_N
Definition: primnodes.h:1465
@ SVFOP_CURRENT_TIME
Definition: primnodes.h:1464
@ SVFOP_LOCALTIMESTAMP
Definition: primnodes.h:1470
@ SVFOP_CURRENT_USER
Definition: primnodes.h:1473
@ SVFOP_SESSION_USER
Definition: primnodes.h:1475
struct ExprEvalStep::@51::@68 sqlvaluefunction
SQLValueFunctionOp op
Definition: primnodes.h:1483
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 2365 of file execExprInterp.c.

2366 {
2367 #if defined(EEO_USE_COMPUTED_GOTO)
2368  if (state->flags & EEO_FLAG_DIRECT_THREADED)
2369  {
2370  ExprEvalOpLookup key;
2371  ExprEvalOpLookup *res;
2372 
2373  key.opcode = (void *) op->opcode;
2374  res = bsearch(&key,
2375  reverse_dispatch_table,
2376  EEOP_LAST /* nmembers */ ,
2377  sizeof(ExprEvalOpLookup),
2378  dispatch_compare_ptr);
2379  Assert(res); /* unknown ops shouldn't get looked up */
2380  return res->op;
2381  }
2382 #endif
2383  return (ExprEvalOp) op->opcode;
2384 }
#define EEO_FLAG_DIRECT_THREADED
Definition: execExpr.h:30
ExprEvalOp
Definition: execExpr.h:66
@ EEOP_LAST
Definition: execExpr.h:264
intptr_t opcode
Definition: execExpr.h:275

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 4177 of file execExprInterp.c.

4178 {
4179  SubPlanState *sstate = op->d.subplan.sstate;
4180 
4181  /* could potentially be nested, so make sure there's enough stack */
4183 
4184  *op->resvalue = ExecSubPlan(sstate, econtext, op->resnull);
4185 }
Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull)
Definition: nodeSubplan.c:62
void check_stack_depth(void)
Definition: postgres.c:3523
struct ExprEvalStep::@51::@89 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 4421 of file execExprInterp.c.

4423 {
4424  Datum d;
4425 
4426  /* slot_getsysattr has sufficient defenses against bad attnums */
4427  d = slot_getsysattr(slot,
4428  op->d.var.attnum,
4429  op->resnull);
4430  *op->resvalue = d;
4431  /* this ought to be unreachable, but it's cheap enough to check */
4432  if (unlikely(*op->resnull))
4433  elog(ERROR, "failed to fetch attribute from slot");
4434 }
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:409

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 4194 of file execExprInterp.c.

4195 {
4196  Var *variable = op->d.wholerow.var;
4197  TupleTableSlot *slot;
4198  TupleDesc output_tupdesc;
4199  MemoryContext oldcontext;
4200  HeapTupleHeader dtuple;
4201  HeapTuple tuple;
4202 
4203  /* This was checked by ExecInitExpr */
4204  Assert(variable->varattno == InvalidAttrNumber);
4205 
4206  /* Get the input slot we want */
4207  switch (variable->varno)
4208  {
4209  case INNER_VAR:
4210  /* get the tuple from the inner node */
4211  slot = econtext->ecxt_innertuple;
4212  break;
4213 
4214  case OUTER_VAR:
4215  /* get the tuple from the outer node */
4216  slot = econtext->ecxt_outertuple;
4217  break;
4218 
4219  /* INDEX_VAR is handled by default case */
4220 
4221  default:
4222  /* get the tuple from the relation being scanned */
4223  slot = econtext->ecxt_scantuple;
4224  break;
4225  }
4226 
4227  /* Apply the junkfilter if any */
4228  if (op->d.wholerow.junkFilter != NULL)
4229  slot = ExecFilterJunk(op->d.wholerow.junkFilter, slot);
4230 
4231  /*
4232  * If first time through, obtain tuple descriptor and check compatibility.
4233  *
4234  * XXX: It'd be great if this could be moved to the expression
4235  * initialization phase, but due to using slots that's currently not
4236  * feasible.
4237  */
4238  if (op->d.wholerow.first)
4239  {
4240  /* optimistically assume we don't need slow path */
4241  op->d.wholerow.slow = false;
4242 
4243  /*
4244  * If the Var identifies a named composite type, we must check that
4245  * the actual tuple type is compatible with it.
4246  */
4247  if (variable->vartype != RECORDOID)
4248  {
4249  TupleDesc var_tupdesc;
4250  TupleDesc slot_tupdesc;
4251 
4252  /*
4253  * We really only care about numbers of attributes and data types.
4254  * Also, we can ignore type mismatch on columns that are dropped
4255  * in the destination type, so long as (1) the physical storage
4256  * matches or (2) the actual column value is NULL. Case (1) is
4257  * helpful in some cases involving out-of-date cached plans, while
4258  * case (2) is expected behavior in situations such as an INSERT
4259  * into a table with dropped columns (the planner typically
4260  * generates an INT4 NULL regardless of the dropped column type).
4261  * If we find a dropped column and cannot verify that case (1)
4262  * holds, we have to use the slow path to check (2) for each row.
4263  *
4264  * If vartype is a domain over composite, just look through that
4265  * to the base composite type.
4266  */
4267  var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
4268  -1, false);
4269 
4270  slot_tupdesc = slot->tts_tupleDescriptor;
4271 
4272  if (var_tupdesc->natts != slot_tupdesc->natts)
4273  ereport(ERROR,
4274  (errcode(ERRCODE_DATATYPE_MISMATCH),
4275  errmsg("table row type and query-specified row type do not match"),
4276  errdetail_plural("Table row contains %d attribute, but query expects %d.",
4277  "Table row contains %d attributes, but query expects %d.",
4278  slot_tupdesc->natts,
4279  slot_tupdesc->natts,
4280  var_tupdesc->natts)));
4281 
4282  for (int i = 0; i < var_tupdesc->natts; i++)
4283  {
4284  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4285  Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i);
4286 
4287  if (vattr->atttypid == sattr->atttypid)
4288  continue; /* no worries */
4289  if (!vattr->attisdropped)
4290  ereport(ERROR,
4291  (errcode(ERRCODE_DATATYPE_MISMATCH),
4292  errmsg("table row type and query-specified row type do not match"),
4293  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
4294  format_type_be(sattr->atttypid),
4295  i + 1,
4296  format_type_be(vattr->atttypid))));
4297 
4298  if (vattr->attlen != sattr->attlen ||
4299  vattr->attalign != sattr->attalign)
4300  op->d.wholerow.slow = true; /* need to check for nulls */
4301  }
4302 
4303  /*
4304  * Use the variable's declared rowtype as the descriptor for the
4305  * output values. In particular, we *must* absorb any
4306  * attisdropped markings.
4307  */
4308  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
4309  output_tupdesc = CreateTupleDescCopy(var_tupdesc);
4310  MemoryContextSwitchTo(oldcontext);
4311 
4312  ReleaseTupleDesc(var_tupdesc);
4313  }
4314  else
4315  {
4316  /*
4317  * In the RECORD case, we use the input slot's rowtype as the
4318  * descriptor for the output values, modulo possibly assigning new
4319  * column names below.
4320  */
4321  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
4322  output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
4323  MemoryContextSwitchTo(oldcontext);
4324 
4325  /*
4326  * It's possible that the input slot is a relation scan slot and
4327  * so is marked with that relation's rowtype. But we're supposed
4328  * to be returning RECORD, so reset to that.
4329  */
4330  output_tupdesc->tdtypeid = RECORDOID;
4331  output_tupdesc->tdtypmod = -1;
4332 
4333  /*
4334  * We already got the correct physical datatype info above, but
4335  * now we should try to find the source RTE and adopt its column
4336  * aliases, since it's unlikely that the input slot has the
4337  * desired names.
4338  *
4339  * If we can't locate the RTE, assume the column names we've got
4340  * are OK. (As of this writing, the only cases where we can't
4341  * locate the RTE are in execution of trigger WHEN clauses, and
4342  * then the Var will have the trigger's relation's rowtype, so its
4343  * names are fine.) Also, if the creator of the RTE didn't bother
4344  * to fill in an eref field, assume our column names are OK. (This
4345  * happens in COPY, and perhaps other places.)
4346  */
4347  if (econtext->ecxt_estate &&
4348  variable->varno <= econtext->ecxt_estate->es_range_table_size)
4349  {
4350  RangeTblEntry *rte = exec_rt_fetch(variable->varno,
4351  econtext->ecxt_estate);
4352 
4353  if (rte->eref)
4354  ExecTypeSetColNames(output_tupdesc, rte->eref->colnames);
4355  }
4356  }
4357 
4358  /* Bless the tupdesc if needed, and save it in the execution state */
4359  op->d.wholerow.tupdesc = BlessTupleDesc(output_tupdesc);
4360 
4361  op->d.wholerow.first = false;
4362  }
4363 
4364  /*
4365  * Make sure all columns of the slot are accessible in the slot's
4366  * Datum/isnull arrays.
4367  */
4368  slot_getallattrs(slot);
4369 
4370  if (op->d.wholerow.slow)
4371  {
4372  /* Check to see if any dropped attributes are non-null */
4373  TupleDesc tupleDesc = slot->tts_tupleDescriptor;
4374  TupleDesc var_tupdesc = op->d.wholerow.tupdesc;
4375 
4376  Assert(var_tupdesc->natts == tupleDesc->natts);
4377 
4378  for (int i = 0; i < var_tupdesc->natts; i++)
4379  {
4380  Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i);
4381  Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i);
4382 
4383  if (!vattr->attisdropped)
4384  continue; /* already checked non-dropped cols */
4385  if (slot->tts_isnull[i])
4386  continue; /* null is always okay */
4387  if (vattr->attlen != sattr->attlen ||
4388  vattr->attalign != sattr->attalign)
4389  ereport(ERROR,
4390  (errcode(ERRCODE_DATATYPE_MISMATCH),
4391  errmsg("table row type and query-specified row type do not match"),
4392  errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
4393  i + 1)));
4394  }
4395  }
4396 
4397  /*
4398  * Build a composite datum, making sure any toasted fields get detoasted.
4399  *
4400  * (Note: it is critical that we not change the slot's state here.)
4401  */
4403  slot->tts_values,
4404  slot->tts_isnull);
4405  dtuple = tuple->t_data;
4406 
4407  /*
4408  * Label the datum with the composite type info we identified before.
4409  *
4410  * (Note: we could skip doing this by passing op->d.wholerow.tupdesc to
4411  * the tuple build step; but that seems a tad risky so let's not.)
4412  */
4413  HeapTupleHeaderSetTypeId(dtuple, op->d.wholerow.tupdesc->tdtypeid);
4414  HeapTupleHeaderSetTypMod(dtuple, op->d.wholerow.tupdesc->tdtypmod);
4415 
4416  *op->resvalue = PointerGetDatum(dtuple);
4417  *op->resnull = false;
4418 }
#define InvalidAttrNumber
Definition: attnum.h:23
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1294
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:247
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2072
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2031
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:586
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:215
#define INNER_VAR
Definition: primnodes.h:214
List * colnames
Definition: primnodes.h:43
Index es_range_table_size
Definition: execnodes.h:619
struct EState * ecxt_estate
Definition: execnodes.h:285
struct ExprEvalStep::@51::@54 wholerow
Alias * eref
Definition: parsenodes.h:1199
int32 tdtypmod
Definition: tupdesc.h:83
Definition: primnodes.h:226
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:361
TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1886

References Assert(), BlessTupleDesc(), Alias::colnames, CreateTupleDescCopy(), ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_scantuple, RangeTblEntry::eref, ereport, errcode(), errdetail(), errdetail_plural(), errmsg(), ERROR, EState::es_range_table_size, exec_rt_fetch(), ExecFilterJunk(), ExecTypeSetColNames(), format_type_be(), HeapTupleHeaderSetTypeId, HeapTupleHeaderSetTypMod, i, INNER_VAR, InvalidAttrNumber, lookup_rowtype_tupdesc_domain(), MemoryContextSwitchTo(), TupleDescData::natts, 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 3764 of file execExprInterp.c.

3765 {
3766  XmlExpr *xexpr = op->d.xmlexpr.xexpr;
3767  Datum value;
3768 
3769  *op->resnull = true; /* until we get a result */
3770  *op->resvalue = (Datum) 0;
3771 
3772  switch (xexpr->op)
3773  {
3774  case IS_XMLCONCAT:
3775  {
3776  Datum *argvalue = op->d.xmlexpr.argvalue;
3777  bool *argnull = op->d.xmlexpr.argnull;
3778  List *values = NIL;
3779 
3780  for (int i = 0; i < list_length(xexpr->args); i++)
3781  {
3782  if (!argnull[i])
3783  values = lappend(values, DatumGetPointer(argvalue[i]));
3784  }
3785 
3786  if (values != NIL)
3787  {
3789  *op->resnull = false;
3790  }
3791  }
3792  break;
3793 
3794  case IS_XMLFOREST:
3795  {
3796  Datum *argvalue = op->d.xmlexpr.named_argvalue;
3797  bool *argnull = op->d.xmlexpr.named_argnull;
3799  ListCell *lc;
3800  ListCell *lc2;
3801  int i;
3802 
3803  initStringInfo(&buf);
3804 
3805  i = 0;
3806  forboth(lc, xexpr->named_args, lc2, xexpr->arg_names)
3807  {
3808  Expr *e = (Expr *) lfirst(lc);
3809  char *argname = strVal(lfirst(lc2));
3810 
3811  if (!argnull[i])
3812  {
3813  value = argvalue[i];
3814  appendStringInfo(&buf, "<%s>%s</%s>",
3815  argname,
3817  exprType((Node *) e), true),
3818  argname);
3819  *op->resnull = false;
3820  }
3821  i++;
3822  }
3823 
3824  if (!*op->resnull)
3825  {
3826  text *result;
3827 
3828  result = cstring_to_text_with_len(buf.data, buf.len);
3829  *op->resvalue = PointerGetDatum(result);
3830  }
3831 
3832  pfree(buf.data);
3833  }
3834  break;
3835 
3836  case IS_XMLELEMENT:
3837  *op->resvalue = PointerGetDatum(xmlelement(xexpr,
3838  op->d.xmlexpr.named_argvalue,
3839  op->d.xmlexpr.named_argnull,
3840  op->d.xmlexpr.argvalue,
3841  op->d.xmlexpr.argnull));
3842  *op->resnull = false;
3843  break;
3844 
3845  case IS_XMLPARSE:
3846  {
3847  Datum *argvalue = op->d.xmlexpr.argvalue;
3848  bool *argnull = op->d.xmlexpr.argnull;
3849  text *data;
3850  bool preserve_whitespace;
3851 
3852  /* arguments are known to be text, bool */
3853  Assert(list_length(xexpr->args) == 2);
3854 
3855  if (argnull[0])
3856  return;
3857  value = argvalue[0];
3859 
3860  if (argnull[1]) /* probably can't happen */
3861  return;
3862  value = argvalue[1];
3863  preserve_whitespace = DatumGetBool(value);
3864 
3866  xexpr->xmloption,
3867  preserve_whitespace));
3868  *op->resnull = false;
3869  }
3870  break;
3871 
3872  case IS_XMLPI:
3873  {
3874  text *arg;
3875  bool isnull;
3876 
3877  /* optional argument is known to be text */
3878  Assert(list_length(xexpr->args) <= 1);
3879 
3880  if (xexpr->args)
3881  {
3882  isnull = op->d.xmlexpr.argnull[0];
3883  if (isnull)
3884  arg = NULL;
3885  else
3886  arg = DatumGetTextPP(op->d.xmlexpr.argvalue[0]);
3887  }
3888  else
3889  {
3890  arg = NULL;
3891  isnull = false;
3892  }
3893 
3894  *op->resvalue = PointerGetDatum(xmlpi(xexpr->name,
3895  arg,
3896  isnull,
3897  op->resnull));
3898  }
3899  break;
3900 
3901  case IS_XMLROOT:
3902  {
3903  Datum *argvalue = op->d.xmlexpr.argvalue;
3904  bool *argnull = op->d.xmlexpr.argnull;
3905  xmltype *data;
3906  text *version;
3907  int standalone;
3908 
3909  /* arguments are known to be xml, text, int */
3910  Assert(list_length(xexpr->args) == 3);
3911 
3912  if (argnull[0])
3913  return;
3914  data = DatumGetXmlP(argvalue[0]);
3915 
3916  if (argnull[1])
3917  version = NULL;
3918  else
3919  version = DatumGetTextPP(argvalue[1]);
3920 
3921  Assert(!argnull[2]); /* always present */
3922  standalone = DatumGetInt32(argvalue[2]);
3923 
3925  version,
3926  standalone));
3927  *op->resnull = false;
3928  }
3929  break;
3930 
3931  case IS_XMLSERIALIZE:
3932  {
3933  Datum *argvalue = op->d.xmlexpr.argvalue;
3934  bool *argnull = op->d.xmlexpr.argnull;
3935 
3936  /* argument type is known to be xml */
3937  Assert(list_length(xexpr->args) == 1);
3938 
3939  if (argnull[0])
3940  return;
3941  value = argvalue[0];
3942 
3943  *op->resvalue =
3945  xexpr->xmloption,
3946  xexpr->indent));
3947  *op->resnull = false;
3948  }
3949  break;
3950 
3951  case IS_DOCUMENT:
3952  {
3953  Datum *argvalue = op->d.xmlexpr.argvalue;
3954  bool *argnull = op->d.xmlexpr.argnull;
3955 
3956  /* optional argument is known to be xml */
3957  Assert(list_length(xexpr->args) == 1);
3958 
3959  if (argnull[0])
3960  return;
3961  value = argvalue[0];
3962 
3963  *op->resvalue =
3965  *op->resnull = false;
3966  }
3967  break;
3968 
3969  default:
3970  elog(ERROR, "unrecognized XML operation");
3971  break;
3972  }
3973 }
#define DatumGetTextPP(X)
Definition: fmgr.h:292
List * lappend(List *list, void *datum)
Definition: list.c:338
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:467
static char * buf
Definition: pg_test_fsync.c:67
e
Definition: preproc-init.c:82
@ IS_DOCUMENT
Definition: primnodes.h:1514
@ IS_XMLFOREST
Definition: primnodes.h:1509
@ IS_XMLCONCAT
Definition: primnodes.h:1507
@ IS_XMLPI
Definition: primnodes.h:1511
@ IS_XMLPARSE
Definition: primnodes.h:1510
@ IS_XMLSERIALIZE
Definition: primnodes.h:1513
@ IS_XMLROOT
Definition: primnodes.h:1512
@ IS_XMLELEMENT
Definition: primnodes.h:1508
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
struct ExprEvalStep::@51::@84 xmlexpr
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1535
bool indent
Definition: primnodes.h:1539
List * named_args
Definition: primnodes.h:1531
XmlExprOp op
Definition: primnodes.h:1527
#define strVal(v)
Definition: value.h:82
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:194
xmltype * xmlconcat(List *args)
Definition: xml.c:522
text * xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
Definition: xml.c:625
xmltype * xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
Definition: xml.c:929
bool xml_is_document(xmltype *arg)
Definition: xml.c:1065
xmltype * xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null)
Definition: xml.c:947
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2384
xmltype * xmlelement(XmlExpr *xexpr, Datum *named_argvalue, bool *named_argnull, Datum *argvalue, bool *argnull)
Definition: xml.c:805
xmltype * xmlroot(xmltype *data, text *version, int standalone)
Definition: xml.c:999
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().

◆ ExecInitInterpreter()

static void ExecInitInterpreter ( void  )
static

Definition at line 2333 of file execExprInterp.c.

2334 {
2335 #if defined(EEO_USE_COMPUTED_GOTO)
2336  /* Set up externally-visible pointer to dispatch table */
2337  if (dispatch_table == NULL)
2338  {
2339  dispatch_table = (const void **)
2340  DatumGetPointer(ExecInterpExpr(NULL, NULL, NULL));
2341 
2342  /* build reverse lookup table */
2343  for (int i = 0; i < EEOP_LAST; i++)
2344  {
2345  reverse_dispatch_table[i].opcode = dispatch_table[i];
2346  reverse_dispatch_table[i].op = (ExprEvalOp) i;
2347  }
2348 
2349  /* make it bsearch()able */
2350  qsort(reverse_dispatch_table,
2351  EEOP_LAST /* nmembers */ ,
2352  sizeof(ExprEvalOpLookup),
2353  dispatch_compare_ptr);
2354  }
2355 #endif
2356 }
static Datum ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
#define qsort(a, b, c, d)
Definition: port.h:445

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 395 of file execExprInterp.c.

396 {
397  ExprEvalStep *op;
398  TupleTableSlot *resultslot;
399  TupleTableSlot *innerslot;
400  TupleTableSlot *outerslot;
401  TupleTableSlot *scanslot;
402 
403  /*
404  * This array has to be in the same order as enum ExprEvalOp.
405  */
406 #if defined(EEO_USE_COMPUTED_GOTO)
407  static const void *const dispatch_table[] = {
408  &&CASE_EEOP_DONE,
409  &&CASE_EEOP_INNER_FETCHSOME,
410  &&CASE_EEOP_OUTER_FETCHSOME,
411  &&CASE_EEOP_SCAN_FETCHSOME,
412  &&CASE_EEOP_INNER_VAR,
413  &&CASE_EEOP_OUTER_VAR,
414  &&CASE_EEOP_SCAN_VAR,
415  &&CASE_EEOP_INNER_SYSVAR,
416  &&CASE_EEOP_OUTER_SYSVAR,
417  &&CASE_EEOP_SCAN_SYSVAR,
418  &&CASE_EEOP_WHOLEROW,
419  &&CASE_EEOP_ASSIGN_INNER_VAR,
420  &&CASE_EEOP_ASSIGN_OUTER_VAR,
421  &&CASE_EEOP_ASSIGN_SCAN_VAR,
422  &&CASE_EEOP_ASSIGN_TMP,
423  &&CASE_EEOP_ASSIGN_TMP_MAKE_RO,
424  &&CASE_EEOP_CONST,
425  &&CASE_EEOP_FUNCEXPR,
426  &&CASE_EEOP_FUNCEXPR_STRICT,
427  &&CASE_EEOP_FUNCEXPR_FUSAGE,
428  &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE,
429  &&CASE_EEOP_BOOL_AND_STEP_FIRST,
430  &&CASE_EEOP_BOOL_AND_STEP,
431  &&CASE_EEOP_BOOL_AND_STEP_LAST,
432  &&CASE_EEOP_BOOL_OR_STEP_FIRST,
433  &&CASE_EEOP_BOOL_OR_STEP,
434  &&CASE_EEOP_BOOL_OR_STEP_LAST,
435  &&CASE_EEOP_BOOL_NOT_STEP,
436  &&CASE_EEOP_QUAL,
437  &&CASE_EEOP_JUMP,
438  &&CASE_EEOP_JUMP_IF_NULL,
439  &&CASE_EEOP_JUMP_IF_NOT_NULL,
440  &&CASE_EEOP_JUMP_IF_NOT_TRUE,
441  &&CASE_EEOP_NULLTEST_ISNULL,
442  &&CASE_EEOP_NULLTEST_ISNOTNULL,
443  &&CASE_EEOP_NULLTEST_ROWISNULL,
444  &&CASE_EEOP_NULLTEST_ROWISNOTNULL,
445  &&CASE_EEOP_BOOLTEST_IS_TRUE,
446  &&CASE_EEOP_BOOLTEST_IS_NOT_TRUE,
447  &&CASE_EEOP_BOOLTEST_IS_FALSE,
448  &&CASE_EEOP_BOOLTEST_IS_NOT_FALSE,
449  &&CASE_EEOP_PARAM_EXEC,
450  &&CASE_EEOP_PARAM_EXTERN,
451  &&CASE_EEOP_PARAM_CALLBACK,
452  &&CASE_EEOP_CASE_TESTVAL,
453  &&CASE_EEOP_MAKE_READONLY,
454  &&CASE_EEOP_IOCOERCE,
455  &&CASE_EEOP_DISTINCT,
456  &&CASE_EEOP_NOT_DISTINCT,
457  &&CASE_EEOP_NULLIF,
458  &&CASE_EEOP_SQLVALUEFUNCTION,
459  &&CASE_EEOP_CURRENTOFEXPR,
460  &&CASE_EEOP_NEXTVALUEEXPR,
461  &&CASE_EEOP_ARRAYEXPR,
462  &&CASE_EEOP_ARRAYCOERCE,
463  &&CASE_EEOP_ROW,
464  &&CASE_EEOP_ROWCOMPARE_STEP,
465  &&CASE_EEOP_ROWCOMPARE_FINAL,
466  &&CASE_EEOP_MINMAX,
467  &&CASE_EEOP_FIELDSELECT,
468  &&CASE_EEOP_FIELDSTORE_DEFORM,
469  &&CASE_EEOP_FIELDSTORE_FORM,
470  &&CASE_EEOP_SBSREF_SUBSCRIPTS,
471  &&CASE_EEOP_SBSREF_OLD,
472  &&CASE_EEOP_SBSREF_ASSIGN,
473  &&CASE_EEOP_SBSREF_FETCH,
474  &&CASE_EEOP_DOMAIN_TESTVAL,
475  &&CASE_EEOP_DOMAIN_NOTNULL,
476  &&CASE_EEOP_DOMAIN_CHECK,
477  &&CASE_EEOP_CONVERT_ROWTYPE,
478  &&CASE_EEOP_SCALARARRAYOP,
479  &&CASE_EEOP_HASHED_SCALARARRAYOP,
480  &&CASE_EEOP_XMLEXPR,
481  &&CASE_EEOP_JSON_CONSTRUCTOR,
482  &&CASE_EEOP_IS_JSON,
483  &&CASE_EEOP_AGGREF,
484  &&CASE_EEOP_GROUPING_FUNC,
485  &&CASE_EEOP_WINDOW_FUNC,
486  &&CASE_EEOP_SUBPLAN,
487  &&CASE_EEOP_AGG_STRICT_DESERIALIZE,
488  &&CASE_EEOP_AGG_DESERIALIZE,
489  &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
490  &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
491  &&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
492  &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
493  &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL,
494  &&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
495  &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
496  &&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
497  &&CASE_EEOP_AGG_PLAIN_TRANS_BYREF,
498  &&CASE_EEOP_AGG_PRESORTED_DISTINCT_SINGLE,
499  &&CASE_EEOP_AGG_PRESORTED_DISTINCT_MULTI,
500  &&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,
501  &&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,
502  &&CASE_EEOP_LAST
503  };
504 
505  StaticAssertDecl(lengthof(dispatch_table) == EEOP_LAST + 1,
506  "dispatch_table out of whack with ExprEvalOp");
507 
508  if (unlikely(state == NULL))
509  return PointerGetDatum(dispatch_table);
510 #else
511  Assert(state != NULL);
512 #endif /* EEO_USE_COMPUTED_GOTO */
513 
514  /* setup state */
515  op = state->steps;
516  resultslot = state->resultslot;
517  innerslot = econtext->ecxt_innertuple;
518  outerslot = econtext->ecxt_outertuple;
519  scanslot = econtext->ecxt_scantuple;
520 
521 #if defined(EEO_USE_COMPUTED_GOTO)
522  EEO_DISPATCH();
523 #endif
524 
525  EEO_SWITCH()
526  {
528  {
529  goto out;
530  }
531 
533  {
534  CheckOpSlotCompatibility(op, innerslot);
535 
536  slot_getsomeattrs(innerslot, op->d.fetch.last_var);
537 
538  EEO_NEXT();
539  }
540 
542  {
543  CheckOpSlotCompatibility(op, outerslot);
544 
545  slot_getsomeattrs(outerslot, op->d.fetch.last_var);
546 
547  EEO_NEXT();
548  }
549 
551  {
552  CheckOpSlotCompatibility(op, scanslot);
553 
554  slot_getsomeattrs(scanslot, op->d.fetch.last_var);
555 
556  EEO_NEXT();
557  }
558 
560  {
561  int attnum = op->d.var.attnum;
562 
563  /*
564  * Since we already extracted all referenced columns from the
565  * tuple with a FETCHSOME step, we can just grab the value
566  * directly out of the slot's decomposed-data arrays. But let's
567  * have an Assert to check that that did happen.
568  */
569  Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
570  *op->resvalue = innerslot->tts_values[attnum];
571  *op->resnull = innerslot->tts_isnull[attnum];
572 
573  EEO_NEXT();
574  }
575 
577  {
578  int attnum = op->d.var.attnum;
579 
580  /* See EEOP_INNER_VAR comments */
581 
582  Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
583  *op->resvalue = outerslot->tts_values[attnum];
584  *op->resnull = outerslot->tts_isnull[attnum];
585 
586  EEO_NEXT();
587  }
588 
590  {
591  int attnum = op->d.var.attnum;
592 
593  /* See EEOP_INNER_VAR comments */
594 
595  Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
596  *op->resvalue = scanslot->tts_values[attnum];
597  *op->resnull = scanslot->tts_isnull[attnum];
598 
599  EEO_NEXT();
600  }
601 
603  {
604  ExecEvalSysVar(state, op, econtext, innerslot);
605  EEO_NEXT();
606  }
607 
609  {
610  ExecEvalSysVar(state, op, econtext, outerslot);
611  EEO_NEXT();
612  }
613 
615  {
616  ExecEvalSysVar(state, op, econtext, scanslot);
617  EEO_NEXT();
618  }
619 
621  {
622  /* too complex for an inline implementation */
623  ExecEvalWholeRowVar(state, op, econtext);
624 
625  EEO_NEXT();
626  }
627 
629  {
630  int resultnum = op->d.assign_var.resultnum;
631  int attnum = op->d.assign_var.attnum;
632 
633  /*
634  * We do not need CheckVarSlotCompatibility here; that was taken
635  * care of at compilation time. But see EEOP_INNER_VAR comments.
636  */
637  Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
638  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
639  resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
640  resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
641 
642  EEO_NEXT();
643  }
644 
646  {
647  int resultnum = op->d.assign_var.resultnum;
648  int attnum = op->d.assign_var.attnum;
649 
650  /*
651  * We do not need CheckVarSlotCompatibility here; that was taken
652  * care of at compilation time. But see EEOP_INNER_VAR comments.
653  */
654  Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
655  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
656  resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
657  resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
658 
659  EEO_NEXT();
660  }
661 
663  {
664  int resultnum = op->d.assign_var.resultnum;
665  int attnum = op->d.assign_var.attnum;
666 
667  /*
668  * We do not need CheckVarSlotCompatibility here; that was taken
669  * care of at compilation time. But see EEOP_INNER_VAR comments.
670  */
671  Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
672  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
673  resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
674  resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
675 
676  EEO_NEXT();
677  }
678 
680  {
681  int resultnum = op->d.assign_tmp.resultnum;
682 
683  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
684  resultslot->tts_values[resultnum] = state->resvalue;
685  resultslot->tts_isnull[resultnum] = state->resnull;
686 
687  EEO_NEXT();
688  }
689 
691  {
692  int resultnum = op->d.assign_tmp.resultnum;
693 
694  Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts);
695  resultslot->tts_isnull[resultnum] = state->resnull;
696  if (!resultslot->tts_isnull[resultnum])
697  resultslot->tts_values[resultnum] =
699  else
700  resultslot->tts_values[resultnum] = state->resvalue;
701 
702  EEO_NEXT();
703  }
704 
706  {
707  *op->resnull = op->d.constval.isnull;
708  *op->resvalue = op->d.constval.value;
709 
710  EEO_NEXT();
711  }
712 
713  /*
714  * Function-call implementations. Arguments have previously been
715  * evaluated directly into fcinfo->args.
716  *
717  * As both STRICT checks and function-usage are noticeable performance
718  * wise, and function calls are a very hot-path (they also back
719  * operators!), it's worth having so many separate opcodes.
720  *
721  * Note: the reason for using a temporary variable "d", here and in
722  * other places, is that some compilers think "*op->resvalue = f();"
723  * requires them to evaluate op->resvalue into a register before
724  * calling f(), just in case f() is able to modify op->resvalue
725  * somehow. The extra line of code can save a useless register spill
726  * and reload across the function call.
727  */
729  {
730  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
731  Datum d;
732 
733  fcinfo->isnull = false;
734  d = op->d.func.fn_addr(fcinfo);
735  *op->resvalue = d;
736  *op->resnull = fcinfo->isnull;
737 
738  EEO_NEXT();
739  }
740 
742  {
743  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
744  NullableDatum *args = fcinfo->args;
745  int nargs = op->d.func.nargs;
746  Datum d;
747 
748  /* strict function, so check for NULL args */
749  for (int argno = 0; argno < nargs; argno++)
750  {
751  if (args[argno].isnull)
752  {
753  *op->resnull = true;
754  goto strictfail;
755  }
756  }
757  fcinfo->isnull = false;
758  d = op->d.func.fn_addr(fcinfo);
759  *op->resvalue = d;
760  *op->resnull = fcinfo->isnull;
761 
762  strictfail:
763  EEO_NEXT();
764  }
765 
767  {
768  /* not common enough to inline */
769  ExecEvalFuncExprFusage(state, op, econtext);
770 
771  EEO_NEXT();
772  }
773 
775  {
776  /* not common enough to inline */
777  ExecEvalFuncExprStrictFusage(state, op, econtext);
778 
779  EEO_NEXT();
780  }
781 
782  /*
783  * If any of its clauses is FALSE, an AND's result is FALSE regardless
784  * of the states of the rest of the clauses, so we can stop evaluating
785  * and return FALSE immediately. If none are FALSE and one or more is
786  * NULL, we return NULL; otherwise we return TRUE. This makes sense
787  * when you interpret NULL as "don't know": perhaps one of the "don't
788  * knows" would have been FALSE if we'd known its value. Only when
789  * all the inputs are known to be TRUE can we state confidently that
790  * the AND's result is TRUE.
791  */
793  {
794  *op->d.boolexpr.anynull = false;
795 
796  /*
797  * EEOP_BOOL_AND_STEP_FIRST resets anynull, otherwise it's the
798  * same as EEOP_BOOL_AND_STEP - so fall through to that.
799  */
800 
801  /* FALL THROUGH */
802  }
803 
805  {
806  if (*op->resnull)
807  {
808  *op->d.boolexpr.anynull = true;
809  }
810  else if (!DatumGetBool(*op->resvalue))
811  {
812  /* result is already set to FALSE, need not change it */
813  /* bail out early */
814  EEO_JUMP(op->d.boolexpr.jumpdone);
815  }
816 
817  EEO_NEXT();
818  }
819 
821  {
822  if (*op->resnull)
823  {
824  /* result is already set to NULL, need not change it */
825  }
826  else if (!DatumGetBool(*op->resvalue))
827  {
828  /* result is already set to FALSE, need not change it */
829 
830  /*
831  * No point jumping early to jumpdone - would be same target
832  * (as this is the last argument to the AND expression),
833  * except more expensive.
834  */
835  }
836  else if (*op->d.boolexpr.anynull)
837  {
838  *op->resvalue = (Datum) 0;
839  *op->resnull = true;
840  }
841  else
842  {
843  /* result is already set to TRUE, need not change it */
844  }
845 
846  EEO_NEXT();
847  }
848 
849  /*
850  * If any of its clauses is TRUE, an OR's result is TRUE regardless of
851  * the states of the rest of the clauses, so we can stop evaluating
852  * and return TRUE immediately. If none are TRUE and one or more is
853  * NULL, we return NULL; otherwise we return FALSE. This makes sense
854  * when you interpret NULL as "don't know": perhaps one of the "don't
855  * knows" would have been TRUE if we'd known its value. Only when all
856  * the inputs are known to be FALSE can we state confidently that the
857  * OR's result is FALSE.
858  */
860  {
861  *op->d.boolexpr.anynull = false;
862 
863  /*
864  * EEOP_BOOL_OR_STEP_FIRST resets anynull, otherwise it's the same
865  * as EEOP_BOOL_OR_STEP - so fall through to that.
866  */
867 
868  /* FALL THROUGH */
869  }
870 
872  {
873  if (*op->resnull)
874  {
875  *op->d.boolexpr.anynull = true;
876  }
877  else if (DatumGetBool(*op->resvalue))
878  {
879  /* result is already set to TRUE, need not change it */
880  /* bail out early */
881  EEO_JUMP(op->d.boolexpr.jumpdone);
882  }
883 
884  EEO_NEXT();
885  }
886 
888  {
889  if (*op->resnull)
890  {
891  /* result is already set to NULL, need not change it */
892  }
893  else if (DatumGetBool(*op->resvalue))
894  {
895  /* result is already set to TRUE, need not change it */
896 
897  /*
898  * No point jumping to jumpdone - would be same target (as
899  * this is the last argument to the AND expression), except
900  * more expensive.
901  */
902  }
903  else if (*op->d.boolexpr.anynull)
904  {
905  *op->resvalue = (Datum) 0;
906  *op->resnull = true;
907  }
908  else
909  {
910  /* result is already set to FALSE, need not change it */
911  }
912 
913  EEO_NEXT();
914  }
915 
917  {
918  /*
919  * Evaluation of 'not' is simple... if expr is false, then return
920  * 'true' and vice versa. It's safe to do this even on a
921  * nominally null value, so we ignore resnull; that means that
922  * NULL in produces NULL out, which is what we want.
923  */
925 
926  EEO_NEXT();
927  }
928 
930  {
931  /* simplified version of BOOL_AND_STEP for use by ExecQual() */
932 
933  /* If argument (also result) is false or null ... */
934  if (*op->resnull ||
935  !DatumGetBool(*op->resvalue))
936  {
937  /* ... bail out early, returning FALSE */
938  *op->resnull = false;
939  *op->resvalue = BoolGetDatum(false);
940  EEO_JUMP(op->d.qualexpr.jumpdone);
941  }
942 
943  /*
944  * Otherwise, leave the TRUE value in place, in case this is the
945  * last qual. Then, TRUE is the correct answer.
946  */
947 
948  EEO_NEXT();
949  }
950 
952  {
953  /* Unconditionally jump to target step */
954  EEO_JUMP(op->d.jump.jumpdone);
955  }
956 
958  {
959  /* Transfer control if current result is null */
960  if (*op->resnull)
961  EEO_JUMP(op->d.jump.jumpdone);
962 
963  EEO_NEXT();
964  }
965 
967  {
968  /* Transfer control if current result is non-null */
969  if (!*op->resnull)
970  EEO_JUMP(op->d.jump.jumpdone);
971 
972  EEO_NEXT();
973  }
974 
976  {
977  /* Transfer control if current result is null or false */
978  if (*op->resnull || !DatumGetBool(*op->resvalue))
979  EEO_JUMP(op->d.jump.jumpdone);
980 
981  EEO_NEXT();
982  }
983 
985  {
986  *op->resvalue = BoolGetDatum(*op->resnull);
987  *op->resnull = false;
988 
989  EEO_NEXT();
990  }
991 
993  {
994  *op->resvalue = BoolGetDatum(!*op->resnull);
995  *op->resnull = false;
996 
997  EEO_NEXT();
998  }
999 
1001  {
1002  /* out of line implementation: too large */
1003  ExecEvalRowNull(state, op, econtext);
1004 
1005  EEO_NEXT();
1006  }
1007 
1009  {
1010  /* out of line implementation: too large */
1011  ExecEvalRowNotNull(state, op, econtext);
1012 
1013  EEO_NEXT();
1014  }
1015 
1016  /* BooleanTest implementations for all booltesttypes */
1017 
1019  {
1020  if (*op->resnull)
1021  {
1022  *op->resvalue = BoolGetDatum(false);
1023  *op->resnull = false;
1024  }
1025  /* else, input value is the correct output as well */
1026 
1027  EEO_NEXT();
1028  }
1029 
1031  {
1032  if (*op->resnull)
1033  {
1034  *op->resvalue = BoolGetDatum(true);
1035  *op->resnull = false;
1036  }
1037  else
1038  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
1039 
1040  EEO_NEXT();
1041  }
1042 
1044  {
1045  if (*op->resnull)
1046  {
1047  *op->resvalue = BoolGetDatum(false);
1048  *op->resnull = false;
1049  }
1050  else
1051  *op->resvalue = BoolGetDatum(!DatumGetBool(*op->resvalue));
1052 
1053  EEO_NEXT();
1054  }
1055 
1057  {
1058  if (*op->resnull)
1059  {
1060  *op->resvalue = BoolGetDatum(true);
1061  *op->resnull = false;
1062  }
1063  /* else, input value is the correct output as well */
1064 
1065  EEO_NEXT();
1066  }
1067 
1069  {
1070  /* out of line implementation: too large */
1071  ExecEvalParamExec(state, op, econtext);
1072 
1073  EEO_NEXT();
1074  }
1075 
1077  {
1078  /* out of line implementation: too large */
1079  ExecEvalParamExtern(state, op, econtext);
1080  EEO_NEXT();
1081  }
1082 
1084  {
1085  /* allow an extension module to supply a PARAM_EXTERN value */
1086  op->d.cparam.paramfunc(state, op, econtext);
1087  EEO_NEXT();
1088  }
1089 
1091  {
1092  /*
1093  * Normally upper parts of the expression tree have setup the
1094  * values to be returned here, but some parts of the system
1095  * currently misuse {caseValue,domainValue}_{datum,isNull} to set
1096  * run-time data. So if no values have been set-up, use
1097  * ExprContext's. This isn't pretty, but also not *that* ugly,
1098  * and this is unlikely to be performance sensitive enough to
1099  * worry about an extra branch.
1100  */
1101  if (op->d.casetest.value)
1102  {
1103  *op->resvalue = *op->d.casetest.value;
1104  *op->resnull = *op->d.casetest.isnull;
1105  }
1106  else
1107  {
1108  *op->resvalue = econtext->caseValue_datum;
1109  *op->resnull = econtext->caseValue_isNull;
1110  }
1111 
1112  EEO_NEXT();
1113  }
1114 
1116  {
1117  /*
1118  * See EEOP_CASE_TESTVAL comment.
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->domainValue_datum;
1128  *op->resnull = econtext->domainValue_isNull;
1129  }
1130 
1131  EEO_NEXT();
1132  }
1133 
1135  {
1136  /*
1137  * Force a varlena value that might be read multiple times to R/O
1138  */
1139  if (!*op->d.make_readonly.isnull)
1140  *op->resvalue =
1142  *op->resnull = *op->d.make_readonly.isnull;
1143 
1144  EEO_NEXT();
1145  }
1146 
1148  {
1149  /*
1150  * Evaluate a CoerceViaIO node. This can be quite a hot path, so
1151  * inline as much work as possible. The source value is in our
1152  * result variable.
1153  */
1154  char *str;
1155 
1156  /* call output function (similar to OutputFunctionCall) */
1157  if (*op->resnull)
1158  {
1159  /* output functions are not called on nulls */
1160  str = NULL;
1161  }
1162  else
1163  {
1164  FunctionCallInfo fcinfo_out;
1165 
1166  fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1167  fcinfo_out->args[0].value = *op->resvalue;
1168  fcinfo_out->args[0].isnull = false;
1169 
1170  fcinfo_out->isnull = false;
1171  str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
1172 
1173  /* OutputFunctionCall assumes result isn't null */
1174  Assert(!fcinfo_out->isnull);
1175  }
1176 
1177  /* call input function (similar to InputFunctionCall) */
1178  if (!op->d.iocoerce.finfo_in->fn_strict || str != NULL)
1179  {
1180  FunctionCallInfo fcinfo_in;
1181  Datum d;
1182 
1183  fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1184  fcinfo_in->args[0].value = PointerGetDatum(str);
1185  fcinfo_in->args[0].isnull = *op->resnull;
1186  /* second and third arguments are already set up */
1187 
1188  fcinfo_in->isnull = false;
1189  d = FunctionCallInvoke(fcinfo_in);
1190  *op->resvalue = d;
1191 
1192  /* Should get null result if and only if str is NULL */
1193  if (str == NULL)
1194  {
1195  Assert(*op->resnull);
1196  Assert(fcinfo_in->isnull);
1197  }
1198  else
1199  {
1200  Assert(!*op->resnull);
1201  Assert(!fcinfo_in->isnull);
1202  }
1203  }
1204 
1205  EEO_NEXT();
1206  }
1207 
1209  {
1210  /*
1211  * IS DISTINCT FROM must evaluate arguments (already done into
1212  * fcinfo->args) to determine whether they are NULL; if either is
1213  * NULL then the result is determined. If neither is NULL, then
1214  * proceed to evaluate the comparison function, which is just the
1215  * type's standard equality operator. We need not care whether
1216  * that function is strict. Because the handling of nulls is
1217  * different, we can't just reuse EEOP_FUNCEXPR.
1218  */
1219  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1220 
1221  /* check function arguments for NULLness */
1222  if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
1223  {
1224  /* Both NULL? Then is not distinct... */
1225  *op->resvalue = BoolGetDatum(false);
1226  *op->resnull = false;
1227  }
1228  else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
1229  {
1230  /* Only one is NULL? Then is distinct... */
1231  *op->resvalue = BoolGetDatum(true);
1232  *op->resnull = false;
1233  }
1234  else
1235  {
1236  /* Neither null, so apply the equality function */
1237  Datum eqresult;
1238 
1239  fcinfo->isnull = false;
1240  eqresult = op->d.func.fn_addr(fcinfo);
1241  /* Must invert result of "="; safe to do even if null */
1242  *op->resvalue = BoolGetDatum(!DatumGetBool(eqresult));
1243  *op->resnull = fcinfo->isnull;
1244  }
1245 
1246  EEO_NEXT();
1247  }
1248 
1249  /* see EEOP_DISTINCT for comments, this is just inverted */
1251  {
1252  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1253 
1254  if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
1255  {
1256  *op->resvalue = BoolGetDatum(true);
1257  *op->resnull = false;
1258  }
1259  else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
1260  {
1261  *op->resvalue = BoolGetDatum(false);
1262  *op->resnull = false;
1263  }
1264  else
1265  {
1266  Datum eqresult;
1267 
1268  fcinfo->isnull = false;
1269  eqresult = op->d.func.fn_addr(fcinfo);
1270  *op->resvalue = eqresult;
1271  *op->resnull = fcinfo->isnull;
1272  }
1273 
1274  EEO_NEXT();
1275  }
1276 
1278  {
1279  /*
1280  * The arguments are already evaluated into fcinfo->args.
1281  */
1282  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1283 
1284  /* if either argument is NULL they can't be equal */
1285  if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
1286  {
1287  Datum result;
1288 
1289  fcinfo->isnull = false;
1290  result = op->d.func.fn_addr(fcinfo);
1291 
1292  /* if the arguments are equal return null */
1293  if (!fcinfo->isnull && DatumGetBool(result))
1294  {
1295  *op->resvalue = (Datum) 0;
1296  *op->resnull = true;
1297 
1298  EEO_NEXT();
1299  }
1300  }
1301 
1302  /* Arguments aren't equal, so return the first one */
1303  *op->resvalue = fcinfo->args[0].value;
1304  *op->resnull = fcinfo->args[0].isnull;
1305 
1306  EEO_NEXT();
1307  }
1308 
1310  {
1311  /*
1312  * Doesn't seem worthwhile to have an inline implementation
1313  * efficiency-wise.
1314  */
1316 
1317  EEO_NEXT();
1318  }
1319 
1321  {
1322  /* error invocation uses space, and shouldn't ever occur */
1324 
1325  EEO_NEXT();
1326  }
1327 
1329  {
1330  /*
1331  * Doesn't seem worthwhile to have an inline implementation
1332  * efficiency-wise.
1333  */
1335 
1336  EEO_NEXT();
1337  }
1338 
1340  {
1341  /* too complex for an inline implementation */
1342  ExecEvalArrayExpr(state, op);
1343 
1344  EEO_NEXT();
1345  }
1346 
1348  {
1349  /* too complex for an inline implementation */
1350  ExecEvalArrayCoerce(state, op, econtext);
1351 
1352  EEO_NEXT();
1353  }
1354 
1356  {
1357  /* too complex for an inline implementation */
1358  ExecEvalRow(state, op);
1359 
1360  EEO_NEXT();
1361  }
1362 
1364  {
1365  FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1366  Datum d;
1367 
1368  /* force NULL result if strict fn and NULL input */
1369  if (op->d.rowcompare_step.finfo->fn_strict &&
1370  (fcinfo->args[0].isnull || fcinfo->args[1].isnull))
1371  {
1372  *op->resnull = true;
1373  EEO_JUMP(op->d.rowcompare_step.jumpnull);
1374  }
1375 
1376  /* Apply comparison function */
1377  fcinfo->isnull = false;
1378  d = op->d.rowcompare_step.fn_addr(fcinfo);
1379  *op->resvalue = d;
1380 
1381  /* force NULL result if NULL function result */
1382  if (fcinfo->isnull)
1383  {
1384  *op->resnull = true;
1385  EEO_JUMP(op->d.rowcompare_step.jumpnull);
1386  }
1387  *op->resnull = false;
1388 
1389  /* If unequal, no need to compare remaining columns */
1390  if (DatumGetInt32(*op->resvalue) != 0)
1391  {
1392  EEO_JUMP(op->d.rowcompare_step.jumpdone);
1393  }
1394 
1395  EEO_NEXT();
1396  }
1397 
1399  {
1400  int32 cmpresult = DatumGetInt32(*op->resvalue);
1401  RowCompareType rctype = op->d.rowcompare_final.rctype;
1402 
1403  *op->resnull = false;
1404  switch (rctype)
1405  {
1406  /* EQ and NE cases aren't allowed here */
1407  case ROWCOMPARE_LT:
1408  *op->resvalue = BoolGetDatum(cmpresult < 0);
1409  break;
1410  case ROWCOMPARE_LE:
1411  *op->resvalue = BoolGetDatum(cmpresult <= 0);
1412  break;
1413  case ROWCOMPARE_GE:
1414  *op->resvalue = BoolGetDatum(cmpresult >= 0);
1415  break;
1416  case ROWCOMPARE_GT:
1417  *op->resvalue = BoolGetDatum(cmpresult > 0);
1418  break;
1419  default:
1420  Assert(false);
1421  break;
1422  }
1423 
1424  EEO_NEXT();
1425  }
1426 
1428  {
1429  /* too complex for an inline implementation */
1430  ExecEvalMinMax(state, op);
1431 
1432  EEO_NEXT();
1433  }
1434 
1436  {
1437  /* too complex for an inline implementation */
1438  ExecEvalFieldSelect(state, op, econtext);
1439 
1440  EEO_NEXT();
1441  }
1442 
1444  {
1445  /* too complex for an inline implementation */
1446  ExecEvalFieldStoreDeForm(state, op, econtext);
1447 
1448  EEO_NEXT();
1449  }
1450 
1452  {
1453  /* too complex for an inline implementation */
1454  ExecEvalFieldStoreForm(state, op, econtext);
1455 
1456  EEO_NEXT();
1457  }
1458 
1460  {
1461  /* Precheck SubscriptingRef subscript(s) */
1462  if (op->d.sbsref_subscript.subscriptfunc(state, op, econtext))
1463  {
1464  EEO_NEXT();
1465  }
1466  else
1467  {
1468  /* Subscript is null, short-circuit SubscriptingRef to NULL */
1469  EEO_JUMP(op->d.sbsref_subscript.jumpdone);
1470  }
1471  }
1472 
1476  {
1477  /* Perform a SubscriptingRef fetch or assignment */
1478  op->d.sbsref.subscriptfunc(state, op, econtext);
1479 
1480  EEO_NEXT();
1481  }
1482 
1484  {
1485  /* too complex for an inline implementation */
1486  ExecEvalConvertRowtype(state, op, econtext);
1487 
1488  EEO_NEXT();
1489  }
1490 
1492  {
1493  /* too complex for an inline implementation */
1495 
1496  EEO_NEXT();
1497  }
1498 
1500  {
1501  /* too complex for an inline implementation */
1502  ExecEvalHashedScalarArrayOp(state, op, econtext);
1503 
1504  EEO_NEXT();
1505  }
1506 
1508  {
1509  /* too complex for an inline implementation */
1511 
1512  EEO_NEXT();
1513  }
1514 
1516  {
1517  /* too complex for an inline implementation */
1519 
1520  EEO_NEXT();
1521  }
1522 
1524  {
1525  /* too complex for an inline implementation */
1526  ExecEvalXmlExpr(state, op);
1527 
1528  EEO_NEXT();
1529  }
1530 
1532  {
1533  /* too complex for an inline implementation */
1534  ExecEvalJsonConstructor(state, op, econtext);
1535  EEO_NEXT();
1536  }
1537 
1539  {
1540  /* too complex for an inline implementation */
1542 
1543  EEO_NEXT();
1544  }
1545 
1547  {
1548  /*
1549  * Returns a Datum whose value is the precomputed aggregate value
1550  * found in the given expression context.
1551  */
1552  int aggno = op->d.aggref.aggno;
1553 
1554  Assert(econtext->ecxt_aggvalues != NULL);
1555 
1556  *op->resvalue = econtext->ecxt_aggvalues[aggno];
1557  *op->resnull = econtext->ecxt_aggnulls[aggno];
1558 
1559  EEO_NEXT();
1560  }
1561 
1563  {
1564  /* too complex/uncommon for an inline implementation */
1566 
1567  EEO_NEXT();
1568  }
1569 
1571  {
1572  /*
1573  * Like Aggref, just return a precomputed value from the econtext.
1574  */
1575  WindowFuncExprState *wfunc = op->d.window_func.wfstate;
1576 
1577  Assert(econtext->ecxt_aggvalues != NULL);
1578 
1579  *op->resvalue = econtext->ecxt_aggvalues[wfunc->wfuncno];
1580  *op->resnull = econtext->ecxt_aggnulls[wfunc->wfuncno];
1581 
1582  EEO_NEXT();
1583  }
1584 
1586  {
1587  /* too complex for an inline implementation */
1588  ExecEvalSubPlan(state, op, econtext);
1589 
1590  EEO_NEXT();
1591  }
1592 
1593  /* evaluate a strict aggregate deserialization function */
1595  {
1596  /* Don't call a strict deserialization function with NULL input */
1597  if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
1598  EEO_JUMP(op->d.agg_deserialize.jumpnull);
1599 
1600  /* fallthrough */
1601  }
1602 
1603  /* evaluate aggregate deserialization function (non-strict portion) */
1605  {
1606  FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
1607  AggState *aggstate = castNode(AggState, state->parent);
1608  MemoryContext oldContext;
1609 
1610  /*
1611  * We run the deserialization functions in per-input-tuple memory
1612  * context.
1613  */
1614  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
1615  fcinfo->isnull = false;
1616  *op->resvalue = FunctionCallInvoke(fcinfo);
1617  *op->resnull = fcinfo->isnull;
1618  MemoryContextSwitchTo(oldContext);
1619 
1620  EEO_NEXT();
1621  }
1622 
1623  /*
1624  * Check that a strict aggregate transition / combination function's
1625  * input is not NULL.
1626  */
1627 
1629  {
1631  int nargs = op->d.agg_strict_input_check.nargs;
1632 
1633  for (int argno = 0; argno < nargs; argno++)
1634  {
1635  if (args[argno].isnull)
1636  EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
1637  }
1638  EEO_NEXT();
1639  }
1640 
1642  {
1643  bool *nulls = op->d.agg_strict_input_check.nulls;
1644  int nargs = op->d.agg_strict_input_check.nargs;
1645 
1646  for (int argno = 0; argno < nargs; argno++)
1647  {
1648  if (nulls[argno])
1649  EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
1650  }
1651  EEO_NEXT();
1652  }
1653 
1654  /*
1655  * Check for a NULL pointer to the per-group states.
1656  */
1657 
1659  {
1660  AggState *aggstate = castNode(AggState, state->parent);
1661  AggStatePerGroup pergroup_allaggs =
1662  aggstate->all_pergroups[op->d.agg_plain_pergroup_nullcheck.setoff];
1663 
1664  if (pergroup_allaggs == NULL)
1665  EEO_JUMP(op->d.agg_plain_pergroup_nullcheck.jumpnull);
1666 
1667  EEO_NEXT();
1668  }
1669 
1670  /*
1671  * Different types of aggregate transition functions are implemented
1672  * as different types of steps, to avoid incurring unnecessary
1673  * overhead. There's a step type for each valid combination of having
1674  * a by value / by reference transition type, [not] needing to the
1675  * initialize the transition value for the first row in a group from
1676  * input, and [not] strict transition function.
1677  *
1678  * Could optimize further by splitting off by-reference for
1679  * fixed-length types, but currently that doesn't seem worth it.
1680  */
1681 
1683  {
1684  AggState *aggstate = castNode(AggState, state->parent);
1685  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1686  AggStatePerGroup pergroup =
1687  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1688 
1689  Assert(pertrans->transtypeByVal);
1690 
1691  if (pergroup->noTransValue)
1692  {
1693  /* If transValue has not yet been initialized, do so now. */
1694  ExecAggInitGroup(aggstate, pertrans, pergroup,
1695  op->d.agg_trans.aggcontext);
1696  /* copied trans value from input, done this round */
1697  }
1698  else if (likely(!pergroup->transValueIsNull))
1699  {
1700  /* invoke transition function, unless prevented by strictness */
1701  ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1702  op->d.agg_trans.aggcontext,
1703  op->d.agg_trans.setno);
1704  }
1705 
1706  EEO_NEXT();
1707  }
1708 
1709  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1711  {
1712  AggState *aggstate = castNode(AggState, state->parent);
1713  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1714  AggStatePerGroup pergroup =
1715  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1716 
1717  Assert(pertrans->transtypeByVal);
1718 
1719  if (likely(!pergroup->transValueIsNull))
1720  ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1721  op->d.agg_trans.aggcontext,
1722  op->d.agg_trans.setno);
1723 
1724  EEO_NEXT();
1725  }
1726 
1727  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1729  {
1730  AggState *aggstate = castNode(AggState, state->parent);
1731  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1732  AggStatePerGroup pergroup =
1733  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1734 
1735  Assert(pertrans->transtypeByVal);
1736 
1737  ExecAggPlainTransByVal(aggstate, pertrans, pergroup,
1738  op->d.agg_trans.aggcontext,
1739  op->d.agg_trans.setno);
1740 
1741  EEO_NEXT();
1742  }
1743 
1744  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1746  {
1747  AggState *aggstate = castNode(AggState, state->parent);
1748  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1749  AggStatePerGroup pergroup =
1750  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1751 
1752  Assert(!pertrans->transtypeByVal);
1753 
1754  if (pergroup->noTransValue)
1755  ExecAggInitGroup(aggstate, pertrans, pergroup,
1756  op->d.agg_trans.aggcontext);
1757  else if (likely(!pergroup->transValueIsNull))
1758  ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1759  op->d.agg_trans.aggcontext,
1760  op->d.agg_trans.setno);
1761 
1762  EEO_NEXT();
1763  }
1764 
1765  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1767  {
1768  AggState *aggstate = castNode(AggState, state->parent);
1769  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1770  AggStatePerGroup pergroup =
1771  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1772 
1773  Assert(!pertrans->transtypeByVal);
1774 
1775  if (likely(!pergroup->transValueIsNull))
1776  ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1777  op->d.agg_trans.aggcontext,
1778  op->d.agg_trans.setno);
1779  EEO_NEXT();
1780  }
1781 
1782  /* see comments above EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL */
1784  {
1785  AggState *aggstate = castNode(AggState, state->parent);
1786  AggStatePerTrans pertrans = op->d.agg_trans.pertrans;
1787  AggStatePerGroup pergroup =
1788  &aggstate->all_pergroups[op->d.agg_trans.setoff][op->d.agg_trans.transno];
1789 
1790  Assert(!pertrans->transtypeByVal);
1791 
1792  ExecAggPlainTransByRef(aggstate, pertrans, pergroup,
1793  op->d.agg_trans.aggcontext,
1794  op->d.agg_trans.setno);
1795 
1796  EEO_NEXT();
1797  }
1798 
1800  {
1801  AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
1802  AggState *aggstate = castNode(AggState, state->parent);
1803 
1804  if (ExecEvalPreOrderedDistinctSingle(aggstate, pertrans))
1805  EEO_NEXT();
1806  else
1807  EEO_JUMP(op->d.agg_presorted_distinctcheck.jumpdistinct);
1808  }
1809 
1811  {
1812  AggState *aggstate = castNode(AggState, state->parent);
1813  AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
1814 
1815  if (ExecEvalPreOrderedDistinctMulti(aggstate, pertrans))
1816  EEO_NEXT();
1817  else
1818  EEO_JUMP(op->d.agg_presorted_distinctcheck.jumpdistinct);
1819  }
1820 
1821  /* process single-column ordered aggregate datum */
1823  {
1824  /* too complex for an inline implementation */
1825  ExecEvalAggOrderedTransDatum(state, op, econtext);
1826 
1827  EEO_NEXT();
1828  }
1829 
1830  /* process multi-column ordered aggregate tuple */
1832  {
1833  /* too complex for an inline implementation */
1834  ExecEvalAggOrderedTransTuple(state, op, econtext);
1835 
1836  EEO_NEXT();
1837  }
1838 
1840  {
1841  /* unreachable */
1842  Assert(false);
1843  goto out;
1844  }
1845  }
1846 
1847 out:
1848  *isnull = state->resnull;
1849  return state->resvalue;
1850 }
#define lengthof(array)
Definition: c.h:777
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:925
void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op)
void ExecEvalRow(ExprState *state, ExprEvalStep *op)
void ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op)
void ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
#define EEO_SWITCH()
void ExecEvalRowNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
#define EEO_DISPATCH()
void ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
static pg_attribute_always_inline void ExecAggPlainTransByVal(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext, int setno)
void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
bool ExecEvalPreOrderedDistinctMulti(AggState *aggstate, AggStatePerTrans pertrans)
void ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op)
#define EEO_NEXT()
void ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
void ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext)
void ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op)
void ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext, TupleTableSlot *slot)
void ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
void ExecEvalSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op)
void ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
void ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
static void CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot)
void ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
#define EEO_CASE(name)
void ExecEvalFuncExprFusage(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
bool ExecEvalPreOrderedDistinctSingle(AggState *aggstate, AggStatePerTrans pertrans)
static pg_attribute_always_inline void ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup, ExprContext *aggcontext, int setno)
void ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
#define EEO_JUMP(stepno)
@ EEOP_ASSIGN_TMP
Definition: execExpr.h:98
@ EEOP_SUBPLAN
Definition: execExpr.h:244
@ EEOP_CONVERT_ROWTYPE
Definition: execExpr.h:235
@ EEOP_FUNCEXPR_STRICT_FUSAGE
Definition: