Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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, Node *escontext)
 

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, Node *escontext)

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

2933{
2935 JsonbValue jbv;
2936
2937 if (!jspGetNext(jsp, &next) && !found)
2938 return jperOk; /* found singleton boolean value */
2939
2940 if (res == jpbUnknown)
2941 {
2942 jbv.type = jbvNull;
2943 }
2944 else
2945 {
2946 jbv.type = jbvBool;
2947 jbv.val.boolean = res == jpbTrue;
2948 }
2949
2950 return executeNextItem(cxt, jsp, &next, &jbv, found, true);
2951}
static int32 next
Definition: blutils.c:224
@ 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, 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 3254 of file jsonpath_exec.c.

3256{
3257 int cmp;
3258
3259 cmp = memcmp(s1, s2, Min(len1, len2));
3260
3261 if (cmp != 0)
3262 return cmp;
3263
3264 if (len1 == len2)
3265 return 0;
3266
3267 return len1 < len2 ? -1 : 1;
3268}
#define Min(x, y)
Definition: c.h:1004
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

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

Referenced by compareStrings().

◆ castTimeToTimeTz()

static Datum castTimeToTimeTz ( Datum  time,
bool  useTz 
)
static

Definition at line 3679 of file jsonpath_exec.c.

3680{
3681 checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3682
3683 return DirectFunctionCall1(time_timetz, time);
3684}
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2975
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
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 3667 of file jsonpath_exec.c.

3668{
3669 if (!useTz)
3670 ereport(ERROR,
3671 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3672 errmsg("cannot convert value from %s to %s without time zone usage",
3673 type1, type2),
3674 errhint("Use *_tz() function for time zone support.")));
3675}
int errhint(const char *fmt,...)
Definition: elog.c:1321
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150

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

3692{
3693 return date_cmp_timestamp_internal(date1, ts2);
3694}
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:808

References date_cmp_timestamp_internal().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 3700 of file jsonpath_exec.c.

3701{
3702 checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
3703
3704 return date_cmp_timestamptz_internal(date1, tstz2);
3705}
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:888

References checkTimezoneIsUsedForCast(), and date_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

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

Definition at line 3711 of file jsonpath_exec.c.

3712{
3713 checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
3714
3715 return timestamp_cmp_timestamptz_internal(ts1, tstz2);
3716}
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2363

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

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

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

Referenced by executeComparison().

◆ compareNumeric()

static int compareNumeric ( Numeric  a,
Numeric  b 
)
static

Definition at line 3438 of file jsonpath_exec.c.

3439{
3442 NumericGetDatum(b)));
3443}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2416
int b
Definition: isn.c:74
int a
Definition: isn.c:73
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:76

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

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

3447{
3448 JsonbValue *dst = palloc(sizeof(*dst));
3449
3450 *dst = *src;
3451
3452 return dst;
3453}
void * palloc(Size size)
Definition: mcxt.c:1365

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void *  cxt)
static

Definition at line 3037 of file jsonpath_exec.c.

3038{
3039 List *vars = (List *) cxt;
3040
3041 return list_length(vars);
3042}
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 3204 of file jsonpath_exec.c.

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

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

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

Referenced by executeAnyItem(), executeItemOptUnwrapTarget(), and executeItemUnwrapTargetArray().

◆ executeBinaryArithmExpr()

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

Definition at line 2106 of file jsonpath_exec.c.

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

References ereport, errcode(), errmsg(), ERROR, ErrorSaveContext::error_occurred, executeItemOptUnwrapResult(), executeNextItem(), getScalar(), jbvNumeric, jperError, jperIsError, jperOk, JsonValueListHead(), JsonValueListLength(), jspGetLeftArg(), jspGetNext(), jspGetRightArg(), jspOperationName(), jspThrowErrors, palloc(), 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 1778 of file jsonpath_exec.c.

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

References JsonPathItem::base, check_stack_depth(), JsonPathItem::content, elog, ERROR, executeBoolItem(), executeComparison(), executeItemOptUnwrapResultNoThrow(), executeLikeRegex(), executePredicate(), executeStartsWith(), JsonPathItem::expr, 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, and JsonPathItem::type.

Referenced by executeBoolItem(), executeItemOptUnwrapTarget(), and executeNestedBoolItem().

◆ executeComparison()

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

Definition at line 3243 of file jsonpath_exec.c.

3244{
3246
3247 return compareItems(cmp->type, lv, rv, cxt->useTz);
3248}
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 2340 of file jsonpath_exec.c.

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

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_safe(), palloc(), parse_datetime(), pfree(), POSTGRES_EPOCH_JDATE, 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 734 of file jsonpath_exec.c.

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

References executeItemOptUnwrapTarget(), and jspAutoUnwrap.

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

◆ executeItemOptUnwrapResult()

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

Definition at line 1726 of file jsonpath_exec.c.

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

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

References executeItemOptUnwrapResult(), and JsonPathExecContext::throwErrors.

Referenced by executeBoolItem(), and executePredicate().

◆ executeItemOptUnwrapTarget()

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

Definition at line 746 of file jsonpath_exec.c.

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

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

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

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

◆ executeJsonPath()

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

Definition at line 678 of file jsonpath_exec.c.

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

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

References Assert(), JsonPathExecContext::baseObject, ereport, errcode(), errmsg(), ERROR, executeNextItem(), JsonBaseObjectInfo::id, int64_to_numeric(), INT64CONST, 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(), 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 2268 of file jsonpath_exec.c.

2270{
2271 JsonLikeRegexContext *cxt = param;
2272
2273 if (!(str = getScalar(str, jbvString)))
2274 return jpbUnknown;
2275
2276 /* Cache regex text and converted flags. */
2277 if (!cxt->regex)
2278 {
2279 cxt->regex =
2283 &(cxt->cflags), NULL);
2284 }
2285
2286 if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2287 str->val.string.len,
2288 cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
2289 return jpbTrue;
2290
2291 return jpbFalse;
2292}
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
uint32 flags
Definition: jsonpath.h:189
int32 patternlen
Definition: jsonpath.h:188
char * pattern
Definition: jsonpath.h:187

References JsonLikeRegexContext::cflags, JsonPathItem::content, cstring_to_text_with_len(), JsonPathItem::flags, getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, jspConvertRegexFlags(), JsonPathItem::like_regex, JsonPathItem::pattern, JsonPathItem::patternlen, 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 1914 of file jsonpath_exec.c.

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

References JsonPathExecContext::current, and executeBoolItem().

Referenced by executeItemOptUnwrapTarget().

◆ executeNextItem()

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

Definition at line 1695 of file jsonpath_exec.c.

1698{
1699 JsonPathItem elem;
1700 bool hasNext;
1701
1702 if (!cur)
1703 hasNext = next != NULL;
1704 else if (next)
1705 hasNext = jspHasNext(cur);
1706 else
1707 {
1708 next = &elem;
1709 hasNext = jspGetNext(cur, next);
1710 }
1711
1712 if (hasNext)
1713 return executeItem(cxt, next, v, found);
1714
1715 if (found)
1716 JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1717
1718 return jperOk;
1719}
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 2299 of file jsonpath_exec.c.

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

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

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

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

Referenced by executeBoolItem().

◆ executeStartsWith()

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

Definition at line 2244 of file jsonpath_exec.c.

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

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

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

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

3462{
3463 JsonbValue *jbv;
3464 JsonValueList found = {0};
3465 JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
3466 Datum numeric_index;
3467 ErrorSaveContext escontext = {T_ErrorSaveContext};
3468
3469 if (jperIsError(res))
3470 return res;
3471
3472 if (JsonValueListLength(&found) != 1 ||
3473 !(jbv = getScalar(JsonValueListHead(&found), jbvNumeric)))
3475 (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
3476 errmsg("jsonpath array subscript is not a single numeric value"))));
3477
3478 numeric_index = DirectFunctionCall2(numeric_trunc,
3479 NumericGetDatum(jbv->val.numeric),
3480 Int32GetDatum(0));
3481
3482 *index = numeric_int4_safe(DatumGetNumeric(numeric_index),
3483 (Node *) &escontext);
3484
3485 if (escontext.error_occurred)
3487 (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
3488 errmsg("jsonpath array subscript is out of integer range"))));
3489
3490 return jperOk;
3491}
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:1580

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

Referenced by executeItemOptUnwrapTarget().

◆ getJsonPathItem()

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

Definition at line 2959 of file jsonpath_exec.c.

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

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

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

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

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

4092{
4093 JsonTableExecContext *result;
4094
4096 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4097 result = (JsonTableExecContext *) state->opaque;
4099 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4100
4101 return result;
4102}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
#define JSON_TABLE_EXEC_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
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 3639 of file jsonpath_exec.c.

3640{
3641 /* Scalars should be always extracted during jsonpath execution. */
3642 Assert(scalar->type != jbvBinary ||
3643 !JsonContainerIsScalar(scalar->val.binary.data));
3644
3645 return scalar->type == type ? scalar : NULL;
3646}
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
const char * type

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

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

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 426 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_internal()

static Datum jsonb_path_exists_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 398 of file jsonpath_exec.c.

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

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

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

◆ jsonb_path_exists_opr()

Datum jsonb_path_exists_opr ( PG_FUNCTION_ARGS  )

Definition at line 443 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 432 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 496 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_internal()

static Datum jsonb_path_match_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 455 of file jsonpath_exec.c.

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

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

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

◆ jsonb_path_match_opr()

Datum jsonb_path_match_opr ( PG_FUNCTION_ARGS  )

Definition at line 513 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 502 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 573 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ jsonb_path_query_array()

Datum jsonb_path_query_array ( PG_FUNCTION_ARGS  )

Definition at line 606 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_array_internal()

static Datum jsonb_path_query_array_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 590 of file jsonpath_exec.c.

591{
592 Jsonb *jb = PG_GETARG_JSONB_P(0);
594 JsonValueList found = {0};
596 bool silent = PG_GETARG_BOOL(3);
597
600 jb, !silent, &found, tz);
601
603}
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
static JsonbValue * wrapItemsInArray(const JsonValueList *items)

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

Referenced by jsonb_path_query_array(), and jsonb_path_query_array_tz().

◆ jsonb_path_query_array_tz()

Datum jsonb_path_query_array_tz ( PG_FUNCTION_ARGS  )

Definition at line 612 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 642 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_first_internal()

static Datum jsonb_path_query_first_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 648 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 525 of file jsonpath_exec.c.

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

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

Referenced by jsonb_path_query(), and jsonb_path_query_tz().

◆ jsonb_path_query_tz()

Datum jsonb_path_query_tz ( PG_FUNCTION_ARGS  )

Definition at line 579 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3226 of file jsonpath_exec.c.

3227{
3228 Assert(jb->type != jbvArray);
3229
3230 if (jb->type == jbvBinary)
3231 {
3232 JsonbContainer *jbc = jb->val.binary.data;
3233
3235 return JsonContainerSize(jbc);
3236 }
3237
3238 return -1;
3239}
#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 3602 of file jsonpath_exec.c.

3603{
3604 jbv->type = jbvBinary;
3605 jbv->val.binary.data = &jb->root;
3606 jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3607
3608 return jbv;
3609}
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition: varatt.h:472

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

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

3133{
3134 jbv->type = jbvNumeric;
3135 jbv->val.numeric = DatumGetNumeric(num);
3136}

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

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

References Assert(), CStringGetDatum(), DatumGetBool(), DatumGetJsonbP(), DatumGetPointer(), 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, JsonItemFromDatum(), pfree(), PG_USED_FOR_ASSERTS_ONLY, Jsonb::root, str, text_to_cstring(), JsonbValue::type, JsonbValue::val, val, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Referenced by GetJsonPathVar(), and JsonItemFromDatum().

◆ JsonPathExists()

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

Definition at line 3889 of file jsonpath_exec.c.

3890{
3892
3893 res = executeJsonPath(jp, vars,
3895 DatumGetJsonbP(jb), !error, NULL, true);
3896
3897 Assert(error || !jperIsError(res));
3898
3899 if (error && jperIsError(res))
3900 *error = true;
3901
3902 return res == jperOk;
3903}
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, and jperOk.

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

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

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(), 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 4006 of file jsonpath_exec.c.

4008{
4009 JsonbValue *res;
4010 JsonValueList found = {0};
4012 int count;
4013
4015 DatumGetJsonbP(jb),
4016 !error, &found, true);
4017
4018 Assert(error || !jperIsError(jper));
4019
4020 if (error && jperIsError(jper))
4021 {
4022 *error = true;
4023 *empty = false;
4024 return NULL;
4025 }
4026
4027 count = JsonValueListLength(&found);
4028
4029 *empty = (count == 0);
4030
4031 if (*empty)
4032 return NULL;
4033
4034 /* JSON_VALUE expects to get only singletons. */
4035 if (count > 1)
4036 {
4037 if (error)
4038 {
4039 *error = true;
4040 return NULL;
4041 }
4042
4043 if (column_name)
4044 ereport(ERROR,
4045 (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
4046 errmsg("JSON path expression for column \"%s\" must return single scalar item",
4047 column_name)));
4048 else
4049 ereport(ERROR,
4050 (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
4051 errmsg("JSON path expression in JSON_VALUE must return single scalar item")));
4052 }
4053
4054 res = JsonValueListHead(&found);
4055 if (res->type == jbvBinary && JsonContainerIsScalar(res->val.binary.data))
4056 JsonbExtractScalar(res->val.binary.data, res);
4057
4058 /* JSON_VALUE expects to get only scalars. */
4059 if (!IsAJsonbScalar(res))
4060 {
4061 if (error)
4062 {
4063 *error = true;
4064 return NULL;
4065 }
4066
4067 if (column_name)
4068 ereport(ERROR,
4069 (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
4070 errmsg("JSON path expression for column \"%s\" must return single scalar item",
4071 column_name)));
4072 else
4073 ereport(ERROR,
4074 (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
4075 errmsg("JSON path expression in JSON_VALUE must return single scalar item")));
4076 }
4077
4078 if (res->type == jbvNull)
4079 return NULL;
4080
4081 return res;
4082}
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297

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

Referenced by ExecEvalJsonExprPath().

◆ JsonTableDestroyOpaque()

static void JsonTableDestroyOpaque ( TableFuncScanState state)
static

Definition at line 4177 of file jsonpath_exec.c.

4178{
4180 GetJsonTableExecContext(state, "JsonTableDestroyOpaque");
4181
4182 /* not valid anymore */
4183 cxt->magic = 0;
4184
4185 state->opaque = NULL;
4186}
static JsonTableExecContext * GetJsonTableExecContext(TableFuncScanState *state, const char *fname)

References GetJsonTableExecContext(), and JsonTableExecContext::magic.

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4439 of file jsonpath_exec.c.

4440{
4442 GetJsonTableExecContext(state, "JsonTableFetchRow");
4443
4445}
static bool JsonTablePlanNextRow(JsonTablePlanState *planstate)
JsonTablePlanState * rootplanstate

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

◆ JsonTableGetValue()

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

Definition at line 4455 of file jsonpath_exec.c.

4457{
4459 GetJsonTableExecContext(state, "JsonTableGetValue");
4460 ExprContext *econtext = state->ss.ps.ps_ExprContext;
4461 ExprState *estate = list_nth(state->colvalexprs, colnum);
4462 JsonTablePlanState *planstate = cxt->colplanstates[colnum];
4463 JsonTablePlanRowSource *current = &planstate->current;
4464 Datum result;
4465
4466 /* Row pattern value is NULL */
4467 if (current->isnull)
4468 {
4469 result = (Datum) 0;
4470 *isnull = true;
4471 }
4472 /* Evaluate JsonExpr. */
4473 else if (estate)
4474 {
4475 Datum saved_caseValue = econtext->caseValue_datum;
4476 bool saved_caseIsNull = econtext->caseValue_isNull;
4477
4478 /* Pass the row pattern value via CaseTestExpr. */
4479 econtext->caseValue_datum = current->value;
4480 econtext->caseValue_isNull = false;
4481
4482 result = ExecEvalExpr(estate, econtext, isnull);
4483
4484 econtext->caseValue_datum = saved_caseValue;
4485 econtext->caseValue_isNull = saved_caseIsNull;
4486 }
4487 /* ORDINAL column */
4488 else
4489 {
4490 result = Int32GetDatum(planstate->ordinal);
4491 *isnull = false;
4492 }
4493
4494 return result;
4495}
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:390
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
bool caseValue_isNull
Definition: execnodes.h:300
Datum caseValue_datum
Definition: execnodes.h:298
JsonTablePlanState ** colplanstates
JsonTablePlanRowSource current

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

◆ JsonTableInitOpaque()

static void JsonTableInitOpaque ( TableFuncScanState state,
int  natts 
)
static

Definition at line 4112 of file jsonpath_exec.c.

4113{
4115 PlanState *ps = &state->ss.ps;
4116 TableFuncScan *tfs = castNode(TableFuncScan, ps->plan);
4117 TableFunc *tf = tfs->tablefunc;
4118 JsonTablePlan *rootplan = (JsonTablePlan *) tf->plan;
4119 JsonExpr *je = castNode(JsonExpr, tf->docexpr);
4120 List *args = NIL;
4121
4122 cxt = palloc0(sizeof(JsonTableExecContext));
4124
4125 /*
4126 * Evaluate JSON_TABLE() PASSING arguments to be passed to the jsonpath
4127 * executor via JsonPathVariables.
4128 */
4129 if (state->passingvalexprs)
4130 {
4131 ListCell *exprlc;
4132 ListCell *namelc;
4133
4134 Assert(list_length(state->passingvalexprs) ==
4135 list_length(je->passing_names));
4136 forboth(exprlc, state->passingvalexprs,
4137 namelc, je->passing_names)
4138 {
4140 String *name = lfirst_node(String, namelc);
4141 JsonPathVariable *var = palloc(sizeof(*var));
4142
4143 var->name = pstrdup(name->sval);
4144 var->namelen = strlen(var->name);
4145 var->typid = exprType((Node *) state->expr);
4146 var->typmod = exprTypmod((Node *) state->expr);
4147
4148 /*
4149 * Evaluate the expression and save the value to be returned by
4150 * GetJsonPathVar().
4151 */
4152 var->value = ExecEvalExpr(state, ps->ps_ExprContext,
4153 &var->isnull);
4154
4155 args = lappend(args, var);
4156 }
4157 }
4158
4159 cxt->colplanstates = palloc(sizeof(JsonTablePlanState *) *
4160 list_length(tf->colvalexprs));
4161
4162 /*
4163 * Initialize plan for the root path and, recursively, also any child
4164 * plans that compute the NESTED paths.
4165 */
4166 cxt->rootplanstate = JsonTableInitPlan(cxt, rootplan, NULL, args,
4168
4169 state->opaque = cxt;
4170}
static JsonTablePlanState * JsonTableInitPlan(JsonTableExecContext *cxt, JsonTablePlan *plan, JsonTablePlanState *parentstate, List *args, MemoryContext mcxt)
List * lappend(List *list, void *datum)
Definition: list.c:339
void * palloc0(Size size)
Definition: mcxt.c:1395
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:301
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
Definition: value.h:64
TableFunc * tablefunc
Definition: plannodes.h:784
Node * docexpr
Definition: primnodes.h:120
const char * name

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

◆ JsonTableInitPlan()

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

Definition at line 4194 of file jsonpath_exec.c.

4197{
4198 JsonTablePlanState *planstate = palloc0(sizeof(*planstate));
4199
4200 planstate->plan = plan;
4201 planstate->parent = parentstate;
4202
4204 {
4206 int i;
4207
4208 planstate->path = DatumGetJsonPathP(scan->path->value->constvalue);
4209 planstate->args = args;
4210 planstate->mcxt = AllocSetContextCreate(mcxt, "JsonTableExecContext",
4212
4213 /* No row pattern evaluated yet. */
4214 planstate->current.value = PointerGetDatum(NULL);
4215 planstate->current.isnull = true;
4216
4217 for (i = scan->colMin; i >= 0 && i <= scan->colMax; i++)
4218 cxt->colplanstates[i] = planstate;
4219
4220 planstate->nested = scan->child ?
4221 JsonTableInitPlan(cxt, scan->child, planstate, args, mcxt) : NULL;
4222 }
4223 else if (IsA(plan, JsonTableSiblingJoin))
4224 {
4226
4227 planstate->left = JsonTableInitPlan(cxt, join->lplan, parentstate,
4228 args, mcxt);
4229 planstate->right = JsonTableInitPlan(cxt, join->rplan, parentstate,
4230 args, mcxt);
4231 }
4232
4233 return planstate;
4234}
static JsonPath * DatumGetJsonPathP(Datum d)
Definition: jsonpath.h:35
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define plan(x)
Definition: pg_regress.c:161
JsonTablePath * path
Definition: primnodes.h:1909
JsonTablePlan * child
Definition: primnodes.h:1918
Const * value
Definition: primnodes.h:1882
struct JsonTablePlanState * left
struct JsonTablePlanState * nested
MemoryContext mcxt
struct JsonTablePlanState * parent
JsonTablePlan * plan
struct JsonTablePlanState * right
JsonTablePlan * rplan
Definition: primnodes.h:1939
JsonTablePlan * lplan
Definition: primnodes.h:1938

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

Referenced by JsonTableInitOpaque(), and JsonTableInitPlan().

◆ JsonTablePlanJoinNextRow()

static bool JsonTablePlanJoinNextRow ( JsonTablePlanState planstate)
static

Definition at line 4412 of file jsonpath_exec.c.

4413{
4414
4415 /* Fetch row from left sibling. */
4416 if (!JsonTablePlanNextRow(planstate->left))
4417 {
4418 /*
4419 * Left sibling ran out of rows, so start fetching from the right
4420 * sibling.
4421 */
4422 if (!JsonTablePlanNextRow(planstate->right))
4423 {
4424 /* Right sibling ran out of row, so there are more rows. */
4425 return false;
4426 }
4427 }
4428
4429 return true;
4430}

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

Referenced by JsonTablePlanNextRow().

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4294 of file jsonpath_exec.c.

4295{
4296 if (IsA(planstate->plan, JsonTablePathScan))
4297 return JsonTablePlanScanNextRow(planstate);
4298 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4299 return JsonTablePlanJoinNextRow(planstate);
4300 else
4301 elog(ERROR, "invalid JsonTablePlan %d", (int) planstate->plan->type);
4302
4303 Assert(false);
4304 /* Appease compiler */
4305 return false;
4306}
static bool JsonTablePlanScanNextRow(JsonTablePlanState *planstate)
static bool JsonTablePlanJoinNextRow(JsonTablePlanState *planstate)

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

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

◆ JsonTablePlanScanNextRow()

static bool JsonTablePlanScanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4321 of file jsonpath_exec.c.

4322{
4323 JsonbValue *jbv;
4324 MemoryContext oldcxt;
4325
4326 /*
4327 * If planstate already has an active row and there is a nested plan,
4328 * check if it has an active row to join with the former.
4329 */
4330 if (!planstate->current.isnull)
4331 {
4332 if (planstate->nested && JsonTablePlanNextRow(planstate->nested))
4333 return true;
4334 }
4335
4336 /* Fetch new row from the list of found values to set as active. */
4337 jbv = JsonValueListNext(&planstate->found, &planstate->iter);
4338
4339 /* End of list? */
4340 if (jbv == NULL)
4341 {
4342 planstate->current.value = PointerGetDatum(NULL);
4343 planstate->current.isnull = true;
4344 return false;
4345 }
4346
4347 /*
4348 * Set current row item for subsequent JsonTableGetValue() calls for
4349 * evaluating individual columns.
4350 */
4351 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4352 planstate->current.value = JsonbPGetDatum(JsonbValueToJsonb(jbv));
4353 planstate->current.isnull = false;
4354 MemoryContextSwitchTo(oldcxt);
4355
4356 /* Next row! */
4357 planstate->ordinal++;
4358
4359 /* Process nested plan(s), if any. */
4360 if (planstate->nested)
4361 {
4362 /* Re-evaluate the nested path using the above parent row. */
4363 JsonTableResetNestedPlan(planstate->nested);
4364
4365 /*
4366 * Now fetch the nested plan's current row to be joined against the
4367 * parent row. Any further nested plans' paths will be re-evaluated
4368 * recursively, level at a time, after setting each nested plan's
4369 * current row.
4370 */
4371 (void) JsonTablePlanNextRow(planstate->nested);
4372 }
4373
4374 /* There are more rows. */
4375 return true;
4376}
static void JsonTableResetNestedPlan(JsonTablePlanState *planstate)
JsonValueList found
JsonValueListIterator iter

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

Referenced by JsonTablePlanNextRow().

◆ JsonTableResetNestedPlan()

static void JsonTableResetNestedPlan ( JsonTablePlanState planstate)
static

Definition at line 4383 of file jsonpath_exec.c.

4384{
4385 /* This better be a child plan. */
4386 Assert(planstate->parent != NULL);
4387 if (IsA(planstate->plan, JsonTablePathScan))
4388 {
4389 JsonTablePlanState *parent = planstate->parent;
4390
4391 if (!parent->current.isnull)
4392 JsonTableResetRowPattern(planstate, parent->current.value);
4393
4394 /*
4395 * If this plan itself has a child nested plan, it will be reset when
4396 * the caller calls JsonTablePlanNextRow() on this plan.
4397 */
4398 }
4399 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4400 {
4401 JsonTableResetNestedPlan(planstate->left);
4402 JsonTableResetNestedPlan(planstate->right);
4403 }
4404}
static void JsonTableResetRowPattern(JsonTablePlanState *planstate, Datum item)

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

Referenced by JsonTablePlanScanNextRow(), and JsonTableResetNestedPlan().

◆ JsonTableResetRowPattern()

static void JsonTableResetRowPattern ( JsonTablePlanState planstate,
Datum  item 
)
static

Definition at line 4254 of file jsonpath_exec.c.

4255{
4256 JsonTablePathScan *scan = castNode(JsonTablePathScan, planstate->plan);
4257 MemoryContext oldcxt;
4259 Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
4260
4261 JsonValueListClear(&planstate->found);
4262
4263 MemoryContextResetOnly(planstate->mcxt);
4264
4265 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4266
4267 res = executeJsonPath(planstate->path, planstate->args,
4269 js, scan->errorOnError,
4270 &planstate->found,
4271 true);
4272
4273 MemoryContextSwitchTo(oldcxt);
4274
4275 if (jperIsError(res))
4276 {
4277 Assert(!scan->errorOnError);
4278 JsonValueListClear(&planstate->found);
4279 }
4280
4281 /* Reset plan iterator to the beginning of the item list */
4282 JsonValueListInitIterator(&planstate->found, &planstate->iter);
4283 planstate->current.value = PointerGetDatum(NULL);
4284 planstate->current.isnull = true;
4285 planstate->ordinal = 0;
4286}
static void JsonValueListClear(JsonValueList *jvl)
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:419

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

Referenced by JsonTableResetNestedPlan(), and JsonTableSetDocument().

◆ JsonTableSetDocument()

static void JsonTableSetDocument ( TableFuncScanState state,
Datum  value 
)
static

◆ JsonValueListAppend()

static void JsonValueListAppend ( JsonValueList jvl,
JsonbValue jbv 
)
static

Definition at line 3514 of file jsonpath_exec.c.

3515{
3516 if (jvl->singleton)
3517 {
3518 jvl->list = list_make2(jvl->singleton, jbv);
3519 jvl->singleton = NULL;
3520 }
3521 else if (!jvl->list)
3522 jvl->singleton = jbv;
3523 else
3524 jvl->list = lappend(jvl->list, jbv);
3525}
#define list_make2(x1, x2)
Definition: pg_list.h:214
JsonbValue * singleton

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

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

◆ JsonValueListClear()

static void JsonValueListClear ( JsonValueList jvl)
static

Definition at line 3507 of file jsonpath_exec.c.

3508{
3509 jvl->singleton = NULL;
3510 jvl->list = NIL;
3511}

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

Referenced by JsonTableResetRowPattern().

◆ JsonValueListGetList()

static List * JsonValueListGetList ( JsonValueList jvl)
static

Definition at line 3546 of file jsonpath_exec.c.

3547{
3548 if (jvl->singleton)
3549 return list_make1(jvl->singleton);
3550
3551 return jvl->list;
3552}
#define list_make1(x1)
Definition: pg_list.h:212

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

Referenced by jsonb_path_query_internal().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

◆ JsonValueListInitIterator()

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

Definition at line 3555 of file jsonpath_exec.c.

3556{
3557 if (jvl->singleton)
3558 {
3559 it->value = jvl->singleton;
3560 it->list = NIL;
3561 it->next = NULL;
3562 }
3563 else if (jvl->list != NIL)
3564 {
3565 it->value = (JsonbValue *) linitial(jvl->list);
3566 it->list = jvl->list;
3567 it->next = list_second_cell(jvl->list);
3568 }
3569 else
3570 {
3571 it->value = NULL;
3572 it->list = NIL;
3573 it->next = NULL;
3574 }
3575}
static ListCell * list_second_cell(const List *l)
Definition: pg_list.h:142

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

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

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( JsonValueList jvl)
static

Definition at line 3534 of file jsonpath_exec.c.

3535{
3536 return !jvl->singleton && (jvl->list == NIL);
3537}

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

Referenced by executeBoolItem(), and executeJsonPath().

◆ JsonValueListLength()

static int JsonValueListLength ( const JsonValueList jvl)
static

◆ JsonValueListNext()

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

Definition at line 3581 of file jsonpath_exec.c.

3582{
3583 JsonbValue *result = it->value;
3584
3585 if (it->next)
3586 {
3587 it->value = lfirst(it->next);
3588 it->next = lnext(it->list, it->next);
3589 }
3590 else
3591 {
3592 it->value = NULL;
3593 }
3594
3595 return result;
3596}
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

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

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

◆ setBaseObject()

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

Definition at line 3495 of file jsonpath_exec.c.

3496{
3497 JsonBaseObjectInfo baseObject = cxt->baseObject;
3498
3499 cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
3500 (JsonbContainer *) jbv->val.binary.data;
3501 cxt->baseObject.id = id;
3502
3503 return baseObject;
3504}

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

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

◆ wrapItemsInArray()

static JsonbValue * wrapItemsInArray ( const JsonValueList items)
static

Definition at line 3650 of file jsonpath_exec.c.

3651{
3652 JsonbParseState *ps = NULL;
3654 JsonbValue *jbv;
3655
3657
3659 while ((jbv = JsonValueListNext(items, &it)))
3660 pushJsonbValue(&ps, WJB_ELEM, jbv);
3661
3662 return pushJsonbValue(&ps, WJB_END_ARRAY, NULL);
3663}
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
static ItemArray items
Definition: test_tidstore.c:48

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

Referenced by jsonb_path_query_array_internal(), and JsonPathQuery().

Variable Documentation

◆ JsonbTableRoutine

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

Definition at line 371 of file jsonpath_exec.c.

Referenced by ExecInitTableFuncScan().