PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
jsonpath_exec.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "nodes/nodeFuncs.h"
#include "regex/regex.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/float.h"
#include "utils/formatting.h"
#include "utils/json.h"
#include "utils/jsonpath.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
Include dependency graph for jsonpath_exec.c:

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Variables

const TableFuncRoutine JsonbTableRoutine
 

Macro Definition Documentation

◆ jperIsError

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

Definition at line 142 of file jsonpath_exec.c.

◆ JSON_TABLE_EXEC_CONTEXT_MAGIC

#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867

Definition at line 219 of file jsonpath_exec.c.

◆ jspAutoUnwrap

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

Definition at line 237 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 238 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 239 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

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

Definition at line 236 of file jsonpath_exec.c.

◆ jspThrowErrors

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

Definition at line 240 of file jsonpath_exec.c.

◆ RETURN_ERROR

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

Definition at line 243 of file jsonpath_exec.c.

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 255 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

typedef enum JsonPathBool JsonPathBool

◆ JsonPathCountVarsCallback

typedef int(* JsonPathCountVarsCallback) (void *vars)

Definition at line 91 of file jsonpath_exec.c.

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathGetVarCallback

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

Definition at line 89 of file jsonpath_exec.c.

◆ JsonPathPredicateCallback

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

Definition at line 251 of file jsonpath_exec.c.

◆ JsonTableExecContext

◆ JsonTablePlanRowSource

◆ JsonTablePlanState

◆ JsonValueList

typedef struct JsonValueList JsonValueList

◆ JsonValueListIterator

Enumeration Type Documentation

◆ JsonPathBool

Enumerator
jpbFalse 
jpbTrue 
jpbUnknown 

Definition at line 127 of file jsonpath_exec.c.

128{
129 jpbFalse = 0,
130 jpbTrue = 1,
131 jpbUnknown = 2
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 2929 of file jsonpath_exec.c.

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

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

3678{
3679 checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3680
3681 return DirectFunctionCall1(time_timetz, time);
3682}
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2847
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
static void checkTimezoneIsUsedForCast(bool useTz, const char *type1, const char *type2)

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

Referenced by compareDatetime().

◆ checkTimezoneIsUsedForCast()

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

Definition at line 3665 of file jsonpath_exec.c.

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

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

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

◆ cmpDateToTimestamp()

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

Definition at line 3689 of file jsonpath_exec.c.

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

References date_cmp_timestamp_internal().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 3698 of file jsonpath_exec.c.

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

References checkTimezoneIsUsedForCast(), and date_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

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

Definition at line 3709 of file jsonpath_exec.c.

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

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

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

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

3437{
3440 NumericGetDatum(b)));
3441}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2517
int b
Definition: isn.c:69
int a
Definition: isn.c:68
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73

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

Referenced by compareItems().

◆ compareStrings()

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

Definition at line 3273 of file jsonpath_exec.c.

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

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

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void *  cxt)
static

Definition at line 3035 of file jsonpath_exec.c.

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

3203{
3204 Jsonb *vars = varsJsonb;
3205
3206 if (vars && !JsonContainerIsObject(&vars->root))
3207 {
3208 ereport(ERROR,
3209 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3210 errmsg("\"vars\" argument is not an object"),
3211 errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3212 }
3213
3214 /* count of base objects */
3215 return vars != NULL ? 1 : 0;
3216}
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define JsonContainerIsObject(jc)
Definition: jsonb.h:208
Definition: jsonb.h:213

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

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

◆ executeAnyItem()

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

Definition at line 1933 of file jsonpath_exec.c.

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

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

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

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

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

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

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

Referenced by executeItemOptUnwrapTarget().

◆ executeItem()

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

Definition at line 733 of file jsonpath_exec.c.

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

References executeItemOptUnwrapTarget(), and jspAutoUnwrap.

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

◆ executeItemOptUnwrapResult()

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

Definition at line 1724 of file jsonpath_exec.c.

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

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

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

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

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

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

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

◆ executeJsonPath()

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

Definition at line 677 of file jsonpath_exec.c.

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

References Assert(), JsonPathExecContext::baseObject, JsonPathExecContext::current, executeItem(), JsonPathExecContext::getVar, JsonPath::header, JsonBaseObjectInfo::id, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, JsonBaseObjectInfo::jbc, jperIsError, jperNotFound, jperOk, JsonbExtractScalar(), JsonbInitBinary(), JSONPATH_LAX, JsonValueListIsEmpty(), jspInit(), jspStrictAbsenceOfErrors, JsonPathExecContext::lastGeneratedObjectId, JsonPathExecContext::laxMode, 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 2819 of file jsonpath_exec.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by executeItemOptUnwrapTarget().

◆ getJsonPathItem()

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

Definition at line 2957 of file jsonpath_exec.c.

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

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

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

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

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

4090{
4091 JsonTableExecContext *result;
4092
4094 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4095 result = (JsonTableExecContext *) state->opaque;
4097 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4098
4099 return result;
4100}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
#define JSON_TABLE_EXEC_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
Definition: regguts.h:323

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

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

◆ getScalar()

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

Definition at line 3637 of file jsonpath_exec.c.

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

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

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

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 425 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_internal()

static Datum jsonb_path_exists_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 397 of file jsonpath_exec.c.

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

References countVariablesFromJsonb(), executeJsonPath(), getJsonPathVariableFromJsonb(), jperIsError, jperOk, PG_FREE_IF_COPY, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_GETARG_JSONPATH_P, PG_NARGS, PG_RETURN_BOOL, 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 442 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 431 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 495 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_internal()

static Datum jsonb_path_match_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 454 of file jsonpath_exec.c.

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

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

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

◆ jsonb_path_match_opr()

Datum jsonb_path_match_opr ( PG_FUNCTION_ARGS  )

Definition at line 512 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 501 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 572 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ jsonb_path_query_array()

Datum jsonb_path_query_array ( PG_FUNCTION_ARGS  )

Definition at line 605 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_array_internal()

static Datum jsonb_path_query_array_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 589 of file jsonpath_exec.c.

590{
591 Jsonb *jb = PG_GETARG_JSONB_P(0);
593 JsonValueList found = {0};
595 bool silent = PG_GETARG_BOOL(3);
596
599 jb, !silent, &found, tz);
600
602}
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
static JsonbValue * wrapItemsInArray(const JsonValueList *items)

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

Referenced by jsonb_path_query_array(), and jsonb_path_query_array_tz().

◆ jsonb_path_query_array_tz()

Datum jsonb_path_query_array_tz ( PG_FUNCTION_ARGS  )

Definition at line 611 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 641 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_first_internal()

static Datum jsonb_path_query_first_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 647 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 524 of file jsonpath_exec.c.

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

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

Referenced by jsonb_path_query(), and jsonb_path_query_tz().

◆ jsonb_path_query_tz()

Datum jsonb_path_query_tz ( PG_FUNCTION_ARGS  )

Definition at line 578 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3224 of file jsonpath_exec.c.

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

3601{
3602 jbv->type = jbvBinary;
3603 jbv->val.binary.data = &jb->root;
3604 jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3605
3606 return jbv;
3607}
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

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

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

◆ JsonbType()

static int JsonbType ( JsonbValue jb)
static

Definition at line 3613 of file jsonpath_exec.c.

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

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

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

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

References Assert(), CStringGetDatum(), DatumGetBool(), DatumGetJsonbP(), DatumGetTextP, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, float4_numeric(), float8_numeric(), format_type_be(), int2_numeric(), int4_numeric(), int8_numeric(), jbvBool, jbvDatetime, jbvString, jsonb_in(), JsonbExtractScalar(), JsonbInitBinary(), JsonbPGetDatum(), JsonbValueInitNumericDatum(), JsonContainerIsScalar, 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 3887 of file jsonpath_exec.c.

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

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

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

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

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

References GetJsonTableExecContext(), and JsonTableExecContext::magic.

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4437 of file jsonpath_exec.c.

4438{
4440 GetJsonTableExecContext(state, "JsonTableFetchRow");
4441
4443}
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 4453 of file jsonpath_exec.c.

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

4111{
4113 PlanState *ps = &state->ss.ps;
4114 TableFuncScan *tfs = castNode(TableFuncScan, ps->plan);
4115 TableFunc *tf = tfs->tablefunc;
4116 JsonTablePlan *rootplan = (JsonTablePlan *) tf->plan;
4117 JsonExpr *je = castNode(JsonExpr, tf->docexpr);
4118 List *args = NIL;
4119
4120 cxt = palloc0(sizeof(JsonTableExecContext));
4122
4123 /*
4124 * Evaluate JSON_TABLE() PASSING arguments to be passed to the jsonpath
4125 * executor via JsonPathVariables.
4126 */
4127 if (state->passingvalexprs)
4128 {
4129 ListCell *exprlc;
4130 ListCell *namelc;
4131
4132 Assert(list_length(state->passingvalexprs) ==
4133 list_length(je->passing_names));
4134 forboth(exprlc, state->passingvalexprs,
4135 namelc, je->passing_names)
4136 {
4138 String *name = lfirst_node(String, namelc);
4139 JsonPathVariable *var = palloc(sizeof(*var));
4140
4141 var->name = pstrdup(name->sval);
4142 var->namelen = strlen(var->name);
4143 var->typid = exprType((Node *) state->expr);
4144 var->typmod = exprTypmod((Node *) state->expr);
4145
4146 /*
4147 * Evaluate the expression and save the value to be returned by
4148 * GetJsonPathVar().
4149 */
4150 var->value = ExecEvalExpr(state, ps->ps_ExprContext,
4151 &var->isnull);
4152
4153 args = lappend(args, var);
4154 }
4155 }
4156
4157 cxt->colplanstates = palloc(sizeof(JsonTablePlanState *) *
4158 list_length(tf->colvalexprs));
4159
4160 /*
4161 * Initialize plan for the root path and, recursively, also any child
4162 * plans that compute the NESTED paths.
4163 */
4164 cxt->rootplanstate = JsonTableInitPlan(cxt, rootplan, NULL, args,
4166
4167 state->opaque = cxt;
4168}
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:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
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:176
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
Definition: value.h:64
TableFunc * tablefunc
Definition: plannodes.h:741
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 4192 of file jsonpath_exec.c.

4195{
4196 JsonTablePlanState *planstate = palloc0(sizeof(*planstate));
4197
4198 planstate->plan = plan;
4199 planstate->parent = parentstate;
4200
4202 {
4204 int i;
4205
4206 planstate->path = DatumGetJsonPathP(scan->path->value->constvalue);
4207 planstate->args = args;
4208 planstate->mcxt = AllocSetContextCreate(mcxt, "JsonTableExecContext",
4210
4211 /* No row pattern evaluated yet. */
4212 planstate->current.value = PointerGetDatum(NULL);
4213 planstate->current.isnull = true;
4214
4215 for (i = scan->colMin; i >= 0 && i <= scan->colMax; i++)
4216 cxt->colplanstates[i] = planstate;
4217
4218 planstate->nested = scan->child ?
4219 JsonTableInitPlan(cxt, scan->child, planstate, args, mcxt) : NULL;
4220 }
4221 else if (IsA(plan, JsonTableSiblingJoin))
4222 {
4224
4225 planstate->left = JsonTableInitPlan(cxt, join->lplan, parentstate,
4226 args, mcxt);
4227 planstate->right = JsonTableInitPlan(cxt, join->rplan, parentstate,
4228 args, mcxt);
4229 }
4230
4231 return planstate;
4232}
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:1903
JsonTablePlan * child
Definition: primnodes.h:1912
Const * value
Definition: primnodes.h:1876
struct JsonTablePlanState * left
struct JsonTablePlanState * nested
MemoryContext mcxt
struct JsonTablePlanState * parent
JsonTablePlan * plan
struct JsonTablePlanState * right
JsonTablePlan * rplan
Definition: primnodes.h:1933
JsonTablePlan * lplan
Definition: primnodes.h:1932

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

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

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

Referenced by JsonTablePlanNextRow().

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4292 of file jsonpath_exec.c.

4293{
4294 if (IsA(planstate->plan, JsonTablePathScan))
4295 return JsonTablePlanScanNextRow(planstate);
4296 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4297 return JsonTablePlanJoinNextRow(planstate);
4298 else
4299 elog(ERROR, "invalid JsonTablePlan %d", (int) planstate->plan->type);
4300
4301 Assert(false);
4302 /* Appease compiler */
4303 return false;
4304}
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 4319 of file jsonpath_exec.c.

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

4382{
4383 /* This better be a child plan. */
4384 Assert(planstate->parent != NULL);
4385 if (IsA(planstate->plan, JsonTablePathScan))
4386 {
4387 JsonTablePlanState *parent = planstate->parent;
4388
4389 if (!parent->current.isnull)
4390 JsonTableResetRowPattern(planstate, parent->current.value);
4391
4392 /*
4393 * If this plan itself has a child nested plan, it will be reset when
4394 * the caller calls JsonTablePlanNextRow() on this plan.
4395 */
4396 }
4397 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4398 {
4399 JsonTableResetNestedPlan(planstate->left);
4400 JsonTableResetNestedPlan(planstate->right);
4401 }
4402}
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 4252 of file jsonpath_exec.c.

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

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

3513{
3514 if (jvl->singleton)
3515 {
3516 jvl->list = list_make2(jvl->singleton, jbv);
3517 jvl->singleton = NULL;
3518 }
3519 else if (!jvl->list)
3520 jvl->singleton = jbv;
3521 else
3522 jvl->list = lappend(jvl->list, jbv);
3523}
#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 3505 of file jsonpath_exec.c.

3506{
3507 jvl->singleton = NULL;
3508 jvl->list = NIL;
3509}

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

Referenced by JsonTableResetRowPattern().

◆ JsonValueListGetList()

static List * JsonValueListGetList ( JsonValueList jvl)
static

Definition at line 3544 of file jsonpath_exec.c.

3545{
3546 if (jvl->singleton)
3547 return list_make1(jvl->singleton);
3548
3549 return jvl->list;
3550}
#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 3553 of file jsonpath_exec.c.

3554{
3555 if (jvl->singleton)
3556 {
3557 it->value = jvl->singleton;
3558 it->list = NIL;
3559 it->next = NULL;
3560 }
3561 else if (jvl->list != NIL)
3562 {
3563 it->value = (JsonbValue *) linitial(jvl->list);
3564 it->list = jvl->list;
3565 it->next = list_second_cell(jvl->list);
3566 }
3567 else
3568 {
3569 it->value = NULL;
3570 it->list = NIL;
3571 it->next = NULL;
3572 }
3573}
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 3532 of file jsonpath_exec.c.

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

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

3580{
3581 JsonbValue *result = it->value;
3582
3583 if (it->next)
3584 {
3585 it->value = lfirst(it->next);
3586 it->next = lnext(it->list, it->next);
3587 }
3588 else
3589 {
3590 it->value = NULL;
3591 }
3592
3593 return result;
3594}
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 3493 of file jsonpath_exec.c.

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

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

3649{
3650 JsonbParseState *ps = NULL;
3652 JsonbValue *jbv;
3653
3655
3657 while ((jbv = JsonValueListNext(items, &it)))
3658 pushJsonbValue(&ps, WJB_ELEM, jbv);
3659
3660 return pushJsonbValue(&ps, WJB_END_ARRAY, NULL);
3661}
@ 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 370 of file jsonpath_exec.c.

Referenced by ExecInitTableFuncScan().