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 executeStringInternalMethod (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 3194 of file jsonpath_exec.c.

3196{
3199
3200 if (!jspGetNext(jsp, &next) && !found)
3201 return jperOk; /* found singleton boolean value */
3202
3203 if (res == jpbUnknown)
3204 {
3205 jbv.type = jbvNull;
3206 }
3207 else
3208 {
3209 jbv.type = jbvBool;
3210 jbv.val.boolean = res == jpbTrue;
3211 }
3212
3213 return executeNextItem(cxt, jsp, &next, &jbv, found);
3214}
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:1188
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 3517 of file jsonpath_exec.c.

3519{
3520 int cmp;
3521
3522 cmp = memcmp(s1, s2, Min(len1, len2));
3523
3524 if (cmp != 0)
3525 return cmp;
3526
3527 if (len1 == len2)
3528 return 0;
3529
3530 return len1 < len2 ? -1 : 1;
3531}
#define Min(x, y)
Definition c.h:1091
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 3992 of file jsonpath_exec.c.

3993{
3994 checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3995
3996 return DirectFunctionCall1(time_timetz, time);
3997}
Datum time_timetz(PG_FUNCTION_ARGS)
Definition date.c:2917
#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 3980 of file jsonpath_exec.c.

3981{
3982 if (!useTz)
3983 ereport(ERROR,
3985 errmsg("cannot convert value from %s to %s without time zone usage",
3986 type1, type2),
3987 errhint("Use *_tz() function for time zone support.")));
3988}
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
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 4004 of file jsonpath_exec.c.

4005{
4007}
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition date.c:759

References date_cmp_timestamp_internal(), and fb().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 4013 of file jsonpath_exec.c.

4014{
4015 checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
4016
4018}
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition date.c:840

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

4025{
4026 checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
4027
4029}
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition timestamp.c:2357

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

4039{
4041
4042 *cast_error = false;
4043
4044 switch (typid1)
4045 {
4046 case DATEOID:
4047 switch (typid2)
4048 {
4049 case DATEOID:
4050 cmpfunc = date_cmp;
4051
4052 break;
4053
4054 case TIMESTAMPOID:
4057 useTz);
4058
4059 case TIMESTAMPTZOID:
4062 useTz);
4063
4064 case TIMEOID:
4065 case TIMETZOID:
4066 *cast_error = true; /* uncomparable types */
4067 return 0;
4068
4069 default:
4070 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4071 typid2);
4072 }
4073 break;
4074
4075 case TIMEOID:
4076 switch (typid2)
4077 {
4078 case TIMEOID:
4079 cmpfunc = time_cmp;
4080
4081 break;
4082
4083 case TIMETZOID:
4084 val1 = castTimeToTimeTz(val1, useTz);
4086
4087 break;
4088
4089 case DATEOID:
4090 case TIMESTAMPOID:
4091 case TIMESTAMPTZOID:
4092 *cast_error = true; /* uncomparable types */
4093 return 0;
4094
4095 default:
4096 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4097 typid2);
4098 }
4099 break;
4100
4101 case TIMETZOID:
4102 switch (typid2)
4103 {
4104 case TIMEOID:
4105 val2 = castTimeToTimeTz(val2, useTz);
4107
4108 break;
4109
4110 case TIMETZOID:
4112
4113 break;
4114
4115 case DATEOID:
4116 case TIMESTAMPOID:
4117 case TIMESTAMPTZOID:
4118 *cast_error = true; /* uncomparable types */
4119 return 0;
4120
4121 default:
4122 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4123 typid2);
4124 }
4125 break;
4126
4127 case TIMESTAMPOID:
4128 switch (typid2)
4129 {
4130 case DATEOID:
4133 useTz);
4134
4135 case TIMESTAMPOID:
4137
4138 break;
4139
4140 case TIMESTAMPTZOID:
4143 useTz);
4144
4145 case TIMEOID:
4146 case TIMETZOID:
4147 *cast_error = true; /* uncomparable types */
4148 return 0;
4149
4150 default:
4151 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4152 typid2);
4153 }
4154 break;
4155
4156 case TIMESTAMPTZOID:
4157 switch (typid2)
4158 {
4159 case DATEOID:
4162 useTz);
4163
4164 case TIMESTAMPOID:
4167 useTz);
4168
4169 case TIMESTAMPTZOID:
4171
4172 break;
4173
4174 case TIMEOID:
4175 case TIMETZOID:
4176 *cast_error = true; /* uncomparable types */
4177 return 0;
4178
4179 default:
4180 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4181 typid2);
4182 }
4183 break;
4184
4185 default:
4186 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
4187 }
4188
4189 if (*cast_error)
4190 return 0; /* cast error */
4191
4193}
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition timestamp.c:2264
Datum date_cmp(PG_FUNCTION_ARGS)
Definition date.c:438
Datum time_cmp(PG_FUNCTION_ARGS)
Definition date.c:1823
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition date.c:2613
static DateADT DatumGetDateADT(Datum X)
Definition date.h:60
#define elog(elevel,...)
Definition elog.h:228
#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 3605 of file jsonpath_exec.c.

3606{
3607 int cmp;
3608 bool res;
3609
3610 if (jb1->type != jb2->type)
3611 {
3612 if (jb1->type == jbvNull || jb2->type == jbvNull)
3613
3614 /*
3615 * Equality and order comparison of nulls to non-nulls returns
3616 * always false, but inequality comparison returns true.
3617 */
3618 return op == jpiNotEqual ? jpbTrue : jpbFalse;
3619
3620 /* Non-null items of different types are not comparable. */
3621 return jpbUnknown;
3622 }
3623
3624 switch (jb1->type)
3625 {
3626 case jbvNull:
3627 cmp = 0;
3628 break;
3629 case jbvBool:
3630 cmp = jb1->val.boolean == jb2->val.boolean ? 0 :
3631 jb1->val.boolean ? 1 : -1;
3632 break;
3633 case jbvNumeric:
3634 cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
3635 break;
3636 case jbvString:
3637 if (op == jpiEqual)
3638 return jb1->val.string.len != jb2->val.string.len ||
3639 memcmp(jb1->val.string.val,
3640 jb2->val.string.val,
3641 jb1->val.string.len) ? jpbFalse : jpbTrue;
3642
3643 cmp = compareStrings(jb1->val.string.val, jb1->val.string.len,
3644 jb2->val.string.val, jb2->val.string.len);
3645 break;
3646 case jbvDatetime:
3647 {
3648 bool cast_error;
3649
3650 cmp = compareDatetime(jb1->val.datetime.value,
3651 jb1->val.datetime.typid,
3652 jb2->val.datetime.value,
3653 jb2->val.datetime.typid,
3654 useTz,
3655 &cast_error);
3656
3657 if (cast_error)
3658 return jpbUnknown;
3659 }
3660 break;
3661
3662 case jbvBinary:
3663 case jbvArray:
3664 case jbvObject:
3665 return jpbUnknown; /* non-scalars are not comparable */
3666
3667 default:
3668 elog(ERROR, "invalid jsonb value type %d", jb1->type);
3669 }
3670
3671 switch (op)
3672 {
3673 case jpiEqual:
3674 res = (cmp == 0);
3675 break;
3676 case jpiNotEqual:
3677 res = (cmp != 0);
3678 break;
3679 case jpiLess:
3680 res = (cmp < 0);
3681 break;
3682 case jpiGreater:
3683 res = (cmp > 0);
3684 break;
3685 case jpiLessOrEqual:
3686 res = (cmp <= 0);
3687 break;
3688 case jpiGreaterOrEqual:
3689 res = (cmp >= 0);
3690 break;
3691 default:
3692 elog(ERROR, "unrecognized jsonpath operation: %d", op);
3693 return jpbUnknown;
3694 }
3695
3696 return res ? jpbTrue : jpbFalse;
3697}
@ 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 3701 of file jsonpath_exec.c.

3702{
3705 NumericGetDatum(b)));
3706}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition numeric.c:2417
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 3538 of file jsonpath_exec.c.

3540{
3543 {
3544 /*
3545 * It's known property of UTF-8 strings that their per-byte comparison
3546 * result matches codepoints comparison result. ASCII can be
3547 * considered as special case of UTF-8.
3548 */
3550 }
3551 else
3552 {
3553 char *utf8str1,
3554 *utf8str2;
3555 int cmp,
3556 utf8len1,
3557 utf8len2;
3558
3559 /*
3560 * We have to convert other encodings to UTF-8 first, then compare.
3561 * Input strings may be not null-terminated and pg_server_to_any() may
3562 * return them "as is". So, use strlen() only if there is real
3563 * conversion.
3564 */
3569
3571
3572 /*
3573 * If pg_server_to_any() did no real conversion, then we actually
3574 * compared original strings. So, we already done.
3575 */
3576 if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
3577 return cmp;
3578
3579 /* Free memory if needed */
3580 if (mbstr1 != utf8str1)
3581 pfree(utf8str1);
3582 if (mbstr2 != utf8str2)
3583 pfree(utf8str2);
3584
3585 /*
3586 * When all Unicode codepoints are equal, return result of binary
3587 * comparison. In some edge cases, same characters may have different
3588 * representations in encoding. Then our behavior could diverge from
3589 * standard. However, that allow us to do simple binary comparison
3590 * for "==" operator, which is performance critical in typical cases.
3591 * In future to implement strict standard conformance, we can do
3592 * normalization of input JSON strings.
3593 */
3594 if (cmp == 0)
3596 else
3597 return cmp;
3598 }
3599}
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:1388
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:76

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

3710{
3712
3713 *dst = *src;
3714
3715 return dst;
3716}
#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 3300 of file jsonpath_exec.c.

3301{
3302 List *vars = (List *) cxt;
3303
3304 return list_length(vars);
3305}
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 3467 of file jsonpath_exec.c.

3468{
3469 Jsonb *vars = varsJsonb;
3470
3471 if (vars && !JsonContainerIsObject(&vars->root))
3472 {
3473 ereport(ERROR,
3475 errmsg("\"vars\" argument is not an object"),
3476 errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3477 }
3478
3479 /* count of base objects */
3480 return vars != NULL ? 1 : 0;
3481}
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 1988 of file jsonpath_exec.c.

1991{
1994 int32 r;
1995 JsonbValue v;
1996
1998
1999 if (level > last)
2000 return res;
2001
2002 it = JsonbIteratorInit(jbc);
2003
2004 /*
2005 * Recursively iterate over jsonb objects/arrays
2006 */
2007 while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
2008 {
2009 if (r == WJB_KEY)
2010 {
2011 r = JsonbIteratorNext(&it, &v, true);
2012 Assert(r == WJB_VALUE);
2013 }
2014
2015 if (r == WJB_VALUE || r == WJB_ELEM)
2016 {
2017
2018 if (level >= first ||
2019 (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
2020 v.type != jbvBinary)) /* leaves only requested */
2021 {
2022 /* check expression */
2023 if (jsp)
2024 {
2025 if (ignoreStructuralErrors)
2026 {
2028
2030 cxt->ignoreStructuralErrors = true;
2031 res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2033 }
2034 else
2035 res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2036
2037 if (jperIsError(res))
2038 break;
2039
2040 if (res == jperOk && !found)
2041 break;
2042 }
2043 else if (found)
2044 JsonValueListAppend(found, &v);
2045 else
2046 return jperOk;
2047 }
2048
2049 if (level < last && v.type == jbvBinary)
2050 {
2051 res = executeAnyItem
2052 (cxt, jsp, v.val.binary.data, found,
2053 level + 1, first, last,
2054 ignoreStructuralErrors, unwrapNext);
2055
2056 if (jperIsError(res))
2057 break;
2058
2059 if (res == jperOk && found == NULL)
2060 break;
2061 }
2062 }
2063 }
2064
2065 return res;
2066}
#define PG_UINT32_MAX
Definition c.h:674
#define Assert(condition)
Definition c.h:943
int32_t int32
Definition c.h:620
@ 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 2173 of file jsonpath_exec.c.

2176{
2178 JsonPathItem elem;
2181 JsonbValue *lval;
2184 Numeric res;
2185
2188
2189 jspGetLeftArg(jsp, &elem);
2190
2191 /*
2192 * XXX: By standard only operands of multiplicative expressions are
2193 * unwrapped. We extend it to other binary arithmetic expressions too.
2194 */
2195 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2196 if (jperIsError(jper))
2197 {
2200 return jper;
2201 }
2202
2203 jspGetRightArg(jsp, &elem);
2204
2205 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2206 if (jperIsError(jper))
2207 {
2210 return jper;
2211 }
2212
2215 {
2220 errmsg("left operand of jsonpath operator %s is not a single numeric value",
2221 jspOperationName(jsp->type)))));
2222 }
2223
2226 {
2231 errmsg("right operand of jsonpath operator %s is not a single numeric value",
2232 jspOperationName(jsp->type)))));
2233 }
2234
2235 if (jspThrowErrors(cxt))
2236 {
2237 res = func(lval->val.numeric, rval->val.numeric, NULL);
2238 }
2239 else
2240 {
2242
2243 res = func(lval->val.numeric, rval->val.numeric, (Node *) &escontext);
2244
2245 if (escontext.error_occurred)
2246 {
2249 return jperError;
2250 }
2251 }
2252
2255
2256 if (!jspGetNext(jsp, &elem) && !found)
2257 return jperOk;
2258
2259 resval.type = jbvNumeric;
2260 resval.val.numeric = res;
2261
2262 return executeNextItem(cxt, jsp, &elem, &resval, found);
2263}
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1263
const char * jspOperationName(JsonPathItemType type)
Definition jsonpath.c:905
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1287
#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 1824 of file jsonpath_exec.c.

1826{
1827 JsonPathItem larg;
1828 JsonPathItem rarg;
1829 JsonPathBool res;
1831
1832 /* since this function recurses, it could be driven to stack overflow */
1834
1835 if (!canHaveNext && jspHasNext(jsp))
1836 elog(ERROR, "boolean jsonpath item cannot have next item");
1837
1838 switch (jsp->type)
1839 {
1840 case jpiAnd:
1841 jspGetLeftArg(jsp, &larg);
1842 res = executeBoolItem(cxt, &larg, jb, false);
1843
1844 if (res == jpbFalse)
1845 return jpbFalse;
1846
1847 /*
1848 * SQL/JSON says that we should check second arg in case of
1849 * jperError
1850 */
1851
1852 jspGetRightArg(jsp, &rarg);
1853 res2 = executeBoolItem(cxt, &rarg, jb, false);
1854
1855 return res2 == jpbTrue ? res : res2;
1856
1857 case jpiOr:
1858 jspGetLeftArg(jsp, &larg);
1859 res = executeBoolItem(cxt, &larg, jb, false);
1860
1861 if (res == jpbTrue)
1862 return jpbTrue;
1863
1864 jspGetRightArg(jsp, &rarg);
1865 res2 = executeBoolItem(cxt, &rarg, jb, false);
1866
1867 return res2 == jpbFalse ? res : res2;
1868
1869 case jpiNot:
1870 jspGetArg(jsp, &larg);
1871
1872 res = executeBoolItem(cxt, &larg, jb, false);
1873
1874 if (res == jpbUnknown)
1875 return jpbUnknown;
1876
1877 return res == jpbTrue ? jpbFalse : jpbTrue;
1878
1879 case jpiIsUnknown:
1880 jspGetArg(jsp, &larg);
1881 res = executeBoolItem(cxt, &larg, jb, false);
1882 return res == jpbUnknown ? jpbTrue : jpbFalse;
1883
1884 case jpiEqual:
1885 case jpiNotEqual:
1886 case jpiLess:
1887 case jpiGreater:
1888 case jpiLessOrEqual:
1889 case jpiGreaterOrEqual:
1890 jspGetLeftArg(jsp, &larg);
1891 jspGetRightArg(jsp, &rarg);
1892 return executePredicate(cxt, jsp, &larg, &rarg, jb, true,
1893 executeComparison, cxt);
1894
1895 case jpiStartsWith: /* 'whole STARTS WITH initial' */
1896 jspGetLeftArg(jsp, &larg); /* 'whole' */
1897 jspGetRightArg(jsp, &rarg); /* 'initial' */
1898 return executePredicate(cxt, jsp, &larg, &rarg, jb, false,
1900
1901 case jpiLikeRegex: /* 'expr LIKE_REGEX pattern FLAGS flags' */
1902 {
1903 /*
1904 * 'expr' is a sequence-returning expression. 'pattern' is a
1905 * regex string literal. SQL/JSON standard requires XQuery
1906 * regexes, but we use Postgres regexes here. 'flags' is a
1907 * string literal converted to integer flags at compile-time.
1908 */
1910
1911 jspInitByBuffer(&larg, jsp->base,
1912 jsp->content.like_regex.expr);
1913
1914 return executePredicate(cxt, jsp, &larg, NULL, jb, false,
1916 }
1917
1918 case jpiExists:
1919 jspGetArg(jsp, &larg);
1920
1921 if (jspStrictAbsenceOfErrors(cxt))
1922 {
1923 /*
1924 * In strict mode we must get a complete list of values to
1925 * check that there are no errors at all.
1926 */
1927 JsonValueList vals;
1929 bool isempty;
1930
1931 JsonValueListInit(&vals);
1932
1933 res = executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1934 false, &vals);
1935
1937 JsonValueListClear(&vals);
1938
1939 if (jperIsError(res))
1940 return jpbUnknown;
1941
1942 return isempty ? jpbFalse : jpbTrue;
1943 }
1944 else
1945 {
1946 JsonPathExecResult res =
1948 false, NULL);
1949
1950 if (jperIsError(res))
1951 return jpbUnknown;
1952
1953 return res == jperOk ? jpbTrue : jpbFalse;
1954 }
1955
1956 default:
1957 elog(ERROR, "invalid boolean jsonpath item type: %d", jsp->type);
1958 return jpbUnknown;
1959 }
1960}
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1167
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition jsonpath.c:1068
#define jspHasNext(jsp)
Definition jsonpath.h:202
@ 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 3506 of file jsonpath_exec.c.

3507{
3509
3510 return compareItems(cmp->type, lv, rv, cxt->useTz);
3511}
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 2445 of file jsonpath_exec.c.

2447{
2449 Datum value;
2450 text *datetime;
2451 Oid collid;
2452 Oid typid;
2453 int32 typmod = -1;
2454 int tz = 0;
2455 bool hasNext;
2457 JsonPathItem elem;
2458 int32 time_precision = -1;
2459
2460 if (!(jb = getScalar(jb, jbvString)))
2463 errmsg("jsonpath item method .%s() can only be applied to a string",
2464 jspOperationName(jsp->type)))));
2465
2466 datetime = cstring_to_text_with_len(jb->val.string.val,
2467 jb->val.string.len);
2468
2469 /*
2470 * At some point we might wish to have callers supply the collation to
2471 * use, but right now it's unclear that they'd be able to do better than
2472 * DEFAULT_COLLATION_OID anyway.
2473 */
2475
2476 /*
2477 * .datetime(template) has an argument, the rest of the methods don't have
2478 * an argument. So we handle that separately.
2479 */
2480 if (jsp->type == jpiDatetime && jsp->content.arg)
2481 {
2482 text *template;
2483 char *template_str;
2484 int template_len;
2486
2487 jspGetArg(jsp, &elem);
2488
2489 if (elem.type != jpiString)
2490 elog(ERROR, "invalid jsonpath item type for .datetime() argument");
2491
2493
2495 template_len);
2496
2497 value = parse_datetime(datetime, template, collid, true,
2498 &typid, &typmod, &tz,
2499 jspThrowErrors(cxt) ? NULL : (Node *) &escontext);
2500
2501 if (escontext.error_occurred)
2502 res = jperError;
2503 else
2504 res = jperOk;
2505 }
2506 else
2507 {
2508 /*
2509 * According to SQL/JSON standard enumerate ISO formats for: date,
2510 * timetz, time, timestamptz, timestamp.
2511 *
2512 * We also support ISO 8601 format (with "T") for timestamps, because
2513 * to_json[b]() functions use this format.
2514 */
2515 static const char *fmt_str[] =
2516 {
2517 "yyyy-mm-dd", /* date */
2518 "HH24:MI:SS.USTZ", /* timetz */
2519 "HH24:MI:SSTZ",
2520 "HH24:MI:SS.US", /* time without tz */
2521 "HH24:MI:SS",
2522 "yyyy-mm-dd HH24:MI:SS.USTZ", /* timestamptz */
2523 "yyyy-mm-dd HH24:MI:SSTZ",
2524 "yyyy-mm-dd\"T\"HH24:MI:SS.USTZ",
2525 "yyyy-mm-dd\"T\"HH24:MI:SSTZ",
2526 "yyyy-mm-dd HH24:MI:SS.US", /* timestamp without tz */
2527 "yyyy-mm-dd HH24:MI:SS",
2528 "yyyy-mm-dd\"T\"HH24:MI:SS.US",
2529 "yyyy-mm-dd\"T\"HH24:MI:SS"
2530 };
2531
2532 /* cache for format texts */
2533 static text *fmt_txt[lengthof(fmt_str)] = {0};
2534 int i;
2535
2536 /*
2537 * Check for optional precision for methods other than .datetime() and
2538 * .date()
2539 */
2540 if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
2541 jsp->content.arg)
2542 {
2544
2545 jspGetArg(jsp, &elem);
2546
2547 if (elem.type != jpiNumeric)
2548 elog(ERROR, "invalid jsonpath item type for %s argument",
2549 jspOperationName(jsp->type));
2550
2552 (Node *) &escontext);
2553 if (escontext.error_occurred)
2556 errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
2557 jspOperationName(jsp->type)))));
2558 }
2559
2560 /* loop until datetime format fits */
2561 for (i = 0; i < lengthof(fmt_str); i++)
2562 {
2564
2565 if (!fmt_txt[i])
2566 {
2569
2572 }
2573
2574 value = parse_datetime(datetime, fmt_txt[i], collid, true,
2575 &typid, &typmod, &tz,
2576 (Node *) &escontext);
2577
2578 if (!escontext.error_occurred)
2579 {
2580 res = jperOk;
2581 break;
2582 }
2583 }
2584
2585 if (res == jperNotFound)
2586 {
2587 if (jsp->type == jpiDatetime)
2590 errmsg("%s format is not recognized: \"%s\"",
2591 "datetime", text_to_cstring(datetime)),
2592 errhint("Use a datetime template argument to specify the input data format."))));
2593 else
2596 errmsg("%s format is not recognized: \"%s\"",
2597 jspOperationName(jsp->type), text_to_cstring(datetime)))));
2598
2599 }
2600 }
2601
2602 /*
2603 * parse_datetime() processes the entire input string per the template or
2604 * ISO format and returns the Datum in best fitted datetime type. So, if
2605 * this call is for a specific datatype, then we do the conversion here.
2606 * Throw an error for incompatible types.
2607 */
2608 switch (jsp->type)
2609 {
2610 case jpiDatetime: /* Nothing to do for DATETIME */
2611 break;
2612 case jpiDate:
2613 {
2614 /* Convert result type to date */
2615 switch (typid)
2616 {
2617 case DATEOID: /* Nothing to do for DATE */
2618 break;
2619 case TIMEOID:
2620 case TIMETZOID:
2623 errmsg("%s format is not recognized: \"%s\"",
2624 "date", text_to_cstring(datetime)))));
2625 break;
2626 case TIMESTAMPOID:
2628 value);
2629 break;
2630 case TIMESTAMPTZOID:
2632 "timestamptz", "date");
2634 value);
2635 break;
2636 default:
2637 elog(ERROR, "type with oid %u not supported", typid);
2638 }
2639
2640 typid = DATEOID;
2641 }
2642 break;
2643 case jpiTime:
2644 {
2645 /* Convert result type to time without time zone */
2646 switch (typid)
2647 {
2648 case DATEOID:
2651 errmsg("%s format is not recognized: \"%s\"",
2652 "time", text_to_cstring(datetime)))));
2653 break;
2654 case TIMEOID: /* Nothing to do for TIME */
2655 break;
2656 case TIMETZOID:
2658 "timetz", "time");
2660 value);
2661 break;
2662 case TIMESTAMPOID:
2664 value);
2665 break;
2666 case TIMESTAMPTZOID:
2668 "timestamptz", "time");
2670 value);
2671 break;
2672 default:
2673 elog(ERROR, "type with oid %u not supported", typid);
2674 }
2675
2676 /* Force the user-given time precision, if any */
2677 if (time_precision != -1)
2678 {
2680
2681 /* Get a warning when precision is reduced */
2687
2688 /* Update the typmod value with the user-given precision */
2689 typmod = time_precision;
2690 }
2691
2692 typid = TIMEOID;
2693 }
2694 break;
2695 case jpiTimeTz:
2696 {
2697 /* Convert result type to time with time zone */
2698 switch (typid)
2699 {
2700 case DATEOID:
2701 case TIMESTAMPOID:
2704 errmsg("%s format is not recognized: \"%s\"",
2705 "time_tz", text_to_cstring(datetime)))));
2706 break;
2707 case TIMEOID:
2709 "time", "timetz");
2711 value);
2712 break;
2713 case TIMETZOID: /* Nothing to do for TIMETZ */
2714 break;
2715 case TIMESTAMPTZOID:
2717 value);
2718 break;
2719 default:
2720 elog(ERROR, "type with oid %u not supported", typid);
2721 }
2722
2723 /* Force the user-given time precision, if any */
2724 if (time_precision != -1)
2725 {
2727
2728 /* Get a warning when precision is reduced */
2734
2735 /* Update the typmod value with the user-given precision */
2736 typmod = time_precision;
2737 }
2738
2739 typid = TIMETZOID;
2740 }
2741 break;
2742 case jpiTimestamp:
2743 {
2744 /* Convert result type to timestamp without time zone */
2745 switch (typid)
2746 {
2747 case DATEOID:
2749 value);
2750 break;
2751 case TIMEOID:
2752 case TIMETZOID:
2755 errmsg("%s format is not recognized: \"%s\"",
2756 "timestamp", text_to_cstring(datetime)))));
2757 break;
2758 case TIMESTAMPOID: /* Nothing to do for TIMESTAMP */
2759 break;
2760 case TIMESTAMPTZOID:
2762 "timestamptz", "timestamp");
2764 value);
2765 break;
2766 default:
2767 elog(ERROR, "type with oid %u not supported", typid);
2768 }
2769
2770 /* Force the user-given time precision, if any */
2771 if (time_precision != -1)
2772 {
2775
2776 /* Get a warning when precision is reduced */
2781 (Node *) &escontext);
2782 if (escontext.error_occurred) /* should not happen */
2785 errmsg("time precision of jsonpath item method .%s() is invalid",
2786 jspOperationName(jsp->type)))));
2788
2789 /* Update the typmod value with the user-given precision */
2790 typmod = time_precision;
2791 }
2792
2793 typid = TIMESTAMPOID;
2794 }
2795 break;
2796 case jpiTimestampTz:
2797 {
2798 struct pg_tm tm;
2799 fsec_t fsec;
2800
2801 /* Convert result type to timestamp with time zone */
2802 switch (typid)
2803 {
2804 case DATEOID:
2806 "date", "timestamptz");
2807
2808 /*
2809 * Get the timezone value explicitly since JsonbValue
2810 * keeps that separate.
2811 */
2813 &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2814 tm.tm_hour = 0;
2815 tm.tm_min = 0;
2816 tm.tm_sec = 0;
2818
2820 value);
2821 break;
2822 case TIMEOID:
2823 case TIMETZOID:
2826 errmsg("%s format is not recognized: \"%s\"",
2827 "timestamp_tz", text_to_cstring(datetime)))));
2828 break;
2829 case TIMESTAMPOID:
2831 "timestamp", "timestamptz");
2832
2833 /*
2834 * Get the timezone value explicitly since JsonbValue
2835 * keeps that separate.
2836 */
2838 &fsec, NULL, NULL) == 0)
2841
2843 value);
2844 break;
2845 case TIMESTAMPTZOID: /* Nothing to do for TIMESTAMPTZ */
2846 break;
2847 default:
2848 elog(ERROR, "type with oid %u not supported", typid);
2849 }
2850
2851 /* Force the user-given time precision, if any */
2852 if (time_precision != -1)
2853 {
2856
2857 /* Get a warning when precision is reduced */
2862 (Node *) &escontext);
2863 if (escontext.error_occurred) /* should not happen */
2866 errmsg("time precision of jsonpath item method .%s() is invalid",
2867 jspOperationName(jsp->type)))));
2869
2870 /* Update the typmod value with the user-given precision */
2871 typmod = time_precision;
2872 }
2873
2874 typid = TIMESTAMPTZOID;
2875 }
2876 break;
2877 default:
2878 elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
2879 }
2880
2881 pfree(datetime);
2882
2883 if (jperIsError(res))
2884 return res;
2885
2886 hasNext = jspGetNext(jsp, &elem);
2887
2888 if (!hasNext && !found)
2889 return res;
2890
2891 jbv.type = jbvDatetime;
2892 jbv.val.datetime.value = value;
2893 jbv.val.datetime.typid = typid;
2894 jbv.val.datetime.typmod = typmod;
2895 jbv.val.datetime.tz = tz;
2896
2897 return executeNextItem(cxt, jsp, &elem, &jbv, found);
2898}
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:4369
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition timestamp.c:360
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition timestamp.c:6424
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition timestamp.c:1904
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition timestamp.c:116
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition timestamp.c:6492
#define lengthof(array)
Definition c.h:873
uint32 result
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:1994
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition date.c:65
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition date.c:1382
Datum timetz_time(PG_FUNCTION_ARGS)
Definition date.c:2904
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition date.c:2943
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition date.c:1734
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition date.c:1399
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition date.c:1320
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition date.c:2024
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition date.c:1304
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 @177 value
int i
Definition isn.c:77
char * jspGetString(JsonPathItem *v, int32 *len)
Definition jsonpath.c:1327
Numeric jspGetNumeric(JsonPathItem *v)
Definition jsonpath.c:1319
@ 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:145
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:776
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, result, RETURN_ERROR, session_timezone, text_to_cstring(), 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 777 of file jsonpath_exec.c.

779{
780 return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
781}
#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 1763 of file jsonpath_exec.c.

1766{
1767 if (unwrap && jspAutoUnwrap(cxt))
1768 {
1772 JsonbValue *item;
1773
1775
1776 res = executeItem(cxt, jsp, jb, &seq);
1777
1778 if (jperIsError(res))
1779 {
1781 return res;
1782 }
1783
1785 while ((item = JsonValueListNext(&it)))
1786 {
1787 Assert(item->type != jbvArray);
1788
1789 if (JsonbType(item) == jbvArray)
1790 executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1791 else
1792 JsonValueListAppend(found, item);
1793 }
1794
1796
1797 return jperOk;
1798 }
1799
1800 return executeItem(cxt, jsp, jb, found);
1801}
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 1807 of file jsonpath_exec.c.

1811{
1813 bool throwErrors = cxt->throwErrors;
1814
1815 cxt->throwErrors = false;
1816 res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1817 cxt->throwErrors = throwErrors;
1818
1819 return res;
1820}

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

791{
792 JsonPathItem elem;
794 JsonBaseObjectInfo baseObject;
795
798
799 switch (jsp->type)
800 {
801 case jpiNull:
802 case jpiBool:
803 case jpiNumeric:
804 case jpiString:
805 case jpiVariable:
806 {
807 JsonbValue v;
808 bool hasNext = jspGetNext(jsp, &elem);
809
810 if (!hasNext && !found && jsp->type != jpiVariable)
811 {
812 /*
813 * Skip evaluation, but not for variables. We must
814 * trigger an error for the missing variable.
815 */
816 res = jperOk;
817 break;
818 }
819
820 baseObject = cxt->baseObject;
821 getJsonPathItem(cxt, jsp, &v);
822
823 res = executeNextItem(cxt, jsp, &elem,
824 &v, found);
825 cxt->baseObject = baseObject;
826 }
827 break;
828
829 /* all boolean item types: */
830 case jpiAnd:
831 case jpiOr:
832 case jpiNot:
833 case jpiIsUnknown:
834 case jpiEqual:
835 case jpiNotEqual:
836 case jpiLess:
837 case jpiGreater:
838 case jpiLessOrEqual:
840 case jpiExists:
841 case jpiStartsWith:
842 case jpiLikeRegex:
843 {
844 JsonPathBool st = executeBoolItem(cxt, jsp, jb, true);
845
846 res = appendBoolResult(cxt, jsp, found, st);
847 break;
848 }
849
850 case jpiAdd:
851 return executeBinaryArithmExpr(cxt, jsp, jb,
852 numeric_add_safe, found);
853
854 case jpiSub:
855 return executeBinaryArithmExpr(cxt, jsp, jb,
856 numeric_sub_safe, found);
857
858 case jpiMul:
859 return executeBinaryArithmExpr(cxt, jsp, jb,
860 numeric_mul_safe, found);
861
862 case jpiDiv:
863 return executeBinaryArithmExpr(cxt, jsp, jb,
864 numeric_div_safe, found);
865
866 case jpiMod:
867 return executeBinaryArithmExpr(cxt, jsp, jb,
868 numeric_mod_safe, found);
869
870 case jpiPlus:
871 return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
872
873 case jpiMinus:
875 found);
876
877 case jpiAnyArray:
878 if (JsonbType(jb) == jbvArray)
879 {
880 bool hasNext = jspGetNext(jsp, &elem);
881
882 res = executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL,
883 jb, found, jspAutoUnwrap(cxt));
884 }
885 else if (jspAutoWrap(cxt))
886 res = executeNextItem(cxt, jsp, NULL, jb, found);
887 else if (!jspIgnoreStructuralErrors(cxt))
890 errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
891 break;
892
893 case jpiAnyKey:
894 if (JsonbType(jb) == jbvObject)
895 {
896 bool hasNext = jspGetNext(jsp, &elem);
897
898 if (jb->type != jbvBinary)
899 elog(ERROR, "invalid jsonb object type: %d", jb->type);
900
901 return executeAnyItem
902 (cxt, hasNext ? &elem : NULL,
903 jb->val.binary.data, found, 1, 1, 1,
904 false, jspAutoUnwrap(cxt));
905 }
906 else if (unwrap && JsonbType(jb) == jbvArray)
907 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
908 else if (!jspIgnoreStructuralErrors(cxt))
909 {
910 Assert(found);
913 errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
914 }
915 break;
916
917 case jpiIndexArray:
918 if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
919 {
920 int innermostArraySize = cxt->innermostArraySize;
921 int i;
922 int size = JsonbArraySize(jb);
923 bool singleton = size < 0;
924 bool hasNext = jspGetNext(jsp, &elem);
925
926 if (singleton)
927 size = 1;
928
929 cxt->innermostArraySize = size; /* for LAST evaluation */
930
931 for (i = 0; i < jsp->content.array.nelems; i++)
932 {
933 JsonPathItem from;
934 JsonPathItem to;
935 int32 index;
938 bool range = jspGetArraySubscript(jsp, &from,
939 &to, i);
940
941 res = getArrayIndex(cxt, &from, jb, &index_from);
942
943 if (jperIsError(res))
944 break;
945
946 if (range)
947 {
948 res = getArrayIndex(cxt, &to, jb, &index_to);
949
950 if (jperIsError(res))
951 break;
952 }
953 else
955
956 if (!jspIgnoreStructuralErrors(cxt) &&
957 (index_from < 0 ||
959 index_to >= size))
962 errmsg("jsonpath array subscript is out of bounds"))));
963
964 if (index_from < 0)
965 index_from = 0;
966
967 if (index_to >= size)
968 index_to = size - 1;
969
970 res = jperNotFound;
971
972 for (index = index_from; index <= index_to; index++)
973 {
974 JsonbValue *v;
975
976 if (singleton)
977 {
978 v = jb;
979 }
980 else
981 {
982 v = getIthJsonbValueFromContainer(jb->val.binary.data,
983 (uint32) index);
984
985 if (v == NULL)
986 continue;
987 }
988
989 if (!hasNext && !found)
990 return jperOk;
991
992 res = executeNextItem(cxt, jsp, &elem, v, found);
993
994 if (jperIsError(res))
995 break;
996
997 if (res == jperOk && !found)
998 break;
999 }
1000
1001 if (jperIsError(res))
1002 break;
1003
1004 if (res == jperOk && !found)
1005 break;
1006 }
1007
1008 cxt->innermostArraySize = innermostArraySize;
1009 }
1010 else if (!jspIgnoreStructuralErrors(cxt))
1011 {
1014 errmsg("jsonpath array accessor can only be applied to an array"))));
1015 }
1016 break;
1017
1018 case jpiAny:
1019 {
1020 bool hasNext = jspGetNext(jsp, &elem);
1021
1022 /* first try without any intermediate steps */
1023 if (jsp->content.anybounds.first == 0)
1024 {
1026
1028 cxt->ignoreStructuralErrors = true;
1029 res = executeNextItem(cxt, jsp, &elem,
1030 jb, found);
1032
1033 if (res == jperOk && !found)
1034 break;
1035 }
1036
1037 if (jb->type == jbvBinary)
1038 res = executeAnyItem
1039 (cxt, hasNext ? &elem : NULL,
1040 jb->val.binary.data, found,
1041 1,
1042 jsp->content.anybounds.first,
1043 jsp->content.anybounds.last,
1044 true, jspAutoUnwrap(cxt));
1045 break;
1046 }
1047
1048 case jpiKey:
1049 if (JsonbType(jb) == jbvObject)
1050 {
1051 JsonbValue *v;
1053
1054 key.type = jbvString;
1055 key.val.string.val = jspGetString(jsp, &key.val.string.len);
1056
1057 v = findJsonbValueFromContainer(jb->val.binary.data,
1058 JB_FOBJECT, &key);
1059
1060 if (v != NULL)
1061 {
1062 res = executeNextItem(cxt, jsp, NULL,
1063 v, found);
1064 pfree(v);
1065 }
1066 else if (!jspIgnoreStructuralErrors(cxt))
1067 {
1068 Assert(found);
1069
1070 if (!jspThrowErrors(cxt))
1071 return jperError;
1072
1073 ereport(ERROR,
1075 errmsg("JSON object does not contain key \"%s\"",
1076 pnstrdup(key.val.string.val,
1077 key.val.string.len))));
1078 }
1079 }
1080 else if (unwrap && JsonbType(jb) == jbvArray)
1081 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1082 else if (!jspIgnoreStructuralErrors(cxt))
1083 {
1084 Assert(found);
1087 errmsg("jsonpath member accessor can only be applied to an object"))));
1088 }
1089 break;
1090
1091 case jpiCurrent:
1092 res = executeNextItem(cxt, jsp, NULL, cxt->current, found);
1093 break;
1094
1095 case jpiRoot:
1096 jb = cxt->root;
1097 baseObject = setBaseObject(cxt, jb, 0);
1098 res = executeNextItem(cxt, jsp, NULL, jb, found);
1099 cxt->baseObject = baseObject;
1100 break;
1101
1102 case jpiFilter:
1103 {
1104 JsonPathBool st;
1105
1106 if (unwrap && JsonbType(jb) == jbvArray)
1107 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1108 false);
1109
1110 jspGetArg(jsp, &elem);
1111 st = executeNestedBoolItem(cxt, &elem, jb);
1112 if (st != jpbTrue)
1113 res = jperNotFound;
1114 else
1115 res = executeNextItem(cxt, jsp, NULL,
1116 jb, found);
1117 break;
1118 }
1119
1120 case jpiType:
1121 {
1123
1124 jbv.type = jbvString;
1125 jbv.val.string.val = pstrdup(JsonbTypeName(jb));
1126 jbv.val.string.len = strlen(jbv.val.string.val);
1127
1128 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1129 }
1130 break;
1131
1132 case jpiSize:
1133 {
1134 int size = JsonbArraySize(jb);
1136
1137 if (size < 0)
1138 {
1139 if (!jspAutoWrap(cxt))
1140 {
1141 if (!jspIgnoreStructuralErrors(cxt))
1144 errmsg("jsonpath item method .%s() can only be applied to an array",
1145 jspOperationName(jsp->type)))));
1146 break;
1147 }
1148
1149 size = 1;
1150 }
1151
1152 jbv.type = jbvNumeric;
1153 jbv.val.numeric = int64_to_numeric(size);
1154
1155 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1156 }
1157 break;
1158
1159 case jpiAbs:
1161 found);
1162
1163 case jpiFloor:
1165 found);
1166
1167 case jpiCeiling:
1169 found);
1170
1171 case jpiDouble:
1172 {
1174
1175 if (unwrap && JsonbType(jb) == jbvArray)
1176 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1177 false);
1178
1179 if (jb->type == jbvNumeric)
1180 {
1182 NumericGetDatum(jb->val.numeric)));
1183 double val;
1185
1186 val = float8in_internal(tmp,
1187 NULL,
1188 "double precision",
1189 tmp,
1190 (Node *) &escontext);
1191
1192 if (escontext.error_occurred)
1195 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1196 tmp, jspOperationName(jsp->type), "double precision"))));
1197 if (isinf(val) || isnan(val))
1200 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1201 jspOperationName(jsp->type)))));
1202 res = jperOk;
1203 }
1204 else if (jb->type == jbvString)
1205 {
1206 /* cast string as double */
1207 double val;
1208 char *tmp = pnstrdup(jb->val.string.val,
1209 jb->val.string.len);
1211
1212 val = float8in_internal(tmp,
1213 NULL,
1214 "double precision",
1215 tmp,
1216 (Node *) &escontext);
1217
1218 if (escontext.error_occurred)
1221 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1222 tmp, jspOperationName(jsp->type), "double precision"))));
1223 if (isinf(val) || isnan(val))
1226 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1227 jspOperationName(jsp->type)))));
1228
1229 jb = &jbv;
1230 jb->type = jbvNumeric;
1233 res = jperOk;
1234 }
1235
1236 if (res == jperNotFound)
1239 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1240 jspOperationName(jsp->type)))));
1241
1242 res = executeNextItem(cxt, jsp, NULL, jb, found);
1243 }
1244 break;
1245
1246 case jpiDatetime:
1247 case jpiDate:
1248 case jpiTime:
1249 case jpiTimeTz:
1250 case jpiTimestamp:
1251 case jpiTimestampTz:
1252 if (unwrap && JsonbType(jb) == jbvArray)
1253 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1254
1255 return executeDateTimeMethod(cxt, jsp, jb, found);
1256
1257 case jpiKeyValue:
1258 if (unwrap && JsonbType(jb) == jbvArray)
1259 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1260
1261 return executeKeyValueMethod(cxt, jsp, jb, found);
1262
1263 case jpiLast:
1264 {
1266 int last;
1267 bool hasNext = jspGetNext(jsp, &elem);
1268
1269 if (cxt->innermostArraySize < 0)
1270 elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
1271
1272 if (!hasNext && !found)
1273 {
1274 res = jperOk;
1275 break;
1276 }
1277
1278 last = cxt->innermostArraySize - 1;
1279
1280 jbv.type = jbvNumeric;
1281 jbv.val.numeric = int64_to_numeric(last);
1282
1283 res = executeNextItem(cxt, jsp, &elem,
1284 &jbv, found);
1285 }
1286 break;
1287
1288 case jpiBigint:
1289 {
1291 Datum datum;
1292
1293 if (unwrap && JsonbType(jb) == jbvArray)
1294 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1295 false);
1296
1297 if (jb->type == jbvNumeric)
1298 {
1300 int64 val;
1301
1302 val = numeric_int8_safe(jb->val.numeric,
1303 (Node *) &escontext);
1304 if (escontext.error_occurred)
1307 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1309 NumericGetDatum(jb->val.numeric))),
1310 jspOperationName(jsp->type),
1311 "bigint"))));
1312
1313 datum = Int64GetDatum(val);
1314 res = jperOk;
1315 }
1316 else if (jb->type == jbvString)
1317 {
1318 /* cast string as bigint */
1319 char *tmp = pnstrdup(jb->val.string.val,
1320 jb->val.string.len);
1322 bool noerr;
1323
1325 InvalidOid, -1,
1326 (Node *) &escontext,
1327 &datum);
1328
1329 if (!noerr || escontext.error_occurred)
1332 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1333 tmp, jspOperationName(jsp->type), "bigint"))));
1334 res = jperOk;
1335 }
1336
1337 if (res == jperNotFound)
1340 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1341 jspOperationName(jsp->type)))));
1342
1343 jbv.type = jbvNumeric;
1345 datum));
1346
1347 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1348 }
1349 break;
1350
1351 case jpiBoolean:
1352 {
1354 bool bval;
1355
1356 if (unwrap && JsonbType(jb) == jbvArray)
1357 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1358 false);
1359
1360 if (jb->type == jbvBool)
1361 {
1362 bval = jb->val.boolean;
1363
1364 res = jperOk;
1365 }
1366 else if (jb->type == jbvNumeric)
1367 {
1368 int ival;
1369 Datum datum;
1370 bool noerr;
1372 NumericGetDatum(jb->val.numeric)));
1374
1376 InvalidOid, -1,
1377 (Node *) &escontext,
1378 &datum);
1379
1380 if (!noerr || escontext.error_occurred)
1383 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1384 tmp, jspOperationName(jsp->type), "boolean"))));
1385
1386 ival = DatumGetInt32(datum);
1387 if (ival == 0)
1388 bval = false;
1389 else
1390 bval = true;
1391
1392 res = jperOk;
1393 }
1394 else if (jb->type == jbvString)
1395 {
1396 /* cast string as boolean */
1397 char *tmp = pnstrdup(jb->val.string.val,
1398 jb->val.string.len);
1399
1400 if (!parse_bool(tmp, &bval))
1403 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1404 tmp, jspOperationName(jsp->type), "boolean"))));
1405
1406 res = jperOk;
1407 }
1408
1409 if (res == jperNotFound)
1412 errmsg("jsonpath item method .%s() can only be applied to a boolean, string, or numeric value",
1413 jspOperationName(jsp->type)))));
1414
1415 jbv.type = jbvBool;
1416 jbv.val.boolean = bval;
1417
1418 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1419 }
1420 break;
1421
1422 case jpiDecimal:
1423 case jpiNumber:
1424 {
1426 Numeric num;
1427 char *numstr = NULL;
1428
1429 if (unwrap && JsonbType(jb) == jbvArray)
1430 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1431 false);
1432
1433 if (jb->type == jbvNumeric)
1434 {
1435 num = jb->val.numeric;
1436 if (numeric_is_nan(num) || numeric_is_inf(num))
1439 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1440 jspOperationName(jsp->type)))));
1441
1442 if (jsp->type == jpiDecimal)
1444 NumericGetDatum(num)));
1445 res = jperOk;
1446 }
1447 else if (jb->type == jbvString)
1448 {
1449 /* cast string as number */
1450 Datum datum;
1451 bool noerr;
1453
1454 numstr = pnstrdup(jb->val.string.val, jb->val.string.len);
1455
1457 InvalidOid, -1,
1458 (Node *) &escontext,
1459 &datum);
1460
1461 if (!noerr || escontext.error_occurred)
1464 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1465 numstr, jspOperationName(jsp->type), "numeric"))));
1466
1467 num = DatumGetNumeric(datum);
1468 if (numeric_is_nan(num) || numeric_is_inf(num))
1471 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1472 jspOperationName(jsp->type)))));
1473
1474 res = jperOk;
1475 }
1476
1477 if (res == jperNotFound)
1480 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1481 jspOperationName(jsp->type)))));
1482
1483 /*
1484 * If we have arguments, then they must be the precision and
1485 * optional scale used in .decimal(). Convert them to the
1486 * typmod equivalent and then truncate the numeric value per
1487 * this typmod details.
1488 */
1489 if (jsp->type == jpiDecimal && jsp->content.args.left)
1490 {
1492 Datum dtypmod;
1493 int32 precision;
1494 int32 scale = 0;
1495 bool noerr;
1497 Datum datums[2];
1498 char pstr[12]; /* sign, 10 digits and '\0' */
1499 char sstr[12]; /* sign, 10 digits and '\0' */
1501
1502 jspGetLeftArg(jsp, &elem);
1503 if (elem.type != jpiNumeric)
1504 elog(ERROR, "invalid jsonpath item type for .decimal() precision");
1505
1506 precision = numeric_int4_safe(jspGetNumeric(&elem),
1507 (Node *) &escontext);
1508 if (escontext.error_occurred)
1511 errmsg("precision of jsonpath item method .%s() is out of range for type integer",
1512 jspOperationName(jsp->type)))));
1513
1514 if (jsp->content.args.right)
1515 {
1516 jspGetRightArg(jsp, &elem);
1517 if (elem.type != jpiNumeric)
1518 elog(ERROR, "invalid jsonpath item type for .decimal() scale");
1519
1521 (Node *) &escontext);
1522 if (escontext.error_occurred)
1525 errmsg("scale of jsonpath item method .%s() is out of range for type integer",
1526 jspOperationName(jsp->type)))));
1527 }
1528
1529 /*
1530 * numerictypmodin() takes the precision and scale in the
1531 * form of CString arrays.
1532 */
1533 pg_ltoa(precision, pstr);
1534 datums[0] = CStringGetDatum(pstr);
1535 pg_ltoa(scale, sstr);
1536 datums[1] = CStringGetDatum(sstr);
1538
1541
1542 /* Convert numstr to Numeric with typmod */
1543 Assert(numstr != NULL);
1546 (Node *) &escontext,
1547 &numdatum);
1548
1549 if (!noerr || escontext.error_occurred)
1552 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1553 numstr, jspOperationName(jsp->type), "numeric"))));
1554
1557 }
1558
1559 jbv.type = jbvNumeric;
1560 jbv.val.numeric = num;
1561
1562 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1563 }
1564 break;
1565
1566 case jpiInteger:
1567 {
1569 Datum datum;
1570
1571 if (unwrap && JsonbType(jb) == jbvArray)
1572 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1573 false);
1574
1575 if (jb->type == jbvNumeric)
1576 {
1577 int32 val;
1579
1580 val = numeric_int4_safe(jb->val.numeric,
1581 (Node *) &escontext);
1582 if (escontext.error_occurred)
1585 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1587 NumericGetDatum(jb->val.numeric))),
1588 jspOperationName(jsp->type), "integer"))));
1589
1590 datum = Int32GetDatum(val);
1591 res = jperOk;
1592 }
1593 else if (jb->type == jbvString)
1594 {
1595 /* cast string as integer */
1596 char *tmp = pnstrdup(jb->val.string.val,
1597 jb->val.string.len);
1599 bool noerr;
1600
1602 InvalidOid, -1,
1603 (Node *) &escontext,
1604 &datum);
1605
1606 if (!noerr || escontext.error_occurred)
1609 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1610 tmp, jspOperationName(jsp->type), "integer"))));
1611 res = jperOk;
1612 }
1613
1614 if (res == jperNotFound)
1617 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1618 jspOperationName(jsp->type)))));
1619
1620 jbv.type = jbvNumeric;
1622 datum));
1623
1624 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1625 }
1626 break;
1627
1628 case jpiStringFunc:
1629 {
1631 char *tmp = NULL;
1632
1633 if (unwrap && JsonbType(jb) == jbvArray)
1634 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1635
1636 switch (JsonbType(jb))
1637 {
1638 case jbvString:
1639
1640 /*
1641 * Value is not necessarily null-terminated, so we do
1642 * pnstrdup() here.
1643 */
1644 tmp = pnstrdup(jb->val.string.val,
1645 jb->val.string.len);
1646 break;
1647 case jbvNumeric:
1649 NumericGetDatum(jb->val.numeric)));
1650 break;
1651 case jbvBool:
1652 tmp = (jb->val.boolean) ? "true" : "false";
1653 break;
1654 case jbvDatetime:
1655 {
1656 char buf[MAXDATELEN + 1];
1657
1659 jb->val.datetime.value,
1660 jb->val.datetime.typid,
1661 &jb->val.datetime.tz);
1662 tmp = pstrdup(buf);
1663 }
1664 break;
1665 case jbvNull:
1666 case jbvArray:
1667 case jbvObject:
1668 case jbvBinary:
1671 errmsg("jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value",
1672 jspOperationName(jsp->type)))));
1673 break;
1674 }
1675
1676 Assert(tmp != NULL); /* We must have set tmp above */
1677 jbv.val.string.val = tmp;
1678 jbv.val.string.len = strlen(jbv.val.string.val);
1679 jbv.type = jbvString;
1680
1681 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1682 }
1683 break;
1684
1685 case jpiStrReplace:
1686 case jpiStrLower:
1687 case jpiStrUpper:
1688 case jpiStrLtrim:
1689 case jpiStrRtrim:
1690 case jpiStrBtrim:
1691 case jpiStrInitcap:
1692 case jpiStrSplitPart:
1693 {
1694 if (unwrap && JsonbType(jb) == jbvArray)
1695 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1696
1697 return executeStringInternalMethod(cxt, jsp, jb, found);
1698 }
1699 break;
1700
1701 default:
1702 elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
1703 }
1704
1705 return res;
1706}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4538
Numeric int64_to_numeric(int64 val)
Definition numeric.c:4264
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4358
Datum numeric_uminus(PG_FUNCTION_ARGS)
Definition numeric.c:1405
Numeric numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3360
Datum numeric_ceil(PG_FUNCTION_ARGS)
Definition numeric.c:1632
Datum numerictypmodin(PG_FUNCTION_ARGS)
Definition numeric.c:1309
Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2883
int64 numeric_int8_safe(Numeric num, Node *escontext)
Definition numeric.c:4445
Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3157
Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2959
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:3038
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition numeric.c:1378
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4434
bool numeric_is_inf(Numeric num)
Definition numeric.c:845
Datum numeric_floor(PG_FUNCTION_ARGS)
Definition numeric.c:1660
bool parse_bool(const char *value, bool *result)
Definition bool.c:31
int64_t int64
Definition c.h:621
uint32_t uint32
Definition c.h:624
float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext)
Definition float.c:436
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:1339
@ jpiAdd
Definition jsonpath.h:78
@ jpiAbs
Definition jsonpath.h:97
@ jpiIndexArray
Definition jsonpath.h:87
@ jpiAny
Definition jsonpath.h:88
@ jpiStrRtrim
Definition jsonpath.h:122
@ jpiBigint
Definition jsonpath.h:107
@ jpiBool
Definition jsonpath.h:67
@ jpiType
Definition jsonpath.h:95
@ jpiStrUpper
Definition jsonpath.h:120
@ jpiFloor
Definition jsonpath.h:98
@ jpiStrBtrim
Definition jsonpath.h:123
@ jpiAnyArray
Definition jsonpath.h:85
@ jpiSize
Definition jsonpath.h:96
@ jpiStrReplace
Definition jsonpath.h:118
@ jpiSub
Definition jsonpath.h:79
@ jpiMul
Definition jsonpath.h:80
@ jpiVariable
Definition jsonpath.h:92
@ jpiPlus
Definition jsonpath.h:83
@ jpiStrInitcap
Definition jsonpath.h:124
@ jpiDouble
Definition jsonpath.h:100
@ jpiNumber
Definition jsonpath.h:112
@ jpiStrLtrim
Definition jsonpath.h:121
@ jpiMod
Definition jsonpath.h:82
@ jpiStrSplitPart
Definition jsonpath.h:125
@ 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
@ jpiStrLower
Definition jsonpath.h:119
@ 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)
static JsonPathExecResult executeStringInternalMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
#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:125
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(), executeStringInternalMethod(), 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, jpiStrBtrim, jpiString, jpiStringFunc, jpiStrInitcap, jpiStrLower, jpiStrLtrim, jpiStrReplace, jpiStrRtrim, jpiStrSplitPart, jpiStrUpper, 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 1712 of file jsonpath_exec.c.

1715{
1716 if (jb->type != jbvBinary)
1717 {
1718 Assert(jb->type != jbvArray);
1719 elog(ERROR, "invalid jsonb array value type: %d", jb->type);
1720 }
1721
1722 return executeAnyItem
1723 (cxt, jsp, jb->val.binary.data, found, 1, 1, 1,
1724 false, unwrapElements);
1725}

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

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

3086{
3089 JsonbContainer *jbc;
3098 int64 id;
3099 bool hasNext;
3100
3101 if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
3104 errmsg("jsonpath item method .%s() can only be applied to an object",
3105 jspOperationName(jsp->type)))));
3106
3107 jbc = jb->val.binary.data;
3108
3109 if (!JsonContainerSize(jbc))
3110 return jperNotFound; /* no key-value pairs */
3111
3113
3114 keystr.type = jbvString;
3115 keystr.val.string.val = "key";
3116 keystr.val.string.len = 3;
3117
3118 valstr.type = jbvString;
3119 valstr.val.string.val = "value";
3120 valstr.val.string.len = 5;
3121
3122 idstr.type = jbvString;
3123 idstr.val.string.val = "id";
3124 idstr.val.string.len = 2;
3125
3126 /* construct object id from its base object and offset inside that */
3127 id = jb->type != jbvBinary ? 0 :
3128 (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
3129 id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
3130
3131 idval.type = jbvNumeric;
3132 idval.val.numeric = int64_to_numeric(id);
3133
3134 it = JsonbIteratorInit(jbc);
3135
3136 while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
3137 {
3138 JsonBaseObjectInfo baseObject;
3139 JsonbValue obj;
3141 Jsonb *jsonb;
3142
3143 if (tok != WJB_KEY)
3144 continue;
3145
3146 res = jperOk;
3147
3148 if (!hasNext && !found)
3149 break;
3150
3151 tok = JsonbIteratorNext(&it, &val, true);
3152 Assert(tok == WJB_VALUE);
3153
3154 memset(&ps, 0, sizeof(ps));
3155
3157
3159 pushJsonbValue(&ps, WJB_VALUE, &key);
3160
3163
3166
3168
3169 jsonb = JsonbValueToJsonb(ps.result);
3170
3171 JsonbInitBinary(&obj, jsonb);
3172
3173 baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
3174
3175 res = executeNextItem(cxt, jsp, &next, &obj, found);
3176
3177 cxt->baseObject = baseObject;
3178
3179 if (jperIsError(res))
3180 return res;
3181
3182 if (res == jperOk && !found)
3183 break;
3184 }
3185
3186 return res;
3187}
#define INT64CONST(x)
Definition c.h:630
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 2373 of file jsonpath_exec.c.

2375{
2376 JsonLikeRegexContext *cxt = param;
2377
2378 if (!(str = getScalar(str, jbvString)))
2379 return jpbUnknown;
2380
2381 /* Cache regex text and converted flags. */
2382 if (!cxt->regex)
2383 {
2384 cxt->regex =
2385 cstring_to_text_with_len(jsp->content.like_regex.pattern,
2386 jsp->content.like_regex.patternlen);
2387 (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2388 &(cxt->cflags), NULL);
2389 }
2390
2391 if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2392 str->val.string.len,
2394 return jpbTrue;
2395
2396 return jpbFalse;
2397}
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 1967 of file jsonpath_exec.c.

1969{
1970 JsonbValue *prev;
1971 JsonPathBool res;
1972
1973 prev = cxt->current;
1974 cxt->current = jb;
1975 res = executeBoolItem(cxt, jsp, jb, false);
1976 cxt->current = prev;
1977
1978 return res;
1979}

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

1735{
1736 JsonPathItem elem;
1737 bool hasNext;
1738
1739 if (!cur)
1740 hasNext = next != NULL;
1741 else if (next)
1743 else
1744 {
1745 next = &elem;
1747 }
1748
1749 if (hasNext)
1750 return executeItem(cxt, next, v, found);
1751
1752 if (found)
1753 JsonValueListAppend(found, v);
1754
1755 return jperOk;
1756}
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(), executeStringInternalMethod(), and executeUnaryArithmExpr().

◆ executeNumericItemMethod()

static JsonPathExecResult executeNumericItemMethod ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
bool  unwrap,
PGFunction  func,
JsonValueList found 
)
static

Definition at line 2404 of file jsonpath_exec.c.

2407{
2409 Datum datum;
2411
2412 if (unwrap && JsonbType(jb) == jbvArray)
2413 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
2414
2415 if (!(jb = getScalar(jb, jbvNumeric)))
2418 errmsg("jsonpath item method .%s() can only be applied to a numeric value",
2419 jspOperationName(jsp->type)))));
2420
2421 datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
2422
2423 if (!jspGetNext(jsp, &next) && !found)
2424 return jperOk;
2425
2426 jbv.type = jbvNumeric;
2427 jbv.val.numeric = DatumGetNumeric(datum);
2428
2429 return executeNextItem(cxt, jsp, &next, &jbv, found);
2430}

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

2083{
2088 JsonbValue *lval;
2089 bool error = false;
2090 bool found = false;
2091
2094
2095 /* Left argument is always auto-unwrapped. */
2096 res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
2097 if (jperIsError(res))
2098 {
2099 error = true;
2100 goto exit;
2101 }
2102
2103 if (rarg)
2104 {
2105 /* Right argument is conditionally auto-unwrapped. */
2106 res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
2108 if (jperIsError(res))
2109 {
2110 error = true;
2111 goto exit;
2112 }
2113 }
2114
2116 while ((lval = JsonValueListNext(&lseqit)))
2117 {
2120 bool first = true;
2121
2123 if (rarg)
2125 else
2126 rval = NULL;
2127
2128 /* Loop over right arg sequence or do single pass otherwise */
2129 while (rarg ? (rval != NULL) : first)
2130 {
2131 JsonPathBool res = exec(pred, lval, rval, param);
2132
2133 if (res == jpbUnknown)
2134 {
2135 error = true;
2136 if (jspStrictAbsenceOfErrors(cxt))
2137 {
2138 found = false; /* return unknown, not success */
2139 goto exit;
2140 }
2141 }
2142 else if (res == jpbTrue)
2143 {
2144 found = true;
2145 if (!jspStrictAbsenceOfErrors(cxt))
2146 goto exit;
2147 }
2148
2149 first = false;
2150 if (rarg)
2152 }
2153 }
2154
2155exit:
2158
2159 if (found) /* possible only in strict mode */
2160 return jpbTrue;
2161
2162 if (error) /* possible only in lax mode */
2163 return jpbUnknown;
2164
2165 return jpbFalse;
2166}
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 2349 of file jsonpath_exec.c.

2351{
2352 if (!(whole = getScalar(whole, jbvString)))
2353 return jpbUnknown; /* error */
2354
2356 return jpbUnknown; /* error */
2357
2358 if (whole->val.string.len >= initial->val.string.len &&
2359 !memcmp(whole->val.string.val,
2360 initial->val.string.val,
2361 initial->val.string.len))
2362 return jpbTrue;
2363
2364 return jpbFalse;
2365}

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

Referenced by executeBoolItem().

◆ executeStringInternalMethod()

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

Definition at line 2905 of file jsonpath_exec.c.

2907{
2909 bool hasNext;
2911 JsonPathItem elem;
2912 Datum str; /* Datum representation for the current string
2913 * value. The first argument to internal
2914 * functions */
2915 char *resStr = NULL;
2916
2917 Assert(jsp->type == jpiStrReplace ||
2918 jsp->type == jpiStrLower ||
2919 jsp->type == jpiStrUpper ||
2920 jsp->type == jpiStrLtrim ||
2921 jsp->type == jpiStrRtrim ||
2922 jsp->type == jpiStrBtrim ||
2923 jsp->type == jpiStrInitcap ||
2924 jsp->type == jpiStrSplitPart);
2925
2926 if (!(jb = getScalar(jb, jbvString)))
2929 errmsg("jsonpath item method .%s() can only be applied to a string",
2930 jspOperationName(jsp->type)))));
2931
2932 str = PointerGetDatum(cstring_to_text_with_len(jb->val.string.val, jb->val.string.len));
2933
2934 /* Dispatch to the appropriate internal string function */
2935 switch (jsp->type)
2936 {
2937 case jpiStrReplace:
2938 {
2939 char *from_str,
2940 *to_str;
2941
2942 jspGetLeftArg(jsp, &elem);
2943 if (elem.type != jpiString)
2944 elog(ERROR, "invalid jsonpath item type for .replace() from");
2945
2946 from_str = jspGetString(&elem, NULL);
2947
2948 jspGetRightArg(jsp, &elem);
2949 if (elem.type != jpiString)
2950 elog(ERROR, "invalid jsonpath item type for .replace() to");
2951
2952 to_str = jspGetString(&elem, NULL);
2953
2956 str,
2959 break;
2960 }
2961 case jpiStrLower:
2963 break;
2964 case jpiStrUpper:
2966 break;
2967 case jpiStrLtrim:
2968 case jpiStrRtrim:
2969 case jpiStrBtrim:
2970 {
2973
2974 switch (jsp->type)
2975 {
2976 case jpiStrLtrim:
2977 func1 = ltrim1;
2978 func2 = ltrim;
2979 break;
2980 case jpiStrRtrim:
2981 func1 = rtrim1;
2982 func2 = rtrim;
2983 break;
2984 case jpiStrBtrim:
2985 func1 = btrim1;
2986 func2 = btrim;
2987 break;
2988 default:
2989 break;
2990 }
2991
2992 if (jsp->content.arg)
2993 {
2994 char *characters_str;
2995
2996 jspGetArg(jsp, &elem);
2997 if (elem.type != jpiString)
2998 elog(ERROR, "invalid jsonpath item type for .%s() argument",
2999 jspOperationName(jsp->type));
3000
3005 }
3006 else
3007 {
3010 }
3011 break;
3012 }
3013
3014 case jpiStrInitcap:
3016 break;
3017 case jpiStrSplitPart:
3018 {
3019 char *from_str;
3020 Numeric n;
3021
3022 jspGetLeftArg(jsp, &elem);
3023 if (elem.type != jpiString)
3024 elog(ERROR, "invalid jsonpath item type for .split_part()");
3025
3026 from_str = jspGetString(&elem, NULL);
3027
3028 jspGetRightArg(jsp, &elem);
3029 if (elem.type != jpiNumeric)
3030 elog(ERROR, "invalid jsonpath item type for .split_part()");
3031
3032 n = jspGetNumeric(&elem);
3033
3036 str,
3039 break;
3040 }
3041 default:
3042 elog(ERROR, "unsupported jsonpath item type: %d", jsp->type);
3043 }
3044
3045 if (resStr)
3046 res = jperOk;
3047
3048 hasNext = jspGetNext(jsp, &elem);
3049
3050 if (!hasNext && !found)
3051 return res;
3052
3053 jbv.type = jbvString;
3054 jbv.val.string.val = resStr;
3055 jbv.val.string.len = strlen(resStr);
3056
3057 return executeNextItem(cxt, jsp, &elem, &jbv, found);
3058}
Datum numeric_int4(PG_FUNCTION_ARGS)
Definition numeric.c:4398
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define TextDatumGetCString(d)
Definition builtins.h:99
Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
Definition fmgr.c:814
Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
Definition fmgr.c:794
Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition fmgr.c:836
Datum ltrim(PG_FUNCTION_ARGS)
Datum lower(PG_FUNCTION_ARGS)
Datum initcap(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
Datum rtrim(PG_FUNCTION_ARGS)
Datum ltrim1(PG_FUNCTION_ARGS)
Datum btrim1(PG_FUNCTION_ARGS)
Datum rtrim1(PG_FUNCTION_ARGS)
Datum btrim(PG_FUNCTION_ARGS)
Datum split_part(PG_FUNCTION_ARGS)
Definition varlena.c:3506
Datum replace_text(PG_FUNCTION_ARGS)
Definition varlena.c:3134

References Assert, btrim(), btrim1(), cstring_to_text_with_len(), CStringGetTextDatum, DirectFunctionCall1, DirectFunctionCall1Coll(), DirectFunctionCall2Coll(), DirectFunctionCall3Coll(), elog, ereport, errcode(), errmsg, ERROR, executeNextItem(), fb(), getScalar(), initcap(), jbvString, jperNotFound, jperOk, jpiNumeric, jpiStrBtrim, jpiString, jpiStrInitcap, jpiStrLower, jpiStrLtrim, jpiStrReplace, jpiStrRtrim, jpiStrSplitPart, jpiStrUpper, jspGetArg(), jspGetLeftArg(), jspGetNext(), jspGetNumeric(), jspGetRightArg(), jspGetString(), jspOperationName(), lower(), ltrim(), ltrim1(), numeric_int4(), NumericGetDatum(), PointerGetDatum(), replace_text(), RETURN_ERROR, rtrim(), rtrim1(), split_part(), str, TextDatumGetCString, JsonPathItem::type, and upper().

Referenced by executeItemOptUnwrapTarget().

◆ executeUnaryArithmExpr()

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

Definition at line 2270 of file jsonpath_exec.c.

2272{
2275 JsonPathItem elem;
2278 JsonbValue *val;
2279 bool hasNext;
2280
2282
2283 jspGetArg(jsp, &elem);
2284 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
2285
2286 if (jperIsError(jper))
2287 goto exit;
2288
2290
2291 hasNext = jspGetNext(jsp, &elem);
2292
2294 while ((val = JsonValueListNext(&it)))
2295 {
2296 if ((val = getScalar(val, jbvNumeric)))
2297 {
2298 if (!found && !hasNext)
2299 {
2300 jper = jperOk;
2301 goto exit;
2302 }
2303 }
2304 else
2305 {
2306 if (!found && !hasNext)
2307 continue; /* skip non-numerics processing */
2308
2312 errmsg("operand of unary jsonpath operator %s is not a numeric value",
2313 jspOperationName(jsp->type)))));
2314 }
2315
2316 if (func)
2317 val->val.numeric =
2319 NumericGetDatum(val->val.numeric)));
2320
2321 jper2 = executeNextItem(cxt, jsp, &elem, val, found);
2322
2323 if (jperIsError(jper2))
2324 {
2325 jper = jper2;
2326 goto exit;
2327 }
2328
2329 if (jper2 == jperOk)
2330 {
2331 jper = jperOk;
2332 if (!found)
2333 goto exit;
2334 }
2335 }
2336
2337exit:
2339
2340 return jper;
2341}

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

3725{
3726 JsonbValue *jbv;
3727 JsonValueList found;
3731
3732 JsonValueListInit(&found);
3733
3734 res = executeItem(cxt, jsp, jb, &found);
3735
3736 if (jperIsError(res))
3737 {
3738 JsonValueListClear(&found);
3739 return res;
3740 }
3741
3742 if (!JsonValueListIsSingleton(&found) ||
3744 {
3745 JsonValueListClear(&found);
3748 errmsg("jsonpath array subscript is not a single numeric value"))));
3749 }
3750
3752 NumericGetDatum(jbv->val.numeric),
3753 Int32GetDatum(0));
3754
3756 (Node *) &escontext);
3757
3758 JsonValueListClear(&found);
3759
3760 if (escontext.error_occurred)
3763 errmsg("jsonpath array subscript is out of integer range"))));
3764
3765 return jperOk;
3766}
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition numeric.c:1582

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

3224{
3225 switch (item->type)
3226 {
3227 case jpiNull:
3228 value->type = jbvNull;
3229 break;
3230 case jpiBool:
3231 value->type = jbvBool;
3232 value->val.boolean = jspGetBool(item);
3233 break;
3234 case jpiNumeric:
3235 value->type = jbvNumeric;
3236 value->val.numeric = jspGetNumeric(item);
3237 break;
3238 case jpiString:
3239 value->type = jbvString;
3240 value->val.string.val = jspGetString(item,
3241 &value->val.string.len);
3242 break;
3243 case jpiVariable:
3244 getJsonPathVariable(cxt, item, value);
3245 return;
3246 default:
3247 elog(ERROR, "unexpected jsonpath item type");
3248 }
3249}
bool jspGetBool(JsonPathItem *v)
Definition jsonpath.c:1311
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 3255 of file jsonpath_exec.c.

3257{
3258 JsonPathVariable *var = NULL;
3259 List *vars = cxt;
3260 ListCell *lc;
3262 int id = 1;
3263
3264 foreach(lc, vars)
3265 {
3266 JsonPathVariable *curvar = lfirst(lc);
3267
3268 if (curvar->namelen == varNameLen &&
3269 strncmp(curvar->name, varName, varNameLen) == 0)
3270 {
3271 var = curvar;
3272 break;
3273 }
3274
3275 id++;
3276 }
3277
3278 if (var == NULL)
3279 {
3280 *baseObjectId = -1;
3281 return NULL;
3282 }
3283
3285 if (var->isnull)
3286 {
3287 *baseObjectId = 0;
3288 result->type = jbvNull;
3289 }
3290 else
3291 JsonItemFromDatum(var->value, var->typid, var->typmod, result);
3292
3293 *baseObject = *result;
3294 *baseObjectId = id;
3295
3296 return result;
3297}
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, result, 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 3405 of file jsonpath_exec.c.

3407{
3408 char *varName;
3409 int varNameLength;
3410 JsonbValue baseObject;
3411 int baseObjectId;
3412 JsonbValue *v;
3413
3415 varName = jspGetString(variable, &varNameLength);
3416
3417 if (cxt->vars == NULL ||
3418 (v = cxt->getVar(cxt->vars, varName, varNameLength,
3419 &baseObject, &baseObjectId)) == NULL)
3420 ereport(ERROR,
3422 errmsg("could not find jsonpath variable \"%s\"",
3423 pnstrdup(varName, varNameLength))));
3424
3425 if (baseObjectId > 0)
3426 {
3427 *value = *v;
3428 setBaseObject(cxt, &baseObject, baseObjectId);
3429 }
3430}
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 3437 of file jsonpath_exec.c.

3439{
3440 Jsonb *vars = varsJsonb;
3441 JsonbValue tmp;
3443
3444 tmp.type = jbvString;
3445 tmp.val.string.val = varName;
3446 tmp.val.string.len = varNameLength;
3447
3449
3450 if (result == NULL)
3451 {
3452 *baseObjectId = -1;
3453 return NULL;
3454 }
3455
3456 *baseObjectId = 1;
3457 JsonbInitBinary(baseObject, vars);
3458
3459 return result;
3460}

References fb(), findJsonbValueFromContainer(), JB_FOBJECT, jbvString, JsonbInitBinary(), result, 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 4399 of file jsonpath_exec.c.

4400{
4402
4404 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4405 result = (JsonTableExecContext *) state->opaque;
4407 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4408
4409 return result;
4410}
#define JSON_TABLE_EXEC_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition nodes.h:164

References elog, ERROR, IsA, JSON_TABLE_EXEC_CONTEXT_MAGIC, and result.

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

◆ getScalar()

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

Definition at line 3950 of file jsonpath_exec.c.

3951{
3952 /* Scalars should be always extracted during jsonpath execution. */
3953 Assert(scalar->type != jbvBinary ||
3954 !JsonContainerIsScalar(scalar->val.binary.data));
3955
3956 return scalar->type == type ? scalar : NULL;
3957}
#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(), executeStringInternalMethod(), executeUnaryArithmExpr(), and getArrayIndex().

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 455 of file jsonpath_exec.c.

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

428{
432 Jsonb *vars = NULL;
433 bool silent = true;
434
435 if (PG_NARGS() == 4)
436 {
439 }
440
443 jb, !silent, NULL, tz);
444
447
448 if (jperIsError(res))
450
451 PG_RETURN_BOOL(res == jperOk);
452}
#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 472 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 461 of file jsonpath_exec.c.

462{
463 return jsonb_path_exists_internal(fcinfo, true);
464}

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 527 of file jsonpath_exec.c.

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

485{
488 Jsonb *vars = NULL;
489 bool silent = true;
490 JsonValueList found;
491
492 if (PG_NARGS() == 4)
493 {
496 }
497
498 JsonValueListInit(&found);
499
502 jb, !silent, &found, tz);
503
506
507 if (JsonValueListIsSingleton(&found))
508 {
510
511 if (jbv->type == jbvBool)
512 PG_RETURN_BOOL(jbv->val.boolean);
513
514 if (jbv->type == jbvNull)
516 }
517
518 if (!silent)
521 errmsg("single boolean result is expected")));
522
524}

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

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 533 of file jsonpath_exec.c.

534{
535 return jsonb_path_match_internal(fcinfo, true);
536}

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 606 of file jsonpath_exec.c.

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

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

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 679 of file jsonpath_exec.c.

680{
681 return jsonb_path_query_first_internal(fcinfo, false);
682}
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 685 of file jsonpath_exec.c.

686{
687 return jsonb_path_query_first_internal(fcinfo, true);
688}

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 556 of file jsonpath_exec.c.

557{
560 JsonbValue *v;
561
562 if (SRF_IS_FIRSTCALL())
563 {
564 JsonPath *jp;
565 Jsonb *jb;
566 Jsonb *vars;
567 bool silent;
568 MemoryContext oldcontext;
569 JsonValueList *found;
570
572 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
573
578
580 JsonValueListInit(found);
581
584 jb, !silent, found, tz);
585
587 JsonValueListInitIterator(found, iter);
588
589 funcctx->user_fctx = iter;
590
591 MemoryContextSwitchTo(oldcontext);
592 }
593
595 iter = funcctx->user_fctx;
596
597 v = JsonValueListNext(iter);
598
599 if (v == NULL)
601
603}
#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 612 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3489 of file jsonpath_exec.c.

3490{
3491 Assert(jb->type != jbvArray);
3492
3493 if (jb->type == jbvBinary)
3494 {
3495 JsonbContainer *jbc = jb->val.binary.data;
3496
3498 return JsonContainerSize(jbc);
3499 }
3500
3501 return -1;
3502}
#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 3913 of file jsonpath_exec.c.

3914{
3915 jbv->type = jbvBinary;
3916 jbv->val.binary.data = &jb->root;
3917 jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3918
3919 return jbv;
3920}
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 3926 of file jsonpath_exec.c.

3927{
3928 int type = jb->type;
3929
3930 if (jb->type == jbvBinary)
3931 {
3932 JsonbContainer *jbc = jb->val.binary.data;
3933
3934 /* Scalars should be always extracted during jsonpath execution. */
3936
3937 if (JsonContainerIsObject(jbc))
3938 type = jbvObject;
3939 else if (JsonContainerIsArray(jbc))
3940 type = jbvArray;
3941 else
3942 elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
3943 }
3944
3945 return type;
3946}
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 3395 of file jsonpath_exec.c.

3396{
3397 jbv->type = jbvNumeric;
3398 jbv->val.numeric = DatumGetNumeric(num);
3399}

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

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

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

Definition at line 3313 of file jsonpath_exec.c.

3314{
3315 switch (typid)
3316 {
3317 case BOOLOID:
3318 res->type = jbvBool;
3319 res->val.boolean = DatumGetBool(val);
3320 break;
3321 case NUMERICOID:
3323 break;
3324 case INT2OID:
3326 break;
3327 case INT4OID:
3329 break;
3330 case INT8OID:
3332 break;
3333 case FLOAT4OID:
3335 break;
3336 case FLOAT8OID:
3338 break;
3339 case TEXTOID:
3340 case VARCHAROID:
3341 res->type = jbvString;
3342 res->val.string.val = VARDATA_ANY(DatumGetPointer(val));
3343 res->val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(val));
3344 break;
3345 case DATEOID:
3346 case TIMEOID:
3347 case TIMETZOID:
3348 case TIMESTAMPOID:
3349 case TIMESTAMPTZOID:
3350 res->type = jbvDatetime;
3351 res->val.datetime.value = val;
3352 res->val.datetime.typid = typid;
3353 res->val.datetime.typmod = typmod;
3354 res->val.datetime.tz = 0;
3355 break;
3356 case JSONBOID:
3357 {
3358 JsonbValue *jbv = res;
3360
3361 if (JsonContainerIsScalar(&jb->root))
3362 {
3364
3365 result = JsonbExtractScalar(&jb->root, jbv);
3366 Assert(result);
3367 }
3368 else
3370 break;
3371 }
3372 case JSONOID:
3373 {
3375 char *str = text_to_cstring(txt);
3376 Jsonb *jb;
3377
3380 pfree(str);
3381
3383 break;
3384 }
3385 default:
3386 ereport(ERROR,
3388 errmsg("could not convert value of type %s to jsonpath",
3389 format_type_be(typid)));
3390 }
3391}
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4637
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4489
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
#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, result, 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 4202 of file jsonpath_exec.c.

4203{
4205
4206 res = executeJsonPath(jp, vars,
4208 DatumGetJsonbP(jb), !error, NULL, true);
4209
4210 Assert(error || !jperIsError(res));
4211
4212 if (error && jperIsError(res))
4213 *error = true;
4214
4215 return res == jperOk;
4216}
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 4225 of file jsonpath_exec.c.

4228{
4229 bool wrap;
4230 JsonValueList found;
4232
4233 JsonValueListInit(&found);
4234
4235 res = executeJsonPath(jp, vars,
4237 DatumGetJsonbP(jb), !error, &found, true);
4238 Assert(error || !jperIsError(res));
4239 if (error && jperIsError(res))
4240 {
4241 *error = true;
4242 *empty = false;
4243 return (Datum) 0;
4244 }
4245
4246 /*
4247 * Determine whether to wrap the result in a JSON array or not.
4248 *
4249 * If the returned JsonValueList is empty, no wrapping is necessary.
4250 *
4251 * If the wrapper mode is JSW_NONE or JSW_UNSPEC, wrapping is explicitly
4252 * disabled. This enforces a WITHOUT WRAPPER clause, which is also the
4253 * default when no WRAPPER clause is specified.
4254 *
4255 * If the mode is JSW_UNCONDITIONAL, wrapping is enforced regardless of
4256 * the number of SQL/JSON items, enforcing a WITH WRAPPER or WITH
4257 * UNCONDITIONAL WRAPPER clause.
4258 *
4259 * For JSW_CONDITIONAL, wrapping occurs only if there is more than one
4260 * SQL/JSON item in the list, enforcing a WITH CONDITIONAL WRAPPER clause.
4261 */
4262 if (JsonValueListIsEmpty(&found))
4263 wrap = false;
4264 else if (wrapper == JSW_NONE || wrapper == JSW_UNSPEC)
4265 wrap = false;
4266 else if (wrapper == JSW_UNCONDITIONAL)
4267 wrap = true;
4268 else if (wrapper == JSW_CONDITIONAL)
4270 else
4271 {
4272 elog(ERROR, "unrecognized json wrapper %d", (int) wrapper);
4273 wrap = false;
4274 }
4275
4276 if (wrap)
4278
4279 /* No wrapping means at most one item is expected. */
4281 {
4282 if (error)
4283 {
4284 *error = true;
4285 return (Datum) 0;
4286 }
4287
4288 if (column_name)
4289 ereport(ERROR,
4291 errmsg("JSON path expression for column \"%s\" must return single item when no wrapper is requested",
4292 column_name),
4293 errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
4294 else
4295 ereport(ERROR,
4297 errmsg("JSON path expression in JSON_QUERY must return single item when no wrapper is requested"),
4298 errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
4299 }
4300
4301 if (!JsonValueListIsEmpty(&found))
4303
4304 *empty = true;
4305 return PointerGetDatum(NULL);
4306}
static bool JsonValueListHasMultipleItems(const JsonValueList *jvl)
@ JSW_UNCONDITIONAL
Definition primnodes.h:1781
@ JSW_CONDITIONAL
Definition primnodes.h:1780
@ JSW_UNSPEC
Definition primnodes.h:1778
@ JSW_NONE
Definition primnodes.h:1779

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

4317{
4318 JsonbValue *res;
4319 JsonValueList found;
4321
4322 JsonValueListInit(&found);
4323
4326 !error, &found, true);
4327
4329
4330 if (error && jperIsError(jper))
4331 {
4332 *error = true;
4333 *empty = false;
4334 return NULL;
4335 }
4336
4337 *empty = JsonValueListIsEmpty(&found);
4338
4339 if (*empty)
4340 return NULL;
4341
4342 /* JSON_VALUE expects to get only singletons. */
4344 {
4345 if (error)
4346 {
4347 *error = true;
4348 return NULL;
4349 }
4350
4351 if (column_name)
4352 ereport(ERROR,
4354 errmsg("JSON path expression for column \"%s\" must return single scalar item",
4355 column_name)));
4356 else
4357 ereport(ERROR,
4359 errmsg("JSON path expression in JSON_VALUE must return single scalar item")));
4360 }
4361
4362 res = copyJsonbValue(JsonValueListHead(&found));
4363 if (res->type == jbvBinary && JsonContainerIsScalar(res->val.binary.data))
4364 JsonbExtractScalar(res->val.binary.data, res);
4365
4366 /* JSON_VALUE expects to get only scalars. */
4367 if (!IsAJsonbScalar(res))
4368 {
4369 if (error)
4370 {
4371 *error = true;
4372 return NULL;
4373 }
4374
4375 if (column_name)
4376 ereport(ERROR,
4378 errmsg("JSON path expression for column \"%s\" must return single scalar item",
4379 column_name)));
4380 else
4381 ereport(ERROR,
4383 errmsg("JSON path expression in JSON_VALUE must return single scalar item")));
4384 }
4385
4386 if (res->type == jbvNull)
4387 return NULL;
4388
4389 return res;
4390}
#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 4484 of file jsonpath_exec.c.

4485{
4487 GetJsonTableExecContext(state, "JsonTableDestroyOpaque");
4488
4489 /* not valid anymore */
4490 cxt->magic = 0;
4491
4492 state->opaque = NULL;
4493}
static JsonTableExecContext * GetJsonTableExecContext(TableFuncScanState *state, const char *fname)

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

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4747 of file jsonpath_exec.c.

4748{
4750 GetJsonTableExecContext(state, "JsonTableFetchRow");
4751
4753}
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 4763 of file jsonpath_exec.c.

4765{
4767 GetJsonTableExecContext(state, "JsonTableGetValue");
4768 ExprContext *econtext = state->ss.ps.ps_ExprContext;
4769 ExprState *estate = list_nth(state->colvalexprs, colnum);
4770 JsonTablePlanState *planstate = cxt->colplanstates[colnum];
4771 JsonTablePlanRowSource *current = &planstate->current;
4772 Datum result;
4773
4774 /* Row pattern value is NULL */
4775 if (current->isnull)
4776 {
4777 result = (Datum) 0;
4778 *isnull = true;
4779 }
4780 /* Evaluate JsonExpr. */
4781 else if (estate)
4782 {
4784 bool saved_caseIsNull = econtext->caseValue_isNull;
4785
4786 /* Pass the row pattern value via CaseTestExpr. */
4787 econtext->caseValue_datum = current->value;
4788 econtext->caseValue_isNull = false;
4789
4790 result = ExecEvalExpr(estate, econtext, isnull);
4791
4792 econtext->caseValue_datum = saved_caseValue;
4794 }
4795 /* ORDINAL column */
4796 else
4797 {
4798 result = Int32GetDatum(planstate->ordinal);
4799 *isnull = false;
4800 }
4801
4802 return result;
4803}
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:403
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
bool caseValue_isNull
Definition execnodes.h:314
Datum caseValue_datum
Definition execnodes.h:312
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, result, and JsonTablePlanRowSource::value.

◆ JsonTableInitOpaque()

static void JsonTableInitOpaque ( TableFuncScanState state,
int  natts 
)
static

Definition at line 4420 of file jsonpath_exec.c.

4421{
4423 PlanState *ps = &state->ss.ps;
4425 TableFunc *tf = tfs->tablefunc;
4426 JsonTablePlan *rootplan = (JsonTablePlan *) tf->plan;
4427 JsonExpr *je = castNode(JsonExpr, tf->docexpr);
4428 List *args = NIL;
4429
4431 cxt->magic = JSON_TABLE_EXEC_CONTEXT_MAGIC;
4432
4433 /*
4434 * Evaluate JSON_TABLE() PASSING arguments to be passed to the jsonpath
4435 * executor via JsonPathVariables.
4436 */
4437 if (state->passingvalexprs)
4438 {
4441
4442 Assert(list_length(state->passingvalexprs) ==
4443 list_length(je->passing_names));
4444 forboth(exprlc, state->passingvalexprs,
4445 namelc, je->passing_names)
4446 {
4450
4451 var->name = pstrdup(name->sval);
4452 var->namelen = strlen(var->name);
4453 var->typid = exprType((Node *) state->expr);
4454 var->typmod = exprTypmod((Node *) state->expr);
4455
4456 /*
4457 * Evaluate the expression and save the value to be returned by
4458 * GetJsonPathVar().
4459 */
4460 var->value = ExecEvalExpr(state, ps->ps_ExprContext,
4461 &var->isnull);
4462
4463 args = lappend(args, var);
4464 }
4465 }
4466
4467 cxt->colplanstates = palloc_array(JsonTablePlanState *, list_length(tf->colvalexprs));
4468
4469 /*
4470 * Initialize plan for the root path and, recursively, also any child
4471 * plans that compute the NESTED paths.
4472 */
4473 cxt->rootplanstate = JsonTableInitPlan(cxt, rootplan, NULL, args,
4475
4476 state->opaque = cxt;
4477}
#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:550
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 4501 of file jsonpath_exec.c.

4504{
4506
4507 planstate->plan = plan;
4508 planstate->parent = parentstate;
4509 JsonValueListInit(&planstate->found);
4510
4512 {
4514 int i;
4515
4516 planstate->path = DatumGetJsonPathP(scan->path->value->constvalue);
4517 planstate->args = args;
4518 planstate->mcxt = AllocSetContextCreate(mcxt, "JsonTableExecContext",
4520
4521 /* No row pattern evaluated yet. */
4522 planstate->current.value = PointerGetDatum(NULL);
4523 planstate->current.isnull = true;
4524
4525 for (i = scan->colMin; i >= 0 && i <= scan->colMax; i++)
4526 cxt->colplanstates[i] = planstate;
4527
4528 planstate->nested = scan->child ?
4529 JsonTableInitPlan(cxt, scan->child, planstate, args, mcxt) : NULL;
4530 }
4531 else if (IsA(plan, JsonTableSiblingJoin))
4532 {
4534
4535 planstate->left = JsonTableInitPlan(cxt, join->lplan, parentstate,
4536 args, mcxt);
4537 planstate->right = JsonTableInitPlan(cxt, join->rplan, parentstate,
4538 args, mcxt);
4539 }
4540
4541 return planstate;
4542}
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:164
JsonTablePath * path
Definition primnodes.h:1926
Const * value
Definition primnodes.h:1899
struct JsonTablePlanState * left
JsonValueList found
struct JsonTablePlanState * nested
MemoryContext mcxt
struct JsonTablePlanState * parent
JsonTablePlan * plan
struct JsonTablePlanState * right
JsonTablePlan * rplan
Definition primnodes.h:1956
JsonTablePlan * lplan
Definition primnodes.h:1955

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

4721{
4722
4723 /* Fetch row from left sibling. */
4724 if (!JsonTablePlanNextRow(planstate->left))
4725 {
4726 /*
4727 * Left sibling ran out of rows, so start fetching from the right
4728 * sibling.
4729 */
4730 if (!JsonTablePlanNextRow(planstate->right))
4731 {
4732 /* Right sibling ran out of row, so there are more rows. */
4733 return false;
4734 }
4735 }
4736
4737 return true;
4738}

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

Referenced by JsonTablePlanNextRow().

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4602 of file jsonpath_exec.c.

4603{
4604 if (IsA(planstate->plan, JsonTablePathScan))
4605 return JsonTablePlanScanNextRow(planstate);
4606 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4607 return JsonTablePlanJoinNextRow(planstate);
4608 else
4609 elog(ERROR, "invalid JsonTablePlan %d", (int) planstate->plan->type);
4610
4611 Assert(false);
4612 /* Appease compiler */
4613 return false;
4614}
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 4629 of file jsonpath_exec.c.

4630{
4631 JsonbValue *jbv;
4633
4634 /*
4635 * If planstate already has an active row and there is a nested plan,
4636 * check if it has an active row to join with the former.
4637 */
4638 if (!planstate->current.isnull)
4639 {
4640 if (planstate->nested && JsonTablePlanNextRow(planstate->nested))
4641 return true;
4642 }
4643
4644 /* Fetch new row from the list of found values to set as active. */
4645 jbv = JsonValueListNext(&planstate->iter);
4646
4647 /* End of list? */
4648 if (jbv == NULL)
4649 {
4650 planstate->current.value = PointerGetDatum(NULL);
4651 planstate->current.isnull = true;
4652 return false;
4653 }
4654
4655 /*
4656 * Set current row item for subsequent JsonTableGetValue() calls for
4657 * evaluating individual columns.
4658 */
4659 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4661 planstate->current.isnull = false;
4663
4664 /* Next row! */
4665 planstate->ordinal++;
4666
4667 /* Process nested plan(s), if any. */
4668 if (planstate->nested)
4669 {
4670 /* Re-evaluate the nested path using the above parent row. */
4671 JsonTableResetNestedPlan(planstate->nested);
4672
4673 /*
4674 * Now fetch the nested plan's current row to be joined against the
4675 * parent row. Any further nested plans' paths will be re-evaluated
4676 * recursively, level at a time, after setting each nested plan's
4677 * current row.
4678 */
4679 (void) JsonTablePlanNextRow(planstate->nested);
4680 }
4681
4682 /* There are more rows. */
4683 return true;
4684}
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 4691 of file jsonpath_exec.c.

4692{
4693 /* This better be a child plan. */
4694 Assert(planstate->parent != NULL);
4695 if (IsA(planstate->plan, JsonTablePathScan))
4696 {
4697 JsonTablePlanState *parent = planstate->parent;
4698
4699 if (!parent->current.isnull)
4700 JsonTableResetRowPattern(planstate, parent->current.value);
4701
4702 /*
4703 * If this plan itself has a child nested plan, it will be reset when
4704 * the caller calls JsonTablePlanNextRow() on this plan.
4705 */
4706 }
4707 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4708 {
4709 JsonTableResetNestedPlan(planstate->left);
4710 JsonTableResetNestedPlan(planstate->right);
4711 }
4712}
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 4562 of file jsonpath_exec.c.

4563{
4564 JsonTablePathScan *scan = castNode(JsonTablePathScan, planstate->plan);
4567 Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
4568
4569 JsonValueListClear(&planstate->found);
4570
4571 MemoryContextResetOnly(planstate->mcxt);
4572
4573 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4574
4575 res = executeJsonPath(planstate->path, planstate->args,
4577 js, scan->errorOnError,
4578 &planstate->found,
4579 true);
4580
4582
4583 if (jperIsError(res))
4584 {
4585 Assert(!scan->errorOnError);
4586 JsonValueListClear(&planstate->found);
4587 }
4588
4589 /* Reset plan iterator to the beginning of the item list */
4590 JsonValueListInitIterator(&planstate->found, &planstate->iter);
4591 planstate->current.value = PointerGetDatum(NULL);
4592 planstate->current.isnull = true;
4593 planstate->ordinal = 0;
4594}
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 3813 of file jsonpath_exec.c.

3814{
3815 JsonValueList *last = jvl->last;
3816
3817 if (last->nitems < last->maxitems)
3818 {
3819 /* there's still room in the last existing chunk */
3820 last->items[last->nitems] = *jbv;
3821 last->nitems++;
3822 }
3823 else
3824 {
3825 /* need a new last chunk */
3827 int nxtsize;
3828
3829 nxtsize = last->maxitems * 2; /* double the size with each chunk */
3830 nxtsize = Max(nxtsize, MIN_EXTRA_JVL_ITEMS); /* but at least this */
3832 nxtsize * sizeof(JsonbValue));
3833 nxt->nitems = 1;
3834 nxt->maxitems = nxtsize;
3835 nxt->next = NULL;
3836 nxt->items[0] = *jbv;
3837 last->next = nxt;
3838 jvl->last = nxt;
3839 }
3840}
#define Max(x, y)
Definition c.h:1085
#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 3795 of file jsonpath_exec.c.

3796{
3798
3799 /* Release any extra chunks */
3800 for (JsonValueList *chunk = jvl->next; chunk != NULL; chunk = nxt)
3801 {
3802 nxt = chunk->next;
3803 pfree(chunk);
3804 }
3805 /* ... and reset to empty */
3806 jvl->nitems = 0;
3807 Assert(jvl->maxitems == BASE_JVL_ITEMS);
3808 jvl->next = NULL;
3809 jvl->last = jvl;
3810}
#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 3861 of file jsonpath_exec.c.

3862{
3863#if BASE_JVL_ITEMS > 1
3864 /* We need not examine extra chunks in this case */
3865 return (jvl->nitems > 1);
3866#else
3867 return (jvl->nitems == 1 && jvl->next != NULL);
3868#endif
3869}

References fb().

Referenced by JsonPathQuery(), and JsonPathValue().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 3872 of file jsonpath_exec.c.

3873{
3874 Assert(jvl->nitems > 0);
3875 return &jvl->items[0];
3876}

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

3884{
3885 it->chunk = jvl;
3886 it->nextitem = 0;
3887}

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

3844{
3845 /* We need not examine extra chunks for this */
3846 return (jvl->nitems == 0);
3847}

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

3851{
3852#if BASE_JVL_ITEMS > 1
3853 /* We need not examine extra chunks in this case */
3854 return (jvl->nitems == 1);
3855#else
3856 return (jvl->nitems == 1 && jvl->next == NULL);
3857#endif
3858}

References fb().

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

◆ JsonValueListNext()

static JsonbValue * JsonValueListNext ( JsonValueListIterator it)
static

Definition at line 3894 of file jsonpath_exec.c.

3895{
3896 if (it->chunk == NULL)
3897 return NULL;
3898 if (it->nextitem >= it->chunk->nitems)
3899 {
3900 it->chunk = it->chunk->next;
3901 if (it->chunk == NULL)
3902 return NULL;
3903 it->nextitem = 0;
3904 Assert(it->chunk->nitems > 0);
3905 }
3906 return &it->chunk->items[it->nextitem++];
3907}

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

3771{
3772 JsonBaseObjectInfo baseObject = cxt->baseObject;
3773
3774 cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
3775 (JsonbContainer *) jbv->val.binary.data;
3776 cxt->baseObject.id = id;
3777
3778 return baseObject;
3779}

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

3962{
3963 JsonbInState ps = {0};
3965 JsonbValue *jbv;
3966
3968
3970 while ((jbv = JsonValueListNext(&it)))
3972
3974
3975 return ps.result;
3976}
@ 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 400 of file jsonpath_exec.c.

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

Referenced by ExecInitTableFuncScan().