PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 BASE_JVL_ITEMS   2 /* number of items a base chunk holds */
 
#define MIN_EXTRA_JVL_ITEMS   16 /* min number of items an extra chunk holds */
 
#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867
 
#define jspStrictAbsenceOfErrors(cxt)   (!(cxt)->laxMode)
 
#define jspAutoUnwrap(cxt)   ((cxt)->laxMode)
 
#define jspAutoWrap(cxt)   ((cxt)->laxMode)
 
#define jspIgnoreStructuralErrors(cxt)   ((cxt)->ignoreStructuralErrors)
 
#define jspThrowErrors(cxt)   ((cxt)->throwErrors)
 
#define RETURN_ERROR(throw_error)
 

Typedefs

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

Enumerations

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

Functions

static JsonPathExecResult executeJsonPath (JsonPath *path, void *vars, JsonPathGetVarCallback getVar, JsonPathCountVarsCallback countVars, Jsonb *json, bool throwErrors, JsonValueList *result, bool useTz)
 
static JsonPathExecResult executeItem (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
 
static JsonPathExecResult executeItemOptUnwrapTarget (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
 
static JsonPathExecResult executeItemUnwrapTargetArray (JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
 
static JsonPathExecResult executeNextItem (JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found)
 
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 JsonValueListInit (JsonValueList *jvl)
 
static void JsonValueListClear (JsonValueList *jvl)
 
static void JsonValueListAppend (JsonValueList *jvl, const JsonbValue *jbv)
 
static bool JsonValueListIsEmpty (const JsonValueList *jvl)
 
static bool JsonValueListIsSingleton (const JsonValueList *jvl)
 
static bool JsonValueListHasMultipleItems (const JsonValueList *jvl)
 
static JsonbValueJsonValueListHead (JsonValueList *jvl)
 
static void JsonValueListInitIterator (JsonValueList *jvl, JsonValueListIterator *it)
 
static JsonbValueJsonValueListNext (JsonValueListIterator *it)
 
static JsonbValueJsonbInitBinary (JsonbValue *jbv, Jsonb *jb)
 
static int JsonbType (JsonbValue *jb)
 
static JsonbValuegetScalar (JsonbValue *scalar, enum jbvType type)
 
static JsonbValuewrapItemsInArray (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

◆ BASE_JVL_ITEMS

#define BASE_JVL_ITEMS   2 /* number of items a base chunk holds */

Definition at line 168 of file jsonpath_exec.c.

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

◆ jspAutoUnwrap

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

Definition at line 264 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 265 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 266 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

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

Definition at line 263 of file jsonpath_exec.c.

◆ jspThrowErrors

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

Definition at line 267 of file jsonpath_exec.c.

◆ MIN_EXTRA_JVL_ITEMS

#define MIN_EXTRA_JVL_ITEMS   16 /* min number of items an extra chunk holds */

Definition at line 169 of file jsonpath_exec.c.

◆ RETURN_ERROR

#define RETURN_ERROR (   throw_error)
Value:
do { \
} while (0)
@ jperError
#define jspThrowErrors(cxt)
static int fb(int x)

Definition at line 270 of file jsonpath_exec.c.

271 { \
272 if (jspThrowErrors(cxt)) \
273 throw_error; \
274 else \
276} while (0)

Typedef Documentation

◆ BinaryArithmFunc

typedef Numeric(* BinaryArithmFunc) (Numeric num1, Numeric num2, Node *escontext)

Definition at line 282 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

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

◆ JsonTableExecContext

◆ JsonTablePlanRowSource

◆ JsonTablePlanState

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

3018{
3021
3022 if (!jspGetNext(jsp, &next) && !found)
3023 return jperOk; /* found singleton boolean value */
3024
3025 if (res == jpbUnknown)
3026 {
3027 jbv.type = jbvNull;
3028 }
3029 else
3030 {
3031 jbv.type = jbvBool;
3032 jbv.val.boolean = res == jpbTrue;
3033 }
3034
3035 return executeNextItem(cxt, jsp, &next, &jbv, found);
3036}
static int32 next
Definition blutils.c:225
@ jbvBool
Definition jsonb.h:233
@ jbvNull
Definition jsonb.h:230
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1099
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found)
enum jbvType type
Definition jsonb.h:257

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

Referenced by executeItemOptUnwrapTarget().

◆ binaryCompareStrings()

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

Definition at line 3339 of file jsonpath_exec.c.

3341{
3342 int cmp;
3343
3344 cmp = memcmp(s1, s2, Min(len1, len2));
3345
3346 if (cmp != 0)
3347 return cmp;
3348
3349 if (len1 == len2)
3350 return 0;
3351
3352 return len1 < len2 ? -1 : 1;
3353}
#define Min(x, y)
Definition c.h:1093
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)

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

Referenced by compareStrings().

◆ castTimeToTimeTz()

static Datum castTimeToTimeTz ( Datum  time,
bool  useTz 
)
static

Definition at line 3814 of file jsonpath_exec.c.

3815{
3816 checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3817
3818 return DirectFunctionCall1(time_timetz, time);
3819}
Datum time_timetz(PG_FUNCTION_ARGS)
Definition date.c:2916
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
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 3802 of file jsonpath_exec.c.

3803{
3804 if (!useTz)
3805 ereport(ERROR,
3807 errmsg("cannot convert value from %s to %s without time zone usage",
3808 type1, type2),
3809 errhint("Use *_tz() function for time zone support.")));
3810}
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
static char * errmsg

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

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

◆ cmpDateToTimestamp()

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

Definition at line 3826 of file jsonpath_exec.c.

3827{
3829}
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition date.c:768

References date_cmp_timestamp_internal(), and fb().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 3835 of file jsonpath_exec.c.

3836{
3837 checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
3838
3840}
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition date.c:849

References checkTimezoneIsUsedForCast(), date_cmp_timestamptz_internal(), and fb().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

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

Definition at line 3846 of file jsonpath_exec.c.

3847{
3848 checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
3849
3851}
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition timestamp.c:2354

References checkTimezoneIsUsedForCast(), fb(), 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 3859 of file jsonpath_exec.c.

3861{
3863
3864 *cast_error = false;
3865
3866 switch (typid1)
3867 {
3868 case DATEOID:
3869 switch (typid2)
3870 {
3871 case DATEOID:
3872 cmpfunc = date_cmp;
3873
3874 break;
3875
3876 case TIMESTAMPOID:
3879 useTz);
3880
3881 case TIMESTAMPTZOID:
3884 useTz);
3885
3886 case TIMEOID:
3887 case TIMETZOID:
3888 *cast_error = true; /* uncomparable types */
3889 return 0;
3890
3891 default:
3892 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3893 typid2);
3894 }
3895 break;
3896
3897 case TIMEOID:
3898 switch (typid2)
3899 {
3900 case TIMEOID:
3901 cmpfunc = time_cmp;
3902
3903 break;
3904
3905 case TIMETZOID:
3906 val1 = castTimeToTimeTz(val1, useTz);
3908
3909 break;
3910
3911 case DATEOID:
3912 case TIMESTAMPOID:
3913 case TIMESTAMPTZOID:
3914 *cast_error = true; /* uncomparable types */
3915 return 0;
3916
3917 default:
3918 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3919 typid2);
3920 }
3921 break;
3922
3923 case TIMETZOID:
3924 switch (typid2)
3925 {
3926 case TIMEOID:
3927 val2 = castTimeToTimeTz(val2, useTz);
3929
3930 break;
3931
3932 case TIMETZOID:
3934
3935 break;
3936
3937 case DATEOID:
3938 case TIMESTAMPOID:
3939 case TIMESTAMPTZOID:
3940 *cast_error = true; /* uncomparable types */
3941 return 0;
3942
3943 default:
3944 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3945 typid2);
3946 }
3947 break;
3948
3949 case TIMESTAMPOID:
3950 switch (typid2)
3951 {
3952 case DATEOID:
3955 useTz);
3956
3957 case TIMESTAMPOID:
3959
3960 break;
3961
3962 case TIMESTAMPTZOID:
3965 useTz);
3966
3967 case TIMEOID:
3968 case TIMETZOID:
3969 *cast_error = true; /* uncomparable types */
3970 return 0;
3971
3972 default:
3973 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
3974 typid2);
3975 }
3976 break;
3977
3978 case TIMESTAMPTZOID:
3979 switch (typid2)
3980 {
3981 case DATEOID:
3984 useTz);
3985
3986 case TIMESTAMPOID:
3989 useTz);
3990
3991 case TIMESTAMPTZOID:
3993
3994 break;
3995
3996 case TIMEOID:
3997 case TIMETZOID:
3998 *cast_error = true; /* uncomparable types */
3999 return 0;
4000
4001 default:
4002 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4003 typid2);
4004 }
4005 break;
4006
4007 default:
4008 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
4009 }
4010
4011 if (*cast_error)
4012 return 0; /* cast error */
4013
4015}
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition timestamp.c:2261
Datum date_cmp(PG_FUNCTION_ARGS)
Definition date.c:438
Datum time_cmp(PG_FUNCTION_ARGS)
Definition date.c:1822
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition date.c:2612
static DateADT DatumGetDateADT(Datum X)
Definition date.h:60
#define elog(elevel,...)
Definition elog.h:226
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:686
Datum(* PGFunction)(FunctionCallInfo fcinfo)
Definition fmgr.h:40
static int cmpDateToTimestamp(DateADT date1, Timestamp ts2, bool useTz)
static Datum castTimeToTimeTz(Datum time, bool useTz)
static int cmpDateToTimestampTz(DateADT date1, TimestampTz tstz2, bool useTz)
static int cmpTimestampToTimestampTz(Timestamp ts1, TimestampTz tstz2, bool useTz)
static int32 DatumGetInt32(Datum X)
Definition postgres.h:202
static Timestamp DatumGetTimestamp(Datum X)
Definition timestamp.h:28
static TimestampTz DatumGetTimestampTz(Datum X)
Definition timestamp.h:34

References castTimeToTimeTz(), cmpDateToTimestamp(), cmpDateToTimestampTz(), cmpTimestampToTimestampTz(), date_cmp(), DatumGetDateADT(), DatumGetInt32(), DatumGetTimestamp(), DatumGetTimestampTz(), DirectFunctionCall2, elog, ERROR, fb(), 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 3427 of file jsonpath_exec.c.

3428{
3429 int cmp;
3430 bool res;
3431
3432 if (jb1->type != jb2->type)
3433 {
3434 if (jb1->type == jbvNull || jb2->type == jbvNull)
3435
3436 /*
3437 * Equality and order comparison of nulls to non-nulls returns
3438 * always false, but inequality comparison returns true.
3439 */
3440 return op == jpiNotEqual ? jpbTrue : jpbFalse;
3441
3442 /* Non-null items of different types are not comparable. */
3443 return jpbUnknown;
3444 }
3445
3446 switch (jb1->type)
3447 {
3448 case jbvNull:
3449 cmp = 0;
3450 break;
3451 case jbvBool:
3452 cmp = jb1->val.boolean == jb2->val.boolean ? 0 :
3453 jb1->val.boolean ? 1 : -1;
3454 break;
3455 case jbvNumeric:
3456 cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
3457 break;
3458 case jbvString:
3459 if (op == jpiEqual)
3460 return jb1->val.string.len != jb2->val.string.len ||
3461 memcmp(jb1->val.string.val,
3462 jb2->val.string.val,
3463 jb1->val.string.len) ? jpbFalse : jpbTrue;
3464
3465 cmp = compareStrings(jb1->val.string.val, jb1->val.string.len,
3466 jb2->val.string.val, jb2->val.string.len);
3467 break;
3468 case jbvDatetime:
3469 {
3470 bool cast_error;
3471
3472 cmp = compareDatetime(jb1->val.datetime.value,
3473 jb1->val.datetime.typid,
3474 jb2->val.datetime.value,
3475 jb2->val.datetime.typid,
3476 useTz,
3477 &cast_error);
3478
3479 if (cast_error)
3480 return jpbUnknown;
3481 }
3482 break;
3483
3484 case jbvBinary:
3485 case jbvArray:
3486 case jbvObject:
3487 return jpbUnknown; /* non-scalars are not comparable */
3488
3489 default:
3490 elog(ERROR, "invalid jsonb value type %d", jb1->type);
3491 }
3492
3493 switch (op)
3494 {
3495 case jpiEqual:
3496 res = (cmp == 0);
3497 break;
3498 case jpiNotEqual:
3499 res = (cmp != 0);
3500 break;
3501 case jpiLess:
3502 res = (cmp < 0);
3503 break;
3504 case jpiGreater:
3505 res = (cmp > 0);
3506 break;
3507 case jpiLessOrEqual:
3508 res = (cmp <= 0);
3509 break;
3510 case jpiGreaterOrEqual:
3511 res = (cmp >= 0);
3512 break;
3513 default:
3514 elog(ERROR, "unrecognized jsonpath operation: %d", op);
3515 return jpbUnknown;
3516 }
3517
3518 return res ? jpbTrue : jpbFalse;
3519}
@ jbvObject
Definition jsonb.h:236
@ jbvNumeric
Definition jsonb.h:232
@ jbvArray
Definition jsonb.h:235
@ jbvBinary
Definition jsonb.h:238
@ jbvDatetime
Definition jsonb.h:246
@ jbvString
Definition jsonb.h:231
@ 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, fb(), jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jpbFalse, jpbTrue, jpbUnknown, jpiEqual, jpiGreater, jpiGreaterOrEqual, jpiLess, jpiLessOrEqual, and jpiNotEqual.

Referenced by executeComparison().

◆ compareNumeric()

static int compareNumeric ( Numeric  a,
Numeric  b 
)
static

Definition at line 3523 of file jsonpath_exec.c.

3524{
3527 NumericGetDatum(b)));
3528}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition numeric.c:2415
int b
Definition isn.c:74
int a
Definition isn.c:73
static Datum NumericGetDatum(Numeric X)
Definition numeric.h:76

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

Referenced by compareItems().

◆ compareStrings()

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

Definition at line 3360 of file jsonpath_exec.c.

3362{
3365 {
3366 /*
3367 * It's known property of UTF-8 strings that their per-byte comparison
3368 * result matches codepoints comparison result. ASCII can be
3369 * considered as special case of UTF-8.
3370 */
3372 }
3373 else
3374 {
3375 char *utf8str1,
3376 *utf8str2;
3377 int cmp,
3378 utf8len1,
3379 utf8len2;
3380
3381 /*
3382 * We have to convert other encodings to UTF-8 first, then compare.
3383 * Input strings may be not null-terminated and pg_server_to_any() may
3384 * return them "as is". So, use strlen() only if there is real
3385 * conversion.
3386 */
3391
3393
3394 /*
3395 * If pg_server_to_any() did no real conversion, then we actually
3396 * compared original strings. So, we already done.
3397 */
3398 if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
3399 return cmp;
3400
3401 /* Free memory if needed */
3402 if (mbstr1 != utf8str1)
3403 pfree(utf8str1);
3404 if (mbstr2 != utf8str2)
3405 pfree(utf8str2);
3406
3407 /*
3408 * When all Unicode codepoints are equal, return result of binary
3409 * comparison. In some edge cases, same characters may have different
3410 * representations in encoding. Then our behavior could diverge from
3411 * standard. However, that allow us to do simple binary comparison
3412 * for "==" operator, which is performance critical in typical cases.
3413 * In future to implement strict standard conformance, we can do
3414 * normalization of input JSON strings.
3415 */
3416 if (cmp == 0)
3418 else
3419 return cmp;
3420 }
3421}
static int binaryCompareStrings(const char *s1, int len1, const char *s2, int len2)
#define PG_UTF8
Definition mbprint.c:43
int GetDatabaseEncoding(void)
Definition mbutils.c:1389
char * pg_server_to_any(const char *s, int len, int encoding)
Definition mbutils.c:760
void pfree(void *pointer)
Definition mcxt.c:1616
@ PG_SQL_ASCII
Definition pg_wchar.h:226

References binaryCompareStrings(), cmp(), fb(), 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 3531 of file jsonpath_exec.c.

3532{
3534
3535 *dst = *src;
3536
3537 return dst;
3538}
#define palloc_object(type)
Definition fe_memutils.h:74

References fb(), and palloc_object.

Referenced by JsonPathValue().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void cxt)
static

Definition at line 3122 of file jsonpath_exec.c.

3123{
3124 List *vars = (List *) cxt;
3125
3126 return list_length(vars);
3127}
static int list_length(const List *l)
Definition pg_list.h:152
Definition pg_list.h:54

References list_length().

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

◆ countVariablesFromJsonb()

static int countVariablesFromJsonb ( void varsJsonb)
static

Definition at line 3289 of file jsonpath_exec.c.

3290{
3291 Jsonb *vars = varsJsonb;
3292
3293 if (vars && !JsonContainerIsObject(&vars->root))
3294 {
3295 ereport(ERROR,
3297 errmsg("\"vars\" argument is not an object"),
3298 errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3299 }
3300
3301 /* count of base objects */
3302 return vars != NULL ? 1 : 0;
3303}
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define JsonContainerIsObject(jc)
Definition jsonb.h:210
Definition jsonb.h:215

References ereport, errcode(), errdetail(), errmsg, ERROR, fb(), 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 1970 of file jsonpath_exec.c.

1973{
1976 int32 r;
1977 JsonbValue v;
1978
1980
1981 if (level > last)
1982 return res;
1983
1984 it = JsonbIteratorInit(jbc);
1985
1986 /*
1987 * Recursively iterate over jsonb objects/arrays
1988 */
1989 while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1990 {
1991 if (r == WJB_KEY)
1992 {
1993 r = JsonbIteratorNext(&it, &v, true);
1994 Assert(r == WJB_VALUE);
1995 }
1996
1997 if (r == WJB_VALUE || r == WJB_ELEM)
1998 {
1999
2000 if (level >= first ||
2001 (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
2002 v.type != jbvBinary)) /* leaves only requested */
2003 {
2004 /* check expression */
2005 if (jsp)
2006 {
2007 if (ignoreStructuralErrors)
2008 {
2010
2012 cxt->ignoreStructuralErrors = true;
2013 res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2015 }
2016 else
2017 res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2018
2019 if (jperIsError(res))
2020 break;
2021
2022 if (res == jperOk && !found)
2023 break;
2024 }
2025 else if (found)
2026 JsonValueListAppend(found, &v);
2027 else
2028 return jperOk;
2029 }
2030
2031 if (level < last && v.type == jbvBinary)
2032 {
2033 res = executeAnyItem
2034 (cxt, jsp, v.val.binary.data, found,
2035 level + 1, first, last,
2036 ignoreStructuralErrors, unwrapNext);
2037
2038 if (jperIsError(res))
2039 break;
2040
2041 if (res == jperOk && found == NULL)
2042 break;
2043 }
2044 }
2045 }
2046
2047 return res;
2048}
#define PG_UINT32_MAX
Definition c.h:676
#define Assert(condition)
Definition c.h:945
int32_t int32
Definition c.h:614
@ 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:935
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition jsonb_util.c:973
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)
#define jperIsError(jper)
static void JsonValueListAppend(JsonValueList *jvl, const JsonbValue *jbv)
void check_stack_depth(void)
Definition stack_depth.c:95
char * val
Definition jsonb.h:266

References Assert, check_stack_depth(), executeAnyItem(), executeItemOptUnwrapTarget(), fb(), 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 2155 of file jsonpath_exec.c.

2158{
2160 JsonPathItem elem;
2163 JsonbValue *lval;
2166 Numeric res;
2167
2170
2171 jspGetLeftArg(jsp, &elem);
2172
2173 /*
2174 * XXX: By standard only operands of multiplicative expressions are
2175 * unwrapped. We extend it to other binary arithmetic expressions too.
2176 */
2177 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2178 if (jperIsError(jper))
2179 {
2182 return jper;
2183 }
2184
2185 jspGetRightArg(jsp, &elem);
2186
2187 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2188 if (jperIsError(jper))
2189 {
2192 return jper;
2193 }
2194
2197 {
2202 errmsg("left operand of jsonpath operator %s is not a single numeric value",
2203 jspOperationName(jsp->type)))));
2204 }
2205
2208 {
2213 errmsg("right operand of jsonpath operator %s is not a single numeric value",
2214 jspOperationName(jsp->type)))));
2215 }
2216
2217 if (jspThrowErrors(cxt))
2218 {
2219 res = func(lval->val.numeric, rval->val.numeric, NULL);
2220 }
2221 else
2222 {
2224
2225 res = func(lval->val.numeric, rval->val.numeric, (Node *) &escontext);
2226
2227 if (escontext.error_occurred)
2228 {
2231 return jperError;
2232 }
2233 }
2234
2237
2238 if (!jspGetNext(jsp, &elem) && !found)
2239 return jperOk;
2240
2241 resval.type = jbvNumeric;
2242 resval.val.numeric = res;
2243
2244 return executeNextItem(cxt, jsp, &elem, &resval, found);
2245}
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 void JsonValueListInit(JsonValueList *jvl)
static bool JsonValueListIsSingleton(const JsonValueList *jvl)
static void JsonValueListClear(JsonValueList *jvl)
static JsonPathExecResult executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonbValue * JsonValueListHead(JsonValueList *jvl)
Definition nodes.h:135

References ereport, errcode(), errmsg, ERROR, ErrorSaveContext::error_occurred, executeItemOptUnwrapResult(), executeNextItem(), fb(), getScalar(), jbvNumeric, jperError, jperIsError, jperOk, JsonValueListClear(), JsonValueListHead(), JsonValueListInit(), JsonValueListIsSingleton(), jspGetLeftArg(), jspGetNext(), jspGetRightArg(), jspOperationName(), jspThrowErrors, RETURN_ERROR, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ executeBoolItem()

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

Definition at line 1806 of file jsonpath_exec.c.

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

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

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

◆ executeComparison()

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

Definition at line 3328 of file jsonpath_exec.c.

3329{
3331
3332 return compareItems(cmp->type, lv, rv, cxt->useTz);
3333}
static JsonPathBool compareItems(int32 op, JsonbValue *jb1, JsonbValue *jb2, bool useTz)

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

Referenced by executeBoolItem().

◆ executeDateTimeMethod()

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

Definition at line 2427 of file jsonpath_exec.c.

2429{
2431 Datum value;
2432 text *datetime;
2433 Oid collid;
2434 Oid typid;
2435 int32 typmod = -1;
2436 int tz = 0;
2437 bool hasNext;
2439 JsonPathItem elem;
2440 int32 time_precision = -1;
2441
2442 if (!(jb = getScalar(jb, jbvString)))
2445 errmsg("jsonpath item method .%s() can only be applied to a string",
2446 jspOperationName(jsp->type)))));
2447
2448 datetime = cstring_to_text_with_len(jb->val.string.val,
2449 jb->val.string.len);
2450
2451 /*
2452 * At some point we might wish to have callers supply the collation to
2453 * use, but right now it's unclear that they'd be able to do better than
2454 * DEFAULT_COLLATION_OID anyway.
2455 */
2457
2458 /*
2459 * .datetime(template) has an argument, the rest of the methods don't have
2460 * an argument. So we handle that separately.
2461 */
2462 if (jsp->type == jpiDatetime && jsp->content.arg)
2463 {
2464 text *template;
2465 char *template_str;
2466 int template_len;
2468
2469 jspGetArg(jsp, &elem);
2470
2471 if (elem.type != jpiString)
2472 elog(ERROR, "invalid jsonpath item type for .datetime() argument");
2473
2475
2477 template_len);
2478
2479 value = parse_datetime(datetime, template, collid, true,
2480 &typid, &typmod, &tz,
2481 jspThrowErrors(cxt) ? NULL : (Node *) &escontext);
2482
2483 if (escontext.error_occurred)
2484 res = jperError;
2485 else
2486 res = jperOk;
2487 }
2488 else
2489 {
2490 /*
2491 * According to SQL/JSON standard enumerate ISO formats for: date,
2492 * timetz, time, timestamptz, timestamp.
2493 *
2494 * We also support ISO 8601 format (with "T") for timestamps, because
2495 * to_json[b]() functions use this format.
2496 */
2497 static const char *fmt_str[] =
2498 {
2499 "yyyy-mm-dd", /* date */
2500 "HH24:MI:SS.USTZ", /* timetz */
2501 "HH24:MI:SSTZ",
2502 "HH24:MI:SS.US", /* time without tz */
2503 "HH24:MI:SS",
2504 "yyyy-mm-dd HH24:MI:SS.USTZ", /* timestamptz */
2505 "yyyy-mm-dd HH24:MI:SSTZ",
2506 "yyyy-mm-dd\"T\"HH24:MI:SS.USTZ",
2507 "yyyy-mm-dd\"T\"HH24:MI:SSTZ",
2508 "yyyy-mm-dd HH24:MI:SS.US", /* timestamp without tz */
2509 "yyyy-mm-dd HH24:MI:SS",
2510 "yyyy-mm-dd\"T\"HH24:MI:SS.US",
2511 "yyyy-mm-dd\"T\"HH24:MI:SS"
2512 };
2513
2514 /* cache for format texts */
2515 static text *fmt_txt[lengthof(fmt_str)] = {0};
2516 int i;
2517
2518 /*
2519 * Check for optional precision for methods other than .datetime() and
2520 * .date()
2521 */
2522 if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
2523 jsp->content.arg)
2524 {
2526
2527 jspGetArg(jsp, &elem);
2528
2529 if (elem.type != jpiNumeric)
2530 elog(ERROR, "invalid jsonpath item type for %s argument",
2531 jspOperationName(jsp->type));
2532
2534 (Node *) &escontext);
2535 if (escontext.error_occurred)
2538 errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
2539 jspOperationName(jsp->type)))));
2540 }
2541
2542 /* loop until datetime format fits */
2543 for (i = 0; i < lengthof(fmt_str); i++)
2544 {
2546
2547 if (!fmt_txt[i])
2548 {
2551
2554 }
2555
2556 value = parse_datetime(datetime, fmt_txt[i], collid, true,
2557 &typid, &typmod, &tz,
2558 (Node *) &escontext);
2559
2560 if (!escontext.error_occurred)
2561 {
2562 res = jperOk;
2563 break;
2564 }
2565 }
2566
2567 if (res == jperNotFound)
2568 {
2569 if (jsp->type == jpiDatetime)
2572 errmsg("%s format is not recognized: \"%s\"",
2573 "datetime", text_to_cstring(datetime)),
2574 errhint("Use a datetime template argument to specify the input data format."))));
2575 else
2578 errmsg("%s format is not recognized: \"%s\"",
2579 jspOperationName(jsp->type), text_to_cstring(datetime)))));
2580
2581 }
2582 }
2583
2584 /*
2585 * parse_datetime() processes the entire input string per the template or
2586 * ISO format and returns the Datum in best fitted datetime type. So, if
2587 * this call is for a specific datatype, then we do the conversion here.
2588 * Throw an error for incompatible types.
2589 */
2590 switch (jsp->type)
2591 {
2592 case jpiDatetime: /* Nothing to do for DATETIME */
2593 break;
2594 case jpiDate:
2595 {
2596 /* Convert result type to date */
2597 switch (typid)
2598 {
2599 case DATEOID: /* Nothing to do for DATE */
2600 break;
2601 case TIMEOID:
2602 case TIMETZOID:
2605 errmsg("%s format is not recognized: \"%s\"",
2606 "date", text_to_cstring(datetime)))));
2607 break;
2608 case TIMESTAMPOID:
2610 value);
2611 break;
2612 case TIMESTAMPTZOID:
2614 "timestamptz", "date");
2616 value);
2617 break;
2618 default:
2619 elog(ERROR, "type with oid %u not supported", typid);
2620 }
2621
2622 typid = DATEOID;
2623 }
2624 break;
2625 case jpiTime:
2626 {
2627 /* Convert result type to time without time zone */
2628 switch (typid)
2629 {
2630 case DATEOID:
2633 errmsg("%s format is not recognized: \"%s\"",
2634 "time", text_to_cstring(datetime)))));
2635 break;
2636 case TIMEOID: /* Nothing to do for TIME */
2637 break;
2638 case TIMETZOID:
2640 "timetz", "time");
2642 value);
2643 break;
2644 case TIMESTAMPOID:
2646 value);
2647 break;
2648 case TIMESTAMPTZOID:
2650 "timestamptz", "time");
2652 value);
2653 break;
2654 default:
2655 elog(ERROR, "type with oid %u not supported", typid);
2656 }
2657
2658 /* Force the user-given time precision, if any */
2659 if (time_precision != -1)
2660 {
2661 TimeADT result;
2662
2663 /* Get a warning when precision is reduced */
2666 result = DatumGetTimeADT(value);
2668 value = TimeADTGetDatum(result);
2669
2670 /* Update the typmod value with the user-given precision */
2671 typmod = time_precision;
2672 }
2673
2674 typid = TIMEOID;
2675 }
2676 break;
2677 case jpiTimeTz:
2678 {
2679 /* Convert result type to time with time zone */
2680 switch (typid)
2681 {
2682 case DATEOID:
2683 case TIMESTAMPOID:
2686 errmsg("%s format is not recognized: \"%s\"",
2687 "time_tz", text_to_cstring(datetime)))));
2688 break;
2689 case TIMEOID:
2691 "time", "timetz");
2693 value);
2694 break;
2695 case TIMETZOID: /* Nothing to do for TIMETZ */
2696 break;
2697 case TIMESTAMPTZOID:
2699 value);
2700 break;
2701 default:
2702 elog(ERROR, "type with oid %u not supported", typid);
2703 }
2704
2705 /* Force the user-given time precision, if any */
2706 if (time_precision != -1)
2707 {
2708 TimeTzADT *result;
2709
2710 /* Get a warning when precision is reduced */
2713 result = DatumGetTimeTzADTP(value);
2715 value = TimeTzADTPGetDatum(result);
2716
2717 /* Update the typmod value with the user-given precision */
2718 typmod = time_precision;
2719 }
2720
2721 typid = TIMETZOID;
2722 }
2723 break;
2724 case jpiTimestamp:
2725 {
2726 /* Convert result type to timestamp without time zone */
2727 switch (typid)
2728 {
2729 case DATEOID:
2731 value);
2732 break;
2733 case TIMEOID:
2734 case TIMETZOID:
2737 errmsg("%s format is not recognized: \"%s\"",
2738 "timestamp", text_to_cstring(datetime)))));
2739 break;
2740 case TIMESTAMPOID: /* Nothing to do for TIMESTAMP */
2741 break;
2742 case TIMESTAMPTZOID:
2744 "timestamptz", "timestamp");
2746 value);
2747 break;
2748 default:
2749 elog(ERROR, "type with oid %u not supported", typid);
2750 }
2751
2752 /* Force the user-given time precision, if any */
2753 if (time_precision != -1)
2754 {
2755 Timestamp result;
2757
2758 /* Get a warning when precision is reduced */
2761 result = DatumGetTimestamp(value);
2763 (Node *) &escontext);
2764 if (escontext.error_occurred) /* should not happen */
2767 errmsg("time precision of jsonpath item method .%s() is invalid",
2768 jspOperationName(jsp->type)))));
2769 value = TimestampGetDatum(result);
2770
2771 /* Update the typmod value with the user-given precision */
2772 typmod = time_precision;
2773 }
2774
2775 typid = TIMESTAMPOID;
2776 }
2777 break;
2778 case jpiTimestampTz:
2779 {
2780 struct pg_tm tm;
2781 fsec_t fsec;
2782
2783 /* Convert result type to timestamp with time zone */
2784 switch (typid)
2785 {
2786 case DATEOID:
2788 "date", "timestamptz");
2789
2790 /*
2791 * Get the timezone value explicitly since JsonbValue
2792 * keeps that separate.
2793 */
2795 &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2796 tm.tm_hour = 0;
2797 tm.tm_min = 0;
2798 tm.tm_sec = 0;
2800
2802 value);
2803 break;
2804 case TIMEOID:
2805 case TIMETZOID:
2808 errmsg("%s format is not recognized: \"%s\"",
2809 "timestamp_tz", text_to_cstring(datetime)))));
2810 break;
2811 case TIMESTAMPOID:
2813 "timestamp", "timestamptz");
2814
2815 /*
2816 * Get the timezone value explicitly since JsonbValue
2817 * keeps that separate.
2818 */
2820 &fsec, NULL, NULL) == 0)
2823
2825 value);
2826 break;
2827 case TIMESTAMPTZOID: /* Nothing to do for TIMESTAMPTZ */
2828 break;
2829 default:
2830 elog(ERROR, "type with oid %u not supported", typid);
2831 }
2832
2833 /* Force the user-given time precision, if any */
2834 if (time_precision != -1)
2835 {
2836 Timestamp result;
2838
2839 /* Get a warning when precision is reduced */
2842 result = DatumGetTimestampTz(value);
2844 (Node *) &escontext);
2845 if (escontext.error_occurred) /* should not happen */
2848 errmsg("time precision of jsonpath item method .%s() is invalid",
2849 jspOperationName(jsp->type)))));
2850 value = TimestampTzGetDatum(result);
2851
2852 /* Update the typmod value with the user-given precision */
2853 typmod = time_precision;
2854 }
2855
2856 typid = TIMESTAMPTZOID;
2857 }
2858 break;
2859 default:
2860 elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
2861 }
2862
2863 pfree(datetime);
2864
2865 if (jperIsError(res))
2866 return res;
2867
2868 hasNext = jspGetNext(jsp, &elem);
2869
2870 if (!hasNext && !found)
2871 return res;
2872
2873 jbv.type = jbvDatetime;
2874 jbv.val.datetime.value = value;
2875 jbv.val.datetime.typid = typid;
2876 jbv.val.datetime.typmod = typmod;
2877 jbv.val.datetime.tz = tz;
2878
2879 return executeNextItem(cxt, jsp, &elem, &jbv, found);
2880}
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition datetime.c:1605
void j2date(int jd, int *year, int *month, int *day)
Definition datetime.c:322
int32 numeric_int4_safe(Numeric num, Node *escontext)
Definition numeric.c:4364
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition timestamp.c:359
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition timestamp.c:6421
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition timestamp.c:1901
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition timestamp.c:116
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition timestamp.c:6484
#define lengthof(array)
Definition c.h:875
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:1993
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition date.c:65
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition date.c:1386
Datum timetz_time(PG_FUNCTION_ARGS)
Definition date.c:2903
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition date.c:2942
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition date.c:1733
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition date.c:1401
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition date.c:1327
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition date.c:2023
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition date.c:1313
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
Definition date.h:72
static TimeADT DatumGetTimeADT(Datum X)
Definition date.h:66
static Datum TimeTzADTPGetDatum(const TimeTzADT *X)
Definition date.h:90
int64 TimeADT
Definition date.h:23
static Datum TimeADTGetDatum(TimeADT X)
Definition date.h:84
Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, Node *escontext)
static struct @174 value
int i
Definition isn.c:77
char * jspGetString(JsonPathItem *v, int32 *len)
Definition jsonpath.c:1226
Numeric jspGetNumeric(JsonPathItem *v)
Definition jsonpath.c:1218
@ jpiString
Definition jsonpath.h:65
@ jpiDatetime
Definition jsonpath.h:101
@ jpiTimeTz
Definition jsonpath.h:115
@ jpiDate
Definition jsonpath.h:109
@ jpiTimestamp
Definition jsonpath.h:116
@ jpiTimestampTz
Definition jsonpath.h:117
@ jpiTime
Definition jsonpath.h:114
@ jpiNumeric
Definition jsonpath.h:66
static struct pg_tm tm
Definition localtime.c:104
MemoryContext TopMemoryContext
Definition mcxt.c:166
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
PGDLLIMPORT pg_tz * session_timezone
Definition pgtz.c:28
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
JsonPathItemType type
Definition jsonpath.h:137
TimeADT time
Definition date.h:27
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:778
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:196
text * cstring_to_text(const char *s)
Definition varlena.c:184
char * text_to_cstring(const text *t)
Definition varlena.c:217

References AdjustTimeForTypmod(), AdjustTimestampForTypmod(), anytime_typmod_check(), anytimestamp_typmod_check(), checkTimezoneIsUsedForCast(), collid, 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(), fb(), getScalar(), i, j2date(), jbvDatetime, jbvString, jperError, jperIsError, jperNotFound, jperOk, jpiDate, jpiDatetime, jpiNumeric, jpiString, jpiTime, jpiTimestamp, jpiTimestampTz, jpiTimeTz, jspGetArg(), jspGetNext(), jspGetNumeric(), jspGetString(), jspOperationName(), jspThrowErrors, lengthof, MemoryContextSwitchTo(), numeric_int4_safe(), 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, JsonPathItem::type, JsonPathExecContext::useTz, and value.

Referenced by executeItemOptUnwrapTarget().

◆ executeItem()

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

Definition at line 775 of file jsonpath_exec.c.

777{
778 return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
779}
#define jspAutoUnwrap(cxt)

References executeItemOptUnwrapTarget(), fb(), 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 1745 of file jsonpath_exec.c.

1748{
1749 if (unwrap && jspAutoUnwrap(cxt))
1750 {
1754 JsonbValue *item;
1755
1757
1758 res = executeItem(cxt, jsp, jb, &seq);
1759
1760 if (jperIsError(res))
1761 {
1763 return res;
1764 }
1765
1767 while ((item = JsonValueListNext(&it)))
1768 {
1769 Assert(item->type != jbvArray);
1770
1771 if (JsonbType(item) == jbvArray)
1772 executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1773 else
1774 JsonValueListAppend(found, item);
1775 }
1776
1778
1779 return jperOk;
1780 }
1781
1782 return executeItem(cxt, jsp, jb, found);
1783}
static JsonbValue * JsonValueListNext(JsonValueListIterator *it)
static int JsonbType(JsonbValue *jb)
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
static void JsonValueListInitIterator(JsonValueList *jvl, JsonValueListIterator *it)

References Assert, executeItem(), executeItemUnwrapTargetArray(), fb(), jbvArray, jperIsError, jperOk, JsonbType(), JsonValueListAppend(), JsonValueListClear(), JsonValueListInit(), 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 1789 of file jsonpath_exec.c.

1793{
1795 bool throwErrors = cxt->throwErrors;
1796
1797 cxt->throwErrors = false;
1798 res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1799 cxt->throwErrors = throwErrors;
1800
1801 return res;
1802}

References executeItemOptUnwrapResult(), fb(), 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 787 of file jsonpath_exec.c.

789{
790 JsonPathItem elem;
792 JsonBaseObjectInfo baseObject;
793
796
797 switch (jsp->type)
798 {
799 case jpiNull:
800 case jpiBool:
801 case jpiNumeric:
802 case jpiString:
803 case jpiVariable:
804 {
805 JsonbValue v;
806 bool hasNext = jspGetNext(jsp, &elem);
807
808 if (!hasNext && !found && jsp->type != jpiVariable)
809 {
810 /*
811 * Skip evaluation, but not for variables. We must
812 * trigger an error for the missing variable.
813 */
814 res = jperOk;
815 break;
816 }
817
818 baseObject = cxt->baseObject;
819 getJsonPathItem(cxt, jsp, &v);
820
821 res = executeNextItem(cxt, jsp, &elem,
822 &v, found);
823 cxt->baseObject = baseObject;
824 }
825 break;
826
827 /* all boolean item types: */
828 case jpiAnd:
829 case jpiOr:
830 case jpiNot:
831 case jpiIsUnknown:
832 case jpiEqual:
833 case jpiNotEqual:
834 case jpiLess:
835 case jpiGreater:
836 case jpiLessOrEqual:
838 case jpiExists:
839 case jpiStartsWith:
840 case jpiLikeRegex:
841 {
842 JsonPathBool st = executeBoolItem(cxt, jsp, jb, true);
843
844 res = appendBoolResult(cxt, jsp, found, st);
845 break;
846 }
847
848 case jpiAdd:
849 return executeBinaryArithmExpr(cxt, jsp, jb,
850 numeric_add_safe, found);
851
852 case jpiSub:
853 return executeBinaryArithmExpr(cxt, jsp, jb,
854 numeric_sub_safe, found);
855
856 case jpiMul:
857 return executeBinaryArithmExpr(cxt, jsp, jb,
858 numeric_mul_safe, found);
859
860 case jpiDiv:
861 return executeBinaryArithmExpr(cxt, jsp, jb,
862 numeric_div_safe, found);
863
864 case jpiMod:
865 return executeBinaryArithmExpr(cxt, jsp, jb,
866 numeric_mod_safe, found);
867
868 case jpiPlus:
869 return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
870
871 case jpiMinus:
873 found);
874
875 case jpiAnyArray:
876 if (JsonbType(jb) == jbvArray)
877 {
878 bool hasNext = jspGetNext(jsp, &elem);
879
880 res = executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL,
881 jb, found, jspAutoUnwrap(cxt));
882 }
883 else if (jspAutoWrap(cxt))
884 res = executeNextItem(cxt, jsp, NULL, jb, found);
885 else if (!jspIgnoreStructuralErrors(cxt))
888 errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
889 break;
890
891 case jpiAnyKey:
892 if (JsonbType(jb) == jbvObject)
893 {
894 bool hasNext = jspGetNext(jsp, &elem);
895
896 if (jb->type != jbvBinary)
897 elog(ERROR, "invalid jsonb object type: %d", jb->type);
898
899 return executeAnyItem
900 (cxt, hasNext ? &elem : NULL,
901 jb->val.binary.data, found, 1, 1, 1,
902 false, jspAutoUnwrap(cxt));
903 }
904 else if (unwrap && JsonbType(jb) == jbvArray)
905 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
906 else if (!jspIgnoreStructuralErrors(cxt))
907 {
908 Assert(found);
911 errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
912 }
913 break;
914
915 case jpiIndexArray:
916 if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
917 {
918 int innermostArraySize = cxt->innermostArraySize;
919 int i;
920 int size = JsonbArraySize(jb);
921 bool singleton = size < 0;
922 bool hasNext = jspGetNext(jsp, &elem);
923
924 if (singleton)
925 size = 1;
926
927 cxt->innermostArraySize = size; /* for LAST evaluation */
928
929 for (i = 0; i < jsp->content.array.nelems; i++)
930 {
931 JsonPathItem from;
932 JsonPathItem to;
933 int32 index;
936 bool range = jspGetArraySubscript(jsp, &from,
937 &to, i);
938
939 res = getArrayIndex(cxt, &from, jb, &index_from);
940
941 if (jperIsError(res))
942 break;
943
944 if (range)
945 {
946 res = getArrayIndex(cxt, &to, jb, &index_to);
947
948 if (jperIsError(res))
949 break;
950 }
951 else
953
954 if (!jspIgnoreStructuralErrors(cxt) &&
955 (index_from < 0 ||
957 index_to >= size))
960 errmsg("jsonpath array subscript is out of bounds"))));
961
962 if (index_from < 0)
963 index_from = 0;
964
965 if (index_to >= size)
966 index_to = size - 1;
967
968 res = jperNotFound;
969
970 for (index = index_from; index <= index_to; index++)
971 {
972 JsonbValue *v;
973
974 if (singleton)
975 {
976 v = jb;
977 }
978 else
979 {
980 v = getIthJsonbValueFromContainer(jb->val.binary.data,
981 (uint32) index);
982
983 if (v == NULL)
984 continue;
985 }
986
987 if (!hasNext && !found)
988 return jperOk;
989
990 res = executeNextItem(cxt, jsp, &elem, v, found);
991
992 if (jperIsError(res))
993 break;
994
995 if (res == jperOk && !found)
996 break;
997 }
998
999 if (jperIsError(res))
1000 break;
1001
1002 if (res == jperOk && !found)
1003 break;
1004 }
1005
1006 cxt->innermostArraySize = innermostArraySize;
1007 }
1008 else if (!jspIgnoreStructuralErrors(cxt))
1009 {
1012 errmsg("jsonpath array accessor can only be applied to an array"))));
1013 }
1014 break;
1015
1016 case jpiAny:
1017 {
1018 bool hasNext = jspGetNext(jsp, &elem);
1019
1020 /* first try without any intermediate steps */
1021 if (jsp->content.anybounds.first == 0)
1022 {
1024
1026 cxt->ignoreStructuralErrors = true;
1027 res = executeNextItem(cxt, jsp, &elem,
1028 jb, found);
1030
1031 if (res == jperOk && !found)
1032 break;
1033 }
1034
1035 if (jb->type == jbvBinary)
1036 res = executeAnyItem
1037 (cxt, hasNext ? &elem : NULL,
1038 jb->val.binary.data, found,
1039 1,
1040 jsp->content.anybounds.first,
1041 jsp->content.anybounds.last,
1042 true, jspAutoUnwrap(cxt));
1043 break;
1044 }
1045
1046 case jpiKey:
1047 if (JsonbType(jb) == jbvObject)
1048 {
1049 JsonbValue *v;
1051
1052 key.type = jbvString;
1053 key.val.string.val = jspGetString(jsp, &key.val.string.len);
1054
1055 v = findJsonbValueFromContainer(jb->val.binary.data,
1056 JB_FOBJECT, &key);
1057
1058 if (v != NULL)
1059 {
1060 res = executeNextItem(cxt, jsp, NULL,
1061 v, found);
1062 pfree(v);
1063 }
1064 else if (!jspIgnoreStructuralErrors(cxt))
1065 {
1066 Assert(found);
1067
1068 if (!jspThrowErrors(cxt))
1069 return jperError;
1070
1071 ereport(ERROR,
1073 errmsg("JSON object does not contain key \"%s\"",
1074 pnstrdup(key.val.string.val,
1075 key.val.string.len))));
1076 }
1077 }
1078 else if (unwrap && JsonbType(jb) == jbvArray)
1079 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1080 else if (!jspIgnoreStructuralErrors(cxt))
1081 {
1082 Assert(found);
1085 errmsg("jsonpath member accessor can only be applied to an object"))));
1086 }
1087 break;
1088
1089 case jpiCurrent:
1090 res = executeNextItem(cxt, jsp, NULL, cxt->current, found);
1091 break;
1092
1093 case jpiRoot:
1094 jb = cxt->root;
1095 baseObject = setBaseObject(cxt, jb, 0);
1096 res = executeNextItem(cxt, jsp, NULL, jb, found);
1097 cxt->baseObject = baseObject;
1098 break;
1099
1100 case jpiFilter:
1101 {
1102 JsonPathBool st;
1103
1104 if (unwrap && JsonbType(jb) == jbvArray)
1105 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1106 false);
1107
1108 jspGetArg(jsp, &elem);
1109 st = executeNestedBoolItem(cxt, &elem, jb);
1110 if (st != jpbTrue)
1111 res = jperNotFound;
1112 else
1113 res = executeNextItem(cxt, jsp, NULL,
1114 jb, found);
1115 break;
1116 }
1117
1118 case jpiType:
1119 {
1121
1122 jbv.type = jbvString;
1123 jbv.val.string.val = pstrdup(JsonbTypeName(jb));
1124 jbv.val.string.len = strlen(jbv.val.string.val);
1125
1126 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1127 }
1128 break;
1129
1130 case jpiSize:
1131 {
1132 int size = JsonbArraySize(jb);
1134
1135 if (size < 0)
1136 {
1137 if (!jspAutoWrap(cxt))
1138 {
1139 if (!jspIgnoreStructuralErrors(cxt))
1142 errmsg("jsonpath item method .%s() can only be applied to an array",
1143 jspOperationName(jsp->type)))));
1144 break;
1145 }
1146
1147 size = 1;
1148 }
1149
1150 jbv.type = jbvNumeric;
1151 jbv.val.numeric = int64_to_numeric(size);
1152
1153 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1154 }
1155 break;
1156
1157 case jpiAbs:
1159 found);
1160
1161 case jpiFloor:
1163 found);
1164
1165 case jpiCeiling:
1167 found);
1168
1169 case jpiDouble:
1170 {
1172
1173 if (unwrap && JsonbType(jb) == jbvArray)
1174 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1175 false);
1176
1177 if (jb->type == jbvNumeric)
1178 {
1180 NumericGetDatum(jb->val.numeric)));
1181 double val;
1183
1184 val = float8in_internal(tmp,
1185 NULL,
1186 "double precision",
1187 tmp,
1188 (Node *) &escontext);
1189
1190 if (escontext.error_occurred)
1193 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1194 tmp, jspOperationName(jsp->type), "double precision"))));
1195 if (isinf(val) || isnan(val))
1198 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1199 jspOperationName(jsp->type)))));
1200 res = jperOk;
1201 }
1202 else if (jb->type == jbvString)
1203 {
1204 /* cast string as double */
1205 double val;
1206 char *tmp = pnstrdup(jb->val.string.val,
1207 jb->val.string.len);
1209
1210 val = float8in_internal(tmp,
1211 NULL,
1212 "double precision",
1213 tmp,
1214 (Node *) &escontext);
1215
1216 if (escontext.error_occurred)
1219 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1220 tmp, jspOperationName(jsp->type), "double precision"))));
1221 if (isinf(val) || isnan(val))
1224 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1225 jspOperationName(jsp->type)))));
1226
1227 jb = &jbv;
1228 jb->type = jbvNumeric;
1231 res = jperOk;
1232 }
1233
1234 if (res == jperNotFound)
1237 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1238 jspOperationName(jsp->type)))));
1239
1240 res = executeNextItem(cxt, jsp, NULL, jb, found);
1241 }
1242 break;
1243
1244 case jpiDatetime:
1245 case jpiDate:
1246 case jpiTime:
1247 case jpiTimeTz:
1248 case jpiTimestamp:
1249 case jpiTimestampTz:
1250 if (unwrap && JsonbType(jb) == jbvArray)
1251 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1252
1253 return executeDateTimeMethod(cxt, jsp, jb, found);
1254
1255 case jpiKeyValue:
1256 if (unwrap && JsonbType(jb) == jbvArray)
1257 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1258
1259 return executeKeyValueMethod(cxt, jsp, jb, found);
1260
1261 case jpiLast:
1262 {
1264 int last;
1265 bool hasNext = jspGetNext(jsp, &elem);
1266
1267 if (cxt->innermostArraySize < 0)
1268 elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
1269
1270 if (!hasNext && !found)
1271 {
1272 res = jperOk;
1273 break;
1274 }
1275
1276 last = cxt->innermostArraySize - 1;
1277
1278 jbv.type = jbvNumeric;
1279 jbv.val.numeric = int64_to_numeric(last);
1280
1281 res = executeNextItem(cxt, jsp, &elem,
1282 &jbv, found);
1283 }
1284 break;
1285
1286 case jpiBigint:
1287 {
1289 Datum datum;
1290
1291 if (unwrap && JsonbType(jb) == jbvArray)
1292 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1293 false);
1294
1295 if (jb->type == jbvNumeric)
1296 {
1298 int64 val;
1299
1300 val = numeric_int8_safe(jb->val.numeric,
1301 (Node *) &escontext);
1302 if (escontext.error_occurred)
1305 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1307 NumericGetDatum(jb->val.numeric))),
1308 jspOperationName(jsp->type),
1309 "bigint"))));
1310
1311 datum = Int64GetDatum(val);
1312 res = jperOk;
1313 }
1314 else if (jb->type == jbvString)
1315 {
1316 /* cast string as bigint */
1317 char *tmp = pnstrdup(jb->val.string.val,
1318 jb->val.string.len);
1320 bool noerr;
1321
1323 InvalidOid, -1,
1324 (Node *) &escontext,
1325 &datum);
1326
1327 if (!noerr || escontext.error_occurred)
1330 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1331 tmp, jspOperationName(jsp->type), "bigint"))));
1332 res = jperOk;
1333 }
1334
1335 if (res == jperNotFound)
1338 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1339 jspOperationName(jsp->type)))));
1340
1341 jbv.type = jbvNumeric;
1343 datum));
1344
1345 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1346 }
1347 break;
1348
1349 case jpiBoolean:
1350 {
1352 bool bval;
1353
1354 if (unwrap && JsonbType(jb) == jbvArray)
1355 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1356 false);
1357
1358 if (jb->type == jbvBool)
1359 {
1360 bval = jb->val.boolean;
1361
1362 res = jperOk;
1363 }
1364 else if (jb->type == jbvNumeric)
1365 {
1366 int ival;
1367 Datum datum;
1368 bool noerr;
1370 NumericGetDatum(jb->val.numeric)));
1372
1374 InvalidOid, -1,
1375 (Node *) &escontext,
1376 &datum);
1377
1378 if (!noerr || escontext.error_occurred)
1381 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1382 tmp, jspOperationName(jsp->type), "boolean"))));
1383
1384 ival = DatumGetInt32(datum);
1385 if (ival == 0)
1386 bval = false;
1387 else
1388 bval = true;
1389
1390 res = jperOk;
1391 }
1392 else if (jb->type == jbvString)
1393 {
1394 /* cast string as boolean */
1395 char *tmp = pnstrdup(jb->val.string.val,
1396 jb->val.string.len);
1397
1398 if (!parse_bool(tmp, &bval))
1401 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1402 tmp, jspOperationName(jsp->type), "boolean"))));
1403
1404 res = jperOk;
1405 }
1406
1407 if (res == jperNotFound)
1410 errmsg("jsonpath item method .%s() can only be applied to a boolean, string, or numeric value",
1411 jspOperationName(jsp->type)))));
1412
1413 jbv.type = jbvBool;
1414 jbv.val.boolean = bval;
1415
1416 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1417 }
1418 break;
1419
1420 case jpiDecimal:
1421 case jpiNumber:
1422 {
1424 Numeric num;
1425 char *numstr = NULL;
1426
1427 if (unwrap && JsonbType(jb) == jbvArray)
1428 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1429 false);
1430
1431 if (jb->type == jbvNumeric)
1432 {
1433 num = jb->val.numeric;
1434 if (numeric_is_nan(num) || numeric_is_inf(num))
1437 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1438 jspOperationName(jsp->type)))));
1439
1440 if (jsp->type == jpiDecimal)
1442 NumericGetDatum(num)));
1443 res = jperOk;
1444 }
1445 else if (jb->type == jbvString)
1446 {
1447 /* cast string as number */
1448 Datum datum;
1449 bool noerr;
1451
1452 numstr = pnstrdup(jb->val.string.val, jb->val.string.len);
1453
1455 InvalidOid, -1,
1456 (Node *) &escontext,
1457 &datum);
1458
1459 if (!noerr || escontext.error_occurred)
1462 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1463 numstr, jspOperationName(jsp->type), "numeric"))));
1464
1465 num = DatumGetNumeric(datum);
1466 if (numeric_is_nan(num) || numeric_is_inf(num))
1469 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1470 jspOperationName(jsp->type)))));
1471
1472 res = jperOk;
1473 }
1474
1475 if (res == jperNotFound)
1478 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1479 jspOperationName(jsp->type)))));
1480
1481 /*
1482 * If we have arguments, then they must be the precision and
1483 * optional scale used in .decimal(). Convert them to the
1484 * typmod equivalent and then truncate the numeric value per
1485 * this typmod details.
1486 */
1487 if (jsp->type == jpiDecimal && jsp->content.args.left)
1488 {
1490 Datum dtypmod;
1491 int32 precision;
1492 int32 scale = 0;
1493 bool noerr;
1495 Datum datums[2];
1496 char pstr[12]; /* sign, 10 digits and '\0' */
1497 char sstr[12]; /* sign, 10 digits and '\0' */
1499
1500 jspGetLeftArg(jsp, &elem);
1501 if (elem.type != jpiNumeric)
1502 elog(ERROR, "invalid jsonpath item type for .decimal() precision");
1503
1504 precision = numeric_int4_safe(jspGetNumeric(&elem),
1505 (Node *) &escontext);
1506 if (escontext.error_occurred)
1509 errmsg("precision of jsonpath item method .%s() is out of range for type integer",
1510 jspOperationName(jsp->type)))));
1511
1512 if (jsp->content.args.right)
1513 {
1514 jspGetRightArg(jsp, &elem);
1515 if (elem.type != jpiNumeric)
1516 elog(ERROR, "invalid jsonpath item type for .decimal() scale");
1517
1519 (Node *) &escontext);
1520 if (escontext.error_occurred)
1523 errmsg("scale of jsonpath item method .%s() is out of range for type integer",
1524 jspOperationName(jsp->type)))));
1525 }
1526
1527 /*
1528 * numerictypmodin() takes the precision and scale in the
1529 * form of CString arrays.
1530 */
1531 pg_ltoa(precision, pstr);
1532 datums[0] = CStringGetDatum(pstr);
1533 pg_ltoa(scale, sstr);
1534 datums[1] = CStringGetDatum(sstr);
1536
1539
1540 /* Convert numstr to Numeric with typmod */
1541 Assert(numstr != NULL);
1544 (Node *) &escontext,
1545 &numdatum);
1546
1547 if (!noerr || escontext.error_occurred)
1550 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1551 numstr, jspOperationName(jsp->type), "numeric"))));
1552
1555 }
1556
1557 jbv.type = jbvNumeric;
1558 jbv.val.numeric = num;
1559
1560 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1561 }
1562 break;
1563
1564 case jpiInteger:
1565 {
1567 Datum datum;
1568
1569 if (unwrap && JsonbType(jb) == jbvArray)
1570 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1571 false);
1572
1573 if (jb->type == jbvNumeric)
1574 {
1575 int32 val;
1577
1578 val = numeric_int4_safe(jb->val.numeric,
1579 (Node *) &escontext);
1580 if (escontext.error_occurred)
1583 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1585 NumericGetDatum(jb->val.numeric))),
1586 jspOperationName(jsp->type), "integer"))));
1587
1588 datum = Int32GetDatum(val);
1589 res = jperOk;
1590 }
1591 else if (jb->type == jbvString)
1592 {
1593 /* cast string as integer */
1594 char *tmp = pnstrdup(jb->val.string.val,
1595 jb->val.string.len);
1597 bool noerr;
1598
1600 InvalidOid, -1,
1601 (Node *) &escontext,
1602 &datum);
1603
1604 if (!noerr || escontext.error_occurred)
1607 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1608 tmp, jspOperationName(jsp->type), "integer"))));
1609 res = jperOk;
1610 }
1611
1612 if (res == jperNotFound)
1615 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1616 jspOperationName(jsp->type)))));
1617
1618 jbv.type = jbvNumeric;
1620 datum));
1621
1622 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1623 }
1624 break;
1625
1626 case jpiStringFunc:
1627 {
1629 char *tmp = NULL;
1630
1631 if (unwrap && JsonbType(jb) == jbvArray)
1632 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1633
1634 switch (JsonbType(jb))
1635 {
1636 case jbvString:
1637
1638 /*
1639 * Value is not necessarily null-terminated, so we do
1640 * pnstrdup() here.
1641 */
1642 tmp = pnstrdup(jb->val.string.val,
1643 jb->val.string.len);
1644 break;
1645 case jbvNumeric:
1647 NumericGetDatum(jb->val.numeric)));
1648 break;
1649 case jbvBool:
1650 tmp = (jb->val.boolean) ? "true" : "false";
1651 break;
1652 case jbvDatetime:
1653 {
1654 char buf[MAXDATELEN + 1];
1655
1657 jb->val.datetime.value,
1658 jb->val.datetime.typid,
1659 &jb->val.datetime.tz);
1660 tmp = pstrdup(buf);
1661 }
1662 break;
1663 case jbvNull:
1664 case jbvArray:
1665 case jbvObject:
1666 case jbvBinary:
1669 errmsg("jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value",
1670 jspOperationName(jsp->type)))));
1671 break;
1672 }
1673
1674 Assert(tmp != NULL); /* We must have set tmp above */
1675 jbv.val.string.val = tmp;
1676 jbv.val.string.len = strlen(jbv.val.string.val);
1677 jbv.type = jbvString;
1678
1679 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1680 }
1681 break;
1682
1683 default:
1684 elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
1685 }
1686
1687 return res;
1688}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4521
Numeric int64_to_numeric(int64 val)
Definition numeric.c:4259
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4353
Datum numeric_uminus(PG_FUNCTION_ARGS)
Definition numeric.c:1403
Numeric numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3355
Datum numeric_ceil(PG_FUNCTION_ARGS)
Definition numeric.c:1630
Datum numerictypmodin(PG_FUNCTION_ARGS)
Definition numeric.c:1307
Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2881
int64 numeric_int8_safe(Numeric num, Node *escontext)
Definition numeric.c:4434
Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3152
Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2957
Datum numeric_out(PG_FUNCTION_ARGS)
Definition numeric.c:799
Datum numeric_in(PG_FUNCTION_ARGS)
Definition numeric.c:626
bool numeric_is_nan(Numeric num)
Definition numeric.c:834
Numeric numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3033
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition numeric.c:1376
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4423
bool numeric_is_inf(Numeric num)
Definition numeric.c:845
Datum numeric_floor(PG_FUNCTION_ARGS)
Definition numeric.c:1658
bool parse_bool(const char *value, bool *result)
Definition bool.c:31
int64_t int64
Definition c.h:615
uint32_t uint32
Definition c.h:618
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition float.c:412
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition fmgr.c:1641
#define MAXDATELEN
Definition datetime.h:200
#define false
long val
Definition informix.c:689
Datum int8in(PG_FUNCTION_ARGS)
Definition int8.c:50
Datum int4in(PG_FUNCTION_ARGS)
Definition int.c:316
return true
Definition isn.c:130
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition json.c:309
const char * JsonbTypeName(JsonbValue *val)
Definition jsonb.c:172
#define JB_FOBJECT
Definition jsonb.h:204
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition jsonb_util.c:348
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition jsonb_util.c:472
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:1781
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1792
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static Numeric DatumGetNumeric(Datum X)
Definition numeric.h:64
int pg_ltoa(int32 value, char *a)
Definition numutils.c:1119
const void * data
static char buf[DEFAULT_XLOG_SEG_SIZE]
static int scale
Definition pgbench.c:182
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static char * DatumGetCString(Datum X)
Definition postgres.h:355
static Datum Float8GetDatum(float8 X)
Definition postgres.h:502
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
JsonBaseObjectInfo baseObject
Definition type.h:96

References appendBoolResult(), Assert, JsonPathExecContext::baseObject, buf, CHECK_FOR_INTERRUPTS, check_stack_depth(), construct_array_builtin(), 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(), fb(), findJsonbValueFromContainer(), float8_numeric(), Float8GetDatum(), float8in_internal(), getArrayIndex(), getIthJsonbValueFromContainer(), getJsonPathItem(), i, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, Int32GetDatum(), int4_numeric(), int4in(), int64_to_numeric(), Int64GetDatum(), int8_numeric(), int8in(), InvalidOid, JB_FOBJECT, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jpbTrue, jperError, jperIsError, jperNotFound, jperOk, jpiAbs, jpiAdd, jpiAnd, jpiAny, jpiAnyArray, jpiAnyKey, jpiBigint, jpiBool, jpiBoolean, jpiCeiling, jpiCurrent, jpiDate, jpiDatetime, jpiDecimal, jpiDiv, jpiDouble, jpiEqual, jpiExists, jpiFilter, jpiFloor, jpiGreater, jpiGreaterOrEqual, jpiIndexArray, jpiInteger, jpiIsUnknown, jpiKey, jpiKeyValue, jpiLast, jpiLess, jpiLessOrEqual, jpiLikeRegex, jpiMinus, jpiMod, jpiMul, jpiNot, jpiNotEqual, jpiNull, jpiNumber, jpiNumeric, jpiOr, jpiPlus, jpiRoot, jpiSize, jpiStartsWith, jpiString, jpiStringFunc, jpiSub, jpiTime, jpiTimestamp, jpiTimestampTz, jpiTimeTz, jpiType, jpiVariable, JsonbArraySize(), JsonbType(), JsonbTypeName(), JsonEncodeDateTime(), jspAutoUnwrap, jspAutoWrap, jspGetArg(), jspGetArraySubscript(), jspGetLeftArg(), jspGetNext(), jspGetNumeric(), jspGetRightArg(), jspGetString(), jspIgnoreStructuralErrors, jspOperationName(), jspThrowErrors, JsonValueList::last, MAXDATELEN, numeric_abs(), numeric_add_safe(), numeric_ceil(), numeric_div_safe(), numeric_floor(), numeric_in(), numeric_int4_safe(), numeric_int8_safe(), numeric_is_inf(), numeric_is_nan(), numeric_mod_safe(), numeric_mul_safe(), numeric_out(), numeric_sub_safe(), numeric_uminus(), NumericGetDatum(), numerictypmodin(), parse_bool(), pfree(), pg_ltoa(), pnstrdup(), PointerGetDatum(), pstrdup(), range(), RETURN_ERROR, JsonPathExecContext::root, scale, setBaseObject(), JsonbValue::type, JsonPathItem::type, 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 1694 of file jsonpath_exec.c.

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

References Assert, elog, ERROR, executeAnyItem(), fb(), jbvArray, and jbvBinary.

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

717{
722
723 jspInit(&jsp, path);
724
725 if (!JsonbExtractScalar(&json->root, &jbv))
726 JsonbInitBinary(&jbv, json);
727
728 cxt.vars = vars;
729 cxt.getVar = getVar;
730 cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
732 cxt.root = &jbv;
733 cxt.current = &jbv;
734 cxt.baseObject.jbc = NULL;
735 cxt.baseObject.id = 0;
736 /* 1 + number of base objects in vars */
738 cxt.innermostArraySize = -1;
739 cxt.throwErrors = throwErrors;
740 cxt.useTz = useTz;
741
742 if (jspStrictAbsenceOfErrors(&cxt) && !result)
743 {
744 /*
745 * In strict mode we must get a complete list of values to check that
746 * there are no errors at all.
747 */
748 JsonValueList vals;
749 bool isempty;
750
751 JsonValueListInit(&vals);
752
753 res = executeItem(&cxt, &jsp, &jbv, &vals);
754
756 JsonValueListClear(&vals);
757
758 if (jperIsError(res))
759 return res;
760
761 return isempty ? jperNotFound : jperOk;
762 }
763
764 res = executeItem(&cxt, &jsp, &jbv, result);
765
766 Assert(!throwErrors || !jperIsError(res));
767
768 return res;
769}
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition jsonb.c:1749
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
JsonPathGetVarCallback getVar
uint32 header
Definition jsonpath.h:26
JsonbContainer root
Definition jsonb.h:217

References Assert, JsonPathExecContext::baseObject, JsonPathExecContext::current, executeItem(), fb(), JsonPathExecContext::getVar, JsonPath::header, JsonBaseObjectInfo::id, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, JsonBaseObjectInfo::jbc, jperIsError, jperNotFound, jperOk, JsonbExtractScalar(), JsonbInitBinary(), JSONPATH_LAX, JsonValueListClear(), JsonValueListInit(), 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 2906 of file jsonpath_exec.c.

2908{
2911 JsonbContainer *jbc;
2920 int64 id;
2921 bool hasNext;
2922
2923 if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
2926 errmsg("jsonpath item method .%s() can only be applied to an object",
2927 jspOperationName(jsp->type)))));
2928
2929 jbc = jb->val.binary.data;
2930
2931 if (!JsonContainerSize(jbc))
2932 return jperNotFound; /* no key-value pairs */
2933
2935
2936 keystr.type = jbvString;
2937 keystr.val.string.val = "key";
2938 keystr.val.string.len = 3;
2939
2940 valstr.type = jbvString;
2941 valstr.val.string.val = "value";
2942 valstr.val.string.len = 5;
2943
2944 idstr.type = jbvString;
2945 idstr.val.string.val = "id";
2946 idstr.val.string.len = 2;
2947
2948 /* construct object id from its base object and offset inside that */
2949 id = jb->type != jbvBinary ? 0 :
2950 (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
2951 id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
2952
2953 idval.type = jbvNumeric;
2954 idval.val.numeric = int64_to_numeric(id);
2955
2956 it = JsonbIteratorInit(jbc);
2957
2958 while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
2959 {
2960 JsonBaseObjectInfo baseObject;
2961 JsonbValue obj;
2963 Jsonb *jsonb;
2964
2965 if (tok != WJB_KEY)
2966 continue;
2967
2968 res = jperOk;
2969
2970 if (!hasNext && !found)
2971 break;
2972
2973 tok = JsonbIteratorNext(&it, &val, true);
2974 Assert(tok == WJB_VALUE);
2975
2976 memset(&ps, 0, sizeof(ps));
2977
2979
2981 pushJsonbValue(&ps, WJB_VALUE, &key);
2982
2985
2988
2990
2991 jsonb = JsonbValueToJsonb(ps.result);
2992
2993 JsonbInitBinary(&obj, jsonb);
2994
2995 baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
2996
2997 res = executeNextItem(cxt, jsp, &next, &obj, found);
2998
2999 cxt->baseObject = baseObject;
3000
3001 if (jperIsError(res))
3002 return res;
3003
3004 if (res == jperOk && !found)
3005 break;
3006 }
3007
3008 return res;
3009}
#define INT64CONST(x)
Definition c.h:632
struct parser_state ps
#define JsonContainerSize(jc)
Definition jsonb.h:208
JsonbIteratorToken
Definition jsonb.h:21
@ WJB_END_OBJECT
Definition jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition jsonb.h:28
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition jsonb_util.c:583
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition jsonb_util.c:96

References Assert, JsonPathExecContext::baseObject, ereport, errcode(), errmsg, ERROR, executeNextItem(), fb(), JsonBaseObjectInfo::id, int64_to_numeric(), INT64CONST, JsonBaseObjectInfo::jbc, jbvBinary, jbvNumeric, jbvObject, jbvString, jperIsError, jperNotFound, jperOk, JsonbInitBinary(), JsonbIteratorInit(), JsonbIteratorNext(), JsonbType(), JsonbValueToJsonb(), JsonContainerSize, jspGetNext(), jspOperationName(), JsonPathExecContext::lastGeneratedObjectId, next, ps, pushJsonbValue(), RETURN_ERROR, setBaseObject(), 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 2355 of file jsonpath_exec.c.

2357{
2358 JsonLikeRegexContext *cxt = param;
2359
2360 if (!(str = getScalar(str, jbvString)))
2361 return jpbUnknown;
2362
2363 /* Cache regex text and converted flags. */
2364 if (!cxt->regex)
2365 {
2366 cxt->regex =
2367 cstring_to_text_with_len(jsp->content.like_regex.pattern,
2368 jsp->content.like_regex.patternlen);
2369 (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2370 &(cxt->cflags), NULL);
2371 }
2372
2373 if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2374 str->val.string.len,
2376 return jpbTrue;
2377
2378 return jpbFalse;
2379}
const char * str
bool jspConvertRegexFlags(uint32 xflags, int *result, struct Node *escontext)
bool RE_compile_and_execute(text *text_re, char *dat, int dat_len, int cflags, Oid collation, int nmatch, regmatch_t *pmatch)
Definition regexp.c:358

References JsonLikeRegexContext::cflags, cstring_to_text_with_len(), fb(), getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, jspConvertRegexFlags(), 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 1949 of file jsonpath_exec.c.

1951{
1952 JsonbValue *prev;
1953 JsonPathBool res;
1954
1955 prev = cxt->current;
1956 cxt->current = jb;
1957 res = executeBoolItem(cxt, jsp, jb, false);
1958 cxt->current = prev;
1959
1960 return res;
1961}

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

Referenced by executeItemOptUnwrapTarget().

◆ executeNextItem()

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

Definition at line 1714 of file jsonpath_exec.c.

1717{
1718 JsonPathItem elem;
1719 bool hasNext;
1720
1721 if (!cur)
1722 hasNext = next != NULL;
1723 else if (next)
1725 else
1726 {
1727 next = &elem;
1729 }
1730
1731 if (hasNext)
1732 return executeItem(cxt, next, v, found);
1733
1734 if (found)
1735 JsonValueListAppend(found, v);
1736
1737 return jperOk;
1738}
struct cursor * cur
Definition ecpg.c:29

References cur, executeItem(), fb(), 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 2386 of file jsonpath_exec.c.

2389{
2391 Datum datum;
2393
2394 if (unwrap && JsonbType(jb) == jbvArray)
2395 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
2396
2397 if (!(jb = getScalar(jb, jbvNumeric)))
2400 errmsg("jsonpath item method .%s() can only be applied to a numeric value",
2401 jspOperationName(jsp->type)))));
2402
2403 datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
2404
2405 if (!jspGetNext(jsp, &next) && !found)
2406 return jperOk;
2407
2408 jbv.type = jbvNumeric;
2409 jbv.val.numeric = DatumGetNumeric(datum);
2410
2411 return executeNextItem(cxt, jsp, &next, &jbv, found);
2412}

References DatumGetNumeric(), DirectFunctionCall1, ereport, errcode(), errmsg, ERROR, executeItemUnwrapTargetArray(), executeNextItem(), fb(), getScalar(), jbvArray, jbvNumeric, jperOk, JsonbType(), jspGetNext(), jspOperationName(), next, NumericGetDatum(), and RETURN_ERROR.

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

2065{
2070 JsonbValue *lval;
2071 bool error = false;
2072 bool found = false;
2073
2076
2077 /* Left argument is always auto-unwrapped. */
2078 res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
2079 if (jperIsError(res))
2080 {
2081 error = true;
2082 goto exit;
2083 }
2084
2085 if (rarg)
2086 {
2087 /* Right argument is conditionally auto-unwrapped. */
2088 res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
2090 if (jperIsError(res))
2091 {
2092 error = true;
2093 goto exit;
2094 }
2095 }
2096
2098 while ((lval = JsonValueListNext(&lseqit)))
2099 {
2102 bool first = true;
2103
2105 if (rarg)
2107 else
2108 rval = NULL;
2109
2110 /* Loop over right arg sequence or do single pass otherwise */
2111 while (rarg ? (rval != NULL) : first)
2112 {
2113 JsonPathBool res = exec(pred, lval, rval, param);
2114
2115 if (res == jpbUnknown)
2116 {
2117 error = true;
2118 if (jspStrictAbsenceOfErrors(cxt))
2119 {
2120 found = false; /* return unknown, not success */
2121 goto exit;
2122 }
2123 }
2124 else if (res == jpbTrue)
2125 {
2126 found = true;
2127 if (!jspStrictAbsenceOfErrors(cxt))
2128 goto exit;
2129 }
2130
2131 first = false;
2132 if (rarg)
2134 }
2135 }
2136
2137exit:
2140
2141 if (found) /* possible only in strict mode */
2142 return jpbTrue;
2143
2144 if (error) /* possible only in lax mode */
2145 return jpbUnknown;
2146
2147 return jpbFalse;
2148}
static void error(void)
Definition type.h:116

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

Referenced by executeBoolItem().

◆ executeStartsWith()

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

Definition at line 2331 of file jsonpath_exec.c.

2333{
2334 if (!(whole = getScalar(whole, jbvString)))
2335 return jpbUnknown; /* error */
2336
2338 return jpbUnknown; /* error */
2339
2340 if (whole->val.string.len >= initial->val.string.len &&
2341 !memcmp(whole->val.string.val,
2342 initial->val.string.val,
2343 initial->val.string.len))
2344 return jpbTrue;
2345
2346 return jpbFalse;
2347}

References fb(), getScalar(), jbvString, jpbFalse, jpbTrue, and jpbUnknown.

Referenced by executeBoolItem().

◆ executeUnaryArithmExpr()

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

Definition at line 2252 of file jsonpath_exec.c.

2254{
2257 JsonPathItem elem;
2260 JsonbValue *val;
2261 bool hasNext;
2262
2264
2265 jspGetArg(jsp, &elem);
2266 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
2267
2268 if (jperIsError(jper))
2269 goto exit;
2270
2272
2273 hasNext = jspGetNext(jsp, &elem);
2274
2276 while ((val = JsonValueListNext(&it)))
2277 {
2278 if ((val = getScalar(val, jbvNumeric)))
2279 {
2280 if (!found && !hasNext)
2281 {
2282 jper = jperOk;
2283 goto exit;
2284 }
2285 }
2286 else
2287 {
2288 if (!found && !hasNext)
2289 continue; /* skip non-numerics processing */
2290
2294 errmsg("operand of unary jsonpath operator %s is not a numeric value",
2295 jspOperationName(jsp->type)))));
2296 }
2297
2298 if (func)
2299 val->val.numeric =
2301 NumericGetDatum(val->val.numeric)));
2302
2303 jper2 = executeNextItem(cxt, jsp, &elem, val, found);
2304
2305 if (jperIsError(jper2))
2306 {
2307 jper = jper2;
2308 goto exit;
2309 }
2310
2311 if (jper2 == jperOk)
2312 {
2313 jper = jperOk;
2314 if (!found)
2315 goto exit;
2316 }
2317 }
2318
2319exit:
2321
2322 return jper;
2323}

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

Referenced by executeItemOptUnwrapTarget().

◆ getArrayIndex()

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

Definition at line 3545 of file jsonpath_exec.c.

3547{
3548 JsonbValue *jbv;
3549 JsonValueList found;
3553
3554 JsonValueListInit(&found);
3555
3556 res = executeItem(cxt, jsp, jb, &found);
3557
3558 if (jperIsError(res))
3559 {
3560 JsonValueListClear(&found);
3561 return res;
3562 }
3563
3564 if (!JsonValueListIsSingleton(&found) ||
3566 {
3567 JsonValueListClear(&found);
3570 errmsg("jsonpath array subscript is not a single numeric value"))));
3571 }
3572
3574 NumericGetDatum(jbv->val.numeric),
3575 Int32GetDatum(0));
3576
3578 (Node *) &escontext);
3579
3580 JsonValueListClear(&found);
3581
3582 if (escontext.error_occurred)
3585 errmsg("jsonpath array subscript is out of integer range"))));
3586
3587 return jperOk;
3588}
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition numeric.c:1580

References DatumGetNumeric(), DirectFunctionCall2, ereport, errcode(), errmsg, ERROR, ErrorSaveContext::error_occurred, executeItem(), fb(), getScalar(), Int32GetDatum(), jbvNumeric, jperIsError, jperOk, JsonValueListClear(), JsonValueListHead(), JsonValueListInit(), JsonValueListIsSingleton(), numeric_int4_safe(), numeric_trunc(), NumericGetDatum(), and RETURN_ERROR.

Referenced by executeItemOptUnwrapTarget().

◆ getJsonPathItem()

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

Definition at line 3044 of file jsonpath_exec.c.

3046{
3047 switch (item->type)
3048 {
3049 case jpiNull:
3050 value->type = jbvNull;
3051 break;
3052 case jpiBool:
3053 value->type = jbvBool;
3054 value->val.boolean = jspGetBool(item);
3055 break;
3056 case jpiNumeric:
3057 value->type = jbvNumeric;
3058 value->val.numeric = jspGetNumeric(item);
3059 break;
3060 case jpiString:
3061 value->type = jbvString;
3062 value->val.string.val = jspGetString(item,
3063 &value->val.string.len);
3064 break;
3065 case jpiVariable:
3066 getJsonPathVariable(cxt, item, value);
3067 return;
3068 default:
3069 elog(ERROR, "unexpected jsonpath item type");
3070 }
3071}
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 3077 of file jsonpath_exec.c.

3079{
3080 JsonPathVariable *var = NULL;
3081 List *vars = cxt;
3082 ListCell *lc;
3083 JsonbValue *result;
3084 int id = 1;
3085
3086 foreach(lc, vars)
3087 {
3088 JsonPathVariable *curvar = lfirst(lc);
3089
3090 if (curvar->namelen == varNameLen &&
3091 strncmp(curvar->name, varName, varNameLen) == 0)
3092 {
3093 var = curvar;
3094 break;
3095 }
3096
3097 id++;
3098 }
3099
3100 if (var == NULL)
3101 {
3102 *baseObjectId = -1;
3103 return NULL;
3104 }
3105
3106 result = palloc_object(JsonbValue);
3107 if (var->isnull)
3108 {
3109 *baseObjectId = 0;
3110 result->type = jbvNull;
3111 }
3112 else
3113 JsonItemFromDatum(var->value, var->typid, var->typmod, result);
3114
3115 *baseObject = *result;
3116 *baseObjectId = id;
3117
3118 return result;
3119}
static void JsonItemFromDatum(Datum val, Oid typid, int32 typmod, JsonbValue *res)
#define lfirst(lc)
Definition pg_list.h:172

References fb(), JsonPathVariable::isnull, jbvNull, JsonItemFromDatum(), lfirst, JsonPathVariable::name, JsonPathVariable::namelen, palloc_object, 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 3227 of file jsonpath_exec.c.

3229{
3230 char *varName;
3231 int varNameLength;
3232 JsonbValue baseObject;
3233 int baseObjectId;
3234 JsonbValue *v;
3235
3237 varName = jspGetString(variable, &varNameLength);
3238
3239 if (cxt->vars == NULL ||
3240 (v = cxt->getVar(cxt->vars, varName, varNameLength,
3241 &baseObject, &baseObjectId)) == NULL)
3242 ereport(ERROR,
3244 errmsg("could not find jsonpath variable \"%s\"",
3245 pnstrdup(varName, varNameLength))));
3246
3247 if (baseObjectId > 0)
3248 {
3249 *value = *v;
3250 setBaseObject(cxt, &baseObject, baseObjectId);
3251 }
3252}
enum ECPGttype type

References Assert, ereport, errcode(), errmsg, ERROR, fb(), 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 3259 of file jsonpath_exec.c.

3261{
3262 Jsonb *vars = varsJsonb;
3263 JsonbValue tmp;
3264 JsonbValue *result;
3265
3266 tmp.type = jbvString;
3267 tmp.val.string.val = varName;
3268 tmp.val.string.len = varNameLength;
3269
3270 result = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
3271
3272 if (result == NULL)
3273 {
3274 *baseObjectId = -1;
3275 return NULL;
3276 }
3277
3278 *baseObjectId = 1;
3279 JsonbInitBinary(baseObject, vars);
3280
3281 return result;
3282}

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

4222{
4223 JsonTableExecContext *result;
4224
4226 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4227 result = (JsonTableExecContext *) state->opaque;
4228 if (result->magic != JSON_TABLE_EXEC_CONTEXT_MAGIC)
4229 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4230
4231 return result;
4232}
#define JSON_TABLE_EXEC_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition nodes.h:164

References elog, ERROR, 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 3772 of file jsonpath_exec.c.

3773{
3774 /* Scalars should be always extracted during jsonpath execution. */
3775 Assert(scalar->type != jbvBinary ||
3776 !JsonContainerIsScalar(scalar->val.binary.data));
3777
3778 return scalar->type == type ? scalar : NULL;
3779}
#define JsonContainerIsScalar(jc)
Definition jsonb.h:209
const char * type

References Assert, fb(), 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 453 of file jsonpath_exec.c.

454{
455 return jsonb_path_exists_internal(fcinfo, false);
456}
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 425 of file jsonpath_exec.c.

426{
430 Jsonb *vars = NULL;
431 bool silent = true;
432
433 if (PG_NARGS() == 4)
434 {
437 }
438
441 jb, !silent, NULL, tz);
442
445
446 if (jperIsError(res))
448
449 PG_RETURN_BOOL(res == jperOk);
450}
#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:346
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define PG_GETARG_JSONB_P(x)
Definition jsonb.h:418
#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(), fb(), 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 470 of file jsonpath_exec.c.

471{
472 /* just call the other one -- it can handle both cases */
473 return jsonb_path_exists_internal(fcinfo, false);
474}

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 459 of file jsonpath_exec.c.

460{
461 return jsonb_path_exists_internal(fcinfo, true);
462}

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 525 of file jsonpath_exec.c.

526{
527 return jsonb_path_match_internal(fcinfo, false);
528}
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 482 of file jsonpath_exec.c.

483{
486 Jsonb *vars = NULL;
487 bool silent = true;
488 JsonValueList found;
489
490 if (PG_NARGS() == 4)
491 {
494 }
495
496 JsonValueListInit(&found);
497
500 jb, !silent, &found, tz);
501
504
505 if (JsonValueListIsSingleton(&found))
506 {
508
509 if (jbv->type == jbvBool)
510 PG_RETURN_BOOL(jbv->val.boolean);
511
512 if (jbv->type == jbvNull)
514 }
515
516 if (!silent)
519 errmsg("single boolean result is expected")));
520
522}

References countVariablesFromJsonb(), ereport, errcode(), errmsg, ERROR, executeJsonPath(), fb(), getJsonPathVariableFromJsonb(), jbvBool, jbvNull, JsonValueListHead(), JsonValueListInit(), JsonValueListIsSingleton(), 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_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 542 of file jsonpath_exec.c.

543{
544 /* just call the other one -- it can handle both cases */
545 return jsonb_path_match_internal(fcinfo, false);
546}

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 531 of file jsonpath_exec.c.

532{
533 return jsonb_path_match_internal(fcinfo, true);
534}

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 604 of file jsonpath_exec.c.

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

640{
641 return jsonb_path_query_array_internal(fcinfo, false);
642}
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

◆ jsonb_path_query_array_tz()

Datum jsonb_path_query_array_tz ( PG_FUNCTION_ARGS  )

Definition at line 645 of file jsonpath_exec.c.

646{
647 return jsonb_path_query_array_internal(fcinfo, true);
648}

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 677 of file jsonpath_exec.c.

678{
679 return jsonb_path_query_first_internal(fcinfo, false);
680}
static Datum jsonb_path_query_first_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_query_first_internal().

◆ jsonb_path_query_first_internal()

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 683 of file jsonpath_exec.c.

684{
685 return jsonb_path_query_first_internal(fcinfo, true);
686}

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 554 of file jsonpath_exec.c.

555{
558 JsonbValue *v;
559
560 if (SRF_IS_FIRSTCALL())
561 {
562 JsonPath *jp;
563 Jsonb *jb;
564 Jsonb *vars;
565 bool silent;
566 MemoryContext oldcontext;
567 JsonValueList *found;
568
570 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
571
576
578 JsonValueListInit(found);
579
582 jb, !silent, found, tz);
583
585 JsonValueListInitIterator(found, iter);
586
587 funcctx->user_fctx = iter;
588
589 MemoryContextSwitchTo(oldcontext);
590 }
591
593 iter = funcctx->user_fctx;
594
595 v = JsonValueListNext(iter);
596
597 if (v == NULL)
599
601}
#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:419
static Datum JsonbPGetDatum(const Jsonb *p)
Definition jsonb.h:413
#define PG_GETARG_JSONPATH_P_COPY(x)
Definition jsonpath.h:47

References countVariablesFromJsonb(), executeJsonPath(), fb(), getJsonPathVariableFromJsonb(), JsonbPGetDatum(), JsonbValueToJsonb(), JsonValueListInit(), JsonValueListInitIterator(), JsonValueListNext(), MemoryContextSwitchTo(), palloc_object, 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, and SRF_RETURN_NEXT.

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

611{
612 return jsonb_path_query_internal(fcinfo, true);
613}

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3311 of file jsonpath_exec.c.

3312{
3313 Assert(jb->type != jbvArray);
3314
3315 if (jb->type == jbvBinary)
3316 {
3317 JsonbContainer *jbc = jb->val.binary.data;
3318
3320 return JsonContainerSize(jbc);
3321 }
3322
3323 return -1;
3324}
#define JsonContainerIsArray(jc)
Definition jsonb.h:211

References Assert, fb(), jbvArray, jbvBinary, JsonContainerIsArray, JsonContainerIsScalar, and JsonContainerSize.

Referenced by executeItemOptUnwrapTarget().

◆ JsonbInitBinary()

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

Definition at line 3735 of file jsonpath_exec.c.

3736{
3737 jbv->type = jbvBinary;
3738 jbv->val.binary.data = &jb->root;
3739 jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3740
3741 return jbv;
3742}
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472

References fb(), jbvBinary, JsonbValue::type, and VARSIZE_ANY_EXHDR().

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

◆ JsonbType()

static int JsonbType ( JsonbValue jb)
static

Definition at line 3748 of file jsonpath_exec.c.

3749{
3750 int type = jb->type;
3751
3752 if (jb->type == jbvBinary)
3753 {
3754 JsonbContainer *jbc = jb->val.binary.data;
3755
3756 /* Scalars should be always extracted during jsonpath execution. */
3758
3759 if (JsonContainerIsObject(jbc))
3760 type = jbvObject;
3761 else if (JsonContainerIsArray(jbc))
3762 type = jbvArray;
3763 else
3764 elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
3765 }
3766
3767 return type;
3768}
uint32 header
Definition jsonb.h:194

References Assert, elog, ERROR, fb(), JsonbContainer::header, jbvArray, jbvBinary, jbvObject, JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, and type.

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

◆ JsonbValueInitNumericDatum()

static void JsonbValueInitNumericDatum ( JsonbValue jbv,
Datum  num 
)
static

Definition at line 3217 of file jsonpath_exec.c.

3218{
3219 jbv->type = jbvNumeric;
3220 jbv->val.numeric = DatumGetNumeric(num);
3221}

References DatumGetNumeric(), fb(), and jbvNumeric.

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

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

Definition at line 3135 of file jsonpath_exec.c.

3136{
3137 switch (typid)
3138 {
3139 case BOOLOID:
3140 res->type = jbvBool;
3141 res->val.boolean = DatumGetBool(val);
3142 break;
3143 case NUMERICOID:
3145 break;
3146 case INT2OID:
3148 break;
3149 case INT4OID:
3151 break;
3152 case INT8OID:
3154 break;
3155 case FLOAT4OID:
3157 break;
3158 case FLOAT8OID:
3160 break;
3161 case TEXTOID:
3162 case VARCHAROID:
3163 res->type = jbvString;
3164 res->val.string.val = VARDATA_ANY(DatumGetPointer(val));
3165 res->val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(val));
3166 break;
3167 case DATEOID:
3168 case TIMEOID:
3169 case TIMETZOID:
3170 case TIMESTAMPOID:
3171 case TIMESTAMPTZOID:
3172 res->type = jbvDatetime;
3173 res->val.datetime.value = val;
3174 res->val.datetime.typid = typid;
3175 res->val.datetime.typmod = typmod;
3176 res->val.datetime.tz = 0;
3177 break;
3178 case JSONBOID:
3179 {
3180 JsonbValue *jbv = res;
3182
3183 if (JsonContainerIsScalar(&jb->root))
3184 {
3185 bool result PG_USED_FOR_ASSERTS_ONLY;
3186
3187 result = JsonbExtractScalar(&jb->root, jbv);
3188 Assert(result);
3189 }
3190 else
3192 break;
3193 }
3194 case JSONOID:
3195 {
3197 char *str = text_to_cstring(txt);
3198 Jsonb *jb;
3199
3202 pfree(str);
3203
3205 break;
3206 }
3207 default:
3208 ereport(ERROR,
3210 errmsg("could not convert value of type %s to jsonpath",
3211 format_type_be(typid)));
3212 }
3213}
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4615
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4472
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:243
#define DatumGetTextP(X)
Definition fmgr.h:333
char * format_type_be(Oid type_oid)
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition jsonb.c:64
static Jsonb * DatumGetJsonbP(Datum d)
Definition jsonb.h:401
static void JsonbValueInitNumericDatum(JsonbValue *jbv, Datum num)
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486

References Assert, CStringGetDatum(), DatumGetBool(), DatumGetJsonbP(), DatumGetPointer(), DatumGetTextP, DirectFunctionCall1, ereport, errcode(), errmsg, ERROR, fb(), 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, 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 4024 of file jsonpath_exec.c.

4025{
4027
4028 res = executeJsonPath(jp, vars,
4030 DatumGetJsonbP(jb), !error, NULL, true);
4031
4032 Assert(error || !jperIsError(res));
4033
4034 if (error && jperIsError(res))
4035 *error = true;
4036
4037 return res == jperOk;
4038}
static JsonbValue * GetJsonPathVar(void *cxt, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
static int CountJsonPathVars(void *cxt)

References Assert, CountJsonPathVars(), DatumGetJsonbP(), error(), executeJsonPath(), fb(), 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 4047 of file jsonpath_exec.c.

4050{
4051 bool wrap;
4052 JsonValueList found;
4054
4055 JsonValueListInit(&found);
4056
4057 res = executeJsonPath(jp, vars,
4059 DatumGetJsonbP(jb), !error, &found, true);
4060 Assert(error || !jperIsError(res));
4061 if (error && jperIsError(res))
4062 {
4063 *error = true;
4064 *empty = false;
4065 return (Datum) 0;
4066 }
4067
4068 /*
4069 * Determine whether to wrap the result in a JSON array or not.
4070 *
4071 * If the returned JsonValueList is empty, no wrapping is necessary.
4072 *
4073 * If the wrapper mode is JSW_NONE or JSW_UNSPEC, wrapping is explicitly
4074 * disabled. This enforces a WITHOUT WRAPPER clause, which is also the
4075 * default when no WRAPPER clause is specified.
4076 *
4077 * If the mode is JSW_UNCONDITIONAL, wrapping is enforced regardless of
4078 * the number of SQL/JSON items, enforcing a WITH WRAPPER or WITH
4079 * UNCONDITIONAL WRAPPER clause.
4080 *
4081 * For JSW_CONDITIONAL, wrapping occurs only if there is more than one
4082 * SQL/JSON item in the list, enforcing a WITH CONDITIONAL WRAPPER clause.
4083 */
4084 if (JsonValueListIsEmpty(&found))
4085 wrap = false;
4086 else if (wrapper == JSW_NONE || wrapper == JSW_UNSPEC)
4087 wrap = false;
4088 else if (wrapper == JSW_UNCONDITIONAL)
4089 wrap = true;
4090 else if (wrapper == JSW_CONDITIONAL)
4092 else
4093 {
4094 elog(ERROR, "unrecognized json wrapper %d", (int) wrapper);
4095 wrap = false;
4096 }
4097
4098 if (wrap)
4100
4101 /* No wrapping means at most one item is expected. */
4103 {
4104 if (error)
4105 {
4106 *error = true;
4107 return (Datum) 0;
4108 }
4109
4110 if (column_name)
4111 ereport(ERROR,
4113 errmsg("JSON path expression for column \"%s\" must return single item when no wrapper is requested",
4114 column_name),
4115 errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
4116 else
4117 ereport(ERROR,
4119 errmsg("JSON path expression in JSON_QUERY must return single item when no wrapper is requested"),
4120 errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
4121 }
4122
4123 if (!JsonValueListIsEmpty(&found))
4125
4126 *empty = true;
4127 return PointerGetDatum(NULL);
4128}
static bool JsonValueListHasMultipleItems(const JsonValueList *jvl)
@ JSW_UNCONDITIONAL
Definition primnodes.h:1780
@ JSW_CONDITIONAL
Definition primnodes.h:1779
@ JSW_UNSPEC
Definition primnodes.h:1777
@ JSW_NONE
Definition primnodes.h:1778

References Assert, CountJsonPathVars(), DatumGetJsonbP(), elog, ereport, errcode(), errhint(), errmsg, ERROR, error(), executeJsonPath(), fb(), GetJsonPathVar(), jperIsError, JsonbPGetDatum(), JsonbValueToJsonb(), JsonValueListHasMultipleItems(), JsonValueListHead(), JsonValueListInit(), JsonValueListIsEmpty(), 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 4137 of file jsonpath_exec.c.

4139{
4140 JsonbValue *res;
4141 JsonValueList found;
4143
4144 JsonValueListInit(&found);
4145
4148 !error, &found, true);
4149
4151
4152 if (error && jperIsError(jper))
4153 {
4154 *error = true;
4155 *empty = false;
4156 return NULL;
4157 }
4158
4159 *empty = JsonValueListIsEmpty(&found);
4160
4161 if (*empty)
4162 return NULL;
4163
4164 /* JSON_VALUE expects to get only singletons. */
4166 {
4167 if (error)
4168 {
4169 *error = true;
4170 return NULL;
4171 }
4172
4173 if (column_name)
4174 ereport(ERROR,
4176 errmsg("JSON path expression for column \"%s\" must return single scalar item",
4177 column_name)));
4178 else
4179 ereport(ERROR,
4181 errmsg("JSON path expression in JSON_VALUE must return single scalar item")));
4182 }
4183
4184 res = copyJsonbValue(JsonValueListHead(&found));
4185 if (res->type == jbvBinary && JsonContainerIsScalar(res->val.binary.data))
4186 JsonbExtractScalar(res->val.binary.data, res);
4187
4188 /* JSON_VALUE expects to get only scalars. */
4189 if (!IsAJsonbScalar(res))
4190 {
4191 if (error)
4192 {
4193 *error = true;
4194 return NULL;
4195 }
4196
4197 if (column_name)
4198 ereport(ERROR,
4200 errmsg("JSON path expression for column \"%s\" must return single scalar item",
4201 column_name)));
4202 else
4203 ereport(ERROR,
4205 errmsg("JSON path expression in JSON_VALUE must return single scalar item")));
4206 }
4207
4208 if (res->type == jbvNull)
4209 return NULL;
4210
4211 return res;
4212}
#define IsAJsonbScalar(jsonbval)
Definition jsonb.h:299
static JsonbValue * copyJsonbValue(JsonbValue *src)

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

Referenced by ExecEvalJsonExprPath().

◆ JsonTableDestroyOpaque()

static void JsonTableDestroyOpaque ( TableFuncScanState state)
static

Definition at line 4306 of file jsonpath_exec.c.

4307{
4309 GetJsonTableExecContext(state, "JsonTableDestroyOpaque");
4310
4311 /* not valid anymore */
4312 cxt->magic = 0;
4313
4314 state->opaque = NULL;
4315}
static JsonTableExecContext * GetJsonTableExecContext(TableFuncScanState *state, const char *fname)

References fb(), GetJsonTableExecContext(), and JsonTableExecContext::magic.

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4569 of file jsonpath_exec.c.

4570{
4572 GetJsonTableExecContext(state, "JsonTableFetchRow");
4573
4575}
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 4585 of file jsonpath_exec.c.

4587{
4589 GetJsonTableExecContext(state, "JsonTableGetValue");
4590 ExprContext *econtext = state->ss.ps.ps_ExprContext;
4591 ExprState *estate = list_nth(state->colvalexprs, colnum);
4592 JsonTablePlanState *planstate = cxt->colplanstates[colnum];
4593 JsonTablePlanRowSource *current = &planstate->current;
4594 Datum result;
4595
4596 /* Row pattern value is NULL */
4597 if (current->isnull)
4598 {
4599 result = (Datum) 0;
4600 *isnull = true;
4601 }
4602 /* Evaluate JsonExpr. */
4603 else if (estate)
4604 {
4606 bool saved_caseIsNull = econtext->caseValue_isNull;
4607
4608 /* Pass the row pattern value via CaseTestExpr. */
4609 econtext->caseValue_datum = current->value;
4610 econtext->caseValue_isNull = false;
4611
4612 result = ExecEvalExpr(estate, econtext, isnull);
4613
4614 econtext->caseValue_datum = saved_caseValue;
4616 }
4617 /* ORDINAL column */
4618 else
4619 {
4620 result = Int32GetDatum(planstate->ordinal);
4621 *isnull = false;
4622 }
4623
4624 return result;
4625}
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:396
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
bool caseValue_isNull
Definition execnodes.h:311
Datum caseValue_datum
Definition execnodes.h:309
JsonTablePlanState ** colplanstates
JsonTablePlanRowSource current

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

◆ JsonTableInitOpaque()

static void JsonTableInitOpaque ( TableFuncScanState state,
int  natts 
)
static

Definition at line 4242 of file jsonpath_exec.c.

4243{
4245 PlanState *ps = &state->ss.ps;
4247 TableFunc *tf = tfs->tablefunc;
4248 JsonTablePlan *rootplan = (JsonTablePlan *) tf->plan;
4249 JsonExpr *je = castNode(JsonExpr, tf->docexpr);
4250 List *args = NIL;
4251
4253 cxt->magic = JSON_TABLE_EXEC_CONTEXT_MAGIC;
4254
4255 /*
4256 * Evaluate JSON_TABLE() PASSING arguments to be passed to the jsonpath
4257 * executor via JsonPathVariables.
4258 */
4259 if (state->passingvalexprs)
4260 {
4263
4264 Assert(list_length(state->passingvalexprs) ==
4265 list_length(je->passing_names));
4266 forboth(exprlc, state->passingvalexprs,
4267 namelc, je->passing_names)
4268 {
4272
4273 var->name = pstrdup(name->sval);
4274 var->namelen = strlen(var->name);
4275 var->typid = exprType((Node *) state->expr);
4276 var->typmod = exprTypmod((Node *) state->expr);
4277
4278 /*
4279 * Evaluate the expression and save the value to be returned by
4280 * GetJsonPathVar().
4281 */
4282 var->value = ExecEvalExpr(state, ps->ps_ExprContext,
4283 &var->isnull);
4284
4285 args = lappend(args, var);
4286 }
4287 }
4288
4289 cxt->colplanstates = palloc_array(JsonTablePlanState *, list_length(tf->colvalexprs));
4290
4291 /*
4292 * Initialize plan for the root path and, recursively, also any child
4293 * plans that compute the NESTED paths.
4294 */
4295 cxt->rootplanstate = JsonTableInitPlan(cxt, rootplan, NULL, args,
4297
4298 state->opaque = cxt;
4299}
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_object(type)
Definition fe_memutils.h:75
static JsonTablePlanState * JsonTableInitPlan(JsonTableExecContext *cxt, JsonTablePlan *plan, JsonTablePlanState *parentstate, List *args, MemoryContext mcxt)
List * lappend(List *list, void *datum)
Definition list.c:339
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
#define castNode(_type_, nodeptr)
Definition nodes.h:182
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define NIL
Definition pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:518
Definition value.h:64
const char * name

References Assert, castNode, JsonTableExecContext::colplanstates, CurrentMemoryContext, TableFunc::docexpr, ExecEvalExpr(), exprType(), exprTypmod(), fb(), forboth, JsonPathVariable::isnull, JSON_TABLE_EXEC_CONTEXT_MAGIC, JsonTableInitPlan(), lappend(), lfirst_node, list_length(), JsonTableExecContext::magic, name, JsonPathVariable::name, JsonPathVariable::namelen, NIL, palloc0_object, palloc_array, palloc_object, ps, pstrdup(), JsonTableExecContext::rootplanstate, 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 4323 of file jsonpath_exec.c.

4326{
4328
4329 planstate->plan = plan;
4330 planstate->parent = parentstate;
4331 JsonValueListInit(&planstate->found);
4332
4334 {
4336 int i;
4337
4338 planstate->path = DatumGetJsonPathP(scan->path->value->constvalue);
4339 planstate->args = args;
4340 planstate->mcxt = AllocSetContextCreate(mcxt, "JsonTableExecContext",
4342
4343 /* No row pattern evaluated yet. */
4344 planstate->current.value = PointerGetDatum(NULL);
4345 planstate->current.isnull = true;
4346
4347 for (i = scan->colMin; i >= 0 && i <= scan->colMax; i++)
4348 cxt->colplanstates[i] = planstate;
4349
4350 planstate->nested = scan->child ?
4351 JsonTableInitPlan(cxt, scan->child, planstate, args, mcxt) : NULL;
4352 }
4353 else if (IsA(plan, JsonTableSiblingJoin))
4354 {
4356
4357 planstate->left = JsonTableInitPlan(cxt, join->lplan, parentstate,
4358 args, mcxt);
4359 planstate->right = JsonTableInitPlan(cxt, join->rplan, parentstate,
4360 args, mcxt);
4361 }
4362
4363 return planstate;
4364}
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:1925
Const * value
Definition primnodes.h:1898
struct JsonTablePlanState * left
JsonValueList found
struct JsonTablePlanState * nested
MemoryContext mcxt
struct JsonTablePlanState * parent
JsonTablePlan * plan
struct JsonTablePlanState * right
JsonTablePlan * rplan
Definition primnodes.h:1955
JsonTablePlan * lplan
Definition primnodes.h:1954

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, JsonTablePlanState::args, JsonTablePathScan::child, JsonTablePathScan::colMax, JsonTablePathScan::colMin, JsonTableExecContext::colplanstates, JsonTablePlanState::current, DatumGetJsonPathP(), fb(), JsonTablePlanState::found, i, IsA, JsonTablePlanRowSource::isnull, JsonTableInitPlan(), JsonValueListInit(), JsonTablePlanState::left, JsonTableSiblingJoin::lplan, JsonTablePlanState::mcxt, JsonTablePlanState::nested, palloc0_object, 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 4542 of file jsonpath_exec.c.

4543{
4544
4545 /* Fetch row from left sibling. */
4546 if (!JsonTablePlanNextRow(planstate->left))
4547 {
4548 /*
4549 * Left sibling ran out of rows, so start fetching from the right
4550 * sibling.
4551 */
4552 if (!JsonTablePlanNextRow(planstate->right))
4553 {
4554 /* Right sibling ran out of row, so there are more rows. */
4555 return false;
4556 }
4557 }
4558
4559 return true;
4560}

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

Referenced by JsonTablePlanNextRow().

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4424 of file jsonpath_exec.c.

4425{
4426 if (IsA(planstate->plan, JsonTablePathScan))
4427 return JsonTablePlanScanNextRow(planstate);
4428 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4429 return JsonTablePlanJoinNextRow(planstate);
4430 else
4431 elog(ERROR, "invalid JsonTablePlan %d", (int) planstate->plan->type);
4432
4433 Assert(false);
4434 /* Appease compiler */
4435 return false;
4436}
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 4451 of file jsonpath_exec.c.

4452{
4453 JsonbValue *jbv;
4455
4456 /*
4457 * If planstate already has an active row and there is a nested plan,
4458 * check if it has an active row to join with the former.
4459 */
4460 if (!planstate->current.isnull)
4461 {
4462 if (planstate->nested && JsonTablePlanNextRow(planstate->nested))
4463 return true;
4464 }
4465
4466 /* Fetch new row from the list of found values to set as active. */
4467 jbv = JsonValueListNext(&planstate->iter);
4468
4469 /* End of list? */
4470 if (jbv == NULL)
4471 {
4472 planstate->current.value = PointerGetDatum(NULL);
4473 planstate->current.isnull = true;
4474 return false;
4475 }
4476
4477 /*
4478 * Set current row item for subsequent JsonTableGetValue() calls for
4479 * evaluating individual columns.
4480 */
4481 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4483 planstate->current.isnull = false;
4485
4486 /* Next row! */
4487 planstate->ordinal++;
4488
4489 /* Process nested plan(s), if any. */
4490 if (planstate->nested)
4491 {
4492 /* Re-evaluate the nested path using the above parent row. */
4493 JsonTableResetNestedPlan(planstate->nested);
4494
4495 /*
4496 * Now fetch the nested plan's current row to be joined against the
4497 * parent row. Any further nested plans' paths will be re-evaluated
4498 * recursively, level at a time, after setting each nested plan's
4499 * current row.
4500 */
4501 (void) JsonTablePlanNextRow(planstate->nested);
4502 }
4503
4504 /* There are more rows. */
4505 return true;
4506}
static void JsonTableResetNestedPlan(JsonTablePlanState *planstate)
JsonValueListIterator iter

References JsonTablePlanState::current, fb(), 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 4513 of file jsonpath_exec.c.

4514{
4515 /* This better be a child plan. */
4516 Assert(planstate->parent != NULL);
4517 if (IsA(planstate->plan, JsonTablePathScan))
4518 {
4519 JsonTablePlanState *parent = planstate->parent;
4520
4521 if (!parent->current.isnull)
4522 JsonTableResetRowPattern(planstate, parent->current.value);
4523
4524 /*
4525 * If this plan itself has a child nested plan, it will be reset when
4526 * the caller calls JsonTablePlanNextRow() on this plan.
4527 */
4528 }
4529 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4530 {
4531 JsonTableResetNestedPlan(planstate->left);
4532 JsonTableResetNestedPlan(planstate->right);
4533 }
4534}
static void JsonTableResetRowPattern(JsonTablePlanState *planstate, Datum item)

References Assert, JsonTablePlanState::current, fb(), 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 4384 of file jsonpath_exec.c.

4385{
4386 JsonTablePathScan *scan = castNode(JsonTablePathScan, planstate->plan);
4389 Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
4390
4391 JsonValueListClear(&planstate->found);
4392
4393 MemoryContextResetOnly(planstate->mcxt);
4394
4395 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4396
4397 res = executeJsonPath(planstate->path, planstate->args,
4399 js, scan->errorOnError,
4400 &planstate->found,
4401 true);
4402
4404
4405 if (jperIsError(res))
4406 {
4407 Assert(!scan->errorOnError);
4408 JsonValueListClear(&planstate->found);
4409 }
4410
4411 /* Reset plan iterator to the beginning of the item list */
4412 JsonValueListInitIterator(&planstate->found, &planstate->iter);
4413 planstate->current.value = PointerGetDatum(NULL);
4414 planstate->current.isnull = true;
4415 planstate->ordinal = 0;
4416}
void MemoryContextResetOnly(MemoryContext context)
Definition mcxt.c:422

References JsonTablePlanState::args, Assert, castNode, CountJsonPathVars(), JsonTablePlanState::current, DatumGetJsonbP(), JsonTablePathScan::errorOnError, executeJsonPath(), fb(), 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,
const JsonbValue jbv 
)
static

Definition at line 3635 of file jsonpath_exec.c.

3636{
3637 JsonValueList *last = jvl->last;
3638
3639 if (last->nitems < last->maxitems)
3640 {
3641 /* there's still room in the last existing chunk */
3642 last->items[last->nitems] = *jbv;
3643 last->nitems++;
3644 }
3645 else
3646 {
3647 /* need a new last chunk */
3649 int nxtsize;
3650
3651 nxtsize = last->maxitems * 2; /* double the size with each chunk */
3652 nxtsize = Max(nxtsize, MIN_EXTRA_JVL_ITEMS); /* but at least this */
3654 nxtsize * sizeof(JsonbValue));
3655 nxt->nitems = 1;
3656 nxt->maxitems = nxtsize;
3657 nxt->next = NULL;
3658 nxt->items[0] = *jbv;
3659 last->next = nxt;
3660 jvl->last = nxt;
3661 }
3662}
#define Max(x, y)
Definition c.h:1087
#define MIN_EXTRA_JVL_ITEMS
void * palloc(Size size)
Definition mcxt.c:1387
struct JsonValueList * last
JsonbValue items[BASE_JVL_ITEMS]
struct JsonValueList * next
static ItemArray items

References fb(), JsonValueList::items, items, JsonValueList::last, Max, JsonValueList::maxitems, MIN_EXTRA_JVL_ITEMS, JsonValueList::next, JsonValueList::nitems, and palloc().

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

◆ JsonValueListClear()

static void JsonValueListClear ( JsonValueList jvl)
static

Definition at line 3617 of file jsonpath_exec.c.

3618{
3620
3621 /* Release any extra chunks */
3622 for (JsonValueList *chunk = jvl->next; chunk != NULL; chunk = nxt)
3623 {
3624 nxt = chunk->next;
3625 pfree(chunk);
3626 }
3627 /* ... and reset to empty */
3628 jvl->nitems = 0;
3629 Assert(jvl->maxitems == BASE_JVL_ITEMS);
3630 jvl->next = NULL;
3631 jvl->last = jvl;
3632}
#define BASE_JVL_ITEMS

References Assert, BASE_JVL_ITEMS, fb(), JsonValueList::next, and pfree().

Referenced by executeBinaryArithmExpr(), executeBoolItem(), executeItemOptUnwrapResult(), executeJsonPath(), executePredicate(), executeUnaryArithmExpr(), getArrayIndex(), and JsonTableResetRowPattern().

◆ JsonValueListHasMultipleItems()

static bool JsonValueListHasMultipleItems ( const JsonValueList jvl)
static

Definition at line 3683 of file jsonpath_exec.c.

3684{
3685#if BASE_JVL_ITEMS > 1
3686 /* We need not examine extra chunks in this case */
3687 return (jvl->nitems > 1);
3688#else
3689 return (jvl->nitems == 1 && jvl->next != NULL);
3690#endif
3691}

References fb().

Referenced by JsonPathQuery(), and JsonPathValue().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 3694 of file jsonpath_exec.c.

3695{
3696 Assert(jvl->nitems > 0);
3697 return &jvl->items[0];
3698}

References Assert, and fb().

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

◆ JsonValueListInit()

◆ JsonValueListInitIterator()

static void JsonValueListInitIterator ( JsonValueList jvl,
JsonValueListIterator it 
)
static

Definition at line 3705 of file jsonpath_exec.c.

3706{
3707 it->chunk = jvl;
3708 it->nextitem = 0;
3709}

References fb().

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

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( const JsonValueList jvl)
static

Definition at line 3665 of file jsonpath_exec.c.

3666{
3667 /* We need not examine extra chunks for this */
3668 return (jvl->nitems == 0);
3669}

References fb().

Referenced by executeBoolItem(), executeJsonPath(), jsonb_path_query_first_internal(), JsonPathQuery(), and JsonPathValue().

◆ JsonValueListIsSingleton()

static bool JsonValueListIsSingleton ( const JsonValueList jvl)
static

Definition at line 3672 of file jsonpath_exec.c.

3673{
3674#if BASE_JVL_ITEMS > 1
3675 /* We need not examine extra chunks in this case */
3676 return (jvl->nitems == 1);
3677#else
3678 return (jvl->nitems == 1 && jvl->next == NULL);
3679#endif
3680}

References fb().

Referenced by executeBinaryArithmExpr(), getArrayIndex(), and jsonb_path_match_internal().

◆ JsonValueListNext()

static JsonbValue * JsonValueListNext ( JsonValueListIterator it)
static

Definition at line 3716 of file jsonpath_exec.c.

3717{
3718 if (it->chunk == NULL)
3719 return NULL;
3720 if (it->nextitem >= it->chunk->nitems)
3721 {
3722 it->chunk = it->chunk->next;
3723 if (it->chunk == NULL)
3724 return NULL;
3725 it->nextitem = 0;
3726 Assert(it->chunk->nitems > 0);
3727 }
3728 return &it->chunk->items[it->nextitem++];
3729}

References Assert, and fb().

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

◆ setBaseObject()

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

Definition at line 3592 of file jsonpath_exec.c.

3593{
3594 JsonBaseObjectInfo baseObject = cxt->baseObject;
3595
3596 cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
3597 (JsonbContainer *) jbv->val.binary.data;
3598 cxt->baseObject.id = id;
3599
3600 return baseObject;
3601}

References JsonPathExecContext::baseObject, fb(), JsonBaseObjectInfo::id, JsonBaseObjectInfo::jbc, and jbvBinary.

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

◆ wrapItemsInArray()

static JsonbValue * wrapItemsInArray ( JsonValueList items)
static

Definition at line 3783 of file jsonpath_exec.c.

3784{
3785 JsonbInState ps = {0};
3787 JsonbValue *jbv;
3788
3790
3792 while ((jbv = JsonValueListNext(&it)))
3794
3796
3797 return ps.result;
3798}
@ WJB_END_ARRAY
Definition jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition jsonb.h:26

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

399{
400 .InitOpaque = JsonTableInitOpaque,
401 .SetDocument = JsonTableSetDocument,
402 .SetNamespace = NULL,
403 .SetRowFilter = NULL,
404 .SetColumnFilter = NULL,
405 .FetchRow = JsonTableFetchRow,
406 .GetValue = JsonTableGetValue,
407 .DestroyOpaque = JsonTableDestroyOpaque
408};

Referenced by ExecInitTableFuncScan().