PostgreSQL Source Code  git master
jsonpath_exec.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "executor/execExpr.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "nodes/nodeFuncs.h"
#include "regex/regex.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/float.h"
#include "utils/formatting.h"
#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
Include dependency graph for jsonpath_exec.c:

Go to the source code of this file.

Data Structures

struct  JsonBaseObjectInfo
 
struct  JsonPathExecContext
 
struct  JsonLikeRegexContext
 
struct  JsonValueList
 
struct  JsonValueListIterator
 
struct  JsonTablePlanRowSource
 
struct  JsonTablePlanState
 
struct  JsonTableExecContext
 

Macros

#define jperIsError(jper)   ((jper) == jperError)
 
#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867
 
#define jspStrictAbsenceOfErrors(cxt)   (!(cxt)->laxMode)
 
#define jspAutoUnwrap(cxt)   ((cxt)->laxMode)
 
#define jspAutoWrap(cxt)   ((cxt)->laxMode)
 
#define jspIgnoreStructuralErrors(cxt)   ((cxt)->ignoreStructuralErrors)
 
#define jspThrowErrors(cxt)   ((cxt)->throwErrors)
 
#define RETURN_ERROR(throw_error)
 

Typedefs

typedef struct JsonBaseObjectInfo JsonBaseObjectInfo
 
typedef JsonbValue *(* JsonPathGetVarCallback) (void *vars, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
 
typedef int(* JsonPathCountVarsCallback) (void *vars)
 
typedef struct JsonPathExecContext JsonPathExecContext
 
typedef struct JsonLikeRegexContext JsonLikeRegexContext
 
typedef enum JsonPathBool JsonPathBool
 
typedef enum JsonPathExecResult JsonPathExecResult
 
typedef struct JsonValueList JsonValueList
 
typedef struct JsonValueListIterator JsonValueListIterator
 
typedef struct JsonTablePlanRowSource JsonTablePlanRowSource
 
typedef struct JsonTablePlanState JsonTablePlanState
 
typedef struct JsonTableExecContext JsonTableExecContext
 
typedef JsonPathBool(* JsonPathPredicateCallback) (JsonPathItem *jsp, JsonbValue *larg, JsonbValue *rarg, void *param)
 
typedef Numeric(* BinaryArithmFunc) (Numeric num1, Numeric num2, bool *error)
 

Enumerations

enum  JsonPathBool { jpbFalse = 0 , jpbTrue = 1 , jpbUnknown = 2 }
 
enum  JsonPathExecResult { jperOk = 0 , jperNotFound = 1 , jperError = 2 }
 

Functions

static JsonPathExecResult executeJsonPath (JsonPath *path, void *vars, JsonPathGetVarCallback getVar, JsonPathCountVarsCallback countVars, Jsonb *json, bool throwErrors, JsonValueList *result, bool useTz)
 
static JsonPathExecResult executeItem (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
 
static JsonPathExecResult executeItemOptUnwrapTarget (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
 
static JsonPathExecResult executeItemUnwrapTargetArray (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
 
static JsonPathExecResult executeNextItem (JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
 
static JsonPathExecResult executeItemOptUnwrapResult (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
 
static JsonPathExecResult executeItemOptUnwrapResultNoThrow (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
 
static JsonPathBool executeBoolItem (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool canHaveNext)
 
static JsonPathBool executeNestedBoolItem (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb)
 
static JsonPathExecResult executeAnyItem (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
 
static JsonPathBool executePredicate (JsonPathExecContext *cxt, JsonPathItem *pred, JsonPathItem *larg, JsonPathItem *rarg, JsonbValue *jb, bool unwrapRightArg, JsonPathPredicateCallback exec, void *param)
 
static JsonPathExecResult executeBinaryArithmExpr (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, BinaryArithmFunc func, JsonValueList *found)
 
static JsonPathExecResult executeUnaryArithmExpr (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, PGFunction func, JsonValueList *found)
 
static JsonPathBool executeStartsWith (JsonPathItem *jsp, JsonbValue *whole, JsonbValue *initial, void *param)
 
static JsonPathBool executeLikeRegex (JsonPathItem *jsp, JsonbValue *str, JsonbValue *rarg, void *param)
 
static JsonPathExecResult executeNumericItemMethod (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, PGFunction func, JsonValueList *found)
 
static JsonPathExecResult executeDateTimeMethod (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
 
static JsonPathExecResult executeKeyValueMethod (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
 
static JsonPathExecResult appendBoolResult (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonValueList *found, JsonPathBool res)
 
static void getJsonPathItem (JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *value)
 
static JsonbValueGetJsonPathVar (void *cxt, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
 
static int CountJsonPathVars (void *cxt)
 
static void JsonItemFromDatum (Datum val, Oid typid, int32 typmod, JsonbValue *res)
 
static void JsonbValueInitNumericDatum (JsonbValue *jbv, Datum num)
 
static void getJsonPathVariable (JsonPathExecContext *cxt, JsonPathItem *variable, JsonbValue *value)
 
static int countVariablesFromJsonb (void *varsJsonb)
 
static JsonbValuegetJsonPathVariableFromJsonb (void *varsJsonb, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
 
static int JsonbArraySize (JsonbValue *jb)
 
static JsonPathBool executeComparison (JsonPathItem *cmp, JsonbValue *lv, JsonbValue *rv, void *p)
 
static JsonPathBool compareItems (int32 op, JsonbValue *jb1, JsonbValue *jb2, bool useTz)
 
static int compareNumeric (Numeric a, Numeric b)
 
static JsonbValuecopyJsonbValue (JsonbValue *src)
 
static JsonPathExecResult getArrayIndex (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, int32 *index)
 
static JsonBaseObjectInfo setBaseObject (JsonPathExecContext *cxt, JsonbValue *jbv, int32 id)
 
static void JsonValueListClear (JsonValueList *jvl)
 
static void JsonValueListAppend (JsonValueList *jvl, JsonbValue *jbv)
 
static int JsonValueListLength (const JsonValueList *jvl)
 
static bool JsonValueListIsEmpty (JsonValueList *jvl)
 
static JsonbValueJsonValueListHead (JsonValueList *jvl)
 
static ListJsonValueListGetList (JsonValueList *jvl)
 
static void JsonValueListInitIterator (const JsonValueList *jvl, JsonValueListIterator *it)
 
static JsonbValueJsonValueListNext (const JsonValueList *jvl, JsonValueListIterator *it)
 
static int JsonbType (JsonbValue *jb)
 
static JsonbValueJsonbInitBinary (JsonbValue *jbv, Jsonb *jb)
 
static JsonbValuegetScalar (JsonbValue *scalar, enum jbvType type)
 
static JsonbValuewrapItemsInArray (const JsonValueList *items)
 
static int compareDatetime (Datum val1, Oid typid1, Datum val2, Oid typid2, bool useTz, bool *cast_error)
 
static void checkTimezoneIsUsedForCast (bool useTz, const char *type1, const char *type2)
 
static void JsonTableInitOpaque (TableFuncScanState *state, int natts)
 
static JsonTablePlanStateJsonTableInitPlan (JsonTableExecContext *cxt, JsonTablePlan *plan, JsonTablePlanState *parentstate, List *args, MemoryContext mcxt)
 
static void JsonTableSetDocument (TableFuncScanState *state, Datum value)
 
static void JsonTableResetRowPattern (JsonTablePlanState *plan, Datum item)
 
static bool JsonTableFetchRow (TableFuncScanState *state)
 
static Datum JsonTableGetValue (TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
 
static void JsonTableDestroyOpaque (TableFuncScanState *state)
 
static bool JsonTablePlanScanNextRow (JsonTablePlanState *planstate)
 
static void JsonTableResetNestedPlan (JsonTablePlanState *planstate)
 
static bool JsonTablePlanJoinNextRow (JsonTablePlanState *planstate)
 
static bool JsonTablePlanNextRow (JsonTablePlanState *planstate)
 
static Datum jsonb_path_exists_internal (FunctionCallInfo fcinfo, bool tz)
 
Datum jsonb_path_exists (PG_FUNCTION_ARGS)
 
Datum jsonb_path_exists_tz (PG_FUNCTION_ARGS)
 
Datum jsonb_path_exists_opr (PG_FUNCTION_ARGS)
 
static Datum jsonb_path_match_internal (FunctionCallInfo fcinfo, bool tz)
 
Datum jsonb_path_match (PG_FUNCTION_ARGS)
 
Datum jsonb_path_match_tz (PG_FUNCTION_ARGS)
 
Datum jsonb_path_match_opr (PG_FUNCTION_ARGS)
 
static Datum jsonb_path_query_internal (FunctionCallInfo fcinfo, bool tz)
 
Datum jsonb_path_query (PG_FUNCTION_ARGS)
 
Datum jsonb_path_query_tz (PG_FUNCTION_ARGS)
 
static Datum jsonb_path_query_array_internal (FunctionCallInfo fcinfo, bool tz)
 
Datum jsonb_path_query_array (PG_FUNCTION_ARGS)
 
Datum jsonb_path_query_array_tz (PG_FUNCTION_ARGS)
 
static Datum jsonb_path_query_first_internal (FunctionCallInfo fcinfo, bool tz)
 
Datum jsonb_path_query_first (PG_FUNCTION_ARGS)
 
Datum jsonb_path_query_first_tz (PG_FUNCTION_ARGS)
 
static int binaryCompareStrings (const char *s1, int len1, const char *s2, int len2)
 
static int compareStrings (const char *mbstr1, int mblen1, const char *mbstr2, int mblen2)
 
static Datum castTimeToTimeTz (Datum time, bool useTz)
 
static int cmpDateToTimestamp (DateADT date1, Timestamp ts2, bool useTz)
 
static int cmpDateToTimestampTz (DateADT date1, TimestampTz tstz2, bool useTz)
 
static int cmpTimestampToTimestampTz (Timestamp ts1, TimestampTz tstz2, bool useTz)
 
bool JsonPathExists (Datum jb, JsonPath *jp, bool *error, List *vars)
 
Datum JsonPathQuery (Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, bool *error, List *vars, const char *column_name)
 
JsonbValueJsonPathValue (Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars, const char *column_name)
 
static JsonTableExecContextGetJsonTableExecContext (TableFuncScanState *state, const char *fname)
 

Variables

const TableFuncRoutine JsonbTableRoutine
 

Macro Definition Documentation

◆ jperIsError

#define jperIsError (   jper)    ((jper) == jperError)

Definition at line 143 of file jsonpath_exec.c.

◆ JSON_TABLE_EXEC_CONTEXT_MAGIC

#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867

Definition at line 220 of file jsonpath_exec.c.

◆ jspAutoUnwrap

#define jspAutoUnwrap (   cxt)    ((cxt)->laxMode)

Definition at line 238 of file jsonpath_exec.c.

◆ jspAutoWrap

#define jspAutoWrap (   cxt)    ((cxt)->laxMode)

Definition at line 239 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

#define jspIgnoreStructuralErrors (   cxt)    ((cxt)->ignoreStructuralErrors)

Definition at line 240 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

#define jspStrictAbsenceOfErrors (   cxt)    (!(cxt)->laxMode)

Definition at line 237 of file jsonpath_exec.c.

◆ jspThrowErrors

#define jspThrowErrors (   cxt)    ((cxt)->throwErrors)

Definition at line 241 of file jsonpath_exec.c.

◆ RETURN_ERROR

#define RETURN_ERROR (   throw_error)
Value:
do { \
if (jspThrowErrors(cxt)) \
throw_error; \
else \
return jperError; \
} while (0)
@ jperError
#define jspThrowErrors(cxt)

Definition at line 244 of file jsonpath_exec.c.

Typedef Documentation

◆ BinaryArithmFunc

typedef Numeric(* BinaryArithmFunc) (Numeric num1, Numeric num2, bool *error)

Definition at line 256 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

typedef enum JsonPathBool JsonPathBool

◆ JsonPathCountVarsCallback

typedef int(* JsonPathCountVarsCallback) (void *vars)

Definition at line 92 of file jsonpath_exec.c.

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathGetVarCallback

typedef JsonbValue*(* JsonPathGetVarCallback) (void *vars, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)

Definition at line 90 of file jsonpath_exec.c.

◆ JsonPathPredicateCallback

typedef JsonPathBool(* JsonPathPredicateCallback) (JsonPathItem *jsp, JsonbValue *larg, JsonbValue *rarg, void *param)

Definition at line 252 of file jsonpath_exec.c.

◆ JsonTableExecContext

◆ JsonTablePlanRowSource

◆ JsonTablePlanState

◆ JsonValueList

typedef struct JsonValueList JsonValueList

◆ JsonValueListIterator

Enumeration Type Documentation

◆ JsonPathBool

Enumerator
jpbFalse 
jpbTrue 
jpbUnknown 

Definition at line 128 of file jsonpath_exec.c.

129 {
130  jpbFalse = 0,
131  jpbTrue = 1,
132  jpbUnknown = 2
133 } JsonPathBool;
JsonPathBool
@ jpbUnknown
@ jpbFalse
@ jpbTrue

◆ JsonPathExecResult

Enumerator
jperOk 
jperNotFound 
jperError 

Definition at line 136 of file jsonpath_exec.c.

137 {
138  jperOk = 0,
139  jperNotFound = 1,
140  jperError = 2
JsonPathExecResult
@ jperNotFound
@ jperOk

Function Documentation

◆ appendBoolResult()

static JsonPathExecResult appendBoolResult ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonValueList found,
JsonPathBool  res 
)
static

Definition at line 2921 of file jsonpath_exec.c.

2923 {
2925  JsonbValue jbv;
2926 
2927  if (!jspGetNext(jsp, &next) && !found)
2928  return jperOk; /* found singleton boolean value */
2929 
2930  if (res == jpbUnknown)
2931  {
2932  jbv.type = jbvNull;
2933  }
2934  else
2935  {
2936  jbv.type = jbvBool;
2937  jbv.val.boolean = res == jpbTrue;
2938  }
2939 
2940  return executeNextItem(cxt, jsp, &next, &jbv, found, true);
2941 }
static int32 next
Definition: blutils.c:221
@ jbvBool
Definition: jsonb.h:231
@ jbvNull
Definition: jsonb.h:228
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1092
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264

References executeNextItem(), jbvBool, jbvNull, jpbTrue, jpbUnknown, jperOk, jspGetNext(), next, res, JsonbValue::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ binaryCompareStrings()

static int binaryCompareStrings ( const char *  s1,
int  len1,
const char *  s2,
int  len2 
)
static

Definition at line 3243 of file jsonpath_exec.c.

3245 {
3246  int cmp;
3247 
3248  cmp = memcmp(s1, s2, Min(len1, len2));
3249 
3250  if (cmp != 0)
3251  return cmp;
3252 
3253  if (len1 == len2)
3254  return 0;
3255 
3256  return len1 < len2 ? -1 : 1;
3257 }
#define Min(x, y)
Definition: c.h:1004
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

References cmp(), Min, s1, and s2.

Referenced by compareStrings().

◆ castTimeToTimeTz()

static Datum castTimeToTimeTz ( Datum  time,
bool  useTz 
)
static

Definition at line 3668 of file jsonpath_exec.c.

3669 {
3670  checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3671 
3672  return DirectFunctionCall1(time_timetz, time);
3673 }
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2828
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
static void checkTimezoneIsUsedForCast(bool useTz, const char *type1, const char *type2)

References checkTimezoneIsUsedForCast(), DirectFunctionCall1, and time_timetz().

Referenced by compareDatetime().

◆ checkTimezoneIsUsedForCast()

static void checkTimezoneIsUsedForCast ( bool  useTz,
const char *  type1,
const char *  type2 
)
static

Definition at line 3656 of file jsonpath_exec.c.

3657 {
3658  if (!useTz)
3659  ereport(ERROR,
3660  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3661  errmsg("cannot convert value from %s to %s without time zone usage",
3662  type1, type2),
3663  errhint("Use *_tz() function for time zone support.")));
3664 }
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149

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

Referenced by castTimeToTimeTz(), cmpDateToTimestampTz(), cmpTimestampToTimestampTz(), and executeDateTimeMethod().

◆ cmpDateToTimestamp()

static int cmpDateToTimestamp ( DateADT  date1,
Timestamp  ts2,
bool  useTz 
)
static

Definition at line 3680 of file jsonpath_exec.c.

3681 {
3682  return date_cmp_timestamp_internal(date1, ts2);
3683 }
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:743

References date_cmp_timestamp_internal().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

static int cmpDateToTimestampTz ( DateADT  date1,
TimestampTz  tstz2,
bool  useTz 
)
static

Definition at line 3689 of file jsonpath_exec.c.

3690 {
3691  checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
3692 
3693  return date_cmp_timestamptz_internal(date1, tstz2);
3694 }
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:823

References checkTimezoneIsUsedForCast(), and date_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

static int cmpTimestampToTimestampTz ( Timestamp  ts1,
TimestampTz  tstz2,
bool  useTz 
)
static

Definition at line 3700 of file jsonpath_exec.c.

3701 {
3702  checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
3703 
3704  return timestamp_cmp_timestamptz_internal(ts1, tstz2);
3705 }
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2325

References checkTimezoneIsUsedForCast(), and timestamp_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ compareDatetime()

static int compareDatetime ( Datum  val1,
Oid  typid1,
Datum  val2,
Oid  typid2,
bool  useTz,
bool cast_error 
)
static

Definition at line 3713 of file jsonpath_exec.c.

3715 {
3716  PGFunction cmpfunc;
3717 
3718  *cast_error = false;
3719 
3720  switch (typid1)
3721  {
3722  case DATEOID:
3723  switch (typid2)
3724  {
3725  case DATEOID:
3726  cmpfunc = date_cmp;
3727 
3728  break;
3729 
3730  case TIMESTAMPOID:
3731  return cmpDateToTimestamp(DatumGetDateADT(val1),
3732  DatumGetTimestamp(val2),
3733  useTz);
3734 
3735  case TIMESTAMPTZOID:
3737  DatumGetTimestampTz(val2),
3738  useTz);
3739 
3740  case TIMEOID:
3741  case TIMETZOID:
3742  *cast_error = true; /* uncomparable types */
3743  return 0;
3744 
3745  default:
3746  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3747  typid2);
3748  }
3749  break;
3750 
3751  case TIMEOID:
3752  switch (typid2)
3753  {
3754  case TIMEOID:
3755  cmpfunc = time_cmp;
3756 
3757  break;
3758 
3759  case TIMETZOID:
3760  val1 = castTimeToTimeTz(val1, useTz);
3761  cmpfunc = timetz_cmp;
3762 
3763  break;
3764 
3765  case DATEOID:
3766  case TIMESTAMPOID:
3767  case TIMESTAMPTZOID:
3768  *cast_error = true; /* uncomparable types */
3769  return 0;
3770 
3771  default:
3772  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3773  typid2);
3774  }
3775  break;
3776 
3777  case TIMETZOID:
3778  switch (typid2)
3779  {
3780  case TIMEOID:
3781  val2 = castTimeToTimeTz(val2, useTz);
3782  cmpfunc = timetz_cmp;
3783 
3784  break;
3785 
3786  case TIMETZOID:
3787  cmpfunc = timetz_cmp;
3788 
3789  break;
3790 
3791  case DATEOID:
3792  case TIMESTAMPOID:
3793  case TIMESTAMPTZOID:
3794  *cast_error = true; /* uncomparable types */
3795  return 0;
3796 
3797  default:
3798  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3799  typid2);
3800  }
3801  break;
3802 
3803  case TIMESTAMPOID:
3804  switch (typid2)
3805  {
3806  case DATEOID:
3807  return -cmpDateToTimestamp(DatumGetDateADT(val2),
3808  DatumGetTimestamp(val1),
3809  useTz);
3810 
3811  case TIMESTAMPOID:
3812  cmpfunc = timestamp_cmp;
3813 
3814  break;
3815 
3816  case TIMESTAMPTZOID:
3818  DatumGetTimestampTz(val2),
3819  useTz);
3820 
3821  case TIMEOID:
3822  case TIMETZOID:
3823  *cast_error = true; /* uncomparable types */
3824  return 0;
3825 
3826  default:
3827  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3828  typid2);
3829  }
3830  break;
3831 
3832  case TIMESTAMPTZOID:
3833  switch (typid2)
3834  {
3835  case DATEOID:
3836  return -cmpDateToTimestampTz(DatumGetDateADT(val2),
3837  DatumGetTimestampTz(val1),
3838  useTz);
3839 
3840  case TIMESTAMPOID:
3842  DatumGetTimestampTz(val1),
3843  useTz);
3844 
3845  case TIMESTAMPTZOID:
3846  cmpfunc = timestamp_cmp;
3847 
3848  break;
3849 
3850  case TIMEOID:
3851  case TIMETZOID:
3852  *cast_error = true; /* uncomparable types */
3853  return 0;
3854 
3855  default:
3856  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3857  typid2);
3858  }
3859  break;
3860 
3861  default:
3862  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
3863  }
3864 
3865  if (*cast_error)
3866  return 0; /* cast error */
3867 
3868  return DatumGetInt32(DirectFunctionCall2(cmpfunc, val1, val2));
3869 }
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2270
Datum date_cmp(PG_FUNCTION_ARGS)
Definition: date.c:437
Datum time_cmp(PG_FUNCTION_ARGS)
Definition: date.c:1734
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition: date.c:2524
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
#define elog(elevel,...)
Definition: elog.h:224
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
Datum(* PGFunction)(FunctionCallInfo fcinfo)
Definition: fmgr.h:40
static int cmpDateToTimestamp(DateADT date1, Timestamp ts2, bool useTz)
static Datum castTimeToTimeTz(Datum time, bool useTz)
static int cmpDateToTimestampTz(DateADT date1, TimestampTz tstz2, bool useTz)
static int cmpTimestampToTimestampTz(Timestamp ts1, TimestampTz tstz2, bool useTz)
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
static TimestampTz DatumGetTimestampTz(Datum X)
Definition: timestamp.h:34

References castTimeToTimeTz(), cmpDateToTimestamp(), cmpDateToTimestampTz(), cmpTimestampToTimestampTz(), date_cmp(), DatumGetDateADT(), DatumGetInt32(), DatumGetTimestamp(), DatumGetTimestampTz(), DirectFunctionCall2, elog, ERROR, time_cmp(), timestamp_cmp(), and timetz_cmp().

Referenced by compareItems().

◆ compareItems()

static JsonPathBool compareItems ( int32  op,
JsonbValue jb1,
JsonbValue jb2,
bool  useTz 
)
static

Definition at line 3331 of file jsonpath_exec.c.

3332 {
3333  int cmp;
3334  bool res;
3335 
3336  if (jb1->type != jb2->type)
3337  {
3338  if (jb1->type == jbvNull || jb2->type == jbvNull)
3339 
3340  /*
3341  * Equality and order comparison of nulls to non-nulls returns
3342  * always false, but inequality comparison returns true.
3343  */
3344  return op == jpiNotEqual ? jpbTrue : jpbFalse;
3345 
3346  /* Non-null items of different types are not comparable. */
3347  return jpbUnknown;
3348  }
3349 
3350  switch (jb1->type)
3351  {
3352  case jbvNull:
3353  cmp = 0;
3354  break;
3355  case jbvBool:
3356  cmp = jb1->val.boolean == jb2->val.boolean ? 0 :
3357  jb1->val.boolean ? 1 : -1;
3358  break;
3359  case jbvNumeric:
3360  cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
3361  break;
3362  case jbvString:
3363  if (op == jpiEqual)
3364  return jb1->val.string.len != jb2->val.string.len ||
3365  memcmp(jb1->val.string.val,
3366  jb2->val.string.val,
3367  jb1->val.string.len) ? jpbFalse : jpbTrue;
3368 
3369  cmp = compareStrings(jb1->val.string.val, jb1->val.string.len,
3370  jb2->val.string.val, jb2->val.string.len);
3371  break;
3372  case jbvDatetime:
3373  {
3374  bool cast_error;
3375 
3376  cmp = compareDatetime(jb1->val.datetime.value,
3377  jb1->val.datetime.typid,
3378  jb2->val.datetime.value,
3379  jb2->val.datetime.typid,
3380  useTz,
3381  &cast_error);
3382 
3383  if (cast_error)
3384  return jpbUnknown;
3385  }
3386  break;
3387 
3388  case jbvBinary:
3389  case jbvArray:
3390  case jbvObject:
3391  return jpbUnknown; /* non-scalars are not comparable */
3392 
3393  default:
3394  elog(ERROR, "invalid jsonb value type %d", jb1->type);
3395  }
3396 
3397  switch (op)
3398  {
3399  case jpiEqual:
3400  res = (cmp == 0);
3401  break;
3402  case jpiNotEqual:
3403  res = (cmp != 0);
3404  break;
3405  case jpiLess:
3406  res = (cmp < 0);
3407  break;
3408  case jpiGreater:
3409  res = (cmp > 0);
3410  break;
3411  case jpiLessOrEqual:
3412  res = (cmp <= 0);
3413  break;
3414  case jpiGreaterOrEqual:
3415  res = (cmp >= 0);
3416  break;
3417  default:
3418  elog(ERROR, "unrecognized jsonpath operation: %d", op);
3419  return jpbUnknown;
3420  }
3421 
3422  return res ? jpbTrue : jpbFalse;
3423 }
@ jbvObject
Definition: jsonb.h:234
@ jbvNumeric
Definition: jsonb.h:230
@ jbvArray
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:236
@ jbvDatetime
Definition: jsonb.h:244
@ jbvString
Definition: jsonb.h:229
@ jpiNotEqual
Definition: jsonpath.h:73
@ jpiGreaterOrEqual
Definition: jsonpath.h:77
@ jpiGreater
Definition: jsonpath.h:75
@ jpiLess
Definition: jsonpath.h:74
@ jpiEqual
Definition: jsonpath.h:72
@ jpiLessOrEqual
Definition: jsonpath.h:76
static int compareStrings(const char *mbstr1, int mblen1, const char *mbstr2, int mblen2)
static int compareDatetime(Datum val1, Oid typid1, Datum val2, Oid typid2, bool useTz, bool *cast_error)
static int compareNumeric(Numeric a, Numeric b)

References cmp(), compareDatetime(), compareNumeric(), compareStrings(), elog, ERROR, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jpbFalse, jpbTrue, jpbUnknown, jpiEqual, jpiGreater, jpiGreaterOrEqual, jpiLess, jpiLessOrEqual, jpiNotEqual, res, JsonbValue::type, and JsonbValue::val.

Referenced by executeComparison().

◆ compareNumeric()

static int compareNumeric ( Numeric  a,
Numeric  b 
)
static

Definition at line 3427 of file jsonpath_exec.c.

3428 {
3430  NumericGetDatum(a),
3431  NumericGetDatum(b)));
3432 }
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2399
int b
Definition: isn.c:70
int a
Definition: isn.c:69
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73

References a, b, DatumGetInt32(), DirectFunctionCall2, numeric_cmp(), and NumericGetDatum().

Referenced by compareItems().

◆ compareStrings()

static int compareStrings ( const char *  mbstr1,
int  mblen1,
const char *  mbstr2,
int  mblen2 
)
static

Definition at line 3264 of file jsonpath_exec.c.

3266 {
3267  if (GetDatabaseEncoding() == PG_SQL_ASCII ||
3269  {
3270  /*
3271  * It's known property of UTF-8 strings that their per-byte comparison
3272  * result matches codepoints comparison result. ASCII can be
3273  * considered as special case of UTF-8.
3274  */
3275  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
3276  }
3277  else
3278  {
3279  char *utf8str1,
3280  *utf8str2;
3281  int cmp,
3282  utf8len1,
3283  utf8len2;
3284 
3285  /*
3286  * We have to convert other encodings to UTF-8 first, then compare.
3287  * Input strings may be not null-terminated and pg_server_to_any() may
3288  * return them "as is". So, use strlen() only if there is real
3289  * conversion.
3290  */
3291  utf8str1 = pg_server_to_any(mbstr1, mblen1, PG_UTF8);
3292  utf8str2 = pg_server_to_any(mbstr2, mblen2, PG_UTF8);
3293  utf8len1 = (mbstr1 == utf8str1) ? mblen1 : strlen(utf8str1);
3294  utf8len2 = (mbstr2 == utf8str2) ? mblen2 : strlen(utf8str2);
3295 
3296  cmp = binaryCompareStrings(utf8str1, utf8len1, utf8str2, utf8len2);
3297 
3298  /*
3299  * If pg_server_to_any() did no real conversion, then we actually
3300  * compared original strings. So, we already done.
3301  */
3302  if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
3303  return cmp;
3304 
3305  /* Free memory if needed */
3306  if (mbstr1 != utf8str1)
3307  pfree(utf8str1);
3308  if (mbstr2 != utf8str2)
3309  pfree(utf8str2);
3310 
3311  /*
3312  * When all Unicode codepoints are equal, return result of binary
3313  * comparison. In some edge cases, same characters may have different
3314  * representations in encoding. Then our behavior could diverge from
3315  * standard. However, that allow us to do simple binary comparison
3316  * for "==" operator, which is performance critical in typical cases.
3317  * In future to implement strict standard conformance, we can do
3318  * normalization of input JSON strings.
3319  */
3320  if (cmp == 0)
3321  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
3322  else
3323  return cmp;
3324  }
3325 }
static int binaryCompareStrings(const char *s1, int len1, const char *s2, int len2)
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
void pfree(void *pointer)
Definition: mcxt.c:1520
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
@ PG_UTF8
Definition: pg_wchar.h:232

References binaryCompareStrings(), cmp(), GetDatabaseEncoding(), pfree(), pg_server_to_any(), PG_SQL_ASCII, and PG_UTF8.

Referenced by compareItems().

◆ copyJsonbValue()

static JsonbValue * copyJsonbValue ( JsonbValue src)
static

Definition at line 3435 of file jsonpath_exec.c.

3436 {
3437  JsonbValue *dst = palloc(sizeof(*dst));
3438 
3439  *dst = *src;
3440 
3441  return dst;
3442 }
void * palloc(Size size)
Definition: mcxt.c:1316

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void *  cxt)
static

Definition at line 3026 of file jsonpath_exec.c.

3027 {
3028  List *vars = (List *) cxt;
3029 
3030  return list_length(vars);
3031 }
static int list_length(const List *l)
Definition: pg_list.h:152
Definition: pg_list.h:54
Definition: regcomp.c:281

References list_length().

Referenced by JsonPathExists(), JsonPathQuery(), JsonPathValue(), and JsonTableResetRowPattern().

◆ countVariablesFromJsonb()

static int countVariablesFromJsonb ( void *  varsJsonb)
static

Definition at line 3193 of file jsonpath_exec.c.

3194 {
3195  Jsonb *vars = varsJsonb;
3196 
3197  if (vars && !JsonContainerIsObject(&vars->root))
3198  {
3199  ereport(ERROR,
3200  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3201  errmsg("\"vars\" argument is not an object"),
3202  errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3203  }
3204 
3205  /* count of base objects */
3206  return vars != NULL ? 1 : 0;
3207 }
int errdetail(const char *fmt,...)
Definition: elog.c:1205
#define JsonContainerIsObject(jc)
Definition: jsonb.h:208
Definition: jsonb.h:213

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

Referenced by jsonb_path_exists_internal(), jsonb_path_match_internal(), jsonb_path_query_array_internal(), jsonb_path_query_first_internal(), and jsonb_path_query_internal().

◆ executeAnyItem()

static JsonPathExecResult executeAnyItem ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbContainer jbc,
JsonValueList found,
uint32  level,
uint32  first,
uint32  last,
bool  ignoreStructuralErrors,
bool  unwrapNext 
)
static

Definition at line 1950 of file jsonpath_exec.c.

1953 {
1955  JsonbIterator *it;
1956  int32 r;
1957  JsonbValue v;
1958 
1960 
1961  if (level > last)
1962  return res;
1963 
1964  it = JsonbIteratorInit(jbc);
1965 
1966  /*
1967  * Recursively iterate over jsonb objects/arrays
1968  */
1969  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1970  {
1971  if (r == WJB_KEY)
1972  {
1973  r = JsonbIteratorNext(&it, &v, true);
1974  Assert(r == WJB_VALUE);
1975  }
1976 
1977  if (r == WJB_VALUE || r == WJB_ELEM)
1978  {
1979 
1980  if (level >= first ||
1981  (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
1982  v.type != jbvBinary)) /* leaves only requested */
1983  {
1984  /* check expression */
1985  if (jsp)
1986  {
1987  if (ignoreStructuralErrors)
1988  {
1989  bool savedIgnoreStructuralErrors;
1990 
1991  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1992  cxt->ignoreStructuralErrors = true;
1993  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1994  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1995  }
1996  else
1997  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1998 
1999  if (jperIsError(res))
2000  break;
2001 
2002  if (res == jperOk && !found)
2003  break;
2004  }
2005  else if (found)
2006  JsonValueListAppend(found, copyJsonbValue(&v));
2007  else
2008  return jperOk;
2009  }
2010 
2011  if (level < last && v.type == jbvBinary)
2012  {
2014  (cxt, jsp, v.val.binary.data, found,
2015  level + 1, first, last,
2016  ignoreStructuralErrors, unwrapNext);
2017 
2018  if (jperIsError(res))
2019  break;
2020 
2021  if (res == jperOk && found == NULL)
2022  break;
2023  }
2024  }
2025  }
2026 
2027  return res;
2028 }
#define PG_UINT32_MAX
Definition: c.h:590
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_ELEM
Definition: jsonb.h:25
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:817
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:853
static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
static void JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv)
#define jperIsError(jper)
static JsonbValue * copyJsonbValue(JsonbValue *src)
void check_stack_depth(void)
Definition: postgres.c:3531

References Assert, check_stack_depth(), copyJsonbValue(), executeItemOptUnwrapTarget(), JsonPathExecContext::ignoreStructuralErrors, jbvBinary, jperIsError, jperNotFound, jperOk, JsonbIteratorInit(), JsonbIteratorNext(), JsonValueListAppend(), PG_UINT32_MAX, res, JsonbValue::type, JsonbValue::val, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by executeItemOptUnwrapTarget(), and executeItemUnwrapTargetArray().

◆ executeBinaryArithmExpr()

static JsonPathExecResult executeBinaryArithmExpr ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
BinaryArithmFunc  func,
JsonValueList found 
)
static

Definition at line 2121 of file jsonpath_exec.c.

2124 {
2125  JsonPathExecResult jper;
2126  JsonPathItem elem;
2127  JsonValueList lseq = {0};
2128  JsonValueList rseq = {0};
2129  JsonbValue *lval;
2130  JsonbValue *rval;
2131  Numeric res;
2132 
2133  jspGetLeftArg(jsp, &elem);
2134 
2135  /*
2136  * XXX: By standard only operands of multiplicative expressions are
2137  * unwrapped. We extend it to other binary arithmetic expressions too.
2138  */
2139  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2140  if (jperIsError(jper))
2141  return jper;
2142 
2143  jspGetRightArg(jsp, &elem);
2144 
2145  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2146  if (jperIsError(jper))
2147  return jper;
2148 
2149  if (JsonValueListLength(&lseq) != 1 ||
2150  !(lval = getScalar(JsonValueListHead(&lseq), jbvNumeric)))
2152  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2153  errmsg("left operand of jsonpath operator %s is not a single numeric value",
2154  jspOperationName(jsp->type)))));
2155 
2156  if (JsonValueListLength(&rseq) != 1 ||
2157  !(rval = getScalar(JsonValueListHead(&rseq), jbvNumeric)))
2159  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2160  errmsg("right operand of jsonpath operator %s is not a single numeric value",
2161  jspOperationName(jsp->type)))));
2162 
2163  if (jspThrowErrors(cxt))
2164  {
2165  res = func(lval->val.numeric, rval->val.numeric, NULL);
2166  }
2167  else
2168  {
2169  bool error = false;
2170 
2171  res = func(lval->val.numeric, rval->val.numeric, &error);
2172 
2173  if (error)
2174  return jperError;
2175  }
2176 
2177  if (!jspGetNext(jsp, &elem) && !found)
2178  return jperOk;
2179 
2180  lval = palloc(sizeof(*lval));
2181  lval->type = jbvNumeric;
2182  lval->val.numeric = res;
2183 
2184  return executeNextItem(cxt, jsp, &elem, lval, found, false);
2185 }
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1159
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:836
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1181
#define RETURN_ERROR(throw_error)
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
static int JsonValueListLength(const JsonValueList *jvl)
static JsonPathExecResult executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonbValue * JsonValueListHead(JsonValueList *jvl)
static void error(void)
Definition: sql-dyntest.c:147
JsonPathItemType type
Definition: jsonpath.h:137

References ereport, errcode(), errmsg(), ERROR, error(), executeItemOptUnwrapResult(), executeNextItem(), getScalar(), jbvNumeric, jperError, jperIsError, jperOk, JsonValueListHead(), JsonValueListLength(), jspGetLeftArg(), jspGetNext(), jspGetRightArg(), jspOperationName(), jspThrowErrors, palloc(), res, RETURN_ERROR, JsonbValue::type, JsonPathItem::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ executeBoolItem()

static JsonPathBool executeBoolItem ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
bool  canHaveNext 
)
static

Definition at line 1793 of file jsonpath_exec.c.

1795 {
1796  JsonPathItem larg;
1797  JsonPathItem rarg;
1798  JsonPathBool res;
1799  JsonPathBool res2;
1800 
1801  /* since this function recurses, it could be driven to stack overflow */
1803 
1804  if (!canHaveNext && jspHasNext(jsp))
1805  elog(ERROR, "boolean jsonpath item cannot have next item");
1806 
1807  switch (jsp->type)
1808  {
1809  case jpiAnd:
1810  jspGetLeftArg(jsp, &larg);
1811  res = executeBoolItem(cxt, &larg, jb, false);
1812 
1813  if (res == jpbFalse)
1814  return jpbFalse;
1815 
1816  /*
1817  * SQL/JSON says that we should check second arg in case of
1818  * jperError
1819  */
1820 
1821  jspGetRightArg(jsp, &rarg);
1822  res2 = executeBoolItem(cxt, &rarg, jb, false);
1823 
1824  return res2 == jpbTrue ? res : res2;
1825 
1826  case jpiOr:
1827  jspGetLeftArg(jsp, &larg);
1828  res = executeBoolItem(cxt, &larg, jb, false);
1829 
1830  if (res == jpbTrue)
1831  return jpbTrue;
1832 
1833  jspGetRightArg(jsp, &rarg);
1834  res2 = executeBoolItem(cxt, &rarg, jb, false);
1835 
1836  return res2 == jpbFalse ? res : res2;
1837 
1838  case jpiNot:
1839  jspGetArg(jsp, &larg);
1840 
1841  res = executeBoolItem(cxt, &larg, jb, false);
1842 
1843  if (res == jpbUnknown)
1844  return jpbUnknown;
1845 
1846  return res == jpbTrue ? jpbFalse : jpbTrue;
1847 
1848  case jpiIsUnknown:
1849  jspGetArg(jsp, &larg);
1850  res = executeBoolItem(cxt, &larg, jb, false);
1851  return res == jpbUnknown ? jpbTrue : jpbFalse;
1852 
1853  case jpiEqual:
1854  case jpiNotEqual:
1855  case jpiLess:
1856  case jpiGreater:
1857  case jpiLessOrEqual:
1858  case jpiGreaterOrEqual:
1859  jspGetLeftArg(jsp, &larg);
1860  jspGetRightArg(jsp, &rarg);
1861  return executePredicate(cxt, jsp, &larg, &rarg, jb, true,
1862  executeComparison, cxt);
1863 
1864  case jpiStartsWith: /* 'whole STARTS WITH initial' */
1865  jspGetLeftArg(jsp, &larg); /* 'whole' */
1866  jspGetRightArg(jsp, &rarg); /* 'initial' */
1867  return executePredicate(cxt, jsp, &larg, &rarg, jb, false,
1868  executeStartsWith, NULL);
1869 
1870  case jpiLikeRegex: /* 'expr LIKE_REGEX pattern FLAGS flags' */
1871  {
1872  /*
1873  * 'expr' is a sequence-returning expression. 'pattern' is a
1874  * regex string literal. SQL/JSON standard requires XQuery
1875  * regexes, but we use Postgres regexes here. 'flags' is a
1876  * string literal converted to integer flags at compile-time.
1877  */
1878  JsonLikeRegexContext lrcxt = {0};
1879 
1880  jspInitByBuffer(&larg, jsp->base,
1881  jsp->content.like_regex.expr);
1882 
1883  return executePredicate(cxt, jsp, &larg, NULL, jb, false,
1884  executeLikeRegex, &lrcxt);
1885  }
1886 
1887  case jpiExists:
1888  jspGetArg(jsp, &larg);
1889 
1890  if (jspStrictAbsenceOfErrors(cxt))
1891  {
1892  /*
1893  * In strict mode we must get a complete list of values to
1894  * check that there are no errors at all.
1895  */
1896  JsonValueList vals = {0};
1898  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1899  false, &vals);
1900 
1901  if (jperIsError(res))
1902  return jpbUnknown;
1903 
1904  return JsonValueListIsEmpty(&vals) ? jpbFalse : jpbTrue;
1905  }
1906  else
1907  {
1909  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1910  false, NULL);
1911 
1912  if (jperIsError(res))
1913  return jpbUnknown;
1914 
1915  return res == jperOk ? jpbTrue : jpbFalse;
1916  }
1917 
1918  default:
1919  elog(ERROR, "invalid boolean jsonpath item type: %d", jsp->type);
1920  return jpbUnknown;
1921  }
1922 }
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1074
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition: jsonpath.c:983
#define jspHasNext(jsp)
Definition: jsonpath.h:194
@ jpiExists
Definition: jsonpath.h:94
@ jpiNot
Definition: jsonpath.h:70
@ jpiAnd
Definition: jsonpath.h:68
@ jpiStartsWith
Definition: jsonpath.h:105
@ jpiOr
Definition: jsonpath.h:69
@ jpiLikeRegex
Definition: jsonpath.h:106
@ jpiIsUnknown
Definition: jsonpath.h:71
static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv, JsonbValue *rv, void *p)
static JsonPathBool executeBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool canHaveNext)
static JsonPathExecResult executeItemOptUnwrapResultNoThrow(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonPathBool executeStartsWith(JsonPathItem *jsp, JsonbValue *whole, JsonbValue *initial, void *param)
#define jspStrictAbsenceOfErrors(cxt)
static JsonPathBool executeLikeRegex(JsonPathItem *jsp, JsonbValue *str, JsonbValue *rarg, void *param)
static bool JsonValueListIsEmpty(JsonValueList *jvl)
static JsonPathBool executePredicate(JsonPathExecContext *cxt, JsonPathItem *pred, JsonPathItem *larg, JsonPathItem *rarg, JsonbValue *jb, bool unwrapRightArg, JsonPathPredicateCallback exec, void *param)
union JsonPathItem::@137 content
char * base
Definition: jsonpath.h:146
struct JsonPathItem::@137::@142 like_regex

References JsonPathItem::base, check_stack_depth(), JsonPathItem::content, elog, ERROR, executeComparison(), executeItemOptUnwrapResultNoThrow(), executeLikeRegex(), executePredicate(), executeStartsWith(), jpbFalse, jpbTrue, jpbUnknown, jperIsError, jperOk, jpiAnd, jpiEqual, jpiExists, jpiGreater, jpiGreaterOrEqual, jpiIsUnknown, jpiLess, jpiLessOrEqual, jpiLikeRegex, jpiNot, jpiNotEqual, jpiOr, jpiStartsWith, JsonValueListIsEmpty(), jspGetArg(), jspGetLeftArg(), jspGetRightArg(), jspHasNext, jspInitByBuffer(), jspStrictAbsenceOfErrors, JsonPathItem::like_regex, res, and JsonPathItem::type.

Referenced by executeItemOptUnwrapTarget(), and executeNestedBoolItem().

◆ executeComparison()

static JsonPathBool executeComparison ( JsonPathItem cmp,
JsonbValue lv,
JsonbValue rv,
void *  p 
)
static

Definition at line 3232 of file jsonpath_exec.c.

3233 {
3235 
3236  return compareItems(cmp->type, lv, rv, cxt->useTz);
3237 }
static JsonPathBool compareItems(int32 op, JsonbValue *jb1, JsonbValue *jb2, bool useTz)

References cmp(), compareItems(), and JsonPathExecContext::useTz.

Referenced by executeBoolItem().

◆ executeDateTimeMethod()

static JsonPathExecResult executeDateTimeMethod ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
JsonValueList found 
)
static

Definition at line 2355 of file jsonpath_exec.c.

2357 {
2358  JsonbValue jbvbuf;
2359  Datum value;
2360  text *datetime;
2361  Oid collid;
2362  Oid typid;
2363  int32 typmod = -1;
2364  int tz = 0;
2365  bool hasNext;
2367  JsonPathItem elem;
2368  int32 time_precision = -1;
2369 
2370  if (!(jb = getScalar(jb, jbvString)))
2372  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2373  errmsg("jsonpath item method .%s() can only be applied to a string",
2374  jspOperationName(jsp->type)))));
2375 
2376  datetime = cstring_to_text_with_len(jb->val.string.val,
2377  jb->val.string.len);
2378 
2379  /*
2380  * At some point we might wish to have callers supply the collation to
2381  * use, but right now it's unclear that they'd be able to do better than
2382  * DEFAULT_COLLATION_OID anyway.
2383  */
2384  collid = DEFAULT_COLLATION_OID;
2385 
2386  /*
2387  * .datetime(template) has an argument, the rest of the methods don't have
2388  * an argument. So we handle that separately.
2389  */
2390  if (jsp->type == jpiDatetime && jsp->content.arg)
2391  {
2392  text *template;
2393  char *template_str;
2394  int template_len;
2395  ErrorSaveContext escontext = {T_ErrorSaveContext};
2396 
2397  jspGetArg(jsp, &elem);
2398 
2399  if (elem.type != jpiString)
2400  elog(ERROR, "invalid jsonpath item type for .datetime() argument");
2401 
2402  template_str = jspGetString(&elem, &template_len);
2403 
2404  template = cstring_to_text_with_len(template_str,
2405  template_len);
2406 
2407  value = parse_datetime(datetime, template, collid, true,
2408  &typid, &typmod, &tz,
2409  jspThrowErrors(cxt) ? NULL : (Node *) &escontext);
2410 
2411  if (escontext.error_occurred)
2412  res = jperError;
2413  else
2414  res = jperOk;
2415  }
2416  else
2417  {
2418  /*
2419  * According to SQL/JSON standard enumerate ISO formats for: date,
2420  * timetz, time, timestamptz, timestamp.
2421  *
2422  * We also support ISO 8601 format (with "T") for timestamps, because
2423  * to_json[b]() functions use this format.
2424  */
2425  static const char *fmt_str[] =
2426  {
2427  "yyyy-mm-dd", /* date */
2428  "HH24:MI:SS.USTZ", /* timetz */
2429  "HH24:MI:SSTZ",
2430  "HH24:MI:SS.US", /* time without tz */
2431  "HH24:MI:SS",
2432  "yyyy-mm-dd HH24:MI:SS.USTZ", /* timestamptz */
2433  "yyyy-mm-dd HH24:MI:SSTZ",
2434  "yyyy-mm-dd\"T\"HH24:MI:SS.USTZ",
2435  "yyyy-mm-dd\"T\"HH24:MI:SSTZ",
2436  "yyyy-mm-dd HH24:MI:SS.US", /* timestamp without tz */
2437  "yyyy-mm-dd HH24:MI:SS",
2438  "yyyy-mm-dd\"T\"HH24:MI:SS.US",
2439  "yyyy-mm-dd\"T\"HH24:MI:SS"
2440  };
2441 
2442  /* cache for format texts */
2443  static text *fmt_txt[lengthof(fmt_str)] = {0};
2444  int i;
2445 
2446  /*
2447  * Check for optional precision for methods other than .datetime() and
2448  * .date()
2449  */
2450  if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
2451  jsp->content.arg)
2452  {
2453  bool have_error;
2454 
2455  jspGetArg(jsp, &elem);
2456 
2457  if (elem.type != jpiNumeric)
2458  elog(ERROR, "invalid jsonpath item type for %s argument",
2459  jspOperationName(jsp->type));
2460 
2461  time_precision = numeric_int4_opt_error(jspGetNumeric(&elem),
2462  &have_error);
2463  if (have_error)
2465  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2466  errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
2467  jspOperationName(jsp->type)))));
2468  }
2469 
2470  /* loop until datetime format fits */
2471  for (i = 0; i < lengthof(fmt_str); i++)
2472  {
2473  ErrorSaveContext escontext = {T_ErrorSaveContext};
2474 
2475  if (!fmt_txt[i])
2476  {
2477  MemoryContext oldcxt =
2479 
2480  fmt_txt[i] = cstring_to_text(fmt_str[i]);
2481  MemoryContextSwitchTo(oldcxt);
2482  }
2483 
2484  value = parse_datetime(datetime, fmt_txt[i], collid, true,
2485  &typid, &typmod, &tz,
2486  (Node *) &escontext);
2487 
2488  if (!escontext.error_occurred)
2489  {
2490  res = jperOk;
2491  break;
2492  }
2493  }
2494 
2495  if (res == jperNotFound)
2496  {
2497  if (jsp->type == jpiDatetime)
2499  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2500  errmsg("%s format is not recognized: \"%s\"",
2501  "datetime", text_to_cstring(datetime)),
2502  errhint("Use a datetime template argument to specify the input data format."))));
2503  else
2505  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2506  errmsg("%s format is not recognized: \"%s\"",
2507  jspOperationName(jsp->type), text_to_cstring(datetime)))));
2508 
2509  }
2510  }
2511 
2512  /*
2513  * parse_datetime() processes the entire input string per the template or
2514  * ISO format and returns the Datum in best fitted datetime type. So, if
2515  * this call is for a specific datatype, then we do the conversion here.
2516  * Throw an error for incompatible types.
2517  */
2518  switch (jsp->type)
2519  {
2520  case jpiDatetime: /* Nothing to do for DATETIME */
2521  break;
2522  case jpiDate:
2523  {
2524  /* Convert result type to date */
2525  switch (typid)
2526  {
2527  case DATEOID: /* Nothing to do for DATE */
2528  break;
2529  case TIMEOID:
2530  case TIMETZOID:
2532  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2533  errmsg("%s format is not recognized: \"%s\"",
2534  "date", text_to_cstring(datetime)))));
2535  break;
2536  case TIMESTAMPOID:
2538  value);
2539  break;
2540  case TIMESTAMPTZOID:
2542  "timestamptz", "date");
2544  value);
2545  break;
2546  default:
2547  elog(ERROR, "type with oid %u not supported", typid);
2548  }
2549 
2550  typid = DATEOID;
2551  }
2552  break;
2553  case jpiTime:
2554  {
2555  /* Convert result type to time without time zone */
2556  switch (typid)
2557  {
2558  case DATEOID:
2560  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2561  errmsg("%s format is not recognized: \"%s\"",
2562  "time", text_to_cstring(datetime)))));
2563  break;
2564  case TIMEOID: /* Nothing to do for TIME */
2565  break;
2566  case TIMETZOID:
2568  "timetz", "time");
2570  value);
2571  break;
2572  case TIMESTAMPOID:
2574  value);
2575  break;
2576  case TIMESTAMPTZOID:
2578  "timestamptz", "time");
2580  value);
2581  break;
2582  default:
2583  elog(ERROR, "type with oid %u not supported", typid);
2584  }
2585 
2586  /* Force the user-given time precision, if any */
2587  if (time_precision != -1)
2588  {
2589  TimeADT result;
2590 
2591  /* Get a warning when precision is reduced */
2592  time_precision = anytime_typmod_check(false,
2593  time_precision);
2594  result = DatumGetTimeADT(value);
2595  AdjustTimeForTypmod(&result, time_precision);
2596  value = TimeADTGetDatum(result);
2597 
2598  /* Update the typmod value with the user-given precision */
2599  typmod = time_precision;
2600  }
2601 
2602  typid = TIMEOID;
2603  }
2604  break;
2605  case jpiTimeTz:
2606  {
2607  /* Convert result type to time with time zone */
2608  switch (typid)
2609  {
2610  case DATEOID:
2611  case TIMESTAMPOID:
2613  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2614  errmsg("%s format is not recognized: \"%s\"",
2615  "time_tz", text_to_cstring(datetime)))));
2616  break;
2617  case TIMEOID:
2619  "time", "timetz");
2621  value);
2622  break;
2623  case TIMETZOID: /* Nothing to do for TIMETZ */
2624  break;
2625  case TIMESTAMPTZOID:
2627  value);
2628  break;
2629  default:
2630  elog(ERROR, "type with oid %u not supported", typid);
2631  }
2632 
2633  /* Force the user-given time precision, if any */
2634  if (time_precision != -1)
2635  {
2636  TimeTzADT *result;
2637 
2638  /* Get a warning when precision is reduced */
2639  time_precision = anytime_typmod_check(true,
2640  time_precision);
2641  result = DatumGetTimeTzADTP(value);
2642  AdjustTimeForTypmod(&result->time, time_precision);
2643  value = TimeTzADTPGetDatum(result);
2644 
2645  /* Update the typmod value with the user-given precision */
2646  typmod = time_precision;
2647  }
2648 
2649  typid = TIMETZOID;
2650  }
2651  break;
2652  case jpiTimestamp:
2653  {
2654  /* Convert result type to timestamp without time zone */
2655  switch (typid)
2656  {
2657  case DATEOID:
2659  value);
2660  break;
2661  case TIMEOID:
2662  case TIMETZOID:
2664  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2665  errmsg("%s format is not recognized: \"%s\"",
2666  "timestamp", text_to_cstring(datetime)))));
2667  break;
2668  case TIMESTAMPOID: /* Nothing to do for TIMESTAMP */
2669  break;
2670  case TIMESTAMPTZOID:
2672  "timestamptz", "timestamp");
2674  value);
2675  break;
2676  default:
2677  elog(ERROR, "type with oid %u not supported", typid);
2678  }
2679 
2680  /* Force the user-given time precision, if any */
2681  if (time_precision != -1)
2682  {
2683  Timestamp result;
2684  ErrorSaveContext escontext = {T_ErrorSaveContext};
2685 
2686  /* Get a warning when precision is reduced */
2687  time_precision = anytimestamp_typmod_check(false,
2688  time_precision);
2689  result = DatumGetTimestamp(value);
2690  AdjustTimestampForTypmod(&result, time_precision,
2691  (Node *) &escontext);
2692  if (escontext.error_occurred) /* should not happen */
2694  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2695  errmsg("time precision of jsonpath item method .%s() is invalid",
2696  jspOperationName(jsp->type)))));
2697  value = TimestampGetDatum(result);
2698 
2699  /* Update the typmod value with the user-given precision */
2700  typmod = time_precision;
2701  }
2702 
2703  typid = TIMESTAMPOID;
2704  }
2705  break;
2706  case jpiTimestampTz:
2707  {
2708  /* Convert result type to timestamp with time zone */
2709  switch (typid)
2710  {
2711  case DATEOID:
2713  "date", "timestamptz");
2715  value);
2716  break;
2717  case TIMEOID:
2718  case TIMETZOID:
2720  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2721  errmsg("%s format is not recognized: \"%s\"",
2722  "timestamp_tz", text_to_cstring(datetime)))));
2723  break;
2724  case TIMESTAMPOID:
2726  "timestamp", "timestamptz");
2728  value);
2729  break;
2730  case TIMESTAMPTZOID: /* Nothing to do for TIMESTAMPTZ */
2731  break;
2732  default:
2733  elog(ERROR, "type with oid %u not supported", typid);
2734  }
2735 
2736  /* Force the user-given time precision, if any */
2737  if (time_precision != -1)
2738  {
2739  Timestamp result;
2740  ErrorSaveContext escontext = {T_ErrorSaveContext};
2741 
2742  /* Get a warning when precision is reduced */
2743  time_precision = anytimestamp_typmod_check(true,
2744  time_precision);
2745  result = DatumGetTimestampTz(value);
2746  AdjustTimestampForTypmod(&result, time_precision,
2747  (Node *) &escontext);
2748  if (escontext.error_occurred) /* should not happen */
2750  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2751  errmsg("time precision of jsonpath item method .%s() is invalid",
2752  jspOperationName(jsp->type)))));
2753  value = TimestampTzGetDatum(result);
2754 
2755  /* Update the typmod value with the user-given precision */
2756  typmod = time_precision;
2757  }
2758 
2759  typid = TIMESTAMPTZOID;
2760  }
2761  break;
2762  default:
2763  elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
2764  }
2765 
2766  pfree(datetime);
2767 
2768  if (jperIsError(res))
2769  return res;
2770 
2771  hasNext = jspGetNext(jsp, &elem);
2772 
2773  if (!hasNext && !found)
2774  return res;
2775 
2776  jb = hasNext ? &jbvbuf : palloc(sizeof(*jb));
2777 
2778  jb->type = jbvDatetime;
2779  jb->val.datetime.value = value;
2780  jb->val.datetime.typid = typid;
2781  jb->val.datetime.typmod = typmod;
2782  jb->val.datetime.tz = tz;
2783 
2784  return executeNextItem(cxt, jsp, &elem, jb, found, hasNext);
2785 }
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4397
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition: timestamp.c:366
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:6274
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition: timestamp.c:123
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:6353
#define lengthof(array)
Definition: c.h:788
Oid collid
int64 Timestamp
Definition: timestamp.h:38
Datum timestamp_time(PG_FUNCTION_ARGS)
Definition: date.c:1905
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition: date.c:71
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:1327
Datum timetz_time(PG_FUNCTION_ARGS)
Definition: date.c:2815
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2854
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1645
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition: date.c:1342
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition: date.c:1297
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition: date.c:1935
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1283
static TimeADT DatumGetTimeADT(Datum X)
Definition: date.h:60
static Datum TimeTzADTPGetDatum(const TimeTzADT *X)
Definition: date.h:84
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
Definition: date.h:66
int64 TimeADT
Definition: date.h:25
static Datum TimeADTGetDatum(TimeADT X)
Definition: date.h:78
Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, Node *escontext)
Definition: formatting.c:4455
static struct @155 value
int i
Definition: isn.c:73
Numeric jspGetNumeric(JsonPathItem *v)
Definition: jsonpath.c:1211
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1219
@ jpiString
Definition: jsonpath.h:65
@ jpiDatetime
Definition: jsonpath.h:101
@ jpiTimeTz
Definition: jsonpath.h:115
@ jpiDate
Definition: jsonpath.h:109
@ jpiTimestamp
Definition: jsonpath.h:116
@ jpiTimestampTz
Definition: jsonpath.h:117
@ jpiTime
Definition: jsonpath.h:114
@ jpiNumeric
Definition: jsonpath.h:66
MemoryContext TopMemoryContext
Definition: mcxt.c:149
uintptr_t Datum
Definition: postgres.h:64
unsigned int Oid
Definition: postgres_ext.h:31
MemoryContextSwitchTo(old_ctx)
bool error_occurred
Definition: miscnodes.h:46
int32 arg
Definition: jsonpath.h:158
Definition: nodes.h:129
Definition: date.h:28
TimeADT time
Definition: date.h:29
Definition: c.h:687
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46
char * text_to_cstring(const text *t)
Definition: varlena.c:217
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196
text * cstring_to_text(const char *s)
Definition: varlena.c:184

References AdjustTimeForTypmod(), AdjustTimestampForTypmod(), anytime_typmod_check(), anytimestamp_typmod_check(), JsonPathItem::arg, checkTimezoneIsUsedForCast(), collid, JsonPathItem::content, cstring_to_text(), cstring_to_text_with_len(), date_timestamp(), date_timestamptz(), DatumGetTimeADT(), DatumGetTimestamp(), DatumGetTimestampTz(), DatumGetTimeTzADTP(), DirectFunctionCall1, elog, ereport, errcode(), errhint(), errmsg(), ERROR, ErrorSaveContext::error_occurred, executeNextItem(), getScalar(), i, jbvDatetime, jbvString, jperError, jperIsError, jperNotFound, jperOk, jpiDate, jpiDatetime, jpiNumeric, jpiString, jpiTime, jpiTimestamp, jpiTimestampTz, jpiTimeTz, jspGetArg(), jspGetNext(), jspGetNumeric(), jspGetString(), jspOperationName(), jspThrowErrors, lengthof, MemoryContextSwitchTo(), numeric_int4_opt_error(), palloc(), parse_datetime(), pfree(), res, RETURN_ERROR, text_to_cstring(), TimeTzADT::time, time_timetz(), TimeADTGetDatum(), timestamp_date(), timestamp_time(), timestamp_timestamptz(), TimestampGetDatum(), timestamptz_date(), timestamptz_time(), timestamptz_timestamp(), timestamptz_timetz(), TimestampTzGetDatum(), timetz_time(), TimeTzADTPGetDatum(), TopMemoryContext, JsonbValue::type, JsonPathItem::type, JsonPathExecContext::useTz, JsonbValue::val, and value.

Referenced by executeItemOptUnwrapTarget().

◆ executeItem()

static JsonPathExecResult executeItem ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
JsonValueList found 
)
static

Definition at line 735 of file jsonpath_exec.c.

737 {
738  return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
739 }
#define jspAutoUnwrap(cxt)

References executeItemOptUnwrapTarget(), and jspAutoUnwrap.

Referenced by executeItemOptUnwrapResult(), executeJsonPath(), executeNextItem(), and getArrayIndex().

◆ executeItemOptUnwrapResult()

static JsonPathExecResult executeItemOptUnwrapResult ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
bool  unwrap,
JsonValueList found 
)
static

Definition at line 1741 of file jsonpath_exec.c.

1744 {
1745  if (unwrap && jspAutoUnwrap(cxt))
1746  {
1747  JsonValueList seq = {0};
1749  JsonPathExecResult res = executeItem(cxt, jsp, jb, &seq);
1750  JsonbValue *item;
1751 
1752  if (jperIsError(res))
1753  return res;
1754 
1755  JsonValueListInitIterator(&seq, &it);
1756  while ((item = JsonValueListNext(&seq, &it)))
1757  {
1758  Assert(item->type != jbvArray);
1759 
1760  if (JsonbType(item) == jbvArray)
1761  executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1762  else
1763  JsonValueListAppend(found, item);
1764  }
1765 
1766  return jperOk;
1767  }
1768 
1769  return executeItem(cxt, jsp, jb, found);
1770 }
static int JsonbType(JsonbValue *jb)
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static void JsonValueListInitIterator(const JsonValueList *jvl, JsonValueListIterator *it)
static JsonbValue * JsonValueListNext(const JsonValueList *jvl, JsonValueListIterator *it)
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)

References Assert, executeItem(), executeItemUnwrapTargetArray(), jbvArray, jperIsError, jperOk, JsonbType(), JsonValueListAppend(), JsonValueListInitIterator(), JsonValueListNext(), jspAutoUnwrap, res, and JsonbValue::type.

Referenced by executeBinaryArithmExpr(), executeItemOptUnwrapResultNoThrow(), and executeUnaryArithmExpr().

◆ executeItemOptUnwrapResultNoThrow()

static JsonPathExecResult executeItemOptUnwrapResultNoThrow ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
bool  unwrap,
JsonValueList found 
)
static

Definition at line 1776 of file jsonpath_exec.c.

1780 {
1782  bool throwErrors = cxt->throwErrors;
1783 
1784  cxt->throwErrors = false;
1785  res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1786  cxt->throwErrors = throwErrors;
1787 
1788  return res;
1789 }

References executeItemOptUnwrapResult(), res, and JsonPathExecContext::throwErrors.

Referenced by executeBoolItem(), and executePredicate().

◆ executeItemOptUnwrapTarget()

static JsonPathExecResult executeItemOptUnwrapTarget ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
JsonValueList found,
bool  unwrap 
)
static

Definition at line 747 of file jsonpath_exec.c.

749 {
750  JsonPathItem elem;
752  JsonBaseObjectInfo baseObject;
753 
756 
757  switch (jsp->type)
758  {
759  case jpiNull:
760  case jpiBool:
761  case jpiNumeric:
762  case jpiString:
763  case jpiVariable:
764  {
765  JsonbValue vbuf;
766  JsonbValue *v;
767  bool hasNext = jspGetNext(jsp, &elem);
768 
769  if (!hasNext && !found && jsp->type != jpiVariable)
770  {
771  /*
772  * Skip evaluation, but not for variables. We must
773  * trigger an error for the missing variable.
774  */
775  res = jperOk;
776  break;
777  }
778 
779  v = hasNext ? &vbuf : palloc(sizeof(*v));
780 
781  baseObject = cxt->baseObject;
782  getJsonPathItem(cxt, jsp, v);
783 
784  res = executeNextItem(cxt, jsp, &elem,
785  v, found, hasNext);
786  cxt->baseObject = baseObject;
787  }
788  break;
789 
790  /* all boolean item types: */
791  case jpiAnd:
792  case jpiOr:
793  case jpiNot:
794  case jpiIsUnknown:
795  case jpiEqual:
796  case jpiNotEqual:
797  case jpiLess:
798  case jpiGreater:
799  case jpiLessOrEqual:
800  case jpiGreaterOrEqual:
801  case jpiExists:
802  case jpiStartsWith:
803  case jpiLikeRegex:
804  {
805  JsonPathBool st = executeBoolItem(cxt, jsp, jb, true);
806 
807  res = appendBoolResult(cxt, jsp, found, st);
808  break;
809  }
810 
811  case jpiAdd:
812  return executeBinaryArithmExpr(cxt, jsp, jb,
813  numeric_add_opt_error, found);
814 
815  case jpiSub:
816  return executeBinaryArithmExpr(cxt, jsp, jb,
817  numeric_sub_opt_error, found);
818 
819  case jpiMul:
820  return executeBinaryArithmExpr(cxt, jsp, jb,
821  numeric_mul_opt_error, found);
822 
823  case jpiDiv:
824  return executeBinaryArithmExpr(cxt, jsp, jb,
825  numeric_div_opt_error, found);
826 
827  case jpiMod:
828  return executeBinaryArithmExpr(cxt, jsp, jb,
829  numeric_mod_opt_error, found);
830 
831  case jpiPlus:
832  return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
833 
834  case jpiMinus:
835  return executeUnaryArithmExpr(cxt, jsp, jb, numeric_uminus,
836  found);
837 
838  case jpiAnyArray:
839  if (JsonbType(jb) == jbvArray)
840  {
841  bool hasNext = jspGetNext(jsp, &elem);
842 
843  res = executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL,
844  jb, found, jspAutoUnwrap(cxt));
845  }
846  else if (jspAutoWrap(cxt))
847  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
848  else if (!jspIgnoreStructuralErrors(cxt))
850  (errcode(ERRCODE_SQL_JSON_ARRAY_NOT_FOUND),
851  errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
852  break;
853 
854  case jpiAnyKey:
855  if (JsonbType(jb) == jbvObject)
856  {
857  bool hasNext = jspGetNext(jsp, &elem);
858 
859  if (jb->type != jbvBinary)
860  elog(ERROR, "invalid jsonb object type: %d", jb->type);
861 
862  return executeAnyItem
863  (cxt, hasNext ? &elem : NULL,
864  jb->val.binary.data, found, 1, 1, 1,
865  false, jspAutoUnwrap(cxt));
866  }
867  else if (unwrap && JsonbType(jb) == jbvArray)
868  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
869  else if (!jspIgnoreStructuralErrors(cxt))
870  {
871  Assert(found);
873  (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
874  errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
875  }
876  break;
877 
878  case jpiIndexArray:
879  if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
880  {
881  int innermostArraySize = cxt->innermostArraySize;
882  int i;
883  int size = JsonbArraySize(jb);
884  bool singleton = size < 0;
885  bool hasNext = jspGetNext(jsp, &elem);
886 
887  if (singleton)
888  size = 1;
889 
890  cxt->innermostArraySize = size; /* for LAST evaluation */
891 
892  for (i = 0; i < jsp->content.array.nelems; i++)
893  {
894  JsonPathItem from;
895  JsonPathItem to;
896  int32 index;
897  int32 index_from;
898  int32 index_to;
899  bool range = jspGetArraySubscript(jsp, &from,
900  &to, i);
901 
902  res = getArrayIndex(cxt, &from, jb, &index_from);
903 
904  if (jperIsError(res))
905  break;
906 
907  if (range)
908  {
909  res = getArrayIndex(cxt, &to, jb, &index_to);
910 
911  if (jperIsError(res))
912  break;
913  }
914  else
915  index_to = index_from;
916 
917  if (!jspIgnoreStructuralErrors(cxt) &&
918  (index_from < 0 ||
919  index_from > index_to ||
920  index_to >= size))
922  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
923  errmsg("jsonpath array subscript is out of bounds"))));
924 
925  if (index_from < 0)
926  index_from = 0;
927 
928  if (index_to >= size)
929  index_to = size - 1;
930 
931  res = jperNotFound;
932 
933  for (index = index_from; index <= index_to; index++)
934  {
935  JsonbValue *v;
936  bool copy;
937 
938  if (singleton)
939  {
940  v = jb;
941  copy = true;
942  }
943  else
944  {
945  v = getIthJsonbValueFromContainer(jb->val.binary.data,
946  (uint32) index);
947 
948  if (v == NULL)
949  continue;
950 
951  copy = false;
952  }
953 
954  if (!hasNext && !found)
955  return jperOk;
956 
957  res = executeNextItem(cxt, jsp, &elem, v, found,
958  copy);
959 
960  if (jperIsError(res))
961  break;
962 
963  if (res == jperOk && !found)
964  break;
965  }
966 
967  if (jperIsError(res))
968  break;
969 
970  if (res == jperOk && !found)
971  break;
972  }
973 
974  cxt->innermostArraySize = innermostArraySize;
975  }
976  else if (!jspIgnoreStructuralErrors(cxt))
977  {
979  (errcode(ERRCODE_SQL_JSON_ARRAY_NOT_FOUND),
980  errmsg("jsonpath array accessor can only be applied to an array"))));
981  }
982  break;
983 
984  case jpiAny:
985  {
986  bool hasNext = jspGetNext(jsp, &elem);
987 
988  /* first try without any intermediate steps */
989  if (jsp->content.anybounds.first == 0)
990  {
991  bool savedIgnoreStructuralErrors;
992 
993  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
994  cxt->ignoreStructuralErrors = true;
995  res = executeNextItem(cxt, jsp, &elem,
996  jb, found, true);
997  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
998 
999  if (res == jperOk && !found)
1000  break;
1001  }
1002 
1003  if (jb->type == jbvBinary)
1005  (cxt, hasNext ? &elem : NULL,
1006  jb->val.binary.data, found,
1007  1,
1008  jsp->content.anybounds.first,
1009  jsp->content.anybounds.last,
1010  true, jspAutoUnwrap(cxt));
1011  break;
1012  }
1013 
1014  case jpiKey:
1015  if (JsonbType(jb) == jbvObject)
1016  {
1017  JsonbValue *v;
1018  JsonbValue key;
1019 
1020  key.type = jbvString;
1021  key.val.string.val = jspGetString(jsp, &key.val.string.len);
1022 
1023  v = findJsonbValueFromContainer(jb->val.binary.data,
1024  JB_FOBJECT, &key);
1025 
1026  if (v != NULL)
1027  {
1028  res = executeNextItem(cxt, jsp, NULL,
1029  v, found, false);
1030 
1031  /* free value if it was not added to found list */
1032  if (jspHasNext(jsp) || !found)
1033  pfree(v);
1034  }
1035  else if (!jspIgnoreStructuralErrors(cxt))
1036  {
1037  Assert(found);
1038 
1039  if (!jspThrowErrors(cxt))
1040  return jperError;
1041 
1042  ereport(ERROR,
1043  (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND), \
1044  errmsg("JSON object does not contain key \"%s\"",
1045  pnstrdup(key.val.string.val,
1046  key.val.string.len))));
1047  }
1048  }
1049  else if (unwrap && JsonbType(jb) == jbvArray)
1050  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1051  else if (!jspIgnoreStructuralErrors(cxt))
1052  {
1053  Assert(found);
1055  (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND),
1056  errmsg("jsonpath member accessor can only be applied to an object"))));
1057  }
1058  break;
1059 
1060  case jpiCurrent:
1061  res = executeNextItem(cxt, jsp, NULL, cxt->current,
1062  found, true);
1063  break;
1064 
1065  case jpiRoot:
1066  jb = cxt->root;
1067  baseObject = setBaseObject(cxt, jb, 0);
1068  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1069  cxt->baseObject = baseObject;
1070  break;
1071 
1072  case jpiFilter:
1073  {
1074  JsonPathBool st;
1075 
1076  if (unwrap && JsonbType(jb) == jbvArray)
1077  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1078  false);
1079 
1080  jspGetArg(jsp, &elem);
1081  st = executeNestedBoolItem(cxt, &elem, jb);
1082  if (st != jpbTrue)
1083  res = jperNotFound;
1084  else
1085  res = executeNextItem(cxt, jsp, NULL,
1086  jb, found, true);
1087  break;
1088  }
1089 
1090  case jpiType:
1091  {
1092  JsonbValue *jbv = palloc(sizeof(*jbv));
1093 
1094  jbv->type = jbvString;
1095  jbv->val.string.val = pstrdup(JsonbTypeName(jb));
1096  jbv->val.string.len = strlen(jbv->val.string.val);
1097 
1098  res = executeNextItem(cxt, jsp, NULL, jbv,
1099  found, false);
1100  }
1101  break;
1102 
1103  case jpiSize:
1104  {
1105  int size = JsonbArraySize(jb);
1106 
1107  if (size < 0)
1108  {
1109  if (!jspAutoWrap(cxt))
1110  {
1111  if (!jspIgnoreStructuralErrors(cxt))
1113  (errcode(ERRCODE_SQL_JSON_ARRAY_NOT_FOUND),
1114  errmsg("jsonpath item method .%s() can only be applied to an array",
1115  jspOperationName(jsp->type)))));
1116  break;
1117  }
1118 
1119  size = 1;
1120  }
1121 
1122  jb = palloc(sizeof(*jb));
1123 
1124  jb->type = jbvNumeric;
1125  jb->val.numeric = int64_to_numeric(size);
1126 
1127  res = executeNextItem(cxt, jsp, NULL, jb, found, false);
1128  }
1129  break;
1130 
1131  case jpiAbs:
1132  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_abs,
1133  found);
1134 
1135  case jpiFloor:
1136  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_floor,
1137  found);
1138 
1139  case jpiCeiling:
1140  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_ceil,
1141  found);
1142 
1143  case jpiDouble:
1144  {
1145  JsonbValue jbv;
1146 
1147  if (unwrap && JsonbType(jb) == jbvArray)
1148  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1149  false);
1150 
1151  if (jb->type == jbvNumeric)
1152  {
1154  NumericGetDatum(jb->val.numeric)));
1155  double val;
1156  ErrorSaveContext escontext = {T_ErrorSaveContext};
1157 
1158  val = float8in_internal(tmp,
1159  NULL,
1160  "double precision",
1161  tmp,
1162  (Node *) &escontext);
1163 
1164  if (escontext.error_occurred)
1166  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1167  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type double precision",
1168  tmp, jspOperationName(jsp->type)))));
1169  if (isinf(val) || isnan(val))
1171  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1172  errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1173  jspOperationName(jsp->type)))));
1174  res = jperOk;
1175  }
1176  else if (jb->type == jbvString)
1177  {
1178  /* cast string as double */
1179  double val;
1180  char *tmp = pnstrdup(jb->val.string.val,
1181  jb->val.string.len);
1182  ErrorSaveContext escontext = {T_ErrorSaveContext};
1183 
1184  val = float8in_internal(tmp,
1185  NULL,
1186  "double precision",
1187  tmp,
1188  (Node *) &escontext);
1189 
1190  if (escontext.error_occurred)
1192  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1193  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type double precision",
1194  tmp, jspOperationName(jsp->type)))));
1195  if (isinf(val) || isnan(val))
1197  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1198  errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1199  jspOperationName(jsp->type)))));
1200 
1201  jb = &jbv;
1202  jb->type = jbvNumeric;
1204  Float8GetDatum(val)));
1205  res = jperOk;
1206  }
1207 
1208  if (res == jperNotFound)
1210  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1211  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1212  jspOperationName(jsp->type)))));
1213 
1214  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1215  }
1216  break;
1217 
1218  case jpiDatetime:
1219  case jpiDate:
1220  case jpiTime:
1221  case jpiTimeTz:
1222  case jpiTimestamp:
1223  case jpiTimestampTz:
1224  if (unwrap && JsonbType(jb) == jbvArray)
1225  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1226 
1227  return executeDateTimeMethod(cxt, jsp, jb, found);
1228 
1229  case jpiKeyValue:
1230  if (unwrap && JsonbType(jb) == jbvArray)
1231  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1232 
1233  return executeKeyValueMethod(cxt, jsp, jb, found);
1234 
1235  case jpiLast:
1236  {
1237  JsonbValue tmpjbv;
1238  JsonbValue *lastjbv;
1239  int last;
1240  bool hasNext = jspGetNext(jsp, &elem);
1241 
1242  if (cxt->innermostArraySize < 0)
1243  elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
1244 
1245  if (!hasNext && !found)
1246  {
1247  res = jperOk;
1248  break;
1249  }
1250 
1251  last = cxt->innermostArraySize - 1;
1252 
1253  lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
1254 
1255  lastjbv->type = jbvNumeric;
1256  lastjbv->val.numeric = int64_to_numeric(last);
1257 
1258  res = executeNextItem(cxt, jsp, &elem,
1259  lastjbv, found, hasNext);
1260  }
1261  break;
1262 
1263  case jpiBigint:
1264  {
1265  JsonbValue jbv;
1266  Datum datum;
1267 
1268  if (unwrap && JsonbType(jb) == jbvArray)
1269  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1270  false);
1271 
1272  if (jb->type == jbvNumeric)
1273  {
1274  bool have_error;
1275  int64 val;
1276 
1277  val = numeric_int8_opt_error(jb->val.numeric, &have_error);
1278  if (have_error)
1280  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1281  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type bigint",
1283  NumericGetDatum(jb->val.numeric))),
1284  jspOperationName(jsp->type)))));
1285 
1286  datum = Int64GetDatum(val);
1287  res = jperOk;
1288  }
1289  else if (jb->type == jbvString)
1290  {
1291  /* cast string as bigint */
1292  char *tmp = pnstrdup(jb->val.string.val,
1293  jb->val.string.len);
1294  ErrorSaveContext escontext = {T_ErrorSaveContext};
1295  bool noerr;
1296 
1297  noerr = DirectInputFunctionCallSafe(int8in, tmp,
1298  InvalidOid, -1,
1299  (Node *) &escontext,
1300  &datum);
1301 
1302  if (!noerr || escontext.error_occurred)
1304  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1305  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type bigint",
1306  tmp, jspOperationName(jsp->type)))));
1307  res = jperOk;
1308  }
1309 
1310  if (res == jperNotFound)
1312  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1313  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1314  jspOperationName(jsp->type)))));
1315 
1316  jb = &jbv;
1317  jb->type = jbvNumeric;
1319  datum));
1320 
1321  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1322  }
1323  break;
1324 
1325  case jpiBoolean:
1326  {
1327  JsonbValue jbv;
1328  bool bval;
1329 
1330  if (unwrap && JsonbType(jb) == jbvArray)
1331  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1332  false);
1333 
1334  if (jb->type == jbvBool)
1335  {
1336  bval = jb->val.boolean;
1337 
1338  res = jperOk;
1339  }
1340  else if (jb->type == jbvNumeric)
1341  {
1342  int ival;
1343  Datum datum;
1344  bool noerr;
1346  NumericGetDatum(jb->val.numeric)));
1347  ErrorSaveContext escontext = {T_ErrorSaveContext};
1348 
1349  noerr = DirectInputFunctionCallSafe(int4in, tmp,
1350  InvalidOid, -1,
1351  (Node *) &escontext,
1352  &datum);
1353 
1354  if (!noerr || escontext.error_occurred)
1356  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1357  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type boolean",
1358  tmp, jspOperationName(jsp->type)))));
1359 
1360  ival = DatumGetInt32(datum);
1361  if (ival == 0)
1362  bval = false;
1363  else
1364  bval = true;
1365 
1366  res = jperOk;
1367  }
1368  else if (jb->type == jbvString)
1369  {
1370  /* cast string as boolean */
1371  char *tmp = pnstrdup(jb->val.string.val,
1372  jb->val.string.len);
1373 
1374  if (!parse_bool(tmp, &bval))
1376  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1377  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type boolean",
1378  tmp, jspOperationName(jsp->type)))));
1379 
1380  res = jperOk;
1381  }
1382 
1383  if (res == jperNotFound)
1385  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1386  errmsg("jsonpath item method .%s() can only be applied to a bool, string, or numeric value",
1387  jspOperationName(jsp->type)))));
1388 
1389  jb = &jbv;
1390  jb->type = jbvBool;
1391  jb->val.boolean = bval;
1392 
1393  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1394  }
1395  break;
1396 
1397  case jpiDecimal:
1398  case jpiNumber:
1399  {
1400  JsonbValue jbv;
1401  Numeric num;
1402  char *numstr = NULL;
1403 
1404  if (unwrap && JsonbType(jb) == jbvArray)
1405  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1406  false);
1407 
1408  if (jb->type == jbvNumeric)
1409  {
1410  num = jb->val.numeric;
1411  if (numeric_is_nan(num) || numeric_is_inf(num))
1413  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1414  errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1415  jspOperationName(jsp->type)))));
1416 
1417  if (jsp->type == jpiDecimal)
1419  NumericGetDatum(num)));
1420  res = jperOk;
1421  }
1422  else if (jb->type == jbvString)
1423  {
1424  /* cast string as number */
1425  Datum datum;
1426  bool noerr;
1427  ErrorSaveContext escontext = {T_ErrorSaveContext};
1428 
1429  numstr = pnstrdup(jb->val.string.val, jb->val.string.len);
1430 
1431  noerr = DirectInputFunctionCallSafe(numeric_in, numstr,
1432  InvalidOid, -1,
1433  (Node *) &escontext,
1434  &datum);
1435 
1436  if (!noerr || escontext.error_occurred)
1438  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1439  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type numeric",
1440  numstr, jspOperationName(jsp->type)))));
1441 
1442  num = DatumGetNumeric(datum);
1443  if (numeric_is_nan(num) || numeric_is_inf(num))
1445  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1446  errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1447  jspOperationName(jsp->type)))));
1448 
1449  res = jperOk;
1450  }
1451 
1452  if (res == jperNotFound)
1454  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1455  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1456  jspOperationName(jsp->type)))));
1457 
1458  /*
1459  * If we have arguments, then they must be the precision and
1460  * optional scale used in .decimal(). Convert them to the
1461  * typmod equivalent and then truncate the numeric value per
1462  * this typmod details.
1463  */
1464  if (jsp->type == jpiDecimal && jsp->content.args.left)
1465  {
1466  Datum numdatum;
1467  Datum dtypmod;
1468  int32 precision;
1469  int32 scale = 0;
1470  bool have_error;
1471  bool noerr;
1472  ArrayType *arrtypmod;
1473  Datum datums[2];
1474  char pstr[12]; /* sign, 10 digits and '\0' */
1475  char sstr[12]; /* sign, 10 digits and '\0' */
1476  ErrorSaveContext escontext = {T_ErrorSaveContext};
1477 
1478  jspGetLeftArg(jsp, &elem);
1479  if (elem.type != jpiNumeric)
1480  elog(ERROR, "invalid jsonpath item type for .decimal() precision");
1481 
1482  precision = numeric_int4_opt_error(jspGetNumeric(&elem),
1483  &have_error);
1484  if (have_error)
1486  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1487  errmsg("precision of jsonpath item method .%s() is out of range for type integer",
1488  jspOperationName(jsp->type)))));
1489 
1490  if (jsp->content.args.right)
1491  {
1492  jspGetRightArg(jsp, &elem);
1493  if (elem.type != jpiNumeric)
1494  elog(ERROR, "invalid jsonpath item type for .decimal() scale");
1495 
1497  &have_error);
1498  if (have_error)
1500  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1501  errmsg("scale of jsonpath item method .%s() is out of range for type integer",
1502  jspOperationName(jsp->type)))));
1503  }
1504 
1505  /*
1506  * numerictypmodin() takes the precision and scale in the
1507  * form of CString arrays.
1508  */
1509  pg_ltoa(precision, pstr);
1510  datums[0] = CStringGetDatum(pstr);
1511  pg_ltoa(scale, sstr);
1512  datums[1] = CStringGetDatum(sstr);
1513  arrtypmod = construct_array_builtin(datums, 2, CSTRINGOID);
1514 
1516  PointerGetDatum(arrtypmod));
1517 
1518  /* Convert numstr to Numeric with typmod */
1519  Assert(numstr != NULL);
1520  noerr = DirectInputFunctionCallSafe(numeric_in, numstr,
1521  InvalidOid, dtypmod,
1522  (Node *) &escontext,
1523  &numdatum);
1524 
1525  if (!noerr || escontext.error_occurred)
1527  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1528  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type numeric",
1529  numstr, jspOperationName(jsp->type)))));
1530 
1531  num = DatumGetNumeric(numdatum);
1532  pfree(arrtypmod);
1533  }
1534 
1535  jb = &jbv;
1536  jb->type = jbvNumeric;
1537  jb->val.numeric = num;
1538 
1539  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1540  }
1541  break;
1542 
1543  case jpiInteger:
1544  {
1545  JsonbValue jbv;
1546  Datum datum;
1547 
1548  if (unwrap && JsonbType(jb) == jbvArray)
1549  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1550  false);
1551 
1552  if (jb->type == jbvNumeric)
1553  {
1554  bool have_error;
1555  int32 val;
1556 
1557  val = numeric_int4_opt_error(jb->val.numeric, &have_error);
1558  if (have_error)
1560  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1561  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type integer",
1563  NumericGetDatum(jb->val.numeric))),
1564  jspOperationName(jsp->type)))));
1565 
1566  datum = Int32GetDatum(val);
1567  res = jperOk;
1568  }
1569  else if (jb->type == jbvString)
1570  {
1571  /* cast string as integer */
1572  char *tmp = pnstrdup(jb->val.string.val,
1573  jb->val.string.len);
1574  ErrorSaveContext escontext = {T_ErrorSaveContext};
1575  bool noerr;
1576 
1577  noerr = DirectInputFunctionCallSafe(int4in, tmp,
1578  InvalidOid, -1,
1579  (Node *) &escontext,
1580  &datum);
1581 
1582  if (!noerr || escontext.error_occurred)
1584  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1585  errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type integer",
1586  tmp, jspOperationName(jsp->type)))));
1587  res = jperOk;
1588  }
1589 
1590  if (res == jperNotFound)
1592  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1593  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1594  jspOperationName(jsp->type)))));
1595 
1596  jb = &jbv;
1597  jb->type = jbvNumeric;
1599  datum));
1600 
1601  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1602  }
1603  break;
1604 
1605  case jpiStringFunc:
1606  {
1607  JsonbValue jbv;
1608  char *tmp = NULL;
1609 
1610  switch (JsonbType(jb))
1611  {
1612  case jbvString:
1613 
1614  /*
1615  * Value is not necessarily null-terminated, so we do
1616  * pnstrdup() here.
1617  */
1618  tmp = pnstrdup(jb->val.string.val,
1619  jb->val.string.len);
1620  break;
1621  case jbvNumeric:
1623  NumericGetDatum(jb->val.numeric)));
1624  break;
1625  case jbvBool:
1626  tmp = (jb->val.boolean) ? "true" : "false";
1627  break;
1628  case jbvDatetime:
1629  {
1630  switch (jb->val.datetime.typid)
1631  {
1632  case DATEOID:
1634  jb->val.datetime.value));
1635  break;
1636  case TIMEOID:
1638  jb->val.datetime.value));
1639  break;
1640  case TIMETZOID:
1642  jb->val.datetime.value));
1643  break;
1644  case TIMESTAMPOID:
1646  jb->val.datetime.value));
1647  break;
1648  case TIMESTAMPTZOID:
1650  jb->val.datetime.value));
1651  break;
1652  default:
1653  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
1654  jb->val.datetime.typid);
1655  }
1656  }
1657  break;
1658  case jbvNull:
1659  case jbvArray:
1660  case jbvObject:
1661  case jbvBinary:
1663  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1664  errmsg("jsonpath item method .%s() can only be applied to a bool, string, numeric, or datetime value",
1665  jspOperationName(jsp->type)))));
1666  break;
1667  }
1668 
1669  jb = &jbv;
1670  Assert(tmp != NULL); /* We must have set tmp above */
1671  jb->val.string.val = tmp;
1672  jb->val.string.len = strlen(jb->val.string.val);
1673  jb->type = jbvString;
1674 
1675  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1676  }
1677  break;
1678 
1679  default:
1680  elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
1681  }
1682 
1683  return res;
1684 }
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3374
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4593
Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3368
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3144
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4283
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4389
Datum numeric_uminus(PG_FUNCTION_ARGS)
Definition: numeric.c:1411
Datum numeric_ceil(PG_FUNCTION_ARGS)
Definition: numeric.c:1630
Datum numerictypmodin(PG_FUNCTION_ARGS)
Definition: numeric.c:1315
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:807
int64 numeric_int8_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4485
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:628
bool numeric_is_nan(Numeric num)
Definition: numeric.c:842
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2945
Numeric numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3023
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition: numeric.c:1384
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4477
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2867
bool numeric_is_inf(Numeric num)
Definition: numeric.c:853
Datum numeric_floor(PG_FUNCTION_ARGS)
Definition: numeric.c:1658
Datum timestamptz_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:785
Datum timestamp_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:232
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
unsigned int uint32
Definition: c.h:506
Datum date_out(PG_FUNCTION_ARGS)
Definition: date.c:184
Datum time_out(PG_FUNCTION_ARGS)
Definition: date.c:1501
Datum timetz_out(PG_FUNCTION_ARGS)
Definition: date.c:2314
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition: float.c:388
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1816
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1640
long val
Definition: informix.c:670
Datum int8in(PG_FUNCTION_ARGS)
Definition: int8.c:50
Datum int4in(PG_FUNCTION_ARGS)
Definition: int.c:287
const char * JsonbTypeName(JsonbValue *val)
Definition: jsonb.c:180
#define JB_FOBJECT
Definition: jsonb.h:202
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:468
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:344
bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to, int i)
Definition: jsonpath.c:1231
@ jpiAdd
Definition: jsonpath.h:78
@ jpiAbs
Definition: jsonpath.h:97
@ jpiIndexArray
Definition: jsonpath.h:87
@ jpiAny
Definition: jsonpath.h:88
@ jpiBigint
Definition: jsonpath.h:107
@ jpiBool
Definition: jsonpath.h:67
@ jpiType
Definition: jsonpath.h:95
@ jpiFloor
Definition: jsonpath.h:98
@ jpiAnyArray
Definition: jsonpath.h:85
@ jpiSize
Definition: jsonpath.h:96
@ jpiSub
Definition: jsonpath.h:79
@ jpiMul
Definition: jsonpath.h:80
@ jpiVariable
Definition: jsonpath.h:92
@ jpiPlus
Definition: jsonpath.h:83
@ jpiDouble
Definition: jsonpath.h:100
@ jpiNumber
Definition: jsonpath.h:112
@ jpiMod
Definition: jsonpath.h:82
@ jpiInteger
Definition: jsonpath.h:111
@ jpiRoot
Definition: jsonpath.h:91
@ jpiFilter
Definition: jsonpath.h:93
@ jpiNull
Definition: jsonpath.h:64
@ jpiCurrent
Definition: jsonpath.h:90
@ jpiKey
Definition: jsonpath.h:89
@ jpiDiv
Definition: jsonpath.h:81
@ jpiLast
Definition: jsonpath.h:104
@ jpiMinus
Definition: jsonpath.h:84
@ jpiCeiling
Definition: jsonpath.h:99
@ jpiKeyValue
Definition: jsonpath.h:102
@ jpiBoolean
Definition: jsonpath.h:108
@ jpiStringFunc
Definition: jsonpath.h:113
@ jpiDecimal
Definition: jsonpath.h:110
@ jpiAnyKey
Definition: jsonpath.h:86
static int JsonbArraySize(JsonbValue *jb)
static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonValueList *found, JsonPathBool res)
static JsonPathExecResult executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, BinaryArithmFunc func, JsonValueList *found)
#define jspAutoWrap(cxt)
static JsonPathExecResult executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt, JsonbValue *jbv, int32 id)
static JsonPathExecResult executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, PGFunction func, JsonValueList *found)
static JsonPathExecResult executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static JsonPathBool executeNestedBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb)
#define jspIgnoreStructuralErrors(cxt)
static JsonPathExecResult getArrayIndex(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, int32 *index)
static JsonPathExecResult executeNumericItemMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, PGFunction func, JsonValueList *found)
static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *value)
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1706
char * pstrdup(const char *in)
Definition: mcxt.c:1695
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:61
int pg_ltoa(int32 value, char *a)
Definition: numutils.c:1122
int scale
Definition: pgbench.c:181
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
static pg_noinline void Size size
Definition: slab.c:607
JsonbValue * current
JsonBaseObjectInfo baseObject
struct JsonPathItem::@137::@139 array
struct JsonPathItem::@137::@140 anybounds
struct JsonPathItem::@137::@138 args
Definition: type.h:95

References JsonPathItem::anybounds, appendBoolResult(), JsonPathItem::args, JsonPathItem::array, Assert, JsonPathExecContext::baseObject, CHECK_FOR_INTERRUPTS, check_stack_depth(), construct_array_builtin(), JsonPathItem::content, CStringGetDatum(), JsonPathExecContext::current, date_out(), DatumGetCString(), DatumGetInt32(), DatumGetNumeric(), DirectFunctionCall1, DirectInputFunctionCallSafe(), elog, ereport, errcode(), errmsg(), ERROR, ErrorSaveContext::error_occurred, executeAnyItem(), executeBinaryArithmExpr(), executeBoolItem(), executeDateTimeMethod(), executeItemUnwrapTargetArray(), executeKeyValueMethod(), executeNestedBoolItem(), executeNextItem(), executeNumericItemMethod(), executeUnaryArithmExpr(), findJsonbValueFromContainer(), float8_numeric(), Float8GetDatum(), float8in_internal(), getArrayIndex(), getIthJsonbValueFromContainer(), getJsonPathItem(), i, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, Int32GetDatum(), int4_numeric(), int4in(), int64_to_numeric(), Int64GetDatum(), int8_numeric(), int8in(), InvalidOid, JB_FOBJECT, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jpbTrue, jperError, jperIsError, jperNotFound, jperOk, jpiAbs, jpiAdd, jpiAnd, jpiAny, jpiAnyArray, jpiAnyKey, jpiBigint, jpiBool, jpiBoolean, jpiCeiling, jpiCurrent, jpiDate, jpiDatetime, jpiDecimal, jpiDiv, jpiDouble, jpiEqual, jpiExists, jpiFilter, jpiFloor, jpiGreater, jpiGreaterOrEqual, jpiIndexArray, jpiInteger, jpiIsUnknown, jpiKey, jpiKeyValue, jpiLast, jpiLess, jpiLessOrEqual, jpiLikeRegex, jpiMinus, jpiMod, jpiMul, jpiNot, jpiNotEqual, jpiNull, jpiNumber, jpiNumeric, jpiOr, jpiPlus, jpiRoot, jpiSize, jpiStartsWith, jpiString, jpiStringFunc, jpiSub, jpiTime, jpiTimestamp, jpiTimestampTz, jpiTimeTz, jpiType, jpiVariable, JsonbArraySize(), JsonbType(), JsonbTypeName(), jspAutoUnwrap, jspAutoWrap, jspGetArg(), jspGetArraySubscript(), jspGetLeftArg(), jspGetNext(), jspGetNumeric(), jspGetRightArg(), jspGetString(), jspHasNext, jspIgnoreStructuralErrors, jspOperationName(), jspThrowErrors, sort-test::key, numeric_abs(), numeric_add_opt_error(), numeric_ceil(), numeric_div_opt_error(), numeric_floor(), numeric_in(), numeric_int4_opt_error(), numeric_int8_opt_error(), numeric_is_inf(), numeric_is_nan(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_out(), numeric_sub_opt_error(), numeric_uminus(), NumericGetDatum(), numerictypmodin(), palloc(), parse_bool(), pfree(), pg_ltoa(), pnstrdup(), PointerGetDatum(), pstrdup(), range(), res, RETURN_ERROR, JsonPathExecContext::root, scale, setBaseObject(), size, time_out(), timestamp_out(), timestamptz_out(), timetz_out(), JsonbValue::type, JsonPathItem::type, JsonbValue::val, and val.

Referenced by executeAnyItem(), and executeItem().

◆ executeItemUnwrapTargetArray()

static JsonPathExecResult executeItemUnwrapTargetArray ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
JsonValueList found,
bool  unwrapElements 
)
static

Definition at line 1690 of file jsonpath_exec.c.

1693 {
1694  if (jb->type != jbvBinary)
1695  {
1696  Assert(jb->type != jbvArray);
1697  elog(ERROR, "invalid jsonb array value type: %d", jb->type);
1698  }
1699 
1700  return executeAnyItem
1701  (cxt, jsp, jb->val.binary.data, found, 1, 1, 1,
1702  false, unwrapElements);
1703 }

References Assert, elog, ERROR, executeAnyItem(), jbvArray, jbvBinary, JsonbValue::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapResult(), executeItemOptUnwrapTarget(), and executeNumericItemMethod().

◆ executeJsonPath()

static JsonPathExecResult executeJsonPath ( JsonPath path,
void *  vars,
JsonPathGetVarCallback  getVar,
JsonPathCountVarsCallback  countVars,
Jsonb json,
bool  throwErrors,
JsonValueList result,
bool  useTz 
)
static

Definition at line 679 of file jsonpath_exec.c.

683 {
686  JsonPathItem jsp;
687  JsonbValue jbv;
688 
689  jspInit(&jsp, path);
690 
691  if (!JsonbExtractScalar(&json->root, &jbv))
692  JsonbInitBinary(&jbv, json);
693 
694  cxt.vars = vars;
695  cxt.getVar = getVar;
696  cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
698  cxt.root = &jbv;
699  cxt.current = &jbv;
700  cxt.baseObject.jbc = NULL;
701  cxt.baseObject.id = 0;
702  /* 1 + number of base objects in vars */
703  cxt.lastGeneratedObjectId = 1 + countVars(vars);
704  cxt.innermostArraySize = -1;
705  cxt.throwErrors = throwErrors;
706  cxt.useTz = useTz;
707 
708  if (jspStrictAbsenceOfErrors(&cxt) && !result)
709  {
710  /*
711  * In strict mode we must get a complete list of values to check that
712  * there are no errors at all.
713  */
714  JsonValueList vals = {0};
715 
716  res = executeItem(&cxt, &jsp, &jbv, &vals);
717 
718  if (jperIsError(res))
719  return res;
720 
721  return JsonValueListIsEmpty(&vals) ? jperNotFound : jperOk;
722  }
723 
724  res = executeItem(&cxt, &jsp, &jbv, result);
725 
726  Assert(!throwErrors || !jperIsError(res));
727 
728  return res;
729 }
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1968
void jspInit(JsonPathItem *v, JsonPath *js)
Definition: jsonpath.c:973
#define JSONPATH_LAX
Definition: jsonpath.h:31
static JsonbValue * JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
JsonbContainer * jbc
Definition: jsonpath_exec.c:85
JsonPathGetVarCallback getVar
uint32 header
Definition: jsonpath.h:26
JsonbContainer root
Definition: jsonb.h:215

References Assert, JsonPathExecContext::baseObject, JsonPathExecContext::current, executeItem(), JsonPathExecContext::getVar, JsonPath::header, JsonBaseObjectInfo::id, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, JsonBaseObjectInfo::jbc, jperIsError, jperNotFound, jperOk, JsonbExtractScalar(), JsonbInitBinary(), JSONPATH_LAX, JsonValueListIsEmpty(), jspInit(), jspStrictAbsenceOfErrors, JsonPathExecContext::lastGeneratedObjectId, JsonPathExecContext::laxMode, res, JsonPathExecContext::root, Jsonb::root, JsonPathExecContext::throwErrors, JsonPathExecContext::useTz, and JsonPathExecContext::vars.

Referenced by jsonb_path_exists_internal(), jsonb_path_match_internal(), jsonb_path_query_array_internal(), jsonb_path_query_first_internal(), jsonb_path_query_internal(), JsonPathExists(), JsonPathQuery(), JsonPathValue(), and JsonTableResetRowPattern().

◆ executeKeyValueMethod()

static JsonPathExecResult executeKeyValueMethod ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
JsonValueList found 
)
static

Definition at line 2811 of file jsonpath_exec.c.

2813 {
2816  JsonbContainer *jbc;
2817  JsonbValue key;
2818  JsonbValue val;
2819  JsonbValue idval;
2820  JsonbValue keystr;
2821  JsonbValue valstr;
2822  JsonbValue idstr;
2823  JsonbIterator *it;
2824  JsonbIteratorToken tok;
2825  int64 id;
2826  bool hasNext;
2827 
2828  if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
2830  (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
2831  errmsg("jsonpath item method .%s() can only be applied to an object",
2832  jspOperationName(jsp->type)))));
2833 
2834  jbc = jb->val.binary.data;
2835 
2836  if (!JsonContainerSize(jbc))
2837  return jperNotFound; /* no key-value pairs */
2838 
2839  hasNext = jspGetNext(jsp, &next);
2840 
2841  keystr.type = jbvString;
2842  keystr.val.string.val = "key";
2843  keystr.val.string.len = 3;
2844 
2845  valstr.type = jbvString;
2846  valstr.val.string.val = "value";
2847  valstr.val.string.len = 5;
2848 
2849  idstr.type = jbvString;
2850  idstr.val.string.val = "id";
2851  idstr.val.string.len = 2;
2852 
2853  /* construct object id from its base object and offset inside that */
2854  id = jb->type != jbvBinary ? 0 :
2855  (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
2856  id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
2857 
2858  idval.type = jbvNumeric;
2859  idval.val.numeric = int64_to_numeric(id);
2860 
2861  it = JsonbIteratorInit(jbc);
2862 
2863  while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
2864  {
2865  JsonBaseObjectInfo baseObject;
2866  JsonbValue obj;
2868  JsonbValue *keyval;
2869  Jsonb *jsonb;
2870 
2871  if (tok != WJB_KEY)
2872  continue;
2873 
2874  res = jperOk;
2875 
2876  if (!hasNext && !found)
2877  break;
2878 
2879  tok = JsonbIteratorNext(&it, &val, true);
2880  Assert(tok == WJB_VALUE);
2881 
2882  ps = NULL;
2884 
2885  pushJsonbValue(&ps, WJB_KEY, &keystr);
2887 
2888  pushJsonbValue(&ps, WJB_KEY, &valstr);
2890 
2891  pushJsonbValue(&ps, WJB_KEY, &idstr);
2892  pushJsonbValue(&ps, WJB_VALUE, &idval);
2893 
2894  keyval = pushJsonbValue(&ps, WJB_END_OBJECT, NULL);
2895 
2896  jsonb = JsonbValueToJsonb(keyval);
2897 
2898  JsonbInitBinary(&obj, jsonb);
2899 
2900  baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
2901 
2902  res = executeNextItem(cxt, jsp, &next, &obj, found, true);
2903 
2904  cxt->baseObject = baseObject;
2905 
2906  if (jperIsError(res))
2907  return res;
2908 
2909  if (res == jperOk && !found)
2910  break;
2911  }
2912 
2913  return res;
2914 }
struct parser_state ps
#define JsonContainerSize(jc)
Definition: jsonb.h:206
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566

References Assert, JsonPathExecContext::baseObject, ereport, errcode(), errmsg(), ERROR, executeNextItem(), JsonBaseObjectInfo::id, int64_to_numeric(), JsonBaseObjectInfo::jbc, jbvBinary, jbvNumeric, jbvObject, jbvString, jperIsError, jperNotFound, jperOk, JsonbInitBinary(), JsonbIteratorInit(), JsonbIteratorNext(), JsonbType(), JsonbValueToJsonb(), JsonContainerSize, jspGetNext(), jspOperationName(), sort-test::key, JsonPathExecContext::lastGeneratedObjectId, next, ps, pushJsonbValue(), res, RETURN_ERROR, setBaseObject(), JsonbValue::type, JsonPathItem::type, JsonbValue::val, val, WJB_BEGIN_OBJECT, WJB_DONE, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by executeItemOptUnwrapTarget().

◆ executeLikeRegex()

static JsonPathBool executeLikeRegex ( JsonPathItem jsp,
JsonbValue str,
JsonbValue rarg,
void *  param 
)
static

Definition at line 2283 of file jsonpath_exec.c.

2285 {
2286  JsonLikeRegexContext *cxt = param;
2287 
2288  if (!(str = getScalar(str, jbvString)))
2289  return jpbUnknown;
2290 
2291  /* Cache regex text and converted flags. */
2292  if (!cxt->regex)
2293  {
2294  cxt->regex =
2296  jsp->content.like_regex.patternlen);
2297  (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2298  &(cxt->cflags), NULL);
2299  }
2300 
2301  if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2302  str->val.string.len,
2303  cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
2304  return jpbTrue;
2305 
2306  return jpbFalse;
2307 }
const char * str
bool jspConvertRegexFlags(uint32 xflags, int *result, struct Node *escontext)
bool RE_compile_and_execute(text *text_re, char *dat, int dat_len, int cflags, Oid collation, int nmatch, regmatch_t *pmatch)
Definition: regexp.c:358

References JsonLikeRegexContext::cflags, JsonPathItem::content, cstring_to_text_with_len(), getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, jspConvertRegexFlags(), JsonPathItem::like_regex, RE_compile_and_execute(), JsonLikeRegexContext::regex, and str.

Referenced by executeBoolItem().

◆ executeNestedBoolItem()

static JsonPathBool executeNestedBoolItem ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb 
)
static

Definition at line 1929 of file jsonpath_exec.c.

1931 {
1932  JsonbValue *prev;
1933  JsonPathBool res;
1934 
1935  prev = cxt->current;
1936  cxt->current = jb;
1937  res = executeBoolItem(cxt, jsp, jb, false);
1938  cxt->current = prev;
1939 
1940  return res;
1941 }

References JsonPathExecContext::current, executeBoolItem(), and res.

Referenced by executeItemOptUnwrapTarget().

◆ executeNextItem()

static JsonPathExecResult executeNextItem ( JsonPathExecContext cxt,
JsonPathItem cur,
JsonPathItem next,
JsonbValue v,
JsonValueList found,
bool  copy 
)
static

Definition at line 1710 of file jsonpath_exec.c.

1713 {
1714  JsonPathItem elem;
1715  bool hasNext;
1716 
1717  if (!cur)
1718  hasNext = next != NULL;
1719  else if (next)
1720  hasNext = jspHasNext(cur);
1721  else
1722  {
1723  next = &elem;
1724  hasNext = jspGetNext(cur, next);
1725  }
1726 
1727  if (hasNext)
1728  return executeItem(cxt, next, v, found);
1729 
1730  if (found)
1731  JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1732 
1733  return jperOk;
1734 }
struct cursor * cur
Definition: ecpg.c:28

References copyJsonbValue(), cur, executeItem(), jperOk, JsonValueListAppend(), jspGetNext(), jspHasNext, and next.

Referenced by appendBoolResult(), executeBinaryArithmExpr(), executeDateTimeMethod(), executeItemOptUnwrapTarget(), executeKeyValueMethod(), executeNumericItemMethod(), and executeUnaryArithmExpr().

◆ executeNumericItemMethod()

static JsonPathExecResult executeNumericItemMethod ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
bool  unwrap,
PGFunction  func,
JsonValueList found 
)
static

Definition at line 2314 of file jsonpath_exec.c.

2317 {
2319  Datum datum;
2320 
2321  if (unwrap && JsonbType(jb) == jbvArray)
2322  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
2323 
2324  if (!(jb = getScalar(jb, jbvNumeric)))
2326  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
2327  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
2328  jspOperationName(jsp->type)))));
2329 
2330  datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
2331 
2332  if (!jspGetNext(jsp, &next) && !found)
2333  return jperOk;
2334 
2335  jb = palloc(sizeof(*jb));
2336  jb->type = jbvNumeric;
2337  jb->val.numeric = DatumGetNumeric(datum);
2338 
2339  return executeNextItem(cxt, jsp, &next, jb, found, false);
2340 }

References DatumGetNumeric(), DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, executeItemUnwrapTargetArray(), executeNextItem(), getScalar(), jbvArray, jbvNumeric, jperOk, JsonbType(), jspGetNext(), jspOperationName(), next, NumericGetDatum(), palloc(), RETURN_ERROR, JsonbValue::type, JsonPathItem::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ executePredicate()

static JsonPathBool executePredicate ( JsonPathExecContext cxt,
JsonPathItem pred,
JsonPathItem larg,
JsonPathItem rarg,
JsonbValue jb,
bool  unwrapRightArg,
JsonPathPredicateCallback  exec,
void *  param 
)
static

Definition at line 2041 of file jsonpath_exec.c.

2045 {
2047  JsonValueListIterator lseqit;
2048  JsonValueList lseq = {0};
2049  JsonValueList rseq = {0};
2050  JsonbValue *lval;
2051  bool error = false;
2052  bool found = false;
2053 
2054  /* Left argument is always auto-unwrapped. */
2055  res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
2056  if (jperIsError(res))
2057  return jpbUnknown;
2058 
2059  if (rarg)
2060  {
2061  /* Right argument is conditionally auto-unwrapped. */
2062  res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
2063  unwrapRightArg, &rseq);
2064  if (jperIsError(res))
2065  return jpbUnknown;
2066  }
2067 
2068  JsonValueListInitIterator(&lseq, &lseqit);
2069  while ((lval = JsonValueListNext(&lseq, &lseqit)))
2070  {
2071  JsonValueListIterator rseqit;
2072  JsonbValue *rval;
2073  bool first = true;
2074 
2075  JsonValueListInitIterator(&rseq, &rseqit);
2076  if (rarg)
2077  rval = JsonValueListNext(&rseq, &rseqit);
2078  else
2079  rval = NULL;
2080 
2081  /* Loop over right arg sequence or do single pass otherwise */
2082  while (rarg ? (rval != NULL) : first)
2083  {
2084  JsonPathBool res = exec(pred, lval, rval, param);
2085 
2086  if (res == jpbUnknown)
2087  {
2088  if (jspStrictAbsenceOfErrors(cxt))
2089  return jpbUnknown;
2090 
2091  error = true;
2092  }
2093  else if (res == jpbTrue)
2094  {
2095  if (!jspStrictAbsenceOfErrors(cxt))
2096  return jpbTrue;
2097 
2098  found = true;
2099  }
2100 
2101  first = false;
2102  if (rarg)
2103  rval = JsonValueListNext(&rseq, &rseqit);
2104  }
2105  }
2106 
2107  if (found) /* possible only in strict mode */
2108  return jpbTrue;
2109 
2110  if (error) /* possible only in lax mode */
2111  return jpbUnknown;
2112 
2113  return jpbFalse;
2114 }
Definition: type.h:115

References error(), executeItemOptUnwrapResultNoThrow(), jpbFalse, jpbTrue, jpbUnknown, jperIsError, JsonValueListInitIterator(), JsonValueListNext(), jspStrictAbsenceOfErrors, and res.

Referenced by executeBoolItem().

◆ executeStartsWith()

static JsonPathBool executeStartsWith ( JsonPathItem jsp,
JsonbValue whole,
JsonbValue initial,
void *  param 
)
static

Definition at line 2259 of file jsonpath_exec.c.

2261 {
2262  if (!(whole = getScalar(whole, jbvString)))
2263  return jpbUnknown; /* error */
2264 
2265  if (!(initial = getScalar(initial, jbvString)))
2266  return jpbUnknown; /* error */
2267 
2268  if (whole->val.string.len >= initial->val.string.len &&
2269  !memcmp(whole->val.string.val,
2270  initial->val.string.val,
2271  initial->val.string.len))
2272  return jpbTrue;
2273 
2274  return jpbFalse;
2275 }

References getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, and JsonbValue::val.

Referenced by executeBoolItem().

◆ executeUnaryArithmExpr()

static JsonPathExecResult executeUnaryArithmExpr ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
PGFunction  func,
JsonValueList found 
)
static

Definition at line 2192 of file jsonpath_exec.c.

2194 {
2195  JsonPathExecResult jper;
2196  JsonPathExecResult jper2;
2197  JsonPathItem elem;
2198  JsonValueList seq = {0};
2200  JsonbValue *val;
2201  bool hasNext;
2202 
2203  jspGetArg(jsp, &elem);
2204  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
2205 
2206  if (jperIsError(jper))
2207  return jper;
2208 
2209  jper = jperNotFound;
2210 
2211  hasNext = jspGetNext(jsp, &elem);
2212 
2213  JsonValueListInitIterator(&seq, &it);
2214  while ((val = JsonValueListNext(&seq, &it)))
2215  {
2216  if ((val = getScalar(val, jbvNumeric)))
2217  {
2218  if (!found && !hasNext)
2219  return jperOk;
2220  }
2221  else
2222  {
2223  if (!found && !hasNext)
2224  continue; /* skip non-numerics processing */
2225 
2227  (errcode(ERRCODE_SQL_JSON_NUMBER_NOT_FOUND),
2228  errmsg("operand of unary jsonpath operator %s is not a numeric value",
2229  jspOperationName(jsp->type)))));
2230  }
2231 
2232  if (func)
2233  val->val.numeric =
2235  NumericGetDatum(val->val.numeric)));
2236 
2237  jper2 = executeNextItem(cxt, jsp, &elem, val, found, false);
2238 
2239  if (jperIsError(jper2))
2240  return jper2;
2241 
2242  if (jper2 == jperOk)
2243  {
2244  if (!found)
2245  return jperOk;
2246  jper = jperOk;
2247  }
2248  }
2249 
2250  return jper;
2251 }

References DatumGetNumeric(), DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, executeItemOptUnwrapResult(), executeNextItem(), getScalar(), jbvNumeric, jperIsError, jperNotFound, jperOk, JsonValueListInitIterator(), JsonValueListNext(), jspGetArg(), jspGetNext(), jspOperationName(), NumericGetDatum(), RETURN_ERROR, JsonPathItem::type, and val.

Referenced by executeItemOptUnwrapTarget().

◆ getArrayIndex()

static JsonPathExecResult getArrayIndex ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
int32 index 
)
static

Definition at line 3449 of file jsonpath_exec.c.

3451 {
3452  JsonbValue *jbv;
3453  JsonValueList found = {0};
3454  JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
3455  Datum numeric_index;
3456  bool have_error = false;
3457 
3458  if (jperIsError(res))
3459  return res;
3460 
3461  if (JsonValueListLength(&found) != 1 ||
3462  !(jbv = getScalar(JsonValueListHead(&found), jbvNumeric)))
3464  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
3465  errmsg("jsonpath array subscript is not a single numeric value"))));
3466 
3467  numeric_index = DirectFunctionCall2(numeric_trunc,
3468  NumericGetDatum(jbv->val.numeric),
3469  Int32GetDatum(0));
3470 
3471  *index = numeric_int4_opt_error(DatumGetNumeric(numeric_index),
3472  &have_error);
3473 
3474  if (have_error)
3476  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
3477  errmsg("jsonpath array subscript is out of integer range"))));
3478 
3479  return jperOk;
3480 }
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:1583

References DatumGetNumeric(), DirectFunctionCall2, ereport, errcode(), errmsg(), ERROR, executeItem(), getScalar(), Int32GetDatum(), jbvNumeric, jperIsError, jperOk, JsonValueListHead(), JsonValueListLength(), numeric_int4_opt_error(), numeric_trunc(), NumericGetDatum(), res, RETURN_ERROR, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ getJsonPathItem()

static void getJsonPathItem ( JsonPathExecContext cxt,
JsonPathItem item,
JsonbValue value 
)
static

Definition at line 2949 of file jsonpath_exec.c.

2951 {
2952  switch (item->type)
2953  {
2954  case jpiNull:
2955  value->type = jbvNull;
2956  break;
2957  case jpiBool:
2958  value->type = jbvBool;
2959  value->val.boolean = jspGetBool(item);
2960  break;
2961  case jpiNumeric:
2962  value->type = jbvNumeric;
2963  value->val.numeric = jspGetNumeric(item);
2964  break;
2965  case jpiString:
2966  value->type = jbvString;
2967  value->val.string.val = jspGetString(item,
2968  &value->val.string.len);
2969  break;
2970  case jpiVariable:
2971  getJsonPathVariable(cxt, item, value);
2972  return;
2973  default:
2974  elog(ERROR, "unexpected jsonpath item type");
2975  }
2976 }
bool jspGetBool(JsonPathItem *v)
Definition: jsonpath.c:1203
static void getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable, JsonbValue *value)

References elog, ERROR, getJsonPathVariable(), jbvBool, jbvNull, jbvNumeric, jbvString, jpiBool, jpiNull, jpiNumeric, jpiString, jpiVariable, jspGetBool(), jspGetNumeric(), jspGetString(), JsonPathItem::type, and value.

Referenced by executeItemOptUnwrapTarget().

◆ GetJsonPathVar()

static JsonbValue * GetJsonPathVar ( void *  cxt,
char *  varName,
int  varNameLen,
JsonbValue baseObject,
int *  baseObjectId 
)
static

Definition at line 2982 of file jsonpath_exec.c.

2984 {
2985  JsonPathVariable *var = NULL;
2986  List *vars = cxt;
2987  ListCell *lc;
2988  JsonbValue *result;
2989  int id = 1;
2990 
2991  foreach(lc, vars)
2992  {
2993  JsonPathVariable *curvar = lfirst(lc);
2994 
2995  if (!strncmp(curvar->name, varName, varNameLen))
2996  {
2997  var = curvar;
2998  break;
2999  }
3000 
3001  id++;
3002  }
3003 
3004  if (var == NULL)
3005  {
3006  *baseObjectId = -1;
3007  return NULL;
3008  }
3009 
3010  result = palloc(sizeof(JsonbValue));
3011  if (var->isnull)
3012  {
3013  *baseObjectId = 0;
3014  result->type = jbvNull;
3015  }
3016  else
3017  JsonItemFromDatum(var->value, var->typid, var->typmod, result);
3018 
3019  *baseObject = *result;
3020  *baseObjectId = id;
3021 
3022  return result;
3023 }
static void JsonItemFromDatum(Datum val, Oid typid, int32 typmod, JsonbValue *res)
#define lfirst(lc)
Definition: pg_list.h:172

References JsonPathVariable::isnull, jbvNull, JsonItemFromDatum(), lfirst, JsonPathVariable::name, palloc(), JsonbValue::type, JsonPathVariable::typid, JsonPathVariable::typmod, and JsonPathVariable::value.

Referenced by JsonPathExists(), JsonPathQuery(), JsonPathValue(), and JsonTableResetRowPattern().

◆ getJsonPathVariable()

static void getJsonPathVariable ( JsonPathExecContext cxt,
JsonPathItem variable,
JsonbValue value 
)
static

Definition at line 3131 of file jsonpath_exec.c.

3133 {
3134  char *varName;
3135  int varNameLength;
3136  JsonbValue baseObject;
3137  int baseObjectId;
3138  JsonbValue *v;
3139 
3141  varName = jspGetString(variable, &varNameLength);
3142 
3143  if (cxt->vars == NULL ||
3144  (v = cxt->getVar(cxt->vars, varName, varNameLength,
3145  &baseObject, &baseObjectId)) == NULL)
3146  ereport(ERROR,
3147  (errcode(ERRCODE_UNDEFINED_OBJECT),
3148  errmsg("could not find jsonpath variable \"%s\"",
3149  pnstrdup(varName, varNameLength))));
3150 
3151  if (baseObjectId > 0)
3152  {
3153  *value = *v;
3154  setBaseObject(cxt, &baseObject, baseObjectId);
3155  }
3156 }
enum ECPGttype type

References Assert, ereport, errcode(), errmsg(), ERROR, JsonPathExecContext::getVar, jpiVariable, jspGetString(), pnstrdup(), setBaseObject(), variable::type, value, and JsonPathExecContext::vars.

Referenced by getJsonPathItem().

◆ getJsonPathVariableFromJsonb()

static JsonbValue * getJsonPathVariableFromJsonb ( void *  varsJsonb,
char *  varName,
int  varNameLen,
JsonbValue baseObject,
int *  baseObjectId 
)
static

Definition at line 3163 of file jsonpath_exec.c.

3165 {
3166  Jsonb *vars = varsJsonb;
3167  JsonbValue tmp;
3168  JsonbValue *result;
3169 
3170  tmp.type = jbvString;
3171  tmp.val.string.val = varName;
3172  tmp.val.string.len = varNameLength;
3173 
3174  result = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
3175 
3176  if (result == NULL)
3177  {
3178  *baseObjectId = -1;
3179  return NULL;
3180  }
3181 
3182  *baseObjectId = 1;
3183  JsonbInitBinary(baseObject, vars);
3184 
3185  return result;
3186 }

References findJsonbValueFromContainer(), JB_FOBJECT, jbvString, JsonbInitBinary(), JsonbValue::type, and JsonbValue::val.

Referenced by jsonb_path_exists_internal(), jsonb_path_match_internal(), jsonb_path_query_array_internal(), jsonb_path_query_first_internal(), and jsonb_path_query_internal().

◆ GetJsonTableExecContext()

static JsonTableExecContext* GetJsonTableExecContext ( TableFuncScanState state,
const char *  fname 
)
inlinestatic

Definition at line 4066 of file jsonpath_exec.c.

4067 {
4068  JsonTableExecContext *result;
4069 
4070  if (!IsA(state, TableFuncScanState))
4071  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4072  result = (JsonTableExecContext *) state->opaque;
4074  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4075 
4076  return result;
4077 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define JSON_TABLE_EXEC_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
Definition: regguts.h:323

References elog, ERROR, if(), IsA, JSON_TABLE_EXEC_CONTEXT_MAGIC, and JsonTableExecContext::magic.

Referenced by JsonTableDestroyOpaque(), JsonTableFetchRow(), JsonTableGetValue(), and JsonTableSetDocument().

◆ getScalar()

static JsonbValue * getScalar ( JsonbValue scalar,
enum jbvType  type 
)
static

Definition at line 3628 of file jsonpath_exec.c.

3629 {
3630  /* Scalars should be always extracted during jsonpath execution. */
3631  Assert(scalar->type != jbvBinary ||
3632  !JsonContainerIsScalar(scalar->val.binary.data));
3633 
3634  return scalar->type == type ? scalar : NULL;
3635 }
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
const char * type

References Assert, jbvBinary, JsonContainerIsScalar, type, JsonbValue::type, and JsonbValue::val.

Referenced by executeBinaryArithmExpr(), executeDateTimeMethod(), executeLikeRegex(), executeNumericItemMethod(), executeStartsWith(), executeUnaryArithmExpr(), and getArrayIndex().

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 427 of file jsonpath_exec.c.

428 {
429  return jsonb_path_exists_internal(fcinfo, false);
430 }
static Datum jsonb_path_exists_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_exists_internal().

◆ jsonb_path_exists_internal()

static Datum jsonb_path_exists_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 399 of file jsonpath_exec.c.

400 {
401  Jsonb *jb = PG_GETARG_JSONB_P(0);
404  Jsonb *vars = NULL;
405  bool silent = true;
406 
407  if (PG_NARGS() == 4)
408  {
409  vars = PG_GETARG_JSONB_P(2);
410  silent = PG_GETARG_BOOL(3);
411  }
412 
415  jb, !silent, NULL, tz);
416 
417  PG_FREE_IF_COPY(jb, 0);
418  PG_FREE_IF_COPY(jp, 1);
419 
420  if (jperIsError(res))
421  PG_RETURN_NULL();
422 
424 }
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_NARGS()
Definition: fmgr.h:203
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:46
static JsonbValue * getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
static int countVariablesFromJsonb(void *varsJsonb)
static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars, JsonPathGetVarCallback getVar, JsonPathCountVarsCallback countVars, Jsonb *json, bool throwErrors, JsonValueList *result, bool useTz)

References countVariablesFromJsonb(), executeJsonPath(), getJsonPathVariableFromJsonb(), jperIsError, jperOk, PG_FREE_IF_COPY, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_GETARG_JSONPATH_P, PG_NARGS, PG_RETURN_BOOL, PG_RETURN_NULL, and res.

Referenced by jsonb_path_exists(), jsonb_path_exists_opr(), and jsonb_path_exists_tz().

◆ jsonb_path_exists_opr()

Datum jsonb_path_exists_opr ( PG_FUNCTION_ARGS  )

Definition at line 444 of file jsonpath_exec.c.

445 {
446  /* just call the other one -- it can handle both cases */
447  return jsonb_path_exists_internal(fcinfo, false);
448 }

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 433 of file jsonpath_exec.c.

434 {
435  return jsonb_path_exists_internal(fcinfo, true);
436 }

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 497 of file jsonpath_exec.c.

498 {
499  return jsonb_path_match_internal(fcinfo, false);
500 }
static Datum jsonb_path_match_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_match_internal().

◆ jsonb_path_match_internal()

static Datum jsonb_path_match_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 456 of file jsonpath_exec.c.

457 {
458  Jsonb *jb = PG_GETARG_JSONB_P(0);
460  JsonValueList found = {0};
461  Jsonb *vars = NULL;
462  bool silent = true;
463 
464  if (PG_NARGS() == 4)
465  {
466  vars = PG_GETARG_JSONB_P(2);
467  silent = PG_GETARG_BOOL(3);
468  }
469 
472  jb, !silent, &found, tz);
473 
474  PG_FREE_IF_COPY(jb, 0);
475  PG_FREE_IF_COPY(jp, 1);
476 
477  if (JsonValueListLength(&found) == 1)
478  {
479  JsonbValue *jbv = JsonValueListHead(&found);
480 
481  if (jbv->type == jbvBool)
482  PG_RETURN_BOOL(jbv->val.boolean);
483 
484  if (jbv->type == jbvNull)
485  PG_RETURN_NULL();
486  }
487 
488  if (!silent)
489  ereport(ERROR,
490  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
491  errmsg("single boolean result is expected")));
492 
493  PG_RETURN_NULL();
494 }

References countVariablesFromJsonb(), ereport, errcode(), errmsg(), ERROR, executeJsonPath(), getJsonPathVariableFromJsonb(), jbvBool, jbvNull, JsonValueListHead(), JsonValueListLength(), PG_FREE_IF_COPY, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_GETARG_JSONPATH_P, PG_NARGS, PG_RETURN_BOOL, PG_RETURN_NULL, JsonbValue::type, and JsonbValue::val.

Referenced by jsonb_path_match(), jsonb_path_match_opr(), and jsonb_path_match_tz().

◆ jsonb_path_match_opr()

Datum jsonb_path_match_opr ( PG_FUNCTION_ARGS  )

Definition at line 514 of file jsonpath_exec.c.

515 {
516  /* just call the other one -- it can handle both cases */
517  return jsonb_path_match_internal(fcinfo, false);
518 }

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 503 of file jsonpath_exec.c.

504 {
505  return jsonb_path_match_internal(fcinfo, true);
506 }

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 574 of file jsonpath_exec.c.

575 {
576  return jsonb_path_query_internal(fcinfo, false);
577 }
static Datum jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_query_internal().

◆ jsonb_path_query_array()

Datum jsonb_path_query_array ( PG_FUNCTION_ARGS  )

Definition at line 607 of file jsonpath_exec.c.

608 {
609  return jsonb_path_query_array_internal(fcinfo, false);
610 }
static Datum jsonb_path_query_array_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_query_array_internal().

◆ jsonb_path_query_array_internal()

static Datum jsonb_path_query_array_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 591 of file jsonpath_exec.c.

592 {
593  Jsonb *jb = PG_GETARG_JSONB_P(0);
595  JsonValueList found = {0};
597  bool silent = PG_GETARG_BOOL(3);
598 
601  jb, !silent, &found, tz);
602 
604 }
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
static JsonbValue * wrapItemsInArray(const JsonValueList *items)

References countVariablesFromJsonb(), executeJsonPath(), getJsonPathVariableFromJsonb(), JsonbValueToJsonb(), PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_GETARG_JSONPATH_P, PG_RETURN_JSONB_P, and wrapItemsInArray().

Referenced by jsonb_path_query_array(), and jsonb_path_query_array_tz().

◆ jsonb_path_query_array_tz()

Datum jsonb_path_query_array_tz ( PG_FUNCTION_ARGS  )

Definition at line 613 of file jsonpath_exec.c.

614 {
615  return jsonb_path_query_array_internal(fcinfo, true);
616 }

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 643 of file jsonpath_exec.c.

644 {
645  return jsonb_path_query_first_internal(fcinfo, false);
646 }
static Datum jsonb_path_query_first_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_query_first_internal().

◆ jsonb_path_query_first_internal()

static Datum jsonb_path_query_first_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 649 of file jsonpath_exec.c.

650 {
651  return jsonb_path_query_first_internal(fcinfo, true);
652 }

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 526 of file jsonpath_exec.c.

527 {
528  FuncCallContext *funcctx;
529  List *found;
530  JsonbValue *v;
531  ListCell *c;
532 
533  if (SRF_IS_FIRSTCALL())
534  {
535  JsonPath *jp;
536  Jsonb *jb;
537  MemoryContext oldcontext;
538  Jsonb *vars;
539  bool silent;
540  JsonValueList found = {0};
541 
542  funcctx = SRF_FIRSTCALL_INIT();
543  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
544 
545  jb = PG_GETARG_JSONB_P_COPY(0);
548  silent = PG_GETARG_BOOL(3);
549 
552  jb, !silent, &found, tz);
553 
554  funcctx->user_fctx = JsonValueListGetList(&found);
555 
556  MemoryContextSwitchTo(oldcontext);
557  }
558 
559  funcctx = SRF_PERCALL_SETUP();
560  found = funcctx->user_fctx;
561 
562  c = list_head(found);
563 
564  if (c == NULL)
565  SRF_RETURN_DONE(funcctx);
566 
567  v = lfirst(c);
568  funcctx->user_fctx = list_delete_first(found);
569 
571 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
#define PG_GETARG_JSONB_P_COPY(x)
Definition: jsonb.h:392
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:386
#define PG_GETARG_JSONPATH_P_COPY(x)
Definition: jsonpath.h:47
static List * JsonValueListGetList(JsonValueList *jvl)
List * list_delete_first(List *list)
Definition: list.c:943
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
char * c
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101

References countVariablesFromJsonb(), executeJsonPath(), getJsonPathVariableFromJsonb(), JsonbPGetDatum(), JsonbValueToJsonb(), JsonValueListGetList(), lfirst, list_delete_first(), list_head(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, PG_GETARG_BOOL, PG_GETARG_JSONB_P_COPY, PG_GETARG_JSONPATH_P_COPY, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.

Referenced by jsonb_path_query(), and jsonb_path_query_tz().

◆ jsonb_path_query_tz()

Datum jsonb_path_query_tz ( PG_FUNCTION_ARGS  )

Definition at line 580 of file jsonpath_exec.c.

581 {
582  return jsonb_path_query_internal(fcinfo, true);
583 }

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3215 of file jsonpath_exec.c.

3216 {
3217  Assert(jb->type != jbvArray);
3218 
3219  if (jb->type == jbvBinary)
3220  {
3221  JsonbContainer *jbc = jb->val.binary.data;
3222 
3223  if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
3224  return JsonContainerSize(jbc);
3225  }
3226 
3227  return -1;
3228 }
#define JsonContainerIsArray(jc)
Definition: jsonb.h:209

References Assert, jbvArray, jbvBinary, JsonContainerIsArray, JsonContainerIsScalar, JsonContainerSize, JsonbValue::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ JsonbInitBinary()

static JsonbValue * JsonbInitBinary ( JsonbValue jbv,
Jsonb jb 
)
static

Definition at line 3591 of file jsonpath_exec.c.

3592 {
3593  jbv->type = jbvBinary;
3594  jbv->val.binary.data = &jb->root;
3595  jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3596 
3597  return jbv;
3598 }
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

References jbvBinary, Jsonb::root, JsonbValue::type, JsonbValue::val, and VARSIZE_ANY_EXHDR.

Referenced by executeJsonPath(), executeKeyValueMethod(), getJsonPathVariableFromJsonb(), and JsonItemFromDatum().

◆ JsonbType()

static int JsonbType ( JsonbValue jb)
static

Definition at line 3604 of file jsonpath_exec.c.

3605 {
3606  int type = jb->type;
3607 
3608  if (jb->type == jbvBinary)
3609  {
3610  JsonbContainer *jbc = (void *) jb->val.binary.data;
3611 
3612  /* Scalars should be always extracted during jsonpath execution. */
3614 
3615  if (JsonContainerIsObject(jbc))
3616  type = jbvObject;
3617  else if (JsonContainerIsArray(jbc))
3618  type = jbvArray;
3619  else
3620  elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
3621  }
3622 
3623  return type;
3624 }
uint32 header
Definition: jsonb.h:192

References Assert, elog, ERROR, JsonbContainer::header, jbvArray, jbvBinary, jbvObject, JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, type, JsonbValue::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapResult(), executeItemOptUnwrapTarget(), executeKeyValueMethod(), and executeNumericItemMethod().

◆ JsonbValueInitNumericDatum()

static void JsonbValueInitNumericDatum ( JsonbValue jbv,
Datum  num 
)
static

Definition at line 3121 of file jsonpath_exec.c.

3122 {
3123  jbv->type = jbvNumeric;
3124  jbv->val.numeric = DatumGetNumeric(num);
3125 }

References DatumGetNumeric(), jbvNumeric, JsonbValue::type, and JsonbValue::val.

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

static void JsonItemFromDatum ( Datum  val,
Oid  typid,
int32  typmod,
JsonbValue res 
)
static

Definition at line 3039 of file jsonpath_exec.c.

3040 {
3041  switch (typid)
3042  {
3043  case BOOLOID:
3044  res->type = jbvBool;
3045  res->val.boolean = DatumGetBool(val);
3046  break;
3047  case NUMERICOID:
3049  break;
3050  case INT2OID:
3052  break;
3053  case INT4OID:
3055  break;
3056  case INT8OID:
3058  break;
3059  case FLOAT4OID:
3061  break;
3062  case FLOAT8OID:
3064  break;
3065  case TEXTOID:
3066  case VARCHAROID:
3067  res->type = jbvString;
3068  res->val.string.val = VARDATA_ANY(val);
3069  res->val.string.len = VARSIZE_ANY_EXHDR(val);
3070  break;
3071  case DATEOID:
3072  case TIMEOID:
3073  case TIMETZOID:
3074  case TIMESTAMPOID:
3075  case TIMESTAMPTZOID:
3076  res->type = jbvDatetime;
3077  res->val.datetime.value = val;
3078  res->val.datetime.typid = typid;
3079  res->val.datetime.typmod = typmod;
3080  res->val.datetime.tz = 0;
3081  break;
3082  case JSONBOID:
3083  {
3084  JsonbValue *jbv = res;
3085  Jsonb *jb = DatumGetJsonbP(val);
3086 
3087  if (JsonContainerIsScalar(&jb->root))
3088  {
3089  bool result PG_USED_FOR_ASSERTS_ONLY;
3090 
3091  result = JsonbExtractScalar(&jb->root, jbv);
3092  Assert(result);
3093  }
3094  else
3095  JsonbInitBinary(jbv, jb);
3096  break;
3097  }
3098  case JSONOID:
3099  {
3100  text *txt = DatumGetTextP(val);
3101  char *str = text_to_cstring(txt);
3102  Jsonb *jb;
3103 
3105  CStringGetDatum(str)));
3106  pfree(str);
3107 
3108  JsonItemFromDatum(JsonbPGetDatum(jb), JSONBOID, -1, res);
3109  break;
3110  }
3111  default:
3112  ereport(ERROR,
3113  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3114  errmsg("could not convert value of type %s to jsonpath",
3115  format_type_be(typid)));
3116  }
3117 }
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4687
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4544
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:182
#define DatumGetTextP(X)
Definition: fmgr.h:332
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:73
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
static void JsonbValueInitNumericDatum(JsonbValue *jbv, Datum num)
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
#define VARDATA_ANY(PTR)
Definition: varatt.h:324

References Assert, CStringGetDatum(), DatumGetBool(), DatumGetJsonbP(), DatumGetTextP, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, float4_numeric(), float8_numeric(), format_type_be(), int2_numeric(), int4_numeric(), int8_numeric(), jbvBool, jbvDatetime, jbvString, jsonb_in(), JsonbExtractScalar(), JsonbInitBinary(), JsonbPGetDatum(), JsonbValueInitNumericDatum(), JsonContainerIsScalar, pfree(), PG_USED_FOR_ASSERTS_ONLY, res, Jsonb::root, str, text_to_cstring(), val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by GetJsonPathVar().

◆ JsonPathExists()

bool JsonPathExists ( Datum  jb,
JsonPath jp,
bool error,
List vars 
)

Definition at line 3878 of file jsonpath_exec.c.

3879 {
3881 
3882  res = executeJsonPath(jp, vars,
3884  DatumGetJsonbP(jb), !error, NULL, true);
3885 
3886  Assert(error || !jperIsError(res));
3887 
3888  if (error && jperIsError(res))
3889  *error = true;
3890 
3891  return res == jperOk;
3892 }
static JsonbValue * GetJsonPathVar(void *cxt, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
static int CountJsonPathVars(void *cxt)

References Assert, CountJsonPathVars(), DatumGetJsonbP(), error(), executeJsonPath(), GetJsonPathVar(), jperIsError, jperOk, and res.

Referenced by ExecEvalJsonExprPath().

◆ JsonPathQuery()

Datum JsonPathQuery ( Datum  jb,
JsonPath jp,
JsonWrapper  wrapper,
bool empty,
bool error,
List vars,
const char *  column_name 
)

Definition at line 3901 of file jsonpath_exec.c.

3904 {
3905  JsonbValue *singleton;
3906  bool wrap;
3907  JsonValueList found = {0};
3909  int count;
3910 
3911  res = executeJsonPath(jp, vars,
3913  DatumGetJsonbP(jb), !error, &found, true);
3914  Assert(error || !jperIsError(res));
3915  if (error && jperIsError(res))
3916  {
3917  *error = true;
3918  *empty = false;
3919  return (Datum) 0;
3920  }
3921 
3922  /* WRAP or not? */
3923  count = JsonValueListLength(&found);
3924  singleton = count > 0 ? JsonValueListHead(&found) : NULL;
3925  if (singleton == NULL)
3926  wrap = false;
3927  else if (wrapper == JSW_NONE || wrapper == JSW_UNSPEC)
3928  wrap = false;
3929  else if (wrapper == JSW_UNCONDITIONAL)
3930  wrap = true;
3931  else if (wrapper == JSW_CONDITIONAL)
3932  wrap = count > 1 ||
3933  IsAJsonbScalar(singleton) ||
3934  (singleton->type == jbvBinary &&
3935  JsonContainerIsScalar(singleton->val.binary.data));
3936  else
3937  {
3938  elog(ERROR, "unrecognized json wrapper %d", (int) wrapper);
3939  wrap = false;
3940  }
3941 
3942  if (wrap)
3944 
3945  /* No wrapping means only one item is expected. */
3946  if (count > 1)
3947  {
3948  if (error)
3949  {
3950  *error = true;
3951  return (Datum) 0;
3952  }
3953 
3954  if (column_name)
3955  ereport(ERROR,
3956  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3957  errmsg("JSON path expression for column \"%s\" should return single item without wrapper",
3958  column_name),
3959  errhint("Use WITH WRAPPER clause to wrap SQL/JSON items into array.")));
3960  else
3961  ereport(ERROR,
3962  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3963  errmsg("JSON path expression in JSON_QUERY should return single item without wrapper"),
3964  errhint("Use WITH WRAPPER clause to wrap SQL/JSON items into array.")));
3965  }
3966 
3967  if (singleton)
3968  return JsonbPGetDatum(JsonbValueToJsonb(singleton));
3969 
3970  *empty = true;
3971  return PointerGetDatum(NULL);
3972 }
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297
@ JSW_UNCONDITIONAL
Definition: primnodes.h:1719
@ JSW_CONDITIONAL
Definition: primnodes.h:1718
@ JSW_UNSPEC
Definition: primnodes.h:1716
@ JSW_NONE
Definition: primnodes.h:1717

References Assert, CountJsonPathVars(), DatumGetJsonbP(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, error(), executeJsonPath(), GetJsonPathVar(), IsAJsonbScalar, jbvBinary, jperIsError, JsonbPGetDatum(), JsonbValueToJsonb(), JsonContainerIsScalar, JsonValueListHead(), JsonValueListLength(), JSW_CONDITIONAL, JSW_NONE, JSW_UNCONDITIONAL, JSW_UNSPEC, PointerGetDatum(), res, JsonbValue::type, JsonbValue::val, and wrapItemsInArray().

Referenced by ExecEvalJsonExprPath().

◆ JsonPathValue()

JsonbValue* JsonPathValue ( Datum  jb,
JsonPath jp,
bool empty,
bool error,
List vars,
const char *  column_name 
)

Definition at line 3981 of file jsonpath_exec.c.

3983 {
3984  JsonbValue *res;
3985  JsonValueList found = {0};
3987  int count;
3988 
3990  DatumGetJsonbP(jb),
3991  !error, &found, true);
3992 
3993  Assert(error || !jperIsError(jper));
3994 
3995  if (error && jperIsError(jper))
3996  {
3997  *error = true;
3998  *empty = false;
3999  return NULL;
4000  }
4001 
4002  count = JsonValueListLength(&found);
4003 
4004  *empty = (count == 0);
4005 
4006  if (*empty)
4007  return NULL;
4008 
4009  /* JSON_VALUE expects to get only singletons. */
4010  if (count > 1)
4011  {
4012  if (error)
4013  {
4014  *error = true;
4015  return NULL;
4016  }
4017 
4018  if (column_name)
4019  ereport(ERROR,
4020  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
4021  errmsg("JSON path expression for column \"%s\" should return single scalar item",
4022  column_name)));
4023  else
4024  ereport(ERROR,
4025  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
4026  errmsg("JSON path expression in JSON_VALUE should return single scalar item")));
4027  }
4028 
4029  res = JsonValueListHead(&found);
4030  if (res->type == jbvBinary && JsonContainerIsScalar(res->val.binary.data))
4031  JsonbExtractScalar(res->val.binary.data, res);
4032 
4033  /* JSON_VALUE expects to get only scalars. */
4034  if (!IsAJsonbScalar(res))
4035  {
4036  if (error)
4037  {
4038  *error = true;
4039  return NULL;
4040  }
4041 
4042  if (column_name)
4043  ereport(ERROR,
4044  (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
4045  errmsg("JSON path expression for column \"%s\" should return single scalar item",
4046  column_name)));
4047  else
4048  ereport(ERROR,
4049  (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
4050  errmsg("JSON path expression in JSON_VALUE should return single scalar item")));
4051  }
4052 
4053  if (res->type == jbvNull)
4054  return NULL;
4055 
4056  return res;
4057 }
int binary
Definition: libpq-int.h:182

References Assert, pg_result::binary, CountJsonPathVars(), DatumGetJsonbP(), ereport, errcode(), errmsg(), ERROR, error(), executeJsonPath(), GetJsonPathVar(), IsAJsonbScalar, jbvBinary, jbvNull, jperIsError, JsonbExtractScalar(), JsonContainerIsScalar, JsonValueListHead(), JsonValueListLength(), PG_USED_FOR_ASSERTS_ONLY, and res.

Referenced by ExecEvalJsonExprPath().

◆ JsonTableDestroyOpaque()

static void JsonTableDestroyOpaque ( TableFuncScanState state)
static

Definition at line 4151 of file jsonpath_exec.c.

4152 {
4153  JsonTableExecContext *cxt =
4154  GetJsonTableExecContext(state, "JsonTableDestroyOpaque");
4155 
4156  /* not valid anymore */
4157  cxt->magic = 0;
4158 
4159  state->opaque = NULL;
4160 }
static JsonTableExecContext * GetJsonTableExecContext(TableFuncScanState *state, const char *fname)

References GetJsonTableExecContext(), and JsonTableExecContext::magic.

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4413 of file jsonpath_exec.c.

4414 {
4415  JsonTableExecContext *cxt =
4416  GetJsonTableExecContext(state, "JsonTableFetchRow");
4417 
4418  return JsonTablePlanNextRow(cxt->rootplanstate);
4419 }
static bool JsonTablePlanNextRow(JsonTablePlanState *planstate)
JsonTablePlanState * rootplanstate

References GetJsonTableExecContext(), JsonTablePlanNextRow(), and JsonTableExecContext::rootplanstate.

◆ JsonTableGetValue()

static Datum JsonTableGetValue ( TableFuncScanState state,
int  colnum,
Oid  typid,
int32  typmod,
bool isnull 
)
static

Definition at line 4429 of file jsonpath_exec.c.

4431 {
4432  JsonTableExecContext *cxt =
4433  GetJsonTableExecContext(state, "JsonTableGetValue");
4434  ExprContext *econtext = state->ss.ps.ps_ExprContext;
4435  ExprState *estate = list_nth(state->colvalexprs, colnum);
4436  JsonTablePlanState *planstate = cxt->colplanstates[colnum];
4437  JsonTablePlanRowSource *current = &planstate->current;
4438  Datum result;
4439 
4440  /* Row pattern value is NULL */
4441  if (current->isnull)
4442  {
4443  result = (Datum) 0;
4444  *isnull = true;
4445  }
4446  /* Evaluate JsonExpr. */
4447  else if (estate)
4448  {
4449  Datum saved_caseValue = econtext->caseValue_datum;
4450  bool saved_caseIsNull = econtext->caseValue_isNull;
4451 
4452  /* Pass the row pattern value via CaseTestExpr. */
4453  econtext->caseValue_datum = current->value;
4454  econtext->caseValue_isNull = false;
4455 
4456  result = ExecEvalExpr(estate, econtext, isnull);
4457 
4458  econtext->caseValue_datum = saved_caseValue;
4459  econtext->caseValue_isNull = saved_caseIsNull;
4460  }
4461  /* ORDINAL column */
4462  else
4463  {
4464  result = Int32GetDatum(planstate->ordinal);
4465  *isnull = false;
4466  }
4467 
4468  return result;
4469 }
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:333
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
bool caseValue_isNull
Definition: execnodes.h:282
Datum caseValue_datum
Definition: execnodes.h:280
JsonTablePlanState ** colplanstates
JsonTablePlanRowSource current

References ExprContext::caseValue_datum, ExprContext::caseValue_isNull, JsonTableExecContext::colplanstates, JsonTablePlanState::current, ExecEvalExpr(), GetJsonTableExecContext(), Int32GetDatum(), JsonTablePlanRowSource::isnull, list_nth(), JsonTablePlanState::ordinal, and JsonTablePlanRowSource::value.

◆ JsonTableInitOpaque()

static void JsonTableInitOpaque ( TableFuncScanState state,
int  natts 
)
static

Definition at line 4087 of file jsonpath_exec.c.

4088 {
4089  JsonTableExecContext *cxt;
4090  PlanState *ps = &state->ss.ps;
4091  TableFuncScan *tfs = castNode(TableFuncScan, ps->plan);
4092  TableFunc *tf = tfs->tablefunc;
4093  JsonTablePlan *rootplan = (JsonTablePlan *) tf->plan;
4094  JsonExpr *je = castNode(JsonExpr, tf->docexpr);
4095  List *args = NIL;
4096 
4097  cxt = palloc0(sizeof(JsonTableExecContext));
4099 
4100  /*
4101  * Evaluate JSON_TABLE() PASSING arguments to be passed to the jsonpath
4102  * executor via JsonPathVariables.
4103  */
4104  if (state->passingvalexprs)
4105  {
4106  ListCell *exprlc;
4107  ListCell *namelc;
4108 
4109  Assert(list_length(state->passingvalexprs) ==
4110  list_length(je->passing_names));
4111  forboth(exprlc, state->passingvalexprs,
4112  namelc, je->passing_names)
4113  {
4114  ExprState *state = lfirst_node(ExprState, exprlc);
4115  String *name = lfirst_node(String, namelc);
4116  JsonPathVariable *var = palloc(sizeof(*var));
4117 
4118  var->name = pstrdup(name->sval);
4119  var->typid = exprType((Node *) state->expr);
4120  var->typmod = exprTypmod((Node *) state->expr);
4121 
4122  /*
4123  * Evaluate the expression and save the value to be returned by
4124  * GetJsonPathVar().
4125  */
4126  var->value = ExecEvalExpr(state, ps->ps_ExprContext,
4127  &var->isnull);
4128 
4129  args = lappend(args, var);
4130  }
4131  }
4132 
4133  cxt->colplanstates = palloc(sizeof(JsonTablePlanState *) *
4134  list_length(tf->colvalexprs));
4135 
4136  /*
4137  * Initialize plan for the root path and, recursively, also any child
4138  * plans that compute the NESTED paths.
4139  */
4140  cxt->rootplanstate = JsonTableInitPlan(cxt, rootplan, NULL, args,
4142 
4143  state->opaque = cxt;
4144 }
static JsonTablePlanState * JsonTableInitPlan(JsonTableExecContext *cxt, JsonTablePlan *plan, JsonTablePlanState *parentstate, List *args, MemoryContext mcxt)
List * lappend(List *list, void *datum)
Definition: list.c:339
void * palloc0(Size size)
Definition: mcxt.c:1346
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
Definition: value.h:64
TableFunc * tablefunc
Definition: plannodes.h:633
Node * docexpr
Definition: primnodes.h:119
const char * name

References generate_unaccent_rules::args, Assert, castNode, JsonTableExecContext::colplanstates, CurrentMemoryContext, TableFunc::docexpr, ExecEvalExpr(), exprType(), exprTypmod(), forboth, JsonPathVariable::isnull, JSON_TABLE_EXEC_CONTEXT_MAGIC, JsonTableInitPlan(), lappend(), lfirst_node, list_length(), JsonTableExecContext::magic, name, JsonPathVariable::name, NIL, palloc(), palloc0(), ps, pstrdup(), JsonTableExecContext::rootplanstate, TableFuncScan::tablefunc, JsonPathVariable::typid, JsonPathVariable::typmod, and JsonPathVariable::value.

◆ JsonTableInitPlan()

static JsonTablePlanState * JsonTableInitPlan ( JsonTableExecContext cxt,
JsonTablePlan plan,
JsonTablePlanState parentstate,
List args,
MemoryContext  mcxt 
)
static

Definition at line 4168 of file jsonpath_exec.c.

4171 {
4172  JsonTablePlanState *planstate = palloc0(sizeof(*planstate));
4173 
4174  planstate->plan = plan;
4175  planstate->parent = parentstate;
4176 
4177  if (IsA(plan, JsonTablePathScan))
4178  {
4180  int i;
4181 
4182  planstate->path = DatumGetJsonPathP(scan->path->value->constvalue);
4183  planstate->args = args;
4184  planstate->mcxt = AllocSetContextCreate(mcxt, "JsonTableExecContext",
4186 
4187  /* No row pattern evaluated yet. */
4188  planstate->current.value = PointerGetDatum(NULL);
4189  planstate->current.isnull = true;
4190 
4191  for (i = scan->colMin; i >= 0 && i <= scan->colMax; i++)
4192  cxt->colplanstates[i] = planstate;
4193 
4194  planstate->nested = scan->child ?
4195  JsonTableInitPlan(cxt, scan->child, planstate, args, mcxt) : NULL;
4196  }
4197  else if (IsA(plan, JsonTableSiblingJoin))
4198  {
4200 
4201  planstate->left = JsonTableInitPlan(cxt, join->lplan, parentstate,
4202  args, mcxt);
4203  planstate->right = JsonTableInitPlan(cxt, join->rplan, parentstate,
4204  args, mcxt);
4205  }
4206 
4207  return planstate;
4208 }
static JsonPath * DatumGetJsonPathP(Datum d)
Definition: jsonpath.h:35
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define plan(x)
Definition: pg_regress.c:162
JsonTablePath * path
Definition: primnodes.h:1870
JsonTablePlan * child
Definition: primnodes.h:1879
Const * value
Definition: primnodes.h:1843
struct JsonTablePlanState * left
struct JsonTablePlanState * nested
MemoryContext mcxt
struct JsonTablePlanState * parent
JsonTablePlan * plan
struct JsonTablePlanState * right
JsonTablePlan * rplan
Definition: primnodes.h:1900
JsonTablePlan * lplan
Definition: primnodes.h:1899

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, generate_unaccent_rules::args, JsonTablePlanState::args, JsonTablePathScan::child, JsonTablePathScan::colMin, JsonTableExecContext::colplanstates, JsonTablePlanState::current, DatumGetJsonPathP(), i, IsA, JsonTablePlanRowSource::isnull, JsonTablePlanState::left, JsonTableSiblingJoin::lplan, JsonTablePlanState::mcxt, JsonTablePlanState::nested, palloc0(), JsonTablePlanState::parent, JsonTablePlanState::path, JsonTablePathScan::path, JsonTablePlanState::plan, plan, PointerGetDatum(), JsonTablePlanState::right, JsonTableSiblingJoin::rplan, JsonTablePlanRowSource::value, and JsonTablePath::value.

Referenced by JsonTableInitOpaque().

◆ JsonTablePlanJoinNextRow()

static bool JsonTablePlanJoinNextRow ( JsonTablePlanState planstate)
static

Definition at line 4386 of file jsonpath_exec.c.

4387 {
4388 
4389  /* Fetch row from left sibling. */
4390  if (!JsonTablePlanNextRow(planstate->left))
4391  {
4392  /*
4393  * Left sibling ran out of rows, so start fetching from the right
4394  * sibling.
4395  */
4396  if (!JsonTablePlanNextRow(planstate->right))
4397  {
4398  /* Right sibling ran out of row, so there are more rows. */
4399  return false;
4400  }
4401  }
4402 
4403  return true;
4404 }

References JsonTablePlanNextRow(), JsonTablePlanState::left, and JsonTablePlanState::right.

Referenced by JsonTablePlanNextRow().

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4268 of file jsonpath_exec.c.

4269 {
4270  if (IsA(planstate->plan, JsonTablePathScan))
4271  return JsonTablePlanScanNextRow(planstate);
4272  else if (IsA(planstate->plan, JsonTableSiblingJoin))
4273  return JsonTablePlanJoinNextRow(planstate);
4274  else
4275  elog(ERROR, "invalid JsonTablePlan %d", (int) planstate->plan->type);
4276 
4277  Assert(false);
4278  /* Appease compiler */
4279  return false;
4280 }
static bool JsonTablePlanScanNextRow(JsonTablePlanState *planstate)
static bool JsonTablePlanJoinNextRow(JsonTablePlanState *planstate)

References Assert, elog, ERROR, IsA, JsonTablePlanJoinNextRow(), JsonTablePlanScanNextRow(), and JsonTablePlanState::plan.

Referenced by JsonTableFetchRow(), JsonTablePlanJoinNextRow(), and JsonTablePlanScanNextRow().

◆ JsonTablePlanScanNextRow()

static bool JsonTablePlanScanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4295 of file jsonpath_exec.c.

4296 {
4297  JsonbValue *jbv;
4298  MemoryContext oldcxt;
4299 
4300  /*
4301  * If planstate already has an active row and there is a nested plan,
4302  * check if it has an active row to join with the former.
4303  */
4304  if (!planstate->current.isnull)
4305  {
4306  if (planstate->nested && JsonTablePlanNextRow(planstate->nested))
4307  return true;
4308  }
4309 
4310  /* Fetch new row from the list of found values to set as active. */
4311  jbv = JsonValueListNext(&planstate->found, &planstate->iter);
4312 
4313  /* End of list? */
4314  if (jbv == NULL)
4315  {
4316  planstate->current.value = PointerGetDatum(NULL);
4317  planstate->current.isnull = true;
4318  return false;
4319  }
4320 
4321  /*
4322  * Set current row item for subsequent JsonTableGetValue() calls for
4323  * evaluating individual columns.
4324  */
4325  oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4326  planstate->current.value = JsonbPGetDatum(JsonbValueToJsonb(jbv));
4327  planstate->current.isnull = false;
4328  MemoryContextSwitchTo(oldcxt);
4329 
4330  /* Next row! */
4331  planstate->ordinal++;
4332 
4333  /* Process nested plan(s), if any. */
4334  if (planstate->nested)
4335  {
4336  /* Re-evaluate the nested path using the above parent row. */
4337  JsonTableResetNestedPlan(planstate->nested);
4338 
4339  /*
4340  * Now fetch the nested plan's current row to be joined against the
4341  * parent row. Any further nested plans' paths will be re-evaluated
4342  * recursively, level at a time, after setting each nested plan's
4343  * current row.
4344  */
4345  (void) JsonTablePlanNextRow(planstate->nested);
4346  }
4347 
4348  /* There are more rows. */
4349  return true;
4350 }
static void JsonTableResetNestedPlan(JsonTablePlanState *planstate)
JsonValueList found
JsonValueListIterator iter

References JsonTablePlanState::current, JsonTablePlanState::found, JsonTablePlanRowSource::isnull, JsonTablePlanState::iter, JsonbPGetDatum(), JsonbValueToJsonb(), JsonTablePlanNextRow(), JsonTableResetNestedPlan(), JsonValueListNext(), JsonTablePlanState::mcxt, MemoryContextSwitchTo(), JsonTablePlanState::nested, JsonTablePlanState::ordinal, PointerGetDatum(), and JsonTablePlanRowSource::value.

Referenced by JsonTablePlanNextRow().

◆ JsonTableResetNestedPlan()

static void JsonTableResetNestedPlan ( JsonTablePlanState planstate)
static

Definition at line 4357 of file jsonpath_exec.c.

4358 {
4359  /* This better be a child plan. */
4360  Assert(planstate->parent != NULL);
4361  if (IsA(planstate->plan, JsonTablePathScan))
4362  {
4363  JsonTablePlanState *parent = planstate->parent;
4364 
4365  if (!parent->current.isnull)
4366  JsonTableResetRowPattern(planstate, parent->current.value);
4367 
4368  /*
4369  * If this plan itself has a child nested plan, it will be reset when
4370  * the caller calls JsonTablePlanNextRow() on this plan.
4371  */
4372  }
4373  else if (IsA(planstate->plan, JsonTableSiblingJoin))
4374  {
4375  JsonTableResetNestedPlan(planstate->left);
4376  JsonTableResetNestedPlan(planstate->right);
4377  }
4378 }
static void JsonTableResetRowPattern(JsonTablePlanState *plan, Datum item)

References Assert, JsonTablePlanState::current, IsA, JsonTablePlanRowSource::isnull, JsonTableResetRowPattern(), JsonTablePlanState::left, JsonTablePlanState::parent, JsonTablePlanState::plan, JsonTablePlanState::right, and JsonTablePlanRowSource::value.

Referenced by JsonTablePlanScanNextRow().

◆ JsonTableResetRowPattern()

static void JsonTableResetRowPattern ( JsonTablePlanState plan,
Datum  item 
)
static

Definition at line 4228 of file jsonpath_exec.c.

4229 {
4230  JsonTablePathScan *scan = castNode(JsonTablePathScan, planstate->plan);
4231  MemoryContext oldcxt;
4233  Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
4234 
4235  JsonValueListClear(&planstate->found);
4236 
4237  MemoryContextResetOnly(planstate->mcxt);
4238 
4239  oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4240 
4241  res = executeJsonPath(planstate->path, planstate->args,
4243  js, scan->errorOnError,
4244  &planstate->found,
4245  true);
4246 
4247  MemoryContextSwitchTo(oldcxt);
4248 
4249  if (jperIsError(res))
4250  {
4251  Assert(!scan->errorOnError);
4252  JsonValueListClear(&planstate->found);
4253  }
4254 
4255  /* Reset plan iterator to the beginning of the item list */
4256  JsonValueListInitIterator(&planstate->found, &planstate->iter);
4257  planstate->current.value = PointerGetDatum(NULL);
4258  planstate->current.isnull = true;
4259  planstate->ordinal = 0;
4260 }
static void JsonValueListClear(JsonValueList *jvl)
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:402
JsonTablePlan plan
Definition: primnodes.h:1867

References JsonTablePlanState::args, Assert, castNode, CountJsonPathVars(), JsonTablePlanState::current, DatumGetJsonbP(), JsonTablePathScan::errorOnError, executeJsonPath(), JsonTablePlanState::found, GetJsonPathVar(), JsonTablePlanRowSource::isnull, JsonTablePlanState::iter, jperIsError, JsonValueListClear(), JsonValueListInitIterator(), JsonTablePlanState::mcxt, MemoryContextResetOnly(), MemoryContextSwitchTo(), JsonTablePlanState::ordinal, JsonTablePlanState::path, JsonTablePlanState::plan, PointerGetDatum(), res, and JsonTablePlanRowSource::value.

Referenced by JsonTableResetNestedPlan(), and JsonTableSetDocument().

◆ JsonTableSetDocument()

static void JsonTableSetDocument ( TableFuncScanState state,
Datum  value 
)
static

Definition at line 4215 of file jsonpath_exec.c.

4216 {
4217  JsonTableExecContext *cxt =
4218  GetJsonTableExecContext(state, "JsonTableSetDocument");
4219 
4221 }

References GetJsonTableExecContext(), JsonTableResetRowPattern(), JsonTableExecContext::rootplanstate, and value.

◆ JsonValueListAppend()

static void JsonValueListAppend ( JsonValueList jvl,
JsonbValue jbv 
)
static

Definition at line 3503 of file jsonpath_exec.c.

3504 {
3505  if (jvl->singleton)
3506  {
3507  jvl->list = list_make2(jvl->singleton, jbv);
3508  jvl->singleton = NULL;
3509  }
3510  else if (!jvl->list)
3511  jvl->singleton = jbv;
3512  else
3513  jvl->list = lappend(jvl->list, jbv);
3514 }
#define list_make2(x1, x2)
Definition: pg_list.h:214
JsonbValue * singleton

References lappend(), JsonValueList::list, list_make2, and JsonValueList::singleton.

Referenced by executeAnyItem(), executeItemOptUnwrapResult(), and executeNextItem().

◆ JsonValueListClear()

static void JsonValueListClear ( JsonValueList jvl)
static

Definition at line 3496 of file jsonpath_exec.c.

3497 {
3498  jvl->singleton = NULL;
3499  jvl->list = NIL;
3500 }

References JsonValueList::list, NIL, and JsonValueList::singleton.

Referenced by JsonTableResetRowPattern().

◆ JsonValueListGetList()

static List * JsonValueListGetList ( JsonValueList jvl)
static

Definition at line 3535 of file jsonpath_exec.c.

3536 {
3537  if (jvl->singleton)
3538  return list_make1(jvl->singleton);
3539 
3540  return jvl->list;
3541 }
#define list_make1(x1)
Definition: pg_list.h:212

References JsonValueList::list, list_make1, and JsonValueList::singleton.

Referenced by jsonb_path_query_internal().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 3529 of file jsonpath_exec.c.

3530 {
3531  return jvl->singleton ? jvl->singleton : linitial(jvl->list);
3532 }
#define linitial(l)
Definition: pg_list.h:178

References linitial, JsonValueList::list, and JsonValueList::singleton.

Referenced by executeBinaryArithmExpr(), getArrayIndex(), jsonb_path_match_internal(), jsonb_path_query_first_internal(), JsonPathQuery(), and JsonPathValue().

◆ JsonValueListInitIterator()

static void JsonValueListInitIterator ( const JsonValueList jvl,
JsonValueListIterator it 
)
static

Definition at line 3544 of file jsonpath_exec.c.

3545 {
3546  if (jvl->singleton)
3547  {
3548  it->value = jvl->singleton;
3549  it->list = NIL;
3550  it->next = NULL;
3551  }
3552  else if (jvl->list != NIL)
3553  {
3554  it->value = (JsonbValue *) linitial(jvl->list);
3555  it->list = jvl->list;
3556  it->next = list_second_cell(jvl->list);
3557  }
3558  else
3559  {
3560  it->value = NULL;
3561  it->list = NIL;
3562  it->next = NULL;
3563  }
3564 }
static ListCell * list_second_cell(const List *l)
Definition: pg_list.h:142

References linitial, JsonValueList::list, JsonValueListIterator::list, list_second_cell(), JsonValueListIterator::next, NIL, JsonValueList::singleton, and JsonValueListIterator::value.

Referenced by executeItemOptUnwrapResult(), executePredicate(), executeUnaryArithmExpr(), JsonTableResetRowPattern(), and wrapItemsInArray().

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( JsonValueList jvl)
static

Definition at line 3523 of file jsonpath_exec.c.

3524 {
3525  return !jvl->singleton && (jvl->list == NIL);
3526 }

References JsonValueList::list, NIL, and JsonValueList::singleton.

Referenced by executeBoolItem(), and executeJsonPath().

◆ JsonValueListLength()

static int JsonValueListLength ( const JsonValueList jvl)
static

◆ JsonValueListNext()

static JsonbValue * JsonValueListNext ( const JsonValueList jvl,
JsonValueListIterator it 
)
static

Definition at line 3570 of file jsonpath_exec.c.

3571 {
3572  JsonbValue *result = it->value;
3573 
3574  if (it->next)
3575  {
3576  it->value = lfirst(it->next);
3577  it->next = lnext(it->list, it->next);
3578  }
3579  else
3580  {
3581  it->value = NULL;
3582  }
3583 
3584  return result;
3585 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

References lfirst, JsonValueListIterator::list, lnext(), JsonValueListIterator::next, and JsonValueListIterator::value.

Referenced by executeItemOptUnwrapResult(), executePredicate(), executeUnaryArithmExpr(), JsonTablePlanScanNextRow(), and wrapItemsInArray().

◆ setBaseObject()

static JsonBaseObjectInfo setBaseObject ( JsonPathExecContext cxt,
JsonbValue jbv,
int32  id 
)
static

Definition at line 3484 of file jsonpath_exec.c.

3485 {
3486  JsonBaseObjectInfo baseObject = cxt->baseObject;
3487 
3488  cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
3489  (JsonbContainer *) jbv->val.binary.data;
3490  cxt->baseObject.id = id;
3491 
3492  return baseObject;
3493 }

References JsonPathExecContext::baseObject, JsonBaseObjectInfo::id, JsonBaseObjectInfo::jbc, jbvBinary, JsonbValue::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget(), executeKeyValueMethod(), and getJsonPathVariable().

◆ wrapItemsInArray()

static JsonbValue * wrapItemsInArray ( const JsonValueList items)
static

Definition at line 3639 of file jsonpath_exec.c.

3640 {
3641  JsonbParseState *ps = NULL;
3643  JsonbValue *jbv;
3644 
3646 
3648  while ((jbv = JsonValueListNext(items, &it)))
3649  pushJsonbValue(&ps, WJB_ELEM, jbv);
3650 
3651  return pushJsonbValue(&ps, WJB_END_ARRAY, NULL);
3652 }
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
static ItemArray items
Definition: test_tidstore.c:49

References items, JsonValueListInitIterator(), JsonValueListNext(), ps, pushJsonbValue(), WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_END_ARRAY.

Referenced by jsonb_path_query_array_internal(), and JsonPathQuery().

Variable Documentation

◆ JsonbTableRoutine

const TableFuncRoutine JsonbTableRoutine
Initial value:
=
{
.InitOpaque = JsonTableInitOpaque,
.SetDocument = JsonTableSetDocument,
.SetNamespace = NULL,
.SetRowFilter = NULL,
.SetColumnFilter = NULL,
.FetchRow = JsonTableFetchRow,
.GetValue = JsonTableGetValue,
.DestroyOpaque = JsonTableDestroyOpaque
}
static void JsonTableSetDocument(TableFuncScanState *state, Datum value)
static void JsonTableDestroyOpaque(TableFuncScanState *state)
static void JsonTableInitOpaque(TableFuncScanState *state, int natts)
static Datum JsonTableGetValue(TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
static bool JsonTableFetchRow(TableFuncScanState *state)

Definition at line 372 of file jsonpath_exec.c.

Referenced by ExecInitTableFuncScan().