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 varNameLength, 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 JsonbValueJsonbInitBinary (JsonbValue *jbv, Jsonb *jb)
 
static int JsonbType (JsonbValue *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 *planstate, 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 2923 of file jsonpath_exec.c.

2925 {
2927  JsonbValue jbv;
2928 
2929  if (!jspGetNext(jsp, &next) && !found)
2930  return jperOk; /* found singleton boolean value */
2931 
2932  if (res == jpbUnknown)
2933  {
2934  jbv.type = jbvNull;
2935  }
2936  else
2937  {
2938  jbv.type = jbvBool;
2939  jbv.val.boolean = res == jpbTrue;
2940  }
2941 
2942  return executeNextItem(cxt, jsp, &next, &jbv, found, true);
2943 }
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 3246 of file jsonpath_exec.c.

3248 {
3249  int cmp;
3250 
3251  cmp = memcmp(s1, s2, Min(len1, len2));
3252 
3253  if (cmp != 0)
3254  return cmp;
3255 
3256  if (len1 == len2)
3257  return 0;
3258 
3259  return len1 < len2 ? -1 : 1;
3260 }
#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 3671 of file jsonpath_exec.c.

3672 {
3673  checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3674 
3675  return DirectFunctionCall1(time_timetz, time);
3676 }
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 3659 of file jsonpath_exec.c.

3660 {
3661  if (!useTz)
3662  ereport(ERROR,
3663  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3664  errmsg("cannot convert value from %s to %s without time zone usage",
3665  type1, type2),
3666  errhint("Use *_tz() function for time zone support.")));
3667 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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 3683 of file jsonpath_exec.c.

3684 {
3685  return date_cmp_timestamp_internal(date1, ts2);
3686 }
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 3692 of file jsonpath_exec.c.

3693 {
3694  checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
3695 
3696  return date_cmp_timestamptz_internal(date1, tstz2);
3697 }
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 3703 of file jsonpath_exec.c.

3704 {
3705  checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
3706 
3707  return timestamp_cmp_timestamptz_internal(ts1, tstz2);
3708 }
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 3716 of file jsonpath_exec.c.

3718 {
3719  PGFunction cmpfunc;
3720 
3721  *cast_error = false;
3722 
3723  switch (typid1)
3724  {
3725  case DATEOID:
3726  switch (typid2)
3727  {
3728  case DATEOID:
3729  cmpfunc = date_cmp;
3730 
3731  break;
3732 
3733  case TIMESTAMPOID:
3734  return cmpDateToTimestamp(DatumGetDateADT(val1),
3735  DatumGetTimestamp(val2),
3736  useTz);
3737 
3738  case TIMESTAMPTZOID:
3740  DatumGetTimestampTz(val2),
3741  useTz);
3742 
3743  case TIMEOID:
3744  case TIMETZOID:
3745  *cast_error = true; /* uncomparable types */
3746  return 0;
3747 
3748  default:
3749  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3750  typid2);
3751  }
3752  break;
3753 
3754  case TIMEOID:
3755  switch (typid2)
3756  {
3757  case TIMEOID:
3758  cmpfunc = time_cmp;
3759 
3760  break;
3761 
3762  case TIMETZOID:
3763  val1 = castTimeToTimeTz(val1, useTz);
3764  cmpfunc = timetz_cmp;
3765 
3766  break;
3767 
3768  case DATEOID:
3769  case TIMESTAMPOID:
3770  case TIMESTAMPTZOID:
3771  *cast_error = true; /* uncomparable types */
3772  return 0;
3773 
3774  default:
3775  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3776  typid2);
3777  }
3778  break;
3779 
3780  case TIMETZOID:
3781  switch (typid2)
3782  {
3783  case TIMEOID:
3784  val2 = castTimeToTimeTz(val2, useTz);
3785  cmpfunc = timetz_cmp;
3786 
3787  break;
3788 
3789  case TIMETZOID:
3790  cmpfunc = timetz_cmp;
3791 
3792  break;
3793 
3794  case DATEOID:
3795  case TIMESTAMPOID:
3796  case TIMESTAMPTZOID:
3797  *cast_error = true; /* uncomparable types */
3798  return 0;
3799 
3800  default:
3801  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3802  typid2);
3803  }
3804  break;
3805 
3806  case TIMESTAMPOID:
3807  switch (typid2)
3808  {
3809  case DATEOID:
3810  return -cmpDateToTimestamp(DatumGetDateADT(val2),
3811  DatumGetTimestamp(val1),
3812  useTz);
3813 
3814  case TIMESTAMPOID:
3815  cmpfunc = timestamp_cmp;
3816 
3817  break;
3818 
3819  case TIMESTAMPTZOID:
3821  DatumGetTimestampTz(val2),
3822  useTz);
3823 
3824  case TIMEOID:
3825  case TIMETZOID:
3826  *cast_error = true; /* uncomparable types */
3827  return 0;
3828 
3829  default:
3830  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3831  typid2);
3832  }
3833  break;
3834 
3835  case TIMESTAMPTZOID:
3836  switch (typid2)
3837  {
3838  case DATEOID:
3839  return -cmpDateToTimestampTz(DatumGetDateADT(val2),
3840  DatumGetTimestampTz(val1),
3841  useTz);
3842 
3843  case TIMESTAMPOID:
3845  DatumGetTimestampTz(val1),
3846  useTz);
3847 
3848  case TIMESTAMPTZOID:
3849  cmpfunc = timestamp_cmp;
3850 
3851  break;
3852 
3853  case TIMEOID:
3854  case TIMETZOID:
3855  *cast_error = true; /* uncomparable types */
3856  return 0;
3857 
3858  default:
3859  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3860  typid2);
3861  }
3862  break;
3863 
3864  default:
3865  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
3866  }
3867 
3868  if (*cast_error)
3869  return 0; /* cast error */
3870 
3871  return DatumGetInt32(DirectFunctionCall2(cmpfunc, val1, val2));
3872 }
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 3334 of file jsonpath_exec.c.

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

3431 {
3433  NumericGetDatum(a),
3434  NumericGetDatum(b)));
3435 }
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 3267 of file jsonpath_exec.c.

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

3439 {
3440  JsonbValue *dst = palloc(sizeof(*dst));
3441 
3442  *dst = *src;
3443 
3444  return dst;
3445 }
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 3029 of file jsonpath_exec.c.

3030 {
3031  List *vars = (List *) cxt;
3032 
3033  return list_length(vars);
3034 }
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 3196 of file jsonpath_exec.c.

3197 {
3198  Jsonb *vars = varsJsonb;
3199 
3200  if (vars && !JsonContainerIsObject(&vars->root))
3201  {
3202  ereport(ERROR,
3203  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3204  errmsg("\"vars\" argument is not an object"),
3205  errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3206  }
3207 
3208  /* count of base objects */
3209  return vars != NULL ? 1 : 0;
3210 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#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 1952 of file jsonpath_exec.c.

1955 {
1957  JsonbIterator *it;
1958  int32 r;
1959  JsonbValue v;
1960 
1962 
1963  if (level > last)
1964  return res;
1965 
1966  it = JsonbIteratorInit(jbc);
1967 
1968  /*
1969  * Recursively iterate over jsonb objects/arrays
1970  */
1971  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1972  {
1973  if (r == WJB_KEY)
1974  {
1975  r = JsonbIteratorNext(&it, &v, true);
1976  Assert(r == WJB_VALUE);
1977  }
1978 
1979  if (r == WJB_VALUE || r == WJB_ELEM)
1980  {
1981 
1982  if (level >= first ||
1983  (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
1984  v.type != jbvBinary)) /* leaves only requested */
1985  {
1986  /* check expression */
1987  if (jsp)
1988  {
1989  if (ignoreStructuralErrors)
1990  {
1991  bool savedIgnoreStructuralErrors;
1992 
1993  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1994  cxt->ignoreStructuralErrors = true;
1995  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1996  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1997  }
1998  else
1999  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2000 
2001  if (jperIsError(res))
2002  break;
2003 
2004  if (res == jperOk && !found)
2005  break;
2006  }
2007  else if (found)
2008  JsonValueListAppend(found, copyJsonbValue(&v));
2009  else
2010  return jperOk;
2011  }
2012 
2013  if (level < last && v.type == jbvBinary)
2014  {
2016  (cxt, jsp, v.val.binary.data, found,
2017  level + 1, first, last,
2018  ignoreStructuralErrors, unwrapNext);
2019 
2020  if (jperIsError(res))
2021  break;
2022 
2023  if (res == jperOk && found == NULL)
2024  break;
2025  }
2026  }
2027  }
2028 
2029  return res;
2030 }
#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 2123 of file jsonpath_exec.c.

2126 {
2127  JsonPathExecResult jper;
2128  JsonPathItem elem;
2129  JsonValueList lseq = {0};
2130  JsonValueList rseq = {0};
2131  JsonbValue *lval;
2132  JsonbValue *rval;
2133  Numeric res;
2134 
2135  jspGetLeftArg(jsp, &elem);
2136 
2137  /*
2138  * XXX: By standard only operands of multiplicative expressions are
2139  * unwrapped. We extend it to other binary arithmetic expressions too.
2140  */
2141  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2142  if (jperIsError(jper))
2143  return jper;
2144 
2145  jspGetRightArg(jsp, &elem);
2146 
2147  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2148  if (jperIsError(jper))
2149  return jper;
2150 
2151  if (JsonValueListLength(&lseq) != 1 ||
2152  !(lval = getScalar(JsonValueListHead(&lseq), jbvNumeric)))
2154  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2155  errmsg("left operand of jsonpath operator %s is not a single numeric value",
2156  jspOperationName(jsp->type)))));
2157 
2158  if (JsonValueListLength(&rseq) != 1 ||
2159  !(rval = getScalar(JsonValueListHead(&rseq), jbvNumeric)))
2161  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2162  errmsg("right operand of jsonpath operator %s is not a single numeric value",
2163  jspOperationName(jsp->type)))));
2164 
2165  if (jspThrowErrors(cxt))
2166  {
2167  res = func(lval->val.numeric, rval->val.numeric, NULL);
2168  }
2169  else
2170  {
2171  bool error = false;
2172 
2173  res = func(lval->val.numeric, rval->val.numeric, &error);
2174 
2175  if (error)
2176  return jperError;
2177  }
2178 
2179  if (!jspGetNext(jsp, &elem) && !found)
2180  return jperOk;
2181 
2182  lval = palloc(sizeof(*lval));
2183  lval->type = jbvNumeric;
2184  lval->val.numeric = res;
2185 
2186  return executeNextItem(cxt, jsp, &elem, lval, found, false);
2187 }
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 1795 of file jsonpath_exec.c.

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

3236 {
3238 
3239  return compareItems(cmp->type, lv, rv, cxt->useTz);
3240 }
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 2357 of file jsonpath_exec.c.

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

736 {
737  return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
738 }
#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 1743 of file jsonpath_exec.c.

1746 {
1747  if (unwrap && jspAutoUnwrap(cxt))
1748  {
1749  JsonValueList seq = {0};
1751  JsonPathExecResult res = executeItem(cxt, jsp, jb, &seq);
1752  JsonbValue *item;
1753 
1754  if (jperIsError(res))
1755  return res;
1756 
1757  JsonValueListInitIterator(&seq, &it);
1758  while ((item = JsonValueListNext(&seq, &it)))
1759  {
1760  Assert(item->type != jbvArray);
1761 
1762  if (JsonbType(item) == jbvArray)
1763  executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1764  else
1765  JsonValueListAppend(found, item);
1766  }
1767 
1768  return jperOk;
1769  }
1770 
1771  return executeItem(cxt, jsp, jb, found);
1772 }
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 1778 of file jsonpath_exec.c.

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

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 746 of file jsonpath_exec.c.

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

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

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 678 of file jsonpath_exec.c.

682 {
685  JsonPathItem jsp;
686  JsonbValue jbv;
687 
688  jspInit(&jsp, path);
689 
690  if (!JsonbExtractScalar(&json->root, &jbv))
691  JsonbInitBinary(&jbv, json);
692 
693  cxt.vars = vars;
694  cxt.getVar = getVar;
695  cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
697  cxt.root = &jbv;
698  cxt.current = &jbv;
699  cxt.baseObject.jbc = NULL;
700  cxt.baseObject.id = 0;
701  /* 1 + number of base objects in vars */
702  cxt.lastGeneratedObjectId = 1 + countVars(vars);
703  cxt.innermostArraySize = -1;
704  cxt.throwErrors = throwErrors;
705  cxt.useTz = useTz;
706 
707  if (jspStrictAbsenceOfErrors(&cxt) && !result)
708  {
709  /*
710  * In strict mode we must get a complete list of values to check that
711  * there are no errors at all.
712  */
713  JsonValueList vals = {0};
714 
715  res = executeItem(&cxt, &jsp, &jbv, &vals);
716 
717  if (jperIsError(res))
718  return res;
719 
720  return JsonValueListIsEmpty(&vals) ? jperNotFound : jperOk;
721  }
722 
723  res = executeItem(&cxt, &jsp, &jbv, result);
724 
725  Assert(!throwErrors || !jperIsError(res));
726 
727  return res;
728 }
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 2813 of file jsonpath_exec.c.

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

2287 {
2288  JsonLikeRegexContext *cxt = param;
2289 
2290  if (!(str = getScalar(str, jbvString)))
2291  return jpbUnknown;
2292 
2293  /* Cache regex text and converted flags. */
2294  if (!cxt->regex)
2295  {
2296  cxt->regex =
2298  jsp->content.like_regex.patternlen);
2299  (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2300  &(cxt->cflags), NULL);
2301  }
2302 
2303  if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2304  str->val.string.len,
2305  cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
2306  return jpbTrue;
2307 
2308  return jpbFalse;
2309 }
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 1931 of file jsonpath_exec.c.

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

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 1712 of file jsonpath_exec.c.

1715 {
1716  JsonPathItem elem;
1717  bool hasNext;
1718 
1719  if (!cur)
1720  hasNext = next != NULL;
1721  else if (next)
1722  hasNext = jspHasNext(cur);
1723  else
1724  {
1725  next = &elem;
1726  hasNext = jspGetNext(cur, next);
1727  }
1728 
1729  if (hasNext)
1730  return executeItem(cxt, next, v, found);
1731 
1732  if (found)
1733  JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1734 
1735  return jperOk;
1736 }
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 2316 of file jsonpath_exec.c.

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

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 2043 of file jsonpath_exec.c.

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

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

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 2194 of file jsonpath_exec.c.

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

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 3452 of file jsonpath_exec.c.

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

2953 {
2954  switch (item->type)
2955  {
2956  case jpiNull:
2957  value->type = jbvNull;
2958  break;
2959  case jpiBool:
2960  value->type = jbvBool;
2961  value->val.boolean = jspGetBool(item);
2962  break;
2963  case jpiNumeric:
2964  value->type = jbvNumeric;
2965  value->val.numeric = jspGetNumeric(item);
2966  break;
2967  case jpiString:
2968  value->type = jbvString;
2969  value->val.string.val = jspGetString(item,
2970  &value->val.string.len);
2971  break;
2972  case jpiVariable:
2973  getJsonPathVariable(cxt, item, value);
2974  return;
2975  default:
2976  elog(ERROR, "unexpected jsonpath item type");
2977  }
2978 }
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 2984 of file jsonpath_exec.c.

2986 {
2987  JsonPathVariable *var = NULL;
2988  List *vars = cxt;
2989  ListCell *lc;
2990  JsonbValue *result;
2991  int id = 1;
2992 
2993  foreach(lc, vars)
2994  {
2995  JsonPathVariable *curvar = lfirst(lc);
2996 
2997  if (curvar->namelen == varNameLen &&
2998  strncmp(curvar->name, varName, varNameLen) == 0)
2999  {
3000  var = curvar;
3001  break;
3002  }
3003 
3004  id++;
3005  }
3006 
3007  if (var == NULL)
3008  {
3009  *baseObjectId = -1;
3010  return NULL;
3011  }
3012 
3013  result = palloc(sizeof(JsonbValue));
3014  if (var->isnull)
3015  {
3016  *baseObjectId = 0;
3017  result->type = jbvNull;
3018  }
3019  else
3020  JsonItemFromDatum(var->value, var->typid, var->typmod, result);
3021 
3022  *baseObject = *result;
3023  *baseObjectId = id;
3024 
3025  return result;
3026 }
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, JsonPathVariable::namelen, 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 3134 of file jsonpath_exec.c.

3136 {
3137  char *varName;
3138  int varNameLength;
3139  JsonbValue baseObject;
3140  int baseObjectId;
3141  JsonbValue *v;
3142 
3144  varName = jspGetString(variable, &varNameLength);
3145 
3146  if (cxt->vars == NULL ||
3147  (v = cxt->getVar(cxt->vars, varName, varNameLength,
3148  &baseObject, &baseObjectId)) == NULL)
3149  ereport(ERROR,
3150  (errcode(ERRCODE_UNDEFINED_OBJECT),
3151  errmsg("could not find jsonpath variable \"%s\"",
3152  pnstrdup(varName, varNameLength))));
3153 
3154  if (baseObjectId > 0)
3155  {
3156  *value = *v;
3157  setBaseObject(cxt, &baseObject, baseObjectId);
3158  }
3159 }
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  varNameLength,
JsonbValue baseObject,
int *  baseObjectId 
)
static

Definition at line 3166 of file jsonpath_exec.c.

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

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 4069 of file jsonpath_exec.c.

4070 {
4071  JsonTableExecContext *result;
4072 
4073  if (!IsA(state, TableFuncScanState))
4074  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4075  result = (JsonTableExecContext *) state->opaque;
4077  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4078 
4079  return result;
4080 }
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 3631 of file jsonpath_exec.c.

3632 {
3633  /* Scalars should be always extracted during jsonpath execution. */
3634  Assert(scalar->type != jbvBinary ||
3635  !JsonContainerIsScalar(scalar->val.binary.data));
3636 
3637  return scalar->type == type ? scalar : NULL;
3638 }
#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 426 of file jsonpath_exec.c.

427 {
428  return jsonb_path_exists_internal(fcinfo, false);
429 }
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 398 of file jsonpath_exec.c.

399 {
400  Jsonb *jb = PG_GETARG_JSONB_P(0);
403  Jsonb *vars = NULL;
404  bool silent = true;
405 
406  if (PG_NARGS() == 4)
407  {
408  vars = PG_GETARG_JSONB_P(2);
409  silent = PG_GETARG_BOOL(3);
410  }
411 
414  jb, !silent, NULL, tz);
415 
416  PG_FREE_IF_COPY(jb, 0);
417  PG_FREE_IF_COPY(jp, 1);
418 
419  if (jperIsError(res))
420  PG_RETURN_NULL();
421 
423 }
#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 int countVariablesFromJsonb(void *varsJsonb)
static JsonbValue * getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, int varNameLength, JsonbValue *baseObject, int *baseObjectId)
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 443 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 432 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 496 of file jsonpath_exec.c.

497 {
498  return jsonb_path_match_internal(fcinfo, false);
499 }
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 455 of file jsonpath_exec.c.

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

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 513 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 502 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 573 of file jsonpath_exec.c.

574 {
575  return jsonb_path_query_internal(fcinfo, false);
576 }
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 606 of file jsonpath_exec.c.

607 {
608  return jsonb_path_query_array_internal(fcinfo, false);
609 }
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 590 of file jsonpath_exec.c.

591 {
592  Jsonb *jb = PG_GETARG_JSONB_P(0);
594  JsonValueList found = {0};
596  bool silent = PG_GETARG_BOOL(3);
597 
600  jb, !silent, &found, tz);
601 
603 }
#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 612 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 642 of file jsonpath_exec.c.

643 {
644  return jsonb_path_query_first_internal(fcinfo, false);
645 }
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 648 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 525 of file jsonpath_exec.c.

526 {
527  FuncCallContext *funcctx;
528  List *found;
529  JsonbValue *v;
530  ListCell *c;
531 
532  if (SRF_IS_FIRSTCALL())
533  {
534  JsonPath *jp;
535  Jsonb *jb;
536  MemoryContext oldcontext;
537  Jsonb *vars;
538  bool silent;
539  JsonValueList found = {0};
540 
541  funcctx = SRF_FIRSTCALL_INIT();
542  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
543 
544  jb = PG_GETARG_JSONB_P_COPY(0);
547  silent = PG_GETARG_BOOL(3);
548 
551  jb, !silent, &found, tz);
552 
553  funcctx->user_fctx = JsonValueListGetList(&found);
554 
555  MemoryContextSwitchTo(oldcontext);
556  }
557 
558  funcctx = SRF_PERCALL_SETUP();
559  found = funcctx->user_fctx;
560 
561  c = list_head(found);
562 
563  if (c == NULL)
564  SRF_RETURN_DONE(funcctx);
565 
566  v = lfirst(c);
567  funcctx->user_fctx = list_delete_first(found);
568 
570 }
#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 579 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3218 of file jsonpath_exec.c.

3219 {
3220  Assert(jb->type != jbvArray);
3221 
3222  if (jb->type == jbvBinary)
3223  {
3224  JsonbContainer *jbc = jb->val.binary.data;
3225 
3226  if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
3227  return JsonContainerSize(jbc);
3228  }
3229 
3230  return -1;
3231 }
#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 3594 of file jsonpath_exec.c.

3595 {
3596  jbv->type = jbvBinary;
3597  jbv->val.binary.data = &jb->root;
3598  jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3599 
3600  return jbv;
3601 }
#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 3607 of file jsonpath_exec.c.

3608 {
3609  int type = jb->type;
3610 
3611  if (jb->type == jbvBinary)
3612  {
3613  JsonbContainer *jbc = (void *) jb->val.binary.data;
3614 
3615  /* Scalars should be always extracted during jsonpath execution. */
3617 
3618  if (JsonContainerIsObject(jbc))
3619  type = jbvObject;
3620  else if (JsonContainerIsArray(jbc))
3621  type = jbvArray;
3622  else
3623  elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
3624  }
3625 
3626  return type;
3627 }
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 3124 of file jsonpath_exec.c.

3125 {
3126  jbv->type = jbvNumeric;
3127  jbv->val.numeric = DatumGetNumeric(num);
3128 }

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 3042 of file jsonpath_exec.c.

3043 {
3044  switch (typid)
3045  {
3046  case BOOLOID:
3047  res->type = jbvBool;
3048  res->val.boolean = DatumGetBool(val);
3049  break;
3050  case NUMERICOID:
3052  break;
3053  case INT2OID:
3055  break;
3056  case INT4OID:
3058  break;
3059  case INT8OID:
3061  break;
3062  case FLOAT4OID:
3064  break;
3065  case FLOAT8OID:
3067  break;
3068  case TEXTOID:
3069  case VARCHAROID:
3070  res->type = jbvString;
3071  res->val.string.val = VARDATA_ANY(val);
3072  res->val.string.len = VARSIZE_ANY_EXHDR(val);
3073  break;
3074  case DATEOID:
3075  case TIMEOID:
3076  case TIMETZOID:
3077  case TIMESTAMPOID:
3078  case TIMESTAMPTZOID:
3079  res->type = jbvDatetime;
3080  res->val.datetime.value = val;
3081  res->val.datetime.typid = typid;
3082  res->val.datetime.typmod = typmod;
3083  res->val.datetime.tz = 0;
3084  break;
3085  case JSONBOID:
3086  {
3087  JsonbValue *jbv = res;
3088  Jsonb *jb = DatumGetJsonbP(val);
3089 
3090  if (JsonContainerIsScalar(&jb->root))
3091  {
3092  bool result PG_USED_FOR_ASSERTS_ONLY;
3093 
3094  result = JsonbExtractScalar(&jb->root, jbv);
3095  Assert(result);
3096  }
3097  else
3098  JsonbInitBinary(jbv, jb);
3099  break;
3100  }
3101  case JSONOID:
3102  {
3103  text *txt = DatumGetTextP(val);
3104  char *str = text_to_cstring(txt);
3105  Jsonb *jb;
3106 
3108  CStringGetDatum(str)));
3109  pfree(str);
3110 
3111  JsonItemFromDatum(JsonbPGetDatum(jb), JSONBOID, -1, res);
3112  break;
3113  }
3114  default:
3115  ereport(ERROR,
3116  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3117  errmsg("could not convert value of type %s to jsonpath",
3118  format_type_be(typid)));
3119  }
3120 }
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 3881 of file jsonpath_exec.c.

3882 {
3884 
3885  res = executeJsonPath(jp, vars,
3887  DatumGetJsonbP(jb), !error, NULL, true);
3888 
3889  Assert(error || !jperIsError(res));
3890 
3891  if (error && jperIsError(res))
3892  *error = true;
3893 
3894  return res == jperOk;
3895 }
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 3904 of file jsonpath_exec.c.

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

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 3984 of file jsonpath_exec.c.

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