PostgreSQL Source Code  git master
jsonpath_exec.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.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/json.h"
#include "utils/jsonpath.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 142 of file jsonpath_exec.c.

◆ JSON_TABLE_EXEC_CONTEXT_MAGIC

#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867

Definition at line 219 of file jsonpath_exec.c.

◆ jspAutoUnwrap

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

Definition at line 237 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 238 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 239 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

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

Definition at line 236 of file jsonpath_exec.c.

◆ jspThrowErrors

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

Definition at line 240 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 243 of file jsonpath_exec.c.

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 255 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

typedef enum JsonPathBool JsonPathBool

◆ JsonPathCountVarsCallback

typedef int(* JsonPathCountVarsCallback) (void *vars)

Definition at line 91 of file jsonpath_exec.c.

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathGetVarCallback

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

Definition at line 89 of file jsonpath_exec.c.

◆ JsonPathPredicateCallback

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

Definition at line 251 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 127 of file jsonpath_exec.c.

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

◆ JsonPathExecResult

Enumerator
jperOk 
jperNotFound 
jperError 

Definition at line 135 of file jsonpath_exec.c.

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

Function Documentation

◆ appendBoolResult()

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

Definition at line 2928 of file jsonpath_exec.c.

2930 {
2932  JsonbValue jbv;
2933 
2934  if (!jspGetNext(jsp, &next) && !found)
2935  return jperOk; /* found singleton boolean value */
2936 
2937  if (res == jpbUnknown)
2938  {
2939  jbv.type = jbvNull;
2940  }
2941  else
2942  {
2943  jbv.type = jbvBool;
2944  jbv.val.boolean = res == jpbTrue;
2945  }
2946 
2947  return executeNextItem(cxt, jsp, &next, &jbv, found, true);
2948 }
static int32 next
Definition: blutils.c:219
@ jbvBool
Definition: jsonb.h:231
@ jbvNull
Definition: jsonb.h:228
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1099
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 3251 of file jsonpath_exec.c.

3253 {
3254  int cmp;
3255 
3256  cmp = memcmp(s1, s2, Min(len1, len2));
3257 
3258  if (cmp != 0)
3259  return cmp;
3260 
3261  if (len1 == len2)
3262  return 0;
3263 
3264  return len1 < len2 ? -1 : 1;
3265 }
#define Min(x, y)
Definition: c.h:983
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 3676 of file jsonpath_exec.c.

3677 {
3678  checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3679 
3680  return DirectFunctionCall1(time_timetz, time);
3681 }
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2840
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
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 3664 of file jsonpath_exec.c.

3665 {
3666  if (!useTz)
3667  ereport(ERROR,
3668  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3669  errmsg("cannot convert value from %s to %s without time zone usage",
3670  type1, type2),
3671  errhint("Use *_tz() function for time zone support.")));
3672 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
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 3688 of file jsonpath_exec.c.

3689 {
3690  return date_cmp_timestamp_internal(date1, ts2);
3691 }
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:755

References date_cmp_timestamp_internal().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 3697 of file jsonpath_exec.c.

3698 {
3699  checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
3700 
3701  return date_cmp_timestamptz_internal(date1, tstz2);
3702 }
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:835

References checkTimezoneIsUsedForCast(), and date_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

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

Definition at line 3708 of file jsonpath_exec.c.

3709 {
3710  checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
3711 
3712  return timestamp_cmp_timestamptz_internal(ts1, tstz2);
3713 }
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2318

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

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

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

3436 {
3438  NumericGetDatum(a),
3439  NumericGetDatum(b)));
3440 }
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2517
int b
Definition: isn.c:69
int a
Definition: isn.c:68
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 3272 of file jsonpath_exec.c.

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

3444 {
3445  JsonbValue *dst = palloc(sizeof(*dst));
3446 
3447  *dst = *src;
3448 
3449  return dst;
3450 }
void * palloc(Size size)
Definition: mcxt.c:1317

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void *  cxt)
static

Definition at line 3034 of file jsonpath_exec.c.

3035 {
3036  List *vars = (List *) cxt;
3037 
3038  return list_length(vars);
3039 }
static int list_length(const List *l)
Definition: pg_list.h:152
Definition: pg_list.h:54
Definition: regcomp.c:282

References list_length().

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

◆ countVariablesFromJsonb()

static int countVariablesFromJsonb ( void *  varsJsonb)
static

Definition at line 3201 of file jsonpath_exec.c.

3202 {
3203  Jsonb *vars = varsJsonb;
3204 
3205  if (vars && !JsonContainerIsObject(&vars->root))
3206  {
3207  ereport(ERROR,
3208  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3209  errmsg("\"vars\" argument is not an object"),
3210  errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3211  }
3212 
3213  /* count of base objects */
3214  return vars != NULL ? 1 : 0;
3215 }
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 1932 of file jsonpath_exec.c.

1935 {
1937  JsonbIterator *it;
1938  int32 r;
1939  JsonbValue v;
1940 
1942 
1943  if (level > last)
1944  return res;
1945 
1946  it = JsonbIteratorInit(jbc);
1947 
1948  /*
1949  * Recursively iterate over jsonb objects/arrays
1950  */
1951  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1952  {
1953  if (r == WJB_KEY)
1954  {
1955  r = JsonbIteratorNext(&it, &v, true);
1956  Assert(r == WJB_VALUE);
1957  }
1958 
1959  if (r == WJB_VALUE || r == WJB_ELEM)
1960  {
1961 
1962  if (level >= first ||
1963  (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
1964  v.type != jbvBinary)) /* leaves only requested */
1965  {
1966  /* check expression */
1967  if (jsp)
1968  {
1969  if (ignoreStructuralErrors)
1970  {
1971  bool savedIgnoreStructuralErrors;
1972 
1973  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1974  cxt->ignoreStructuralErrors = true;
1975  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1976  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1977  }
1978  else
1979  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1980 
1981  if (jperIsError(res))
1982  break;
1983 
1984  if (res == jperOk && !found)
1985  break;
1986  }
1987  else if (found)
1988  JsonValueListAppend(found, copyJsonbValue(&v));
1989  else
1990  return jperOk;
1991  }
1992 
1993  if (level < last && v.type == jbvBinary)
1994  {
1996  (cxt, jsp, v.val.binary.data, found,
1997  level + 1, first, last,
1998  ignoreStructuralErrors, unwrapNext);
1999 
2000  if (jperIsError(res))
2001  break;
2002 
2003  if (res == jperOk && found == NULL)
2004  break;
2005  }
2006  }
2007  }
2008 
2009  return res;
2010 }
#define PG_UINT32_MAX
Definition: c.h:569
signed int int32
Definition: c.h:482
#define Assert(condition)
Definition: c.h:837
@ 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:3574

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

2106 {
2107  JsonPathExecResult jper;
2108  JsonPathItem elem;
2109  JsonValueList lseq = {0};
2110  JsonValueList rseq = {0};
2111  JsonbValue *lval;
2112  JsonbValue *rval;
2113  Numeric res;
2114 
2115  jspGetLeftArg(jsp, &elem);
2116 
2117  /*
2118  * XXX: By standard only operands of multiplicative expressions are
2119  * unwrapped. We extend it to other binary arithmetic expressions too.
2120  */
2121  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2122  if (jperIsError(jper))
2123  return jper;
2124 
2125  jspGetRightArg(jsp, &elem);
2126 
2127  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2128  if (jperIsError(jper))
2129  return jper;
2130 
2131  if (JsonValueListLength(&lseq) != 1 ||
2132  !(lval = getScalar(JsonValueListHead(&lseq), jbvNumeric)))
2134  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2135  errmsg("left operand of jsonpath operator %s is not a single numeric value",
2136  jspOperationName(jsp->type)))));
2137 
2138  if (JsonValueListLength(&rseq) != 1 ||
2139  !(rval = getScalar(JsonValueListHead(&rseq), jbvNumeric)))
2141  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2142  errmsg("right operand of jsonpath operator %s is not a single numeric value",
2143  jspOperationName(jsp->type)))));
2144 
2145  if (jspThrowErrors(cxt))
2146  {
2147  res = func(lval->val.numeric, rval->val.numeric, NULL);
2148  }
2149  else
2150  {
2151  bool error = false;
2152 
2153  res = func(lval->val.numeric, rval->val.numeric, &error);
2154 
2155  if (error)
2156  return jperError;
2157  }
2158 
2159  if (!jspGetNext(jsp, &elem) && !found)
2160  return jperOk;
2161 
2162  lval = palloc(sizeof(*lval));
2163  lval->type = jbvNumeric;
2164  lval->val.numeric = res;
2165 
2166  return executeNextItem(cxt, jsp, &elem, lval, found, false);
2167 }
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1166
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:843
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1188
#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 1775 of file jsonpath_exec.c.

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

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

3241 {
3243 
3244  return compareItems(cmp->type, lv, rv, cxt->useTz);
3245 }
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 2337 of file jsonpath_exec.c.

2339 {
2340  JsonbValue jbvbuf;
2341  Datum value;
2342  text *datetime;
2343  Oid collid;
2344  Oid typid;
2345  int32 typmod = -1;
2346  int tz = 0;
2347  bool hasNext;
2349  JsonPathItem elem;
2350  int32 time_precision = -1;
2351 
2352  if (!(jb = getScalar(jb, jbvString)))
2354  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2355  errmsg("jsonpath item method .%s() can only be applied to a string",
2356  jspOperationName(jsp->type)))));
2357 
2358  datetime = cstring_to_text_with_len(jb->val.string.val,
2359  jb->val.string.len);
2360 
2361  /*
2362  * At some point we might wish to have callers supply the collation to
2363  * use, but right now it's unclear that they'd be able to do better than
2364  * DEFAULT_COLLATION_OID anyway.
2365  */
2366  collid = DEFAULT_COLLATION_OID;
2367 
2368  /*
2369  * .datetime(template) has an argument, the rest of the methods don't have
2370  * an argument. So we handle that separately.
2371  */
2372  if (jsp->type == jpiDatetime && jsp->content.arg)
2373  {
2374  text *template;
2375  char *template_str;
2376  int template_len;
2377  ErrorSaveContext escontext = {T_ErrorSaveContext};
2378 
2379  jspGetArg(jsp, &elem);
2380 
2381  if (elem.type != jpiString)
2382  elog(ERROR, "invalid jsonpath item type for .datetime() argument");
2383 
2384  template_str = jspGetString(&elem, &template_len);
2385 
2386  template = cstring_to_text_with_len(template_str,
2387  template_len);
2388 
2389  value = parse_datetime(datetime, template, collid, true,
2390  &typid, &typmod, &tz,
2391  jspThrowErrors(cxt) ? NULL : (Node *) &escontext);
2392 
2393  if (escontext.error_occurred)
2394  res = jperError;
2395  else
2396  res = jperOk;
2397  }
2398  else
2399  {
2400  /*
2401  * According to SQL/JSON standard enumerate ISO formats for: date,
2402  * timetz, time, timestamptz, timestamp.
2403  *
2404  * We also support ISO 8601 format (with "T") for timestamps, because
2405  * to_json[b]() functions use this format.
2406  */
2407  static const char *fmt_str[] =
2408  {
2409  "yyyy-mm-dd", /* date */
2410  "HH24:MI:SS.USTZ", /* timetz */
2411  "HH24:MI:SSTZ",
2412  "HH24:MI:SS.US", /* time without tz */
2413  "HH24:MI:SS",
2414  "yyyy-mm-dd HH24:MI:SS.USTZ", /* timestamptz */
2415  "yyyy-mm-dd HH24:MI:SSTZ",
2416  "yyyy-mm-dd\"T\"HH24:MI:SS.USTZ",
2417  "yyyy-mm-dd\"T\"HH24:MI:SSTZ",
2418  "yyyy-mm-dd HH24:MI:SS.US", /* timestamp without tz */
2419  "yyyy-mm-dd HH24:MI:SS",
2420  "yyyy-mm-dd\"T\"HH24:MI:SS.US",
2421  "yyyy-mm-dd\"T\"HH24:MI:SS"
2422  };
2423 
2424  /* cache for format texts */
2425  static text *fmt_txt[lengthof(fmt_str)] = {0};
2426  int i;
2427 
2428  /*
2429  * Check for optional precision for methods other than .datetime() and
2430  * .date()
2431  */
2432  if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
2433  jsp->content.arg)
2434  {
2435  bool have_error;
2436 
2437  jspGetArg(jsp, &elem);
2438 
2439  if (elem.type != jpiNumeric)
2440  elog(ERROR, "invalid jsonpath item type for %s argument",
2441  jspOperationName(jsp->type));
2442 
2443  time_precision = numeric_int4_opt_error(jspGetNumeric(&elem),
2444  &have_error);
2445  if (have_error)
2447  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2448  errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
2449  jspOperationName(jsp->type)))));
2450  }
2451 
2452  /* loop until datetime format fits */
2453  for (i = 0; i < lengthof(fmt_str); i++)
2454  {
2455  ErrorSaveContext escontext = {T_ErrorSaveContext};
2456 
2457  if (!fmt_txt[i])
2458  {
2459  MemoryContext oldcxt =
2461 
2462  fmt_txt[i] = cstring_to_text(fmt_str[i]);
2463  MemoryContextSwitchTo(oldcxt);
2464  }
2465 
2466  value = parse_datetime(datetime, fmt_txt[i], collid, true,
2467  &typid, &typmod, &tz,
2468  (Node *) &escontext);
2469 
2470  if (!escontext.error_occurred)
2471  {
2472  res = jperOk;
2473  break;
2474  }
2475  }
2476 
2477  if (res == jperNotFound)
2478  {
2479  if (jsp->type == jpiDatetime)
2481  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2482  errmsg("%s format is not recognized: \"%s\"",
2483  "datetime", text_to_cstring(datetime)),
2484  errhint("Use a datetime template argument to specify the input data format."))));
2485  else
2487  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2488  errmsg("%s format is not recognized: \"%s\"",
2489  jspOperationName(jsp->type), text_to_cstring(datetime)))));
2490 
2491  }
2492  }
2493 
2494  /*
2495  * parse_datetime() processes the entire input string per the template or
2496  * ISO format and returns the Datum in best fitted datetime type. So, if
2497  * this call is for a specific datatype, then we do the conversion here.
2498  * Throw an error for incompatible types.
2499  */
2500  switch (jsp->type)
2501  {
2502  case jpiDatetime: /* Nothing to do for DATETIME */
2503  break;
2504  case jpiDate:
2505  {
2506  /* Convert result type to date */
2507  switch (typid)
2508  {
2509  case DATEOID: /* Nothing to do for DATE */
2510  break;
2511  case TIMEOID:
2512  case TIMETZOID:
2514  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2515  errmsg("%s format is not recognized: \"%s\"",
2516  "date", text_to_cstring(datetime)))));
2517  break;
2518  case TIMESTAMPOID:
2520  value);
2521  break;
2522  case TIMESTAMPTZOID:
2524  "timestamptz", "date");
2526  value);
2527  break;
2528  default:
2529  elog(ERROR, "type with oid %u not supported", typid);
2530  }
2531 
2532  typid = DATEOID;
2533  }
2534  break;
2535  case jpiTime:
2536  {
2537  /* Convert result type to time without time zone */
2538  switch (typid)
2539  {
2540  case DATEOID:
2542  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2543  errmsg("%s format is not recognized: \"%s\"",
2544  "time", text_to_cstring(datetime)))));
2545  break;
2546  case TIMEOID: /* Nothing to do for TIME */
2547  break;
2548  case TIMETZOID:
2550  "timetz", "time");
2552  value);
2553  break;
2554  case TIMESTAMPOID:
2556  value);
2557  break;
2558  case TIMESTAMPTZOID:
2560  "timestamptz", "time");
2562  value);
2563  break;
2564  default:
2565  elog(ERROR, "type with oid %u not supported", typid);
2566  }
2567 
2568  /* Force the user-given time precision, if any */
2569  if (time_precision != -1)
2570  {
2571  TimeADT result;
2572 
2573  /* Get a warning when precision is reduced */
2574  time_precision = anytime_typmod_check(false,
2575  time_precision);
2576  result = DatumGetTimeADT(value);
2577  AdjustTimeForTypmod(&result, time_precision);
2578  value = TimeADTGetDatum(result);
2579 
2580  /* Update the typmod value with the user-given precision */
2581  typmod = time_precision;
2582  }
2583 
2584  typid = TIMEOID;
2585  }
2586  break;
2587  case jpiTimeTz:
2588  {
2589  /* Convert result type to time with time zone */
2590  switch (typid)
2591  {
2592  case DATEOID:
2593  case TIMESTAMPOID:
2595  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2596  errmsg("%s format is not recognized: \"%s\"",
2597  "time_tz", text_to_cstring(datetime)))));
2598  break;
2599  case TIMEOID:
2601  "time", "timetz");
2603  value);
2604  break;
2605  case TIMETZOID: /* Nothing to do for TIMETZ */
2606  break;
2607  case TIMESTAMPTZOID:
2609  value);
2610  break;
2611  default:
2612  elog(ERROR, "type with oid %u not supported", typid);
2613  }
2614 
2615  /* Force the user-given time precision, if any */
2616  if (time_precision != -1)
2617  {
2618  TimeTzADT *result;
2619 
2620  /* Get a warning when precision is reduced */
2621  time_precision = anytime_typmod_check(true,
2622  time_precision);
2623  result = DatumGetTimeTzADTP(value);
2624  AdjustTimeForTypmod(&result->time, time_precision);
2625  value = TimeTzADTPGetDatum(result);
2626 
2627  /* Update the typmod value with the user-given precision */
2628  typmod = time_precision;
2629  }
2630 
2631  typid = TIMETZOID;
2632  }
2633  break;
2634  case jpiTimestamp:
2635  {
2636  /* Convert result type to timestamp without time zone */
2637  switch (typid)
2638  {
2639  case DATEOID:
2641  value);
2642  break;
2643  case TIMEOID:
2644  case TIMETZOID:
2646  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2647  errmsg("%s format is not recognized: \"%s\"",
2648  "timestamp", text_to_cstring(datetime)))));
2649  break;
2650  case TIMESTAMPOID: /* Nothing to do for TIMESTAMP */
2651  break;
2652  case TIMESTAMPTZOID:
2654  "timestamptz", "timestamp");
2656  value);
2657  break;
2658  default:
2659  elog(ERROR, "type with oid %u not supported", typid);
2660  }
2661 
2662  /* Force the user-given time precision, if any */
2663  if (time_precision != -1)
2664  {
2665  Timestamp result;
2666  ErrorSaveContext escontext = {T_ErrorSaveContext};
2667 
2668  /* Get a warning when precision is reduced */
2669  time_precision = anytimestamp_typmod_check(false,
2670  time_precision);
2671  result = DatumGetTimestamp(value);
2672  AdjustTimestampForTypmod(&result, time_precision,
2673  (Node *) &escontext);
2674  if (escontext.error_occurred) /* should not happen */
2676  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2677  errmsg("time precision of jsonpath item method .%s() is invalid",
2678  jspOperationName(jsp->type)))));
2679  value = TimestampGetDatum(result);
2680 
2681  /* Update the typmod value with the user-given precision */
2682  typmod = time_precision;
2683  }
2684 
2685  typid = TIMESTAMPOID;
2686  }
2687  break;
2688  case jpiTimestampTz:
2689  {
2690  struct pg_tm tm;
2691  fsec_t fsec;
2692 
2693  /* Convert result type to timestamp with time zone */
2694  switch (typid)
2695  {
2696  case DATEOID:
2698  "date", "timestamptz");
2699 
2700  /*
2701  * Get the timezone value explicitly since JsonbValue
2702  * keeps that separate.
2703  */
2705  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2706  tm.tm_hour = 0;
2707  tm.tm_min = 0;
2708  tm.tm_sec = 0;
2710 
2712  value);
2713  break;
2714  case TIMEOID:
2715  case TIMETZOID:
2717  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2718  errmsg("%s format is not recognized: \"%s\"",
2719  "timestamp_tz", text_to_cstring(datetime)))));
2720  break;
2721  case TIMESTAMPOID:
2723  "timestamp", "timestamptz");
2724 
2725  /*
2726  * Get the timezone value explicitly since JsonbValue
2727  * keeps that separate.
2728  */
2729  if (timestamp2tm(DatumGetTimestamp(value), NULL, &tm,
2730  &fsec, NULL, NULL) == 0)
2733 
2735  value);
2736  break;
2737  case TIMESTAMPTZOID: /* Nothing to do for TIMESTAMPTZ */
2738  break;
2739  default:
2740  elog(ERROR, "type with oid %u not supported", typid);
2741  }
2742 
2743  /* Force the user-given time precision, if any */
2744  if (time_precision != -1)
2745  {
2746  Timestamp result;
2747  ErrorSaveContext escontext = {T_ErrorSaveContext};
2748 
2749  /* Get a warning when precision is reduced */
2750  time_precision = anytimestamp_typmod_check(true,
2751  time_precision);
2752  result = DatumGetTimestampTz(value);
2753  AdjustTimestampForTypmod(&result, time_precision,
2754  (Node *) &escontext);
2755  if (escontext.error_occurred) /* should not happen */
2757  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
2758  errmsg("time precision of jsonpath item method .%s() is invalid",
2759  jspOperationName(jsp->type)))));
2760  value = TimestampTzGetDatum(result);
2761 
2762  /* Update the typmod value with the user-given precision */
2763  typmod = time_precision;
2764  }
2765 
2766  typid = TIMESTAMPTZOID;
2767  }
2768  break;
2769  default:
2770  elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
2771  }
2772 
2773  pfree(datetime);
2774 
2775  if (jperIsError(res))
2776  return res;
2777 
2778  hasNext = jspGetNext(jsp, &elem);
2779 
2780  if (!hasNext && !found)
2781  return res;
2782 
2783  jb = hasNext ? &jbvbuf : palloc(sizeof(*jb));
2784 
2785  jb->type = jbvDatetime;
2786  jb->val.datetime.value = value;
2787  jb->val.datetime.typid = typid;
2788  jb->val.datetime.typmod = typmod;
2789  jb->val.datetime.tz = tz;
2790 
2791  return executeNextItem(cxt, jsp, &elem, jb, found, hasNext);
2792 }
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1585
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:311
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4515
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition: timestamp.c:367
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition: timestamp.c:6295
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1891
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition: timestamp.c:124
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition: timestamp.c:6374
#define lengthof(array)
Definition: c.h:767
Oid collid
int64 Timestamp
Definition: timestamp.h:38
int32 fsec_t
Definition: timestamp.h:41
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
Datum timestamp_time(PG_FUNCTION_ARGS)
Definition: date.c:1917
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition: date.c:71
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:1339
Datum timetz_time(PG_FUNCTION_ARGS)
Definition: date.c:2827
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2866
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1657
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition: date.c:1354
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition: date.c:1309
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition: date.c:1947
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1295
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:4430
static struct @160 value
int i
Definition: isn.c:72
Numeric jspGetNumeric(JsonPathItem *v)
Definition: jsonpath.c:1218
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1226
@ 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
static struct pg_tm tm
Definition: localtime.c:104
MemoryContext TopMemoryContext
Definition: mcxt.c:149
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
uintptr_t Datum
Definition: postgres.h:64
unsigned int Oid
Definition: postgres_ext.h:31
MemoryContextSwitchTo(old_ctx)
bool error_occurred
Definition: miscnodes.h:47
int32 arg
Definition: jsonpath.h:158
Definition: nodes.h:129
Definition: date.h:28
TimeADT time
Definition: date.h:29
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
int tm_sec
Definition: pgtime.h:36
int tm_year
Definition: pgtime.h:41
Definition: c.h:666
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(), DatumGetDateADT(), DatumGetTimeADT(), DatumGetTimestamp(), DatumGetTimestampTz(), DatumGetTimeTzADTP(), DetermineTimeZoneOffset(), DirectFunctionCall1, elog, ereport, errcode(), errhint(), errmsg(), ERROR, ErrorSaveContext::error_occurred, executeNextItem(), getScalar(), i, j2date(), 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(), POSTGRES_EPOCH_JDATE, res, RETURN_ERROR, session_timezone, text_to_cstring(), TimeTzADT::time, time_timetz(), TimeADTGetDatum(), timestamp2tm(), timestamp_date(), timestamp_time(), timestamp_timestamptz(), TimestampGetDatum(), timestamptz_date(), timestamptz_time(), timestamptz_timestamp(), timestamptz_timetz(), TimestampTzGetDatum(), timetz_time(), TimeTzADTPGetDatum(), tm, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, 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 733 of file jsonpath_exec.c.

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

1726 {
1727  if (unwrap && jspAutoUnwrap(cxt))
1728  {
1729  JsonValueList seq = {0};
1731  JsonPathExecResult res = executeItem(cxt, jsp, jb, &seq);
1732  JsonbValue *item;
1733 
1734  if (jperIsError(res))
1735  return res;
1736 
1737  JsonValueListInitIterator(&seq, &it);
1738  while ((item = JsonValueListNext(&seq, &it)))
1739  {
1740  Assert(item->type != jbvArray);
1741 
1742  if (JsonbType(item) == jbvArray)
1743  executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1744  else
1745  JsonValueListAppend(found, item);
1746  }
1747 
1748  return jperOk;
1749  }
1750 
1751  return executeItem(cxt, jsp, jb, found);
1752 }
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 1758 of file jsonpath_exec.c.

1762 {
1764  bool throwErrors = cxt->throwErrors;
1765 
1766  cxt->throwErrors = false;
1767  res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1768  cxt->throwErrors = throwErrors;
1769 
1770  return res;
1771 }

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

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

References JsonPathItem::anybounds, appendBoolResult(), JsonPathItem::args, JsonPathItem::array, Assert, JsonPathExecContext::baseObject, buf, CHECK_FOR_INTERRUPTS, check_stack_depth(), construct_array_builtin(), JsonPathItem::content, CStringGetDatum(), JsonPathExecContext::current, 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(), JsonEncodeDateTime(), jspAutoUnwrap, jspAutoWrap, jspGetArg(), jspGetArraySubscript(), jspGetLeftArg(), jspGetNext(), jspGetNumeric(), jspGetRightArg(), jspGetString(), jspHasNext, jspIgnoreStructuralErrors, jspOperationName(), jspThrowErrors, sort-test::key, MAXDATELEN, 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, 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 1672 of file jsonpath_exec.c.

1675 {
1676  if (jb->type != jbvBinary)
1677  {
1678  Assert(jb->type != jbvArray);
1679  elog(ERROR, "invalid jsonb array value type: %d", jb->type);
1680  }
1681 
1682  return executeAnyItem
1683  (cxt, jsp, jb->val.binary.data, found, 1, 1, 1,
1684  false, unwrapElements);
1685 }

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

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

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

2267 {
2268  JsonLikeRegexContext *cxt = param;
2269 
2270  if (!(str = getScalar(str, jbvString)))
2271  return jpbUnknown;
2272 
2273  /* Cache regex text and converted flags. */
2274  if (!cxt->regex)
2275  {
2276  cxt->regex =
2278  jsp->content.like_regex.patternlen);
2279  (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2280  &(cxt->cflags), NULL);
2281  }
2282 
2283  if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2284  str->val.string.len,
2285  cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
2286  return jpbTrue;
2287 
2288  return jpbFalse;
2289 }
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 1911 of file jsonpath_exec.c.

1913 {
1914  JsonbValue *prev;
1915  JsonPathBool res;
1916 
1917  prev = cxt->current;
1918  cxt->current = jb;
1919  res = executeBoolItem(cxt, jsp, jb, false);
1920  cxt->current = prev;
1921 
1922  return res;
1923 }

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

1695 {
1696  JsonPathItem elem;
1697  bool hasNext;
1698 
1699  if (!cur)
1700  hasNext = next != NULL;
1701  else if (next)
1702  hasNext = jspHasNext(cur);
1703  else
1704  {
1705  next = &elem;
1706  hasNext = jspGetNext(cur, next);
1707  }
1708 
1709  if (hasNext)
1710  return executeItem(cxt, next, v, found);
1711 
1712  if (found)
1713  JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1714 
1715  return jperOk;
1716 }
struct cursor * cur
Definition: ecpg.c:29

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

2299 {
2301  Datum datum;
2302 
2303  if (unwrap && JsonbType(jb) == jbvArray)
2304  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
2305 
2306  if (!(jb = getScalar(jb, jbvNumeric)))
2308  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
2309  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
2310  jspOperationName(jsp->type)))));
2311 
2312  datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
2313 
2314  if (!jspGetNext(jsp, &next) && !found)
2315  return jperOk;
2316 
2317  jb = palloc(sizeof(*jb));
2318  jb->type = jbvNumeric;
2319  jb->val.numeric = DatumGetNumeric(datum);
2320 
2321  return executeNextItem(cxt, jsp, &next, jb, found, false);
2322 }

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

2027 {
2029  JsonValueListIterator lseqit;
2030  JsonValueList lseq = {0};
2031  JsonValueList rseq = {0};
2032  JsonbValue *lval;
2033  bool error = false;
2034  bool found = false;
2035 
2036  /* Left argument is always auto-unwrapped. */
2037  res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
2038  if (jperIsError(res))
2039  return jpbUnknown;
2040 
2041  if (rarg)
2042  {
2043  /* Right argument is conditionally auto-unwrapped. */
2044  res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
2045  unwrapRightArg, &rseq);
2046  if (jperIsError(res))
2047  return jpbUnknown;
2048  }
2049 
2050  JsonValueListInitIterator(&lseq, &lseqit);
2051  while ((lval = JsonValueListNext(&lseq, &lseqit)))
2052  {
2053  JsonValueListIterator rseqit;
2054  JsonbValue *rval;
2055  bool first = true;
2056 
2057  JsonValueListInitIterator(&rseq, &rseqit);
2058  if (rarg)
2059  rval = JsonValueListNext(&rseq, &rseqit);
2060  else
2061  rval = NULL;
2062 
2063  /* Loop over right arg sequence or do single pass otherwise */
2064  while (rarg ? (rval != NULL) : first)
2065  {
2066  JsonPathBool res = exec(pred, lval, rval, param);
2067 
2068  if (res == jpbUnknown)
2069  {
2070  if (jspStrictAbsenceOfErrors(cxt))
2071  return jpbUnknown;
2072 
2073  error = true;
2074  }
2075  else if (res == jpbTrue)
2076  {
2077  if (!jspStrictAbsenceOfErrors(cxt))
2078  return jpbTrue;
2079 
2080  found = true;
2081  }
2082 
2083  first = false;
2084  if (rarg)
2085  rval = JsonValueListNext(&rseq, &rseqit);
2086  }
2087  }
2088 
2089  if (found) /* possible only in strict mode */
2090  return jpbTrue;
2091 
2092  if (error) /* possible only in lax mode */
2093  return jpbUnknown;
2094 
2095  return jpbFalse;
2096 }
Definition: type.h:116

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

2243 {
2244  if (!(whole = getScalar(whole, jbvString)))
2245  return jpbUnknown; /* error */
2246 
2247  if (!(initial = getScalar(initial, jbvString)))
2248  return jpbUnknown; /* error */
2249 
2250  if (whole->val.string.len >= initial->val.string.len &&
2251  !memcmp(whole->val.string.val,
2252  initial->val.string.val,
2253  initial->val.string.len))
2254  return jpbTrue;
2255 
2256  return jpbFalse;
2257 }

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

2176 {
2177  JsonPathExecResult jper;
2178  JsonPathExecResult jper2;
2179  JsonPathItem elem;
2180  JsonValueList seq = {0};
2182  JsonbValue *val;
2183  bool hasNext;
2184 
2185  jspGetArg(jsp, &elem);
2186  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
2187 
2188  if (jperIsError(jper))
2189  return jper;
2190 
2191  jper = jperNotFound;
2192 
2193  hasNext = jspGetNext(jsp, &elem);
2194 
2195  JsonValueListInitIterator(&seq, &it);
2196  while ((val = JsonValueListNext(&seq, &it)))
2197  {
2198  if ((val = getScalar(val, jbvNumeric)))
2199  {
2200  if (!found && !hasNext)
2201  return jperOk;
2202  }
2203  else
2204  {
2205  if (!found && !hasNext)
2206  continue; /* skip non-numerics processing */
2207 
2209  (errcode(ERRCODE_SQL_JSON_NUMBER_NOT_FOUND),
2210  errmsg("operand of unary jsonpath operator %s is not a numeric value",
2211  jspOperationName(jsp->type)))));
2212  }
2213 
2214  if (func)
2215  val->val.numeric =
2217  NumericGetDatum(val->val.numeric)));
2218 
2219  jper2 = executeNextItem(cxt, jsp, &elem, val, found, false);
2220 
2221  if (jperIsError(jper2))
2222  return jper2;
2223 
2224  if (jper2 == jperOk)
2225  {
2226  if (!found)
2227  return jperOk;
2228  jper = jperOk;
2229  }
2230  }
2231 
2232  return jper;
2233 }

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

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

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

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

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

3141 {
3142  char *varName;
3143  int varNameLength;
3144  JsonbValue baseObject;
3145  int baseObjectId;
3146  JsonbValue *v;
3147 
3149  varName = jspGetString(variable, &varNameLength);
3150 
3151  if (cxt->vars == NULL ||
3152  (v = cxt->getVar(cxt->vars, varName, varNameLength,
3153  &baseObject, &baseObjectId)) == NULL)
3154  ereport(ERROR,
3155  (errcode(ERRCODE_UNDEFINED_OBJECT),
3156  errmsg("could not find jsonpath variable \"%s\"",
3157  pnstrdup(varName, varNameLength))));
3158 
3159  if (baseObjectId > 0)
3160  {
3161  *value = *v;
3162  setBaseObject(cxt, &baseObject, baseObjectId);
3163  }
3164 }
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 3171 of file jsonpath_exec.c.

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

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

4089 {
4090  JsonTableExecContext *result;
4091 
4092  if (!IsA(state, TableFuncScanState))
4093  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4094  result = (JsonTableExecContext *) state->opaque;
4096  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4097 
4098  return result;
4099 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
#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 3636 of file jsonpath_exec.c.

3637 {
3638  /* Scalars should be always extracted during jsonpath execution. */
3639  Assert(scalar->type != jbvBinary ||
3640  !JsonContainerIsScalar(scalar->val.binary.data));
3641 
3642  return scalar->type == type ? scalar : NULL;
3643 }
#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 425 of file jsonpath_exec.c.

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

398 {
399  Jsonb *jb = PG_GETARG_JSONB_P(0);
402  Jsonb *vars = NULL;
403  bool silent = true;
404 
405  if (PG_NARGS() == 4)
406  {
407  vars = PG_GETARG_JSONB_P(2);
408  silent = PG_GETARG_BOOL(3);
409  }
410 
413  jb, !silent, NULL, tz);
414 
415  PG_FREE_IF_COPY(jb, 0);
416  PG_FREE_IF_COPY(jp, 1);
417 
418  if (jperIsError(res))
419  PG_RETURN_NULL();
420 
422 }
#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 442 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 431 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 495 of file jsonpath_exec.c.

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

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

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

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 501 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 572 of file jsonpath_exec.c.

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

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

590 {
591  Jsonb *jb = PG_GETARG_JSONB_P(0);
593  JsonValueList found = {0};
595  bool silent = PG_GETARG_BOOL(3);
596 
599  jb, !silent, &found, tz);
600 
602 }
#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 611 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 641 of file jsonpath_exec.c.

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

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 524 of file jsonpath_exec.c.

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

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3223 of file jsonpath_exec.c.

3224 {
3225  Assert(jb->type != jbvArray);
3226 
3227  if (jb->type == jbvBinary)
3228  {
3229  JsonbContainer *jbc = jb->val.binary.data;
3230 
3231  if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
3232  return JsonContainerSize(jbc);
3233  }
3234 
3235  return -1;
3236 }
#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 3599 of file jsonpath_exec.c.

3600 {
3601  jbv->type = jbvBinary;
3602  jbv->val.binary.data = &jb->root;
3603  jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3604 
3605  return jbv;
3606 }
#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 3612 of file jsonpath_exec.c.

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

3130 {
3131  jbv->type = jbvNumeric;
3132  jbv->val.numeric = DatumGetNumeric(num);
3133 }

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

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

3887 {
3889 
3890  res = executeJsonPath(jp, vars,
3892  DatumGetJsonbP(jb), !error, NULL, true);
3893 
3894  Assert(error || !jperIsError(res));
3895 
3896  if (error && jperIsError(res))
3897  *error = true;
3898 
3899  return res == jperOk;
3900 }
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 3909 of file jsonpath_exec.c.

3912 {
3913  JsonbValue *singleton;
3914  bool wrap;
3915  JsonValueList found = {0};
3917  int count;
3918 
3919  res = executeJsonPath(jp, vars,
3921  DatumGetJsonbP(jb), !error, &found, true);
3922  Assert(error || !jperIsError(res));
3923  if (error && jperIsError(res))
3924  {
3925  *error = true;
3926  *empty = false;
3927  return (Datum) 0;
3928  }
3929 
3930  /*
3931  * Determine whether to wrap the result in a JSON array or not.
3932  *
3933  * First, count the number of SQL/JSON items in the returned
3934  * JsonValueList. If the list is empty (singleton == NULL), no wrapping is
3935  * necessary.
3936  *
3937  * If the wrapper mode is JSW_NONE or JSW_UNSPEC, wrapping is explicitly
3938  * disabled. This enforces a WITHOUT WRAPPER clause, which is also the
3939  * default when no WRAPPER clause is specified.
3940  *
3941  * If the mode is JSW_UNCONDITIONAL, wrapping is enforced regardless of
3942  * the number of SQL/JSON items, enforcing a WITH WRAPPER or WITH
3943  * UNCONDITIONAL WRAPPER clause.
3944  *
3945  * For JSW_CONDITIONAL, wrapping occurs only if there is more than one
3946  * SQL/JSON item in the list, enforcing a WITH CONDITIONAL WRAPPER clause.
3947  */
3948  count = JsonValueListLength(&found);
3949  singleton = count > 0 ? JsonValueListHead(&found) : NULL;
3950  if (singleton == NULL)
3951  wrap = false;
3952  else if (wrapper == JSW_NONE || wrapper == JSW_UNSPEC)
3953  wrap = false;
3954  else if (wrapper == JSW_UNCONDITIONAL)
3955  wrap = true;
3956  else if (wrapper == JSW_CONDITIONAL)
3957  wrap = count > 1;
3958  else
3959  {
3960  elog(ERROR, "unrecognized json wrapper %d", (int) wrapper);
3961  wrap = false;
3962  }
3963 
3964  if (wrap)
3966 
3967  /* No wrapping means only one item is expected. */
3968  if (count > 1)
3969  {
3970  if (error)
3971  {
3972  *error = true;
3973  return (Datum) 0;
3974  }
3975 
3976  if (column_name)
3977  ereport(ERROR,
3978  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3979  errmsg("JSON path expression for column \"%s\" should return single item without wrapper",
3980  column_name),
3981  errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
3982  else
3983  ereport(ERROR,
3984  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3985  errmsg("JSON path expression in JSON_QUERY should return single item without wrapper"),
3986  errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
3987  }
3988 
3989  if (singleton)
3990  return JsonbPGetDatum(JsonbValueToJsonb(singleton));
3991 
3992  *empty = true;
3993  return PointerGetDatum(NULL);
3994 }
@ JSW_UNCONDITIONAL
Definition: primnodes.h:1753
@ JSW_CONDITIONAL
Definition: primnodes.h:1752
@ JSW_UNSPEC
Definition: primnodes.h:1750
@ JSW_NONE
Definition: primnodes.h:1751

References Assert, CountJsonPathVars(), DatumGetJsonbP(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, error(), executeJsonPath(), GetJsonPathVar(), jperIsError, JsonbPGetDatum(), JsonbValueToJsonb(), JsonValueListHead(), JsonValueListLength(), JSW_CONDITIONAL, JSW_NONE, JSW_UNCONDITIONAL, JSW_UNSPEC, PointerGetDatum(), res, 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 4003 of file jsonpath_exec.c.

4005 {
4006  JsonbValue *res;
4007  JsonValueList found = {0};
4009  int count;
4010 
4012  DatumGetJsonbP(jb),
4013  !error, &found, true);
4014 
4015  Assert(error || !jperIsError(jper));
4016 
4017  if (error && jperIsError(jper))
4018  {
4019  *error = true;
4020  *empty = false;
4021  return NULL;
4022  }
4023 
4024  count = JsonValueListLength(&found);
4025 
4026  *empty = (count == 0);
4027 
4028  if (*empty)
4029  return NULL;
4030 
4031  /* JSON_VALUE expects to get only singletons. */
4032  if (count > 1)
4033  {
4034  if (error)
4035  {
4036  *error = true;
4037  return NULL;
4038  }
4039 
4040  if (column_name)
4041  ereport(ERROR,
4042  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
4043  errmsg("JSON path expression for column \"%s\" should return single scalar item",
4044  column_name)));
4045  else
4046  ereport(ERROR,
4047  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
4048  errmsg("JSON path expression in JSON_VALUE should return single scalar item")));
4049  }
4050 
4051  res = JsonValueListHead(&found);
4052  if (res->type == jbvBinary && JsonContainerIsScalar(