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 void JsonTableRescan (JsonTablePlanState *planstate)
 
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 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 254 of file jsonpath_exec.c.

◆ jspAutoUnwrap

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

Definition at line 272 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 273 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 274 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

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

Definition at line 271 of file jsonpath_exec.c.

◆ jspThrowErrors

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

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

279 { \
280 if (jspThrowErrors(cxt)) \
281 throw_error; \
282 else \
284} while (0)

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 290 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 286 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 3202 of file jsonpath_exec.c.

3204{
3207
3208 if (!jspGetNext(jsp, &next) && !found)
3209 return jperOk; /* found singleton boolean value */
3210
3211 if (res == jpbUnknown)
3212 {
3213 jbv.type = jbvNull;
3214 }
3215 else
3216 {
3217 jbv.type = jbvBool;
3218 jbv.val.boolean = res == jpbTrue;
3219 }
3220
3221 return executeNextItem(cxt, jsp, &next, &jbv, found);
3222}
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 3525 of file jsonpath_exec.c.

3527{
3528 int cmp;
3529
3530 cmp = memcmp(s1, s2, Min(len1, len2));
3531
3532 if (cmp != 0)
3533 return cmp;
3534
3535 if (len1 == len2)
3536 return 0;
3537
3538 return len1 < len2 ? -1 : 1;
3539}
#define Min(x, y)
Definition c.h:1131
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 4000 of file jsonpath_exec.c.

4001{
4002 checkTimezoneIsUsedForCast(useTz, "time", "timetz");
4003
4004 return DirectFunctionCall1(time_timetz, time);
4005}
Datum time_timetz(PG_FUNCTION_ARGS)
Definition date.c:2952
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
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 3988 of file jsonpath_exec.c.

3989{
3990 if (!useTz)
3991 ereport(ERROR,
3993 errmsg("cannot convert value from %s to %s without time zone usage",
3994 type1, type2),
3995 errhint("Use *_tz() function for time zone support.")));
3996}
int errcode(int sqlerrcode)
Definition elog.c:875
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 4012 of file jsonpath_exec.c.

4013{
4015}
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition date.c:764

References date_cmp_timestamp_internal(), and fb().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 4021 of file jsonpath_exec.c.

4022{
4023 checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
4024
4026}
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition date.c:845

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

4033{
4034 checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
4035
4037}
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition timestamp.c:2375

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

4047{
4049
4050 *cast_error = false;
4051
4052 switch (typid1)
4053 {
4054 case DATEOID:
4055 switch (typid2)
4056 {
4057 case DATEOID:
4058 cmpfunc = date_cmp;
4059
4060 break;
4061
4062 case TIMESTAMPOID:
4065 useTz);
4066
4067 case TIMESTAMPTZOID:
4070 useTz);
4071
4072 case TIMEOID:
4073 case TIMETZOID:
4074 *cast_error = true; /* uncomparable types */
4075 return 0;
4076
4077 default:
4078 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4079 typid2);
4080 }
4081 break;
4082
4083 case TIMEOID:
4084 switch (typid2)
4085 {
4086 case TIMEOID:
4087 cmpfunc = time_cmp;
4088
4089 break;
4090
4091 case TIMETZOID:
4092 val1 = castTimeToTimeTz(val1, useTz);
4094
4095 break;
4096
4097 case DATEOID:
4098 case TIMESTAMPOID:
4099 case TIMESTAMPTZOID:
4100 *cast_error = true; /* uncomparable types */
4101 return 0;
4102
4103 default:
4104 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4105 typid2);
4106 }
4107 break;
4108
4109 case TIMETZOID:
4110 switch (typid2)
4111 {
4112 case TIMEOID:
4113 val2 = castTimeToTimeTz(val2, useTz);
4115
4116 break;
4117
4118 case TIMETZOID:
4120
4121 break;
4122
4123 case DATEOID:
4124 case TIMESTAMPOID:
4125 case TIMESTAMPTZOID:
4126 *cast_error = true; /* uncomparable types */
4127 return 0;
4128
4129 default:
4130 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4131 typid2);
4132 }
4133 break;
4134
4135 case TIMESTAMPOID:
4136 switch (typid2)
4137 {
4138 case DATEOID:
4141 useTz);
4142
4143 case TIMESTAMPOID:
4145
4146 break;
4147
4148 case TIMESTAMPTZOID:
4151 useTz);
4152
4153 case TIMEOID:
4154 case TIMETZOID:
4155 *cast_error = true; /* uncomparable types */
4156 return 0;
4157
4158 default:
4159 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4160 typid2);
4161 }
4162 break;
4163
4164 case TIMESTAMPTZOID:
4165 switch (typid2)
4166 {
4167 case DATEOID:
4170 useTz);
4171
4172 case TIMESTAMPOID:
4175 useTz);
4176
4177 case TIMESTAMPTZOID:
4179
4180 break;
4181
4182 case TIMEOID:
4183 case TIMETZOID:
4184 *cast_error = true; /* uncomparable types */
4185 return 0;
4186
4187 default:
4188 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4189 typid2);
4190 }
4191 break;
4192
4193 default:
4194 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
4195 }
4196
4197 if (*cast_error)
4198 return 0; /* cast error */
4199
4201}
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition timestamp.c:2282
Datum date_cmp(PG_FUNCTION_ARGS)
Definition date.c:440
Datum time_cmp(PG_FUNCTION_ARGS)
Definition date.c:1842
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition date.c:2645
static DateADT DatumGetDateADT(Datum X)
Definition date.h:60
#define elog(elevel,...)
Definition elog.h:228
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:690
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 3613 of file jsonpath_exec.c.

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

3710{
3713 NumericGetDatum(b)));
3714}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition numeric.c:2423
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 3546 of file jsonpath_exec.c.

3548{
3551 {
3552 /*
3553 * It's known property of UTF-8 strings that their per-byte comparison
3554 * result matches codepoints comparison result. ASCII can be
3555 * considered as special case of UTF-8.
3556 */
3558 }
3559 else
3560 {
3561 char *utf8str1,
3562 *utf8str2;
3563 int cmp,
3564 utf8len1,
3565 utf8len2;
3566
3567 /*
3568 * We have to convert other encodings to UTF-8 first, then compare.
3569 * Input strings may be not null-terminated and pg_server_to_any() may
3570 * return them "as is". So, use strlen() only if there is real
3571 * conversion.
3572 */
3577
3579
3580 /*
3581 * If pg_server_to_any() did no real conversion, then we actually
3582 * compared original strings. So, we already done.
3583 */
3584 if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
3585 return cmp;
3586
3587 /* Free memory if needed */
3588 if (mbstr1 != utf8str1)
3589 pfree(utf8str1);
3590 if (mbstr2 != utf8str2)
3591 pfree(utf8str2);
3592
3593 /*
3594 * When all Unicode codepoints are equal, return result of binary
3595 * comparison. In some edge cases, same characters may have different
3596 * representations in encoding. Then our behavior could diverge from
3597 * standard. However, that allow us to do simple binary comparison
3598 * for "==" operator, which is performance critical in typical cases.
3599 * In future to implement strict standard conformance, we can do
3600 * normalization of input JSON strings.
3601 */
3602 if (cmp == 0)
3604 else
3605 return cmp;
3606 }
3607}
static int binaryCompareStrings(const char *s1, int len1, const char *s2, int len2)
#define PG_UTF8
Definition mbprint.c:43
int GetDatabaseEncoding(void)
Definition mbutils.c:1389
char * pg_server_to_any(const char *s, int len, int encoding)
Definition mbutils.c:760
void pfree(void *pointer)
Definition mcxt.c:1619
@ 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 3717 of file jsonpath_exec.c.

3718{
3720
3721 *dst = *src;
3722
3723 return dst;
3724}
#define palloc_object(type)
Definition fe_memutils.h:89

References fb(), and palloc_object.

Referenced by JsonPathValue().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void cxt)
static

Definition at line 3308 of file jsonpath_exec.c.

3309{
3310 List *vars = (List *) cxt;
3311
3312 return list_length(vars);
3313}
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 3475 of file jsonpath_exec.c.

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

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

2172{
2174 JsonPathItem elem;
2177 JsonbValue *lval;
2180 Numeric res;
2181
2184
2185 jspGetLeftArg(jsp, &elem);
2186
2187 /*
2188 * XXX: By standard only operands of multiplicative expressions are
2189 * unwrapped. We extend it to other binary arithmetic expressions too.
2190 */
2191 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2192 if (jperIsError(jper))
2193 {
2196 return jper;
2197 }
2198
2199 jspGetRightArg(jsp, &elem);
2200
2201 jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2202 if (jperIsError(jper))
2203 {
2206 return jper;
2207 }
2208
2211 {
2216 errmsg("left operand of jsonpath operator %s is not a single numeric value",
2217 jspOperationName(jsp->type)))));
2218 }
2219
2222 {
2227 errmsg("right operand of jsonpath operator %s is not a single numeric value",
2228 jspOperationName(jsp->type)))));
2229 }
2230
2231 if (jspThrowErrors(cxt))
2232 {
2233 res = func(lval->val.numeric, rval->val.numeric, NULL);
2234 }
2235 else
2236 {
2238
2239 res = func(lval->val.numeric, rval->val.numeric, (Node *) &escontext);
2240
2241 if (escontext.error_occurred)
2242 {
2245 return jperError;
2246 }
2247 }
2248
2251
2252 if (!jspGetNext(jsp, &elem) && !found)
2253 return jperOk;
2254
2255 resval.type = jbvNumeric;
2256 resval.val.numeric = res;
2257
2258 return executeNextItem(cxt, jsp, &elem, &resval, found);
2259}
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:133

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

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

3515{
3517
3518 return compareItems(cmp->type, lv, rv, cxt->useTz);
3519}
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 2441 of file jsonpath_exec.c.

2443{
2445 Datum value;
2446 text *datetime;
2447 Oid collid;
2448 Oid typid;
2449 int32 typmod = -1;
2450 int tz = 0;
2451 bool hasNext;
2453 JsonPathItem elem;
2454 int32 time_precision = -1;
2455
2456 if (!(jb = getScalar(jb, jbvString)))
2459 errmsg("jsonpath item method .%s() can only be applied to a string",
2460 jspOperationName(jsp->type)))));
2461
2462 datetime = cstring_to_text_with_len(jb->val.string.val,
2463 jb->val.string.len);
2464
2465 /*
2466 * At some point we might wish to have callers supply the collation to
2467 * use, but right now it's unclear that they'd be able to do better than
2468 * DEFAULT_COLLATION_OID anyway.
2469 */
2471
2472 /*
2473 * .datetime(template) has an argument, the rest of the methods don't have
2474 * an argument. So we handle that separately.
2475 */
2476 if (jsp->type == jpiDatetime && jsp->content.arg)
2477 {
2478 text *template;
2479 char *template_str;
2480 int template_len;
2482
2483 jspGetArg(jsp, &elem);
2484
2485 if (elem.type != jpiString)
2486 elog(ERROR, "invalid jsonpath item type for .datetime() argument");
2487
2489
2491 template_len);
2492
2493 value = parse_datetime(datetime, template, collid, true,
2494 &typid, &typmod, &tz,
2495 jspThrowErrors(cxt) ? NULL : (Node *) &escontext);
2496
2497 if (escontext.error_occurred)
2498 res = jperError;
2499 else
2500 res = jperOk;
2501 }
2502 else
2503 {
2504 /*
2505 * According to SQL/JSON standard enumerate ISO formats for: date,
2506 * timetz, time, timestamptz, timestamp.
2507 *
2508 * We also support ISO 8601 format (with "T") for timestamps, because
2509 * to_json[b]() functions use this format.
2510 */
2511 static const char *fmt_str[] =
2512 {
2513 "yyyy-mm-dd", /* date */
2514 "HH24:MI:SS.USTZ", /* timetz */
2515 "HH24:MI:SSTZ",
2516 "HH24:MI:SS.US", /* time without tz */
2517 "HH24:MI:SS",
2518 "yyyy-mm-dd HH24:MI:SS.USTZ", /* timestamptz */
2519 "yyyy-mm-dd HH24:MI:SSTZ",
2520 "yyyy-mm-dd\"T\"HH24:MI:SS.USTZ",
2521 "yyyy-mm-dd\"T\"HH24:MI:SSTZ",
2522 "yyyy-mm-dd HH24:MI:SS.US", /* timestamp without tz */
2523 "yyyy-mm-dd HH24:MI:SS",
2524 "yyyy-mm-dd\"T\"HH24:MI:SS.US",
2525 "yyyy-mm-dd\"T\"HH24:MI:SS"
2526 };
2527
2528 /* cache for format texts */
2529 static text *fmt_txt[lengthof(fmt_str)] = {0};
2530
2531 /*
2532 * Check for optional precision for methods other than .datetime() and
2533 * .date()
2534 */
2535 if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
2536 jsp->content.arg)
2537 {
2539
2540 jspGetArg(jsp, &elem);
2541
2542 if (elem.type != jpiNumeric)
2543 elog(ERROR, "invalid jsonpath item type for %s argument",
2544 jspOperationName(jsp->type));
2545
2547 (Node *) &escontext);
2548 if (escontext.error_occurred)
2551 errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
2552 jspOperationName(jsp->type)))));
2553 }
2554
2555 /* loop until datetime format fits */
2556 for (size_t i = 0; i < lengthof(fmt_str); i++)
2557 {
2559
2560 if (!fmt_txt[i])
2561 {
2564
2567 }
2568
2569 value = parse_datetime(datetime, fmt_txt[i], collid, true,
2570 &typid, &typmod, &tz,
2571 (Node *) &escontext);
2572
2573 if (!escontext.error_occurred)
2574 {
2575 res = jperOk;
2576 break;
2577 }
2578 }
2579
2580 if (res == jperNotFound)
2581 {
2582 if (jsp->type == jpiDatetime)
2585 errmsg("%s format is not recognized: \"%s\"",
2586 "datetime", text_to_cstring(datetime)),
2587 errhint("Use a datetime template argument to specify the input data format."))));
2588 else
2591 errmsg("%s format is not recognized: \"%s\"",
2592 jspOperationName(jsp->type), text_to_cstring(datetime)))));
2593
2594 }
2595 }
2596
2597 /*
2598 * parse_datetime() processes the entire input string per the template or
2599 * ISO format and returns the Datum in best fitted datetime type. So, if
2600 * this call is for a specific datatype, then we do the conversion here.
2601 * Throw an error for incompatible types.
2602 */
2603 switch (jsp->type)
2604 {
2605 case jpiDatetime: /* Nothing to do for DATETIME */
2606 break;
2607 case jpiDate:
2608 {
2609 /* Convert result type to date */
2610 switch (typid)
2611 {
2612 case DATEOID: /* Nothing to do for DATE */
2613 break;
2614 case TIMEOID:
2615 case TIMETZOID:
2618 errmsg("%s format is not recognized: \"%s\"",
2619 "date", text_to_cstring(datetime)))));
2620 break;
2621 case TIMESTAMPOID:
2623 value);
2624 break;
2625 case TIMESTAMPTZOID:
2627 "timestamptz", "date");
2629 value);
2630 break;
2631 default:
2632 elog(ERROR, "type with oid %u not supported", typid);
2633 }
2634
2635 typid = DATEOID;
2636 }
2637 break;
2638 case jpiTime:
2639 {
2640 /* Convert result type to time without time zone */
2641 switch (typid)
2642 {
2643 case DATEOID:
2646 errmsg("%s format is not recognized: \"%s\"",
2647 "time", text_to_cstring(datetime)))));
2648 break;
2649 case TIMEOID: /* Nothing to do for TIME */
2650 break;
2651 case TIMETZOID:
2653 "timetz", "time");
2655 value);
2656 break;
2657 case TIMESTAMPOID:
2659 value);
2660 break;
2661 case TIMESTAMPTZOID:
2663 "timestamptz", "time");
2665 value);
2666 break;
2667 default:
2668 elog(ERROR, "type with oid %u not supported", typid);
2669 }
2670
2671 /* Force the user-given time precision, if any */
2672 if (time_precision != -1)
2673 {
2675
2676 /* Get a warning when precision is reduced */
2682
2683 /* Update the typmod value with the user-given precision */
2684 typmod = time_precision;
2685 }
2686
2687 typid = TIMEOID;
2688 }
2689 break;
2690 case jpiTimeTz:
2691 {
2692 /* Convert result type to time with time zone */
2693 switch (typid)
2694 {
2695 case DATEOID:
2696 case TIMESTAMPOID:
2699 errmsg("%s format is not recognized: \"%s\"",
2700 "time_tz", text_to_cstring(datetime)))));
2701 break;
2702 case TIMEOID:
2704 "time", "timetz");
2706 value);
2707 break;
2708 case TIMETZOID: /* Nothing to do for TIMETZ */
2709 break;
2710 case TIMESTAMPTZOID:
2712 value);
2713 break;
2714 default:
2715 elog(ERROR, "type with oid %u not supported", typid);
2716 }
2717
2718 /* Force the user-given time precision, if any */
2719 if (time_precision != -1)
2720 {
2722
2723 /* Get a warning when precision is reduced */
2729
2730 /* Update the typmod value with the user-given precision */
2731 typmod = time_precision;
2732 }
2733
2734 typid = TIMETZOID;
2735 }
2736 break;
2737 case jpiTimestamp:
2738 {
2739 /* Convert result type to timestamp without time zone */
2740 switch (typid)
2741 {
2742 case DATEOID:
2744 value);
2745 break;
2746 case TIMEOID:
2747 case TIMETZOID:
2750 errmsg("%s format is not recognized: \"%s\"",
2751 "timestamp", text_to_cstring(datetime)))));
2752 break;
2753 case TIMESTAMPOID: /* Nothing to do for TIMESTAMP */
2754 break;
2755 case TIMESTAMPTZOID:
2757 "timestamptz", "timestamp");
2759 value);
2760 break;
2761 default:
2762 elog(ERROR, "type with oid %u not supported", typid);
2763 }
2764
2765 /* Force the user-given time precision, if any */
2766 if (time_precision != -1)
2767 {
2770
2771 /* Get a warning when precision is reduced */
2776 (Node *) &escontext);
2777 if (escontext.error_occurred) /* should not happen */
2780 errmsg("time precision of jsonpath item method .%s() is invalid",
2781 jspOperationName(jsp->type)))));
2783
2784 /* Update the typmod value with the user-given precision */
2785 typmod = time_precision;
2786 }
2787
2788 typid = TIMESTAMPOID;
2789 }
2790 break;
2791 case jpiTimestampTz:
2792 {
2793 struct pg_tm tm;
2794 fsec_t fsec;
2795
2796 /* Convert result type to timestamp with time zone */
2797 switch (typid)
2798 {
2799 case DATEOID:
2801 "date", "timestamptz");
2802
2803 /*
2804 * Get the timezone value explicitly since JsonbValue
2805 * keeps that separate.
2806 */
2808 &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2809 tm.tm_hour = 0;
2810 tm.tm_min = 0;
2811 tm.tm_sec = 0;
2813
2815 value);
2816 break;
2817 case TIMEOID:
2818 case TIMETZOID:
2821 errmsg("%s format is not recognized: \"%s\"",
2822 "timestamp_tz", text_to_cstring(datetime)))));
2823 break;
2824 case TIMESTAMPOID:
2826 "timestamp", "timestamptz");
2827
2828 /*
2829 * Get the timezone value explicitly since JsonbValue
2830 * keeps that separate.
2831 */
2833 &fsec, NULL, NULL) == 0)
2836
2838 value);
2839 break;
2840 case TIMESTAMPTZOID: /* Nothing to do for TIMESTAMPTZ */
2841 break;
2842 default:
2843 elog(ERROR, "type with oid %u not supported", typid);
2844 }
2845
2846 /* Force the user-given time precision, if any */
2847 if (time_precision != -1)
2848 {
2851
2852 /* Get a warning when precision is reduced */
2857 (Node *) &escontext);
2858 if (escontext.error_occurred) /* should not happen */
2861 errmsg("time precision of jsonpath item method .%s() is invalid",
2862 jspOperationName(jsp->type)))));
2864
2865 /* Update the typmod value with the user-given precision */
2866 typmod = time_precision;
2867 }
2868
2869 typid = TIMESTAMPTZOID;
2870 }
2871 break;
2872 default:
2873 elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
2874 }
2875
2876 pfree(datetime);
2877
2878 if (jperIsError(res))
2879 return res;
2880
2881 hasNext = jspGetNext(jsp, &elem);
2882
2883 if (!hasNext && !found)
2884 return res;
2885
2886 jbv.type = jbvDatetime;
2887 jbv.val.datetime.value = value;
2888 jbv.val.datetime.typid = typid;
2889 jbv.val.datetime.typmod = typmod;
2890 jbv.val.datetime.tz = tz;
2891
2892 return executeNextItem(cxt, jsp, &elem, &jbv, found);
2893}
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition datetime.c:1608
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:4375
bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
Definition timestamp.c:363
Datum timestamp_timestamptz(PG_FUNCTION_ARGS)
Definition timestamp.c:6470
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition timestamp.c:1918
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition timestamp.c:116
Datum timestamptz_timestamp(PG_FUNCTION_ARGS)
Definition timestamp.c:6539
#define lengthof(array)
Definition c.h:932
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:2015
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition date.c:65
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition date.c:1393
Datum timetz_time(PG_FUNCTION_ARGS)
Definition date.c:2939
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition date.c:2979
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition date.c:1753
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition date.c:1411
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition date.c:1330
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition date.c:2046
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition date.c:1313
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
Definition date.h:72
static TimeADT DatumGetTimeADT(Datum X)
Definition date.h:66
static Datum TimeTzADTPGetDatum(const TimeTzADT *X)
Definition date.h:90
int64 TimeADT
Definition date.h:23
static Datum TimeADTGetDatum(TimeADT X)
Definition date.h:84
Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, Node *escontext)
static struct @175 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:148
MemoryContext TopMemoryContext
Definition mcxt.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
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:835
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 785 of file jsonpath_exec.c.

787{
788 return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
789}
#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 1759 of file jsonpath_exec.c.

1762{
1763 if (unwrap && jspAutoUnwrap(cxt))
1764 {
1768 JsonbValue *item;
1769
1771
1772 res = executeItem(cxt, jsp, jb, &seq);
1773
1774 if (jperIsError(res))
1775 {
1777 return res;
1778 }
1779
1781 while ((item = JsonValueListNext(&it)))
1782 {
1783 Assert(item->type != jbvArray);
1784
1785 if (JsonbType(item) == jbvArray)
1786 executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1787 else
1788 JsonValueListAppend(found, item);
1789 }
1790
1792
1793 return jperOk;
1794 }
1795
1796 return executeItem(cxt, jsp, jb, found);
1797}
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 1803 of file jsonpath_exec.c.

1807{
1809 bool throwErrors = cxt->throwErrors;
1810
1811 cxt->throwErrors = false;
1812 res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1813 cxt->throwErrors = throwErrors;
1814
1815 return res;
1816}

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

799{
800 JsonPathItem elem;
802 JsonBaseObjectInfo baseObject;
803
806
807 switch (jsp->type)
808 {
809 case jpiNull:
810 case jpiBool:
811 case jpiNumeric:
812 case jpiString:
813 case jpiVariable:
814 {
815 JsonbValue v;
816 bool hasNext = jspGetNext(jsp, &elem);
817
818 if (!hasNext && !found && jsp->type != jpiVariable)
819 {
820 /*
821 * Skip evaluation, but not for variables. We must
822 * trigger an error for the missing variable.
823 */
824 res = jperOk;
825 break;
826 }
827
828 baseObject = cxt->baseObject;
829 getJsonPathItem(cxt, jsp, &v);
830
831 res = executeNextItem(cxt, jsp, &elem,
832 &v, found);
833 cxt->baseObject = baseObject;
834 }
835 break;
836
837 /* all boolean item types: */
838 case jpiAnd:
839 case jpiOr:
840 case jpiNot:
841 case jpiIsUnknown:
842 case jpiEqual:
843 case jpiNotEqual:
844 case jpiLess:
845 case jpiGreater:
846 case jpiLessOrEqual:
848 case jpiExists:
849 case jpiStartsWith:
850 case jpiLikeRegex:
851 {
852 JsonPathBool st = executeBoolItem(cxt, jsp, jb, true);
853
854 res = appendBoolResult(cxt, jsp, found, st);
855 break;
856 }
857
858 case jpiAdd:
859 return executeBinaryArithmExpr(cxt, jsp, jb,
860 numeric_add_safe, found);
861
862 case jpiSub:
863 return executeBinaryArithmExpr(cxt, jsp, jb,
864 numeric_sub_safe, found);
865
866 case jpiMul:
867 return executeBinaryArithmExpr(cxt, jsp, jb,
868 numeric_mul_safe, found);
869
870 case jpiDiv:
871 return executeBinaryArithmExpr(cxt, jsp, jb,
872 numeric_div_safe, found);
873
874 case jpiMod:
875 return executeBinaryArithmExpr(cxt, jsp, jb,
876 numeric_mod_safe, found);
877
878 case jpiPlus:
879 return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
880
881 case jpiMinus:
883 found);
884
885 case jpiAnyArray:
886 if (JsonbType(jb) == jbvArray)
887 {
888 bool hasNext = jspGetNext(jsp, &elem);
889
890 res = executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL,
891 jb, found, jspAutoUnwrap(cxt));
892 }
893 else if (jspAutoWrap(cxt))
894 res = executeNextItem(cxt, jsp, NULL, jb, found);
895 else if (!jspIgnoreStructuralErrors(cxt))
898 errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
899 break;
900
901 case jpiAnyKey:
902 if (JsonbType(jb) == jbvObject)
903 {
904 bool hasNext = jspGetNext(jsp, &elem);
905
906 if (jb->type != jbvBinary)
907 elog(ERROR, "invalid jsonb object type: %d", jb->type);
908
909 return executeAnyItem
910 (cxt, hasNext ? &elem : NULL,
911 jb->val.binary.data, found, 1, 1, 1,
912 false, jspAutoUnwrap(cxt));
913 }
914 else if (unwrap && JsonbType(jb) == jbvArray)
915 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
916 else if (!jspIgnoreStructuralErrors(cxt))
917 {
918 Assert(found);
921 errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
922 }
923 break;
924
925 case jpiIndexArray:
926 if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
927 {
928 int innermostArraySize = cxt->innermostArraySize;
929 int i;
930 int size = JsonbArraySize(jb);
931 bool singleton = size < 0;
932 bool hasNext = jspGetNext(jsp, &elem);
933
934 if (singleton)
935 size = 1;
936
937 cxt->innermostArraySize = size; /* for LAST evaluation */
938
939 for (i = 0; i < jsp->content.array.nelems; i++)
940 {
941 JsonPathItem from;
942 JsonPathItem to;
943 int32 index;
946 bool range = jspGetArraySubscript(jsp, &from,
947 &to, i);
948
949 res = getArrayIndex(cxt, &from, jb, &index_from);
950
951 if (jperIsError(res))
952 break;
953
954 if (range)
955 {
956 res = getArrayIndex(cxt, &to, jb, &index_to);
957
958 if (jperIsError(res))
959 break;
960 }
961 else
963
964 if (!jspIgnoreStructuralErrors(cxt) &&
965 (index_from < 0 ||
967 index_to >= size))
970 errmsg("jsonpath array subscript is out of bounds"))));
971
972 if (index_from < 0)
973 index_from = 0;
974
975 if (index_to >= size)
976 index_to = size - 1;
977
978 res = jperNotFound;
979
980 for (index = index_from; index <= index_to; index++)
981 {
982 JsonbValue *v;
983
984 if (singleton)
985 {
986 v = jb;
987 }
988 else
989 {
990 v = getIthJsonbValueFromContainer(jb->val.binary.data,
991 (uint32) index);
992
993 if (v == NULL)
994 continue;
995 }
996
997 if (!hasNext && !found)
998 return jperOk;
999
1000 res = executeNextItem(cxt, jsp, &elem, v, found);
1001
1002 if (jperIsError(res))
1003 break;
1004
1005 if (res == jperOk && !found)
1006 break;
1007 }
1008
1009 if (jperIsError(res))
1010 break;
1011
1012 if (res == jperOk && !found)
1013 break;
1014 }
1015
1016 cxt->innermostArraySize = innermostArraySize;
1017 }
1018 else if (!jspIgnoreStructuralErrors(cxt))
1019 {
1022 errmsg("jsonpath array accessor can only be applied to an array"))));
1023 }
1024 break;
1025
1026 case jpiAny:
1027 {
1028 bool hasNext = jspGetNext(jsp, &elem);
1029
1030 /* first try without any intermediate steps */
1031 if (jsp->content.anybounds.first == 0)
1032 {
1034
1036 cxt->ignoreStructuralErrors = true;
1037 res = executeNextItem(cxt, jsp, &elem,
1038 jb, found);
1040
1041 if (res == jperOk && !found)
1042 break;
1043 }
1044
1045 if (jb->type == jbvBinary)
1046 res = executeAnyItem
1047 (cxt, hasNext ? &elem : NULL,
1048 jb->val.binary.data, found,
1049 1,
1050 jsp->content.anybounds.first,
1051 jsp->content.anybounds.last,
1052 true, jspAutoUnwrap(cxt));
1053 break;
1054 }
1055
1056 case jpiKey:
1057 if (JsonbType(jb) == jbvObject)
1058 {
1059 JsonbValue *v;
1061
1062 key.type = jbvString;
1063 key.val.string.val = jspGetString(jsp, &key.val.string.len);
1064
1065 v = findJsonbValueFromContainer(jb->val.binary.data,
1066 JB_FOBJECT, &key);
1067
1068 if (v != NULL)
1069 {
1070 res = executeNextItem(cxt, jsp, NULL,
1071 v, found);
1072 pfree(v);
1073 }
1074 else if (!jspIgnoreStructuralErrors(cxt))
1075 {
1076 Assert(found);
1077
1078 if (!jspThrowErrors(cxt))
1079 return jperError;
1080
1081 ereport(ERROR,
1083 errmsg("JSON object does not contain key \"%s\"",
1084 pnstrdup(key.val.string.val,
1085 key.val.string.len))));
1086 }
1087 }
1088 else if (unwrap && JsonbType(jb) == jbvArray)
1089 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1090 else if (!jspIgnoreStructuralErrors(cxt))
1091 {
1092 Assert(found);
1095 errmsg("jsonpath member accessor can only be applied to an object"))));
1096 }
1097 break;
1098
1099 case jpiCurrent:
1100 res = executeNextItem(cxt, jsp, NULL, cxt->current, found);
1101 break;
1102
1103 case jpiRoot:
1104 jb = cxt->root;
1105 baseObject = setBaseObject(cxt, jb, 0);
1106 res = executeNextItem(cxt, jsp, NULL, jb, found);
1107 cxt->baseObject = baseObject;
1108 break;
1109
1110 case jpiFilter:
1111 {
1112 JsonPathBool st;
1113
1114 if (unwrap && JsonbType(jb) == jbvArray)
1115 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1116 false);
1117
1118 jspGetArg(jsp, &elem);
1119 st = executeNestedBoolItem(cxt, &elem, jb);
1120 if (st != jpbTrue)
1121 res = jperNotFound;
1122 else
1123 res = executeNextItem(cxt, jsp, NULL,
1124 jb, found);
1125 break;
1126 }
1127
1128 case jpiType:
1129 {
1131
1132 jbv.type = jbvString;
1133 jbv.val.string.val = pstrdup(JsonbTypeName(jb));
1134 jbv.val.string.len = strlen(jbv.val.string.val);
1135
1136 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1137 }
1138 break;
1139
1140 case jpiSize:
1141 {
1142 int size = JsonbArraySize(jb);
1144
1145 if (size < 0)
1146 {
1147 if (!jspAutoWrap(cxt))
1148 {
1149 if (!jspIgnoreStructuralErrors(cxt))
1152 errmsg("jsonpath item method .%s() can only be applied to an array",
1153 jspOperationName(jsp->type)))));
1154 break;
1155 }
1156
1157 size = 1;
1158 }
1159
1160 jbv.type = jbvNumeric;
1161 jbv.val.numeric = int64_to_numeric(size);
1162
1163 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1164 }
1165 break;
1166
1167 case jpiAbs:
1169 found);
1170
1171 case jpiFloor:
1173 found);
1174
1175 case jpiCeiling:
1177 found);
1178
1179 case jpiDouble:
1180 {
1182
1183 if (unwrap && JsonbType(jb) == jbvArray)
1184 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1185 false);
1186
1187 if (jb->type == jbvNumeric)
1188 {
1190 NumericGetDatum(jb->val.numeric)));
1191 double val;
1193
1194 val = float8in_internal(tmp,
1195 NULL,
1196 "double precision",
1197 tmp,
1198 (Node *) &escontext);
1199
1200 if (escontext.error_occurred)
1203 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1204 tmp, jspOperationName(jsp->type), "double precision"))));
1205 if (isinf(val) || isnan(val))
1208 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1209 jspOperationName(jsp->type)))));
1210 res = jperOk;
1211 }
1212 else if (jb->type == jbvString)
1213 {
1214 /* cast string as double */
1215 double val;
1216 char *tmp = pnstrdup(jb->val.string.val,
1217 jb->val.string.len);
1219
1220 val = float8in_internal(tmp,
1221 NULL,
1222 "double precision",
1223 tmp,
1224 (Node *) &escontext);
1225
1226 if (escontext.error_occurred)
1229 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1230 tmp, jspOperationName(jsp->type), "double precision"))));
1231 if (isinf(val) || isnan(val))
1234 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1235 jspOperationName(jsp->type)))));
1236
1237 jb = &jbv;
1238 jb->type = jbvNumeric;
1241 res = jperOk;
1242 }
1243
1244 if (res == jperNotFound)
1247 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1248 jspOperationName(jsp->type)))));
1249
1250 res = executeNextItem(cxt, jsp, NULL, jb, found);
1251 }
1252 break;
1253
1254 case jpiDatetime:
1255 case jpiDate:
1256 case jpiTime:
1257 case jpiTimeTz:
1258 case jpiTimestamp:
1259 case jpiTimestampTz:
1260 if (unwrap && JsonbType(jb) == jbvArray)
1261 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1262
1263 return executeDateTimeMethod(cxt, jsp, jb, found);
1264
1265 case jpiKeyValue:
1266 if (unwrap && JsonbType(jb) == jbvArray)
1267 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1268
1269 return executeKeyValueMethod(cxt, jsp, jb, found);
1270
1271 case jpiLast:
1272 {
1274 int last;
1275 bool hasNext = jspGetNext(jsp, &elem);
1276
1277 if (cxt->innermostArraySize < 0)
1278 elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
1279
1280 if (!hasNext && !found)
1281 {
1282 res = jperOk;
1283 break;
1284 }
1285
1286 last = cxt->innermostArraySize - 1;
1287
1288 jbv.type = jbvNumeric;
1289 jbv.val.numeric = int64_to_numeric(last);
1290
1291 res = executeNextItem(cxt, jsp, &elem,
1292 &jbv, found);
1293 }
1294 break;
1295
1296 case jpiBigint:
1297 {
1299 Datum datum;
1300
1301 if (unwrap && JsonbType(jb) == jbvArray)
1302 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1303 false);
1304
1305 if (jb->type == jbvNumeric)
1306 {
1308 int64 val;
1309
1310 val = numeric_int8_safe(jb->val.numeric,
1311 (Node *) &escontext);
1312 if (escontext.error_occurred)
1315 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1317 NumericGetDatum(jb->val.numeric))),
1318 jspOperationName(jsp->type),
1319 "bigint"))));
1320
1321 datum = Int64GetDatum(val);
1322 res = jperOk;
1323 }
1324 else if (jb->type == jbvString)
1325 {
1326 /* cast string as bigint */
1327 char *tmp = pnstrdup(jb->val.string.val,
1328 jb->val.string.len);
1330 bool noerr;
1331
1333 InvalidOid, -1,
1334 (Node *) &escontext,
1335 &datum);
1336
1337 if (!noerr || escontext.error_occurred)
1340 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1341 tmp, jspOperationName(jsp->type), "bigint"))));
1342 res = jperOk;
1343 }
1344
1345 if (res == jperNotFound)
1348 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1349 jspOperationName(jsp->type)))));
1350
1351 jbv.type = jbvNumeric;
1353 datum));
1354
1355 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1356 }
1357 break;
1358
1359 case jpiBoolean:
1360 {
1362 bool bval;
1363
1364 if (unwrap && JsonbType(jb) == jbvArray)
1365 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1366 false);
1367
1368 if (jb->type == jbvBool)
1369 {
1370 bval = jb->val.boolean;
1371
1372 res = jperOk;
1373 }
1374 else if (jb->type == jbvNumeric)
1375 {
1376 int ival;
1377 Datum datum;
1378 bool noerr;
1380 NumericGetDatum(jb->val.numeric)));
1382
1384 InvalidOid, -1,
1385 (Node *) &escontext,
1386 &datum);
1387
1388 if (!noerr || escontext.error_occurred)
1391 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1392 tmp, jspOperationName(jsp->type), "boolean"))));
1393
1394 ival = DatumGetInt32(datum);
1395 if (ival == 0)
1396 bval = false;
1397 else
1398 bval = true;
1399
1400 res = jperOk;
1401 }
1402 else if (jb->type == jbvString)
1403 {
1404 /* cast string as boolean */
1405 char *tmp = pnstrdup(jb->val.string.val,
1406 jb->val.string.len);
1407
1408 if (!parse_bool(tmp, &bval))
1411 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1412 tmp, jspOperationName(jsp->type), "boolean"))));
1413
1414 res = jperOk;
1415 }
1416
1417 if (res == jperNotFound)
1420 errmsg("jsonpath item method .%s() can only be applied to a boolean, string, or numeric value",
1421 jspOperationName(jsp->type)))));
1422
1423 jbv.type = jbvBool;
1424 jbv.val.boolean = bval;
1425
1426 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1427 }
1428 break;
1429
1430 case jpiDecimal:
1431 case jpiNumber:
1432 {
1434 Numeric num;
1435 char *numstr = NULL;
1436
1437 if (unwrap && JsonbType(jb) == jbvArray)
1438 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1439 false);
1440
1441 if (jb->type == jbvNumeric)
1442 {
1443 num = jb->val.numeric;
1444 if (numeric_is_nan(num) || numeric_is_inf(num))
1447 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1448 jspOperationName(jsp->type)))));
1449
1450 if (jsp->type == jpiDecimal)
1452 NumericGetDatum(num)));
1453 res = jperOk;
1454 }
1455 else if (jb->type == jbvString)
1456 {
1457 /* cast string as number */
1458 Datum datum;
1459 bool noerr;
1461
1462 numstr = pnstrdup(jb->val.string.val, jb->val.string.len);
1463
1465 InvalidOid, -1,
1466 (Node *) &escontext,
1467 &datum);
1468
1469 if (!noerr || escontext.error_occurred)
1472 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1473 numstr, jspOperationName(jsp->type), "numeric"))));
1474
1475 num = DatumGetNumeric(datum);
1476 if (numeric_is_nan(num) || numeric_is_inf(num))
1479 errmsg("NaN or Infinity is not allowed for jsonpath item method .%s()",
1480 jspOperationName(jsp->type)))));
1481
1482 res = jperOk;
1483 }
1484
1485 if (res == jperNotFound)
1488 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1489 jspOperationName(jsp->type)))));
1490
1491 /*
1492 * If we have arguments, then they must be the precision and
1493 * optional scale used in .decimal(). Convert them to the
1494 * typmod equivalent and then truncate the numeric value per
1495 * this typmod details.
1496 */
1497 if (jsp->type == jpiDecimal && jsp->content.args.left)
1498 {
1500 int32 dtypmod;
1501 int32 precision;
1502 int32 scale = 0;
1503 bool noerr;
1505
1506 jspGetLeftArg(jsp, &elem);
1507 if (elem.type != jpiNumeric)
1508 elog(ERROR, "invalid jsonpath item type for .decimal() precision");
1509
1510 precision = numeric_int4_safe(jspGetNumeric(&elem),
1511 (Node *) &escontext);
1512 if (escontext.error_occurred)
1515 errmsg("precision of jsonpath item method .%s() is out of range for type integer",
1516 jspOperationName(jsp->type)))));
1517
1518 if (jsp->content.args.right)
1519 {
1520 jspGetRightArg(jsp, &elem);
1521 if (elem.type != jpiNumeric)
1522 elog(ERROR, "invalid jsonpath item type for .decimal() scale");
1523
1525 (Node *) &escontext);
1526 if (escontext.error_occurred)
1529 errmsg("scale of jsonpath item method .%s() is out of range for type integer",
1530 jspOperationName(jsp->type)))));
1531 }
1532
1533 /* Pack the precision and scale into a numeric typmod */
1535 jspThrowErrors(cxt) ? NULL : (Node *) &escontext);
1536 if (escontext.error_occurred)
1537 return jperError;
1538
1539 /* Convert numstr to Numeric with typmod */
1540 Assert(numstr != NULL);
1543 (Node *) &escontext,
1544 &numdatum);
1545
1546 if (!noerr || escontext.error_occurred)
1549 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1550 numstr, jspOperationName(jsp->type), "numeric"))));
1551
1553 }
1554
1555 jbv.type = jbvNumeric;
1556 jbv.val.numeric = num;
1557
1558 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1559 }
1560 break;
1561
1562 case jpiInteger:
1563 {
1565 Datum datum;
1566
1567 if (unwrap && JsonbType(jb) == jbvArray)
1568 return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1569 false);
1570
1571 if (jb->type == jbvNumeric)
1572 {
1573 int32 val;
1575
1576 val = numeric_int4_safe(jb->val.numeric,
1577 (Node *) &escontext);
1578 if (escontext.error_occurred)
1581 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1583 NumericGetDatum(jb->val.numeric))),
1584 jspOperationName(jsp->type), "integer"))));
1585
1586 datum = Int32GetDatum(val);
1587 res = jperOk;
1588 }
1589 else if (jb->type == jbvString)
1590 {
1591 /* cast string as integer */
1592 char *tmp = pnstrdup(jb->val.string.val,
1593 jb->val.string.len);
1595 bool noerr;
1596
1598 InvalidOid, -1,
1599 (Node *) &escontext,
1600 &datum);
1601
1602 if (!noerr || escontext.error_occurred)
1605 errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
1606 tmp, jspOperationName(jsp->type), "integer"))));
1607 res = jperOk;
1608 }
1609
1610 if (res == jperNotFound)
1613 errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1614 jspOperationName(jsp->type)))));
1615
1616 jbv.type = jbvNumeric;
1618 datum));
1619
1620 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1621 }
1622 break;
1623
1624 case jpiStringFunc:
1625 {
1627 char *tmp = NULL;
1628
1629 if (unwrap && JsonbType(jb) == jbvArray)
1630 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1631
1632 switch (JsonbType(jb))
1633 {
1634 case jbvString:
1635
1636 /*
1637 * Value is not necessarily null-terminated, so we do
1638 * pnstrdup() here.
1639 */
1640 tmp = pnstrdup(jb->val.string.val,
1641 jb->val.string.len);
1642 break;
1643 case jbvNumeric:
1645 NumericGetDatum(jb->val.numeric)));
1646 break;
1647 case jbvBool:
1648 tmp = (jb->val.boolean) ? "true" : "false";
1649 break;
1650 case jbvDatetime:
1651 {
1652 char buf[MAXDATELEN + 1];
1653
1655 jb->val.datetime.value,
1656 jb->val.datetime.typid,
1657 &jb->val.datetime.tz);
1658 tmp = pstrdup(buf);
1659 }
1660 break;
1661 case jbvNull:
1662 case jbvArray:
1663 case jbvObject:
1664 case jbvBinary:
1667 errmsg("jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value",
1668 jspOperationName(jsp->type)))));
1669 break;
1670 }
1671
1672 Assert(tmp != NULL); /* We must have set tmp above */
1673 jbv.val.string.val = tmp;
1674 jbv.val.string.len = strlen(jbv.val.string.val);
1675 jbv.type = jbvString;
1676
1677 res = executeNextItem(cxt, jsp, NULL, &jbv, found);
1678 }
1679 break;
1680
1681 case jpiStrReplace:
1682 case jpiStrLower:
1683 case jpiStrUpper:
1684 case jpiStrLtrim:
1685 case jpiStrRtrim:
1686 case jpiStrBtrim:
1687 case jpiStrInitcap:
1688 case jpiStrSplitPart:
1689 {
1690 if (unwrap && JsonbType(jb) == jbvArray)
1691 return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1692
1693 return executeStringInternalMethod(cxt, jsp, jb, found);
1694 }
1695 break;
1696
1697 default:
1698 elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
1699 }
1700
1701 return res;
1702}
int32 make_numeric_typmod_safe(int32 precision, int32 scale, Node *escontext)
Definition numeric.c:1315
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4544
Numeric int64_to_numeric(int64 val)
Definition numeric.c:4270
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4364
Datum numeric_uminus(PG_FUNCTION_ARGS)
Definition numeric.c:1411
Numeric numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3366
Datum numeric_ceil(PG_FUNCTION_ARGS)
Definition numeric.c:1638
Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2889
int64 numeric_int8_safe(Numeric num, Node *escontext)
Definition numeric.c:4451
Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3163
Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2965
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:3044
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition numeric.c:1384
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4440
bool numeric_is_inf(Numeric num)
Definition numeric.c:845
Datum numeric_floor(PG_FUNCTION_ARGS)
Definition numeric.c:1666
bool parse_bool(const char *value, bool *result)
Definition bool.c:31
int64_t int64
Definition c.h:680
uint32_t uint32
Definition c.h:683
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:51
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:1910
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1921
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
static Numeric DatumGetNumeric(Datum X)
Definition numeric.h:64
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:426
static char * DatumGetCString(Datum X)
Definition postgres.h:365
static Datum Float8GetDatum(float8 X)
Definition postgres.h:515
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:97

References appendBoolResult(), Assert, JsonPathExecContext::baseObject, buf, CHECK_FOR_INTERRUPTS, check_stack_depth(), 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, make_numeric_typmod_safe(), 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(), parse_bool(), pfree(), pnstrdup(), 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 1708 of file jsonpath_exec.c.

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

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

727{
732
733 jspInit(&jsp, path);
734
735 if (!JsonbExtractScalar(&json->root, &jbv))
736 JsonbInitBinary(&jbv, json);
737
738 cxt.vars = vars;
739 cxt.getVar = getVar;
740 cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
742 cxt.root = &jbv;
743 cxt.current = &jbv;
744 cxt.baseObject.jbc = NULL;
745 cxt.baseObject.id = 0;
746 /* 1 + number of base objects in vars */
748 cxt.innermostArraySize = -1;
749 cxt.throwErrors = throwErrors;
750 cxt.useTz = useTz;
751
752 if (jspStrictAbsenceOfErrors(&cxt) && !result)
753 {
754 /*
755 * In strict mode we must get a complete list of values to check that
756 * there are no errors at all.
757 */
758 JsonValueList vals;
759 bool isempty;
760
761 JsonValueListInit(&vals);
762
763 res = executeItem(&cxt, &jsp, &jbv, &vals);
764
766 JsonValueListClear(&vals);
767
768 if (jperIsError(res))
769 return res;
770
771 return isempty ? jperNotFound : jperOk;
772 }
773
774 res = executeItem(&cxt, &jsp, &jbv, result);
775
776 Assert(!throwErrors || !jperIsError(res));
777
778 return res;
779}
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 3092 of file jsonpath_exec.c.

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

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

1965{
1966 JsonbValue *prev;
1967 JsonPathBool res;
1968
1969 prev = cxt->current;
1970 cxt->current = jb;
1971 res = executeBoolItem(cxt, jsp, jb, false);
1972 cxt->current = prev;
1973
1974 return res;
1975}

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

1731{
1732 JsonPathItem elem;
1733 bool hasNext;
1734
1735 if (!cur)
1736 hasNext = next != NULL;
1737 else if (next)
1739 else
1740 {
1741 next = &elem;
1743 }
1744
1745 if (hasNext)
1746 return executeItem(cxt, next, v, found);
1747
1748 if (found)
1749 JsonValueListAppend(found, v);
1750
1751 return jperOk;
1752}
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 2400 of file jsonpath_exec.c.

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

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

2079{
2084 JsonbValue *lval;
2085 bool error = false;
2086 bool found = false;
2087
2090
2091 /* Left argument is always auto-unwrapped. */
2092 res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
2093 if (jperIsError(res))
2094 {
2095 error = true;
2096 goto exit;
2097 }
2098
2099 if (rarg)
2100 {
2101 /* Right argument is conditionally auto-unwrapped. */
2102 res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
2104 if (jperIsError(res))
2105 {
2106 error = true;
2107 goto exit;
2108 }
2109 }
2110
2112 while ((lval = JsonValueListNext(&lseqit)))
2113 {
2116 bool first = true;
2117
2119 if (rarg)
2121 else
2122 rval = NULL;
2123
2124 /* Loop over right arg sequence or do single pass otherwise */
2125 while (rarg ? (rval != NULL) : first)
2126 {
2127 JsonPathBool res = exec(pred, lval, rval, param);
2128
2129 if (res == jpbUnknown)
2130 {
2131 error = true;
2132 if (jspStrictAbsenceOfErrors(cxt))
2133 {
2134 found = false; /* return unknown, not success */
2135 goto exit;
2136 }
2137 }
2138 else if (res == jpbTrue)
2139 {
2140 found = true;
2141 if (!jspStrictAbsenceOfErrors(cxt))
2142 goto exit;
2143 }
2144
2145 first = false;
2146 if (rarg)
2148 }
2149 }
2150
2151exit:
2154
2155 if (found) /* possible only in strict mode */
2156 return jpbTrue;
2157
2158 if (error) /* possible only in lax mode */
2159 return jpbUnknown;
2160
2161 return jpbFalse;
2162}
static void error(void)
Definition type.h:117

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

2347{
2348 if (!(whole = getScalar(whole, jbvString)))
2349 return jpbUnknown; /* error */
2350
2352 return jpbUnknown; /* error */
2353
2354 if (whole->val.string.len >= initial->val.string.len &&
2355 !memcmp(whole->val.string.val,
2356 initial->val.string.val,
2357 initial->val.string.len))
2358 return jpbTrue;
2359
2360 return jpbFalse;
2361}

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

2902{
2904 bool hasNext;
2906 JsonPathItem elem;
2907 Datum str; /* Datum representation for the current string
2908 * value. The first argument to internal
2909 * functions */
2910 char *resStr = NULL;
2911
2912 Assert(jsp->type == jpiStrReplace ||
2913 jsp->type == jpiStrLower ||
2914 jsp->type == jpiStrUpper ||
2915 jsp->type == jpiStrLtrim ||
2916 jsp->type == jpiStrRtrim ||
2917 jsp->type == jpiStrBtrim ||
2918 jsp->type == jpiStrInitcap ||
2919 jsp->type == jpiStrSplitPart);
2920
2921 if (!(jb = getScalar(jb, jbvString)))
2924 errmsg("jsonpath item method .%s() can only be applied to a string",
2925 jspOperationName(jsp->type)))));
2926
2927 str = PointerGetDatum(cstring_to_text_with_len(jb->val.string.val, jb->val.string.len));
2928
2929 /* Dispatch to the appropriate internal string function */
2930 switch (jsp->type)
2931 {
2932 case jpiStrReplace:
2933 {
2934 char *from_str,
2935 *to_str;
2936
2937 jspGetLeftArg(jsp, &elem);
2938 if (elem.type != jpiString)
2939 elog(ERROR, "invalid jsonpath item type for .replace() from");
2940
2941 from_str = jspGetString(&elem, NULL);
2942
2943 jspGetRightArg(jsp, &elem);
2944 if (elem.type != jpiString)
2945 elog(ERROR, "invalid jsonpath item type for .replace() to");
2946
2947 to_str = jspGetString(&elem, NULL);
2948
2951 str,
2954 break;
2955 }
2956 case jpiStrLower:
2958 break;
2959 case jpiStrUpper:
2961 break;
2962 case jpiStrLtrim:
2963 case jpiStrRtrim:
2964 case jpiStrBtrim:
2965 {
2968
2969 switch (jsp->type)
2970 {
2971 case jpiStrLtrim:
2972 func1 = ltrim1;
2973 func2 = ltrim;
2974 break;
2975 case jpiStrRtrim:
2976 func1 = rtrim1;
2977 func2 = rtrim;
2978 break;
2979 case jpiStrBtrim:
2980 func1 = btrim1;
2981 func2 = btrim;
2982 break;
2983 default:
2984 break;
2985 }
2986
2987 if (jsp->content.arg)
2988 {
2989 char *characters_str;
2990
2991 jspGetArg(jsp, &elem);
2992 if (elem.type != jpiString)
2993 elog(ERROR, "invalid jsonpath item type for .%s() argument",
2994 jspOperationName(jsp->type));
2995
3000 }
3001 else
3002 {
3005 }
3006 break;
3007 }
3008
3009 case jpiStrInitcap:
3011 break;
3012 case jpiStrSplitPart:
3013 {
3014 char *from_str;
3015 int32 n;
3017
3018 jspGetLeftArg(jsp, &elem);
3019 if (elem.type != jpiString)
3020 elog(ERROR, "invalid jsonpath item type for .split_part()");
3021
3022 from_str = jspGetString(&elem, NULL);
3023
3024 jspGetRightArg(jsp, &elem);
3025 if (elem.type != jpiNumeric)
3026 elog(ERROR, "invalid jsonpath item type for .split_part()");
3027
3029 (Node *) &escontext);
3030 if (escontext.error_occurred)
3033 errmsg("field position of jsonpath item method .%s() is out of range for type integer",
3034 jspOperationName(jsp->type))));
3035
3036 if (n == 0)
3039 errmsg("field position of jsonpath item method .%s() must not be zero",
3040 jspOperationName(jsp->type))));
3041
3044 str,
3046 Int32GetDatum(n)));
3047 break;
3048 }
3049 default:
3050 elog(ERROR, "unsupported jsonpath item type: %d", jsp->type);
3051 }
3052
3053 if (resStr)
3054 res = jperOk;
3055
3056 hasNext = jspGetNext(jsp, &elem);
3057
3058 if (!hasNext && !found)
3059 return res;
3060
3061 jbv.type = jbvString;
3062 jbv.val.string.val = resStr;
3063 jbv.val.string.len = strlen(resStr);
3064
3065 return executeNextItem(cxt, jsp, &elem, &jbv, found);
3066}
#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)
#define PointerGetDatum(X)
Definition postgres.h:354
Datum split_part(PG_FUNCTION_ARGS)
Definition varlena.c:3509
Datum replace_text(PG_FUNCTION_ARGS)
Definition varlena.c:3137

References Assert, btrim(), btrim1(), cstring_to_text_with_len(), CStringGetTextDatum, DirectFunctionCall1Coll(), DirectFunctionCall2Coll(), DirectFunctionCall3Coll(), elog, ereport, errcode(), errmsg, ERROR, ErrorSaveContext::error_occurred, executeNextItem(), fb(), getScalar(), initcap(), Int32GetDatum(), 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_safe(), 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 2266 of file jsonpath_exec.c.

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

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

3733{
3734 JsonbValue *jbv;
3735 JsonValueList found;
3739
3740 JsonValueListInit(&found);
3741
3742 res = executeItem(cxt, jsp, jb, &found);
3743
3744 if (jperIsError(res))
3745 {
3746 JsonValueListClear(&found);
3747 return res;
3748 }
3749
3750 if (!JsonValueListIsSingleton(&found) ||
3752 {
3753 JsonValueListClear(&found);
3756 errmsg("jsonpath array subscript is not a single numeric value"))));
3757 }
3758
3760 NumericGetDatum(jbv->val.numeric),
3761 Int32GetDatum(0));
3762
3764 (Node *) &escontext);
3765
3766 JsonValueListClear(&found);
3767
3768 if (escontext.error_occurred)
3771 errmsg("jsonpath array subscript is out of integer range"))));
3772
3773 return jperOk;
3774}
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition numeric.c:1588

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

3232{
3233 switch (item->type)
3234 {
3235 case jpiNull:
3236 value->type = jbvNull;
3237 break;
3238 case jpiBool:
3239 value->type = jbvBool;
3240 value->val.boolean = jspGetBool(item);
3241 break;
3242 case jpiNumeric:
3243 value->type = jbvNumeric;
3244 value->val.numeric = jspGetNumeric(item);
3245 break;
3246 case jpiString:
3247 value->type = jbvString;
3248 value->val.string.val = jspGetString(item,
3249 &value->val.string.len);
3250 break;
3251 case jpiVariable:
3252 getJsonPathVariable(cxt, item, value);
3253 return;
3254 default:
3255 elog(ERROR, "unexpected jsonpath item type");
3256 }
3257}
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 3263 of file jsonpath_exec.c.

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

3415{
3416 char *varName;
3417 int varNameLength;
3418 JsonbValue baseObject;
3419 int baseObjectId;
3420 JsonbValue *v;
3421
3423 varName = jspGetString(variable, &varNameLength);
3424
3425 if (cxt->vars == NULL ||
3426 (v = cxt->getVar(cxt->vars, varName, varNameLength,
3427 &baseObject, &baseObjectId)) == NULL)
3428 ereport(ERROR,
3430 errmsg("could not find jsonpath variable \"%s\"",
3431 pnstrdup(varName, varNameLength))));
3432
3433 if (baseObjectId > 0)
3434 {
3435 *value = *v;
3436 setBaseObject(cxt, &baseObject, baseObjectId);
3437 }
3438}
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 3445 of file jsonpath_exec.c.

3447{
3448 Jsonb *vars = varsJsonb;
3449 JsonbValue tmp;
3451
3452 tmp.type = jbvString;
3453 tmp.val.string.val = varName;
3454 tmp.val.string.len = varNameLength;
3455
3457
3458 if (result == NULL)
3459 {
3460 *baseObjectId = -1;
3461 return NULL;
3462 }
3463
3464 *baseObjectId = 1;
3465 JsonbInitBinary(baseObject, vars);
3466
3467 return result;
3468}

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

4408{
4410
4412 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4413 result = (JsonTableExecContext *) state->opaque;
4415 elog(ERROR, "%s called with invalid TableFuncScanState", fname);
4416
4417 return result;
4418}
#define JSON_TABLE_EXEC_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition nodes.h:162

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

3959{
3960 /* Scalars should be always extracted during jsonpath execution. */
3961 Assert(scalar->type != jbvBinary ||
3962 !JsonContainerIsScalar(scalar->val.binary.data));
3963
3964 return scalar->type == type ? scalar : NULL;
3965}
#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 463 of file jsonpath_exec.c.

464{
465 return jsonb_path_exists_internal(fcinfo, false);
466}
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 435 of file jsonpath_exec.c.

436{
440 Jsonb *vars = NULL;
441 bool silent = true;
442
443 if (PG_NARGS() == 4)
444 {
447 }
448
451 jb, !silent, NULL, tz);
452
455
456 if (jperIsError(res))
458
459 PG_RETURN_BOOL(res == jperOk);
460}
#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 480 of file jsonpath_exec.c.

481{
482 /* just call the other one -- it can handle both cases */
483 return jsonb_path_exists_internal(fcinfo, false);
484}

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 469 of file jsonpath_exec.c.

470{
471 return jsonb_path_exists_internal(fcinfo, true);
472}

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 535 of file jsonpath_exec.c.

536{
537 return jsonb_path_match_internal(fcinfo, false);
538}
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 492 of file jsonpath_exec.c.

493{
496 Jsonb *vars = NULL;
497 bool silent = true;
498 JsonValueList found;
499
500 if (PG_NARGS() == 4)
501 {
504 }
505
506 JsonValueListInit(&found);
507
510 jb, !silent, &found, tz);
511
514
515 if (JsonValueListIsSingleton(&found))
516 {
518
519 if (jbv->type == jbvBool)
520 PG_RETURN_BOOL(jbv->val.boolean);
521
522 if (jbv->type == jbvNull)
524 }
525
526 if (!silent)
529 errmsg("single boolean result is expected")));
530
532}

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

553{
554 /* just call the other one -- it can handle both cases */
555 return jsonb_path_match_internal(fcinfo, false);
556}

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 541 of file jsonpath_exec.c.

542{
543 return jsonb_path_match_internal(fcinfo, true);
544}

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 614 of file jsonpath_exec.c.

615{
616 return jsonb_path_query_internal(fcinfo, false);
617}
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 649 of file jsonpath_exec.c.

650{
651 return jsonb_path_query_array_internal(fcinfo, false);
652}
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 655 of file jsonpath_exec.c.

656{
657 return jsonb_path_query_array_internal(fcinfo, true);
658}

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 687 of file jsonpath_exec.c.

688{
689 return jsonb_path_query_first_internal(fcinfo, false);
690}
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 693 of file jsonpath_exec.c.

694{
695 return jsonb_path_query_first_internal(fcinfo, true);
696}

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 564 of file jsonpath_exec.c.

565{
568 JsonbValue *v;
569
570 if (SRF_IS_FIRSTCALL())
571 {
572 JsonPath *jp;
573 Jsonb *jb;
574 Jsonb *vars;
575 bool silent;
576 MemoryContext oldcontext;
577 JsonValueList *found;
578
580 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
581
586
588 JsonValueListInit(found);
589
592 jb, !silent, found, tz);
593
595 JsonValueListInitIterator(found, iter);
596
597 funcctx->user_fctx = iter;
598
599 MemoryContextSwitchTo(oldcontext);
600 }
601
603 iter = funcctx->user_fctx;
604
605 v = JsonValueListNext(iter);
606
607 if (v == NULL)
609
611}
#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 620 of file jsonpath_exec.c.

621{
622 return jsonb_path_query_internal(fcinfo, true);
623}

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3497 of file jsonpath_exec.c.

3498{
3499 Assert(jb->type != jbvArray);
3500
3501 if (jb->type == jbvBinary)
3502 {
3503 JsonbContainer *jbc = jb->val.binary.data;
3504
3506 return JsonContainerSize(jbc);
3507 }
3508
3509 return -1;
3510}
#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 3921 of file jsonpath_exec.c.

3922{
3923 jbv->type = jbvBinary;
3924 jbv->val.binary.data = &jb->root;
3925 jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3926
3927 return jbv;
3928}
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 3934 of file jsonpath_exec.c.

3935{
3936 int type = jb->type;
3937
3938 if (jb->type == jbvBinary)
3939 {
3940 JsonbContainer *jbc = jb->val.binary.data;
3941
3942 /* Scalars should be always extracted during jsonpath execution. */
3944
3945 if (JsonContainerIsObject(jbc))
3946 type = jbvObject;
3947 else if (JsonContainerIsArray(jbc))
3948 type = jbvArray;
3949 else
3950 elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
3951 }
3952
3953 return type;
3954}
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 3403 of file jsonpath_exec.c.

3404{
3405 jbv->type = jbvNumeric;
3406 jbv->val.numeric = DatumGetNumeric(num);
3407}

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

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

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

Definition at line 3321 of file jsonpath_exec.c.

3322{
3323 switch (typid)
3324 {
3325 case BOOLOID:
3326 res->type = jbvBool;
3327 res->val.boolean = DatumGetBool(val);
3328 break;
3329 case NUMERICOID:
3331 break;
3332 case INT2OID:
3334 break;
3335 case INT4OID:
3337 break;
3338 case INT8OID:
3340 break;
3341 case FLOAT4OID:
3343 break;
3344 case FLOAT8OID:
3346 break;
3347 case TEXTOID:
3348 case VARCHAROID:
3349 res->type = jbvString;
3350 res->val.string.val = VARDATA_ANY(DatumGetPointer(val));
3351 res->val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(val));
3352 break;
3353 case DATEOID:
3354 case TIMEOID:
3355 case TIMETZOID:
3356 case TIMESTAMPOID:
3357 case TIMESTAMPTZOID:
3358 res->type = jbvDatetime;
3359 res->val.datetime.value = val;
3360 res->val.datetime.typid = typid;
3361 res->val.datetime.typmod = typmod;
3362 res->val.datetime.tz = 0;
3363 break;
3364 case JSONBOID:
3365 {
3366 JsonbValue *jbv = res;
3368
3369 if (JsonContainerIsScalar(&jb->root))
3370 {
3372
3373 result = JsonbExtractScalar(&jb->root, jbv);
3374 Assert(result);
3375 }
3376 else
3378 break;
3379 }
3380 case JSONOID:
3381 {
3383 char *str = text_to_cstring(txt);
3384 Jsonb *jb;
3385
3388 pfree(str);
3389
3391 break;
3392 }
3393 default:
3394 ereport(ERROR,
3396 errmsg("could not convert value of type %s to jsonpath",
3397 format_type_be(typid)));
3398 }
3399}
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4643
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4495
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:308
#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 Datum CStringGetDatum(const char *X)
Definition postgres.h:383
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 4210 of file jsonpath_exec.c.

4211{
4213
4214 res = executeJsonPath(jp, vars,
4216 DatumGetJsonbP(jb), !error, NULL, true);
4217
4218 Assert(error || !jperIsError(res));
4219
4220 if (error && jperIsError(res))
4221 *error = true;
4222
4223 return res == jperOk;
4224}
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 4233 of file jsonpath_exec.c.

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

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

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

4493{
4495 GetJsonTableExecContext(state, "JsonTableDestroyOpaque");
4496
4497 /* not valid anymore */
4498 cxt->magic = 0;
4499
4500 state->opaque = NULL;
4501}
static JsonTableExecContext * GetJsonTableExecContext(TableFuncScanState *state, const char *fname)

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

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4785 of file jsonpath_exec.c.

4786{
4788 GetJsonTableExecContext(state, "JsonTableFetchRow");
4789
4791}
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 4801 of file jsonpath_exec.c.

4803{
4805 GetJsonTableExecContext(state, "JsonTableGetValue");
4806 ExprContext *econtext = state->ss.ps.ps_ExprContext;
4807 ExprState *estate = list_nth(state->colvalexprs, colnum);
4808 JsonTablePlanState *planstate = cxt->colplanstates[colnum];
4809 JsonTablePlanRowSource *current = &planstate->current;
4810 Datum result;
4811
4812 /* Row pattern value is NULL */
4813 if (current->isnull)
4814 {
4815 result = (Datum) 0;
4816 *isnull = true;
4817 }
4818 /* Evaluate JsonExpr. */
4819 else if (estate)
4820 {
4822 bool saved_caseIsNull = econtext->caseValue_isNull;
4823
4824 /* Pass the row pattern value via CaseTestExpr. */
4825 econtext->caseValue_datum = current->value;
4826 econtext->caseValue_isNull = false;
4827
4828 result = ExecEvalExpr(estate, econtext, isnull);
4829
4830 econtext->caseValue_datum = saved_caseValue;
4832 }
4833 /* ORDINAL column */
4834 else
4835 {
4836 result = Int32GetDatum(planstate->ordinal);
4837 *isnull = false;
4838 }
4839
4840 return result;
4841}
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:401
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 4428 of file jsonpath_exec.c.

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

4512{
4514
4515 planstate->plan = plan;
4516 planstate->parent = parentstate;
4517 JsonValueListInit(&planstate->found);
4518
4520 {
4522 int i;
4523
4524 planstate->outerJoin = scan->outerJoin;
4525 planstate->path = DatumGetJsonPathP(scan->path->value->constvalue);
4526 planstate->args = args;
4527 planstate->mcxt = AllocSetContextCreate(mcxt, "JsonTableExecContext",
4529
4530 /* No row pattern evaluated yet. */
4531 planstate->current.value = PointerGetDatum(NULL);
4532 planstate->current.isnull = true;
4533
4534 for (i = scan->colMin; i >= 0 && i <= scan->colMax; i++)
4535 cxt->colplanstates[i] = planstate;
4536
4537 planstate->nested = scan->child ?
4538 JsonTableInitPlan(cxt, scan->child, planstate, args, mcxt) : NULL;
4539 }
4540 else if (IsA(plan, JsonTableSiblingJoin))
4541 {
4543
4544 planstate->cross = join->cross;
4545
4546 planstate->left = JsonTableInitPlan(cxt, join->lplan, parentstate,
4547 args, mcxt);
4548 planstate->right = JsonTableInitPlan(cxt, join->rplan, parentstate,
4549 args, mcxt);
4550 }
4551
4552 return planstate;
4553}
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:1919
Const * value
Definition primnodes.h:1892
struct JsonTablePlanState * left
JsonValueList found
struct JsonTablePlanState * nested
MemoryContext mcxt
struct JsonTablePlanState * parent
JsonTablePlan * plan
struct JsonTablePlanState * right
JsonTablePlan * rplan
Definition primnodes.h:1950
JsonTablePlan * lplan
Definition primnodes.h:1949

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

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4609 of file jsonpath_exec.c.

4610{
4611 if (IsA(planstate->plan, JsonTableSiblingJoin))
4612 {
4613 if (planstate->advanceRight)
4614 {
4615 /* fetch next inner row */
4616 if (JsonTablePlanNextRow(planstate->right))
4617 return true;
4618
4619 /* inner rows are exhausted */
4620 if (planstate->cross)
4621 planstate->advanceRight = false; /* next outer row */
4622 else
4623 return false; /* end of scan */
4624 }
4625
4626 while (!planstate->advanceRight)
4627 {
4628 /* fetch next outer row */
4629 bool more = JsonTablePlanNextRow(planstate->left);
4630
4631 if (planstate->cross)
4632 {
4633 if (!more)
4634 return false; /* end of scan */
4635
4636 JsonTableRescan(planstate->right);
4637
4638 if (!JsonTablePlanNextRow(planstate->right))
4639 continue; /* next outer row */
4640
4641 planstate->advanceRight = true; /* next inner row */
4642 }
4643 else if (!more)
4644 {
4645 if (!JsonTablePlanNextRow(planstate->right))
4646 return false; /* end of scan */
4647
4648 planstate->advanceRight = true; /* next inner row */
4649 }
4650
4651 break;
4652 }
4653 }
4654 else
4655 {
4656 /* reset context item if requested */
4657 if (planstate->reset)
4658 {
4659 JsonTablePlanState *parent = planstate->parent;
4660
4661 Assert(parent != NULL && !parent->current.isnull);
4662 JsonTableResetRowPattern(planstate, parent->current.value);
4663 planstate->reset = false;
4664 }
4665
4666 if (planstate->advanceNested)
4667 {
4668 /* fetch next nested row */
4669 planstate->advanceNested = JsonTablePlanNextRow(planstate->nested);
4670 if (planstate->advanceNested)
4671 return true;
4672 }
4673
4674 for (;;)
4675 {
4676 if (!JsonTablePlanScanNextRow(planstate))
4677 return false;
4678
4679 if (planstate->nested == NULL)
4680 break;
4681
4682 JsonTableResetNestedPlan(planstate->nested);
4683 planstate->advanceNested = JsonTablePlanNextRow(planstate->nested);
4684
4685 if (!planstate->advanceNested && !planstate->outerJoin)
4686 continue;
4687
4688 /*
4689 * We have a row to return: either the nested plan produced one,
4690 * or this is an outer join and we emit the parent row with the
4691 * nested columns set to NULL.
4692 */
4693 break;
4694 }
4695 }
4696
4697 return true;
4698}
static void JsonTableResetRowPattern(JsonTablePlanState *planstate, Datum item)
static void JsonTableRescan(JsonTablePlanState *planstate)
static void JsonTableResetNestedPlan(JsonTablePlanState *planstate)
static bool JsonTablePlanScanNextRow(JsonTablePlanState *planstate)

References JsonTablePlanState::advanceNested, JsonTablePlanState::advanceRight, Assert, JsonTablePlanState::cross, JsonTablePlanState::current, fb(), IsA, JsonTablePlanRowSource::isnull, JsonTablePlanNextRow(), JsonTablePlanScanNextRow(), JsonTableRescan(), JsonTableResetNestedPlan(), JsonTableResetRowPattern(), JsonTablePlanState::left, JsonTablePlanState::nested, JsonTablePlanState::outerJoin, JsonTablePlanState::parent, JsonTablePlanState::plan, JsonTablePlanState::reset, JsonTablePlanState::right, and JsonTablePlanRowSource::value.

Referenced by JsonTableFetchRow(), and JsonTablePlanNextRow().

◆ JsonTablePlanScanNextRow()

static bool JsonTablePlanScanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4709 of file jsonpath_exec.c.

4710{
4711 JsonbValue *jbv;
4713
4714 /* Fetch new row from the list of found values to set as active. */
4715 jbv = JsonValueListNext(&planstate->iter);
4716
4717 /* End of list? */
4718 if (jbv == NULL)
4719 {
4720 planstate->current.value = PointerGetDatum(NULL);
4721 planstate->current.isnull = true;
4722 return false;
4723 }
4724
4725 /*
4726 * Set current row item for subsequent JsonTableGetValue() calls for
4727 * evaluating individual columns.
4728 */
4729 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4731 planstate->current.isnull = false;
4733
4734 /* Next row! */
4735 planstate->ordinal++;
4736
4737 /* There are more rows. */
4738 return true;
4739}
JsonValueListIterator iter

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

Referenced by JsonTablePlanNextRow().

◆ JsonTableRescan()

static void JsonTableRescan ( JsonTablePlanState planstate)
static

Definition at line 4845 of file jsonpath_exec.c.

4846{
4847 if (IsA(planstate->plan, JsonTablePathScan))
4848 {
4849 /* Reset plan iterator to the beginning of the item list */
4850 JsonValueListInitIterator(&planstate->found, &planstate->iter);
4851 planstate->current.value = PointerGetDatum(NULL);
4852 planstate->current.isnull = true;
4853 planstate->ordinal = 0;
4854
4855 if (planstate->nested)
4856 JsonTableRescan(planstate->nested);
4857 }
4858 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4859 {
4860 JsonTableRescan(planstate->left);
4861 JsonTableRescan(planstate->right);
4862 planstate->advanceRight = false;
4863 }
4864}

References JsonTablePlanState::advanceRight, JsonTablePlanState::current, fb(), JsonTablePlanState::found, IsA, JsonTablePlanRowSource::isnull, JsonTablePlanState::iter, JsonTableRescan(), JsonValueListInitIterator(), JsonTablePlanState::left, JsonTablePlanState::nested, JsonTablePlanState::ordinal, JsonTablePlanState::plan, PointerGetDatum, JsonTablePlanState::right, and JsonTablePlanRowSource::value.

Referenced by JsonTablePlanNextRow(), JsonTableRescan(), JsonTableResetNestedPlan(), and JsonTableResetRowPattern().

◆ JsonTableResetNestedPlan()

static void JsonTableResetNestedPlan ( JsonTablePlanState planstate)
static

Definition at line 4746 of file jsonpath_exec.c.

4747{
4748 /* This better be a child plan. */
4749 Assert(planstate->parent != NULL);
4750 if (IsA(planstate->plan, JsonTablePathScan))
4751 {
4752 JsonTablePlanState *parent = planstate->parent;
4753
4754 planstate->reset = true;
4755 planstate->advanceNested = false;
4756
4757 if (planstate->nested)
4758 JsonTableResetNestedPlan(planstate->nested);
4759
4760 /*
4761 * Reset this plan's transient scan state so that its columns read as
4762 * NULL until it is actually advanced. Re-evaluating the path against
4763 * the new parent row is deferred (see the reset flag) until the plan
4764 * is advanced by JsonTablePlanNextRow(), so that the path is not
4765 * evaluated more than once per parent row.
4766 */
4767 if (!parent->current.isnull)
4768 JsonTableRescan(planstate);
4769 }
4770 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4771 {
4772 JsonTableResetNestedPlan(planstate->left);
4773 JsonTableResetNestedPlan(planstate->right);
4774 planstate->advanceRight = false;
4775 }
4776}

References JsonTablePlanState::advanceNested, JsonTablePlanState::advanceRight, Assert, JsonTablePlanState::current, fb(), IsA, JsonTablePlanRowSource::isnull, JsonTableRescan(), JsonTableResetNestedPlan(), JsonTablePlanState::left, JsonTablePlanState::nested, JsonTablePlanState::parent, JsonTablePlanState::plan, JsonTablePlanState::reset, and JsonTablePlanState::right.

Referenced by JsonTablePlanNextRow(), and JsonTableResetNestedPlan().

◆ JsonTableResetRowPattern()

static void JsonTableResetRowPattern ( JsonTablePlanState planstate,
Datum  item 
)
static

Definition at line 4573 of file jsonpath_exec.c.

4574{
4575 JsonTablePathScan *scan = castNode(JsonTablePathScan, planstate->plan);
4578 Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
4579
4580 JsonValueListClear(&planstate->found);
4581
4582 MemoryContextResetOnly(planstate->mcxt);
4583
4584 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4585
4586 res = executeJsonPath(planstate->path, planstate->args,
4588 js, scan->errorOnError,
4589 &planstate->found,
4590 true);
4591
4593
4594 if (jperIsError(res))
4595 {
4596 Assert(!scan->errorOnError);
4597 JsonValueListClear(&planstate->found);
4598 }
4599
4600 JsonTableRescan(planstate);
4601}
void MemoryContextResetOnly(MemoryContext context)
Definition mcxt.c:425

References JsonTablePlanState::args, Assert, castNode, CountJsonPathVars(), DatumGetJsonbP(), JsonTablePathScan::errorOnError, executeJsonPath(), fb(), JsonTablePlanState::found, GetJsonPathVar(), jperIsError, JsonTableRescan(), JsonValueListClear(), JsonTablePlanState::mcxt, MemoryContextResetOnly(), MemoryContextSwitchTo(), JsonTablePlanState::path, and JsonTablePlanState::plan.

Referenced by JsonTablePlanNextRow(), and JsonTableSetDocument().

◆ JsonTableSetDocument()

static void JsonTableSetDocument ( TableFuncScanState state,
Datum  value 
)
static

◆ JsonValueListAppend()

static void JsonValueListAppend ( JsonValueList jvl,
const JsonbValue jbv 
)
static

Definition at line 3821 of file jsonpath_exec.c.

3822{
3823 JsonValueList *last = jvl->last;
3824
3825 if (last->nitems < last->maxitems)
3826 {
3827 /* there's still room in the last existing chunk */
3828 last->items[last->nitems] = *jbv;
3829 last->nitems++;
3830 }
3831 else
3832 {
3833 /* need a new last chunk */
3835 int nxtsize;
3836
3837 nxtsize = last->maxitems * 2; /* double the size with each chunk */
3838 nxtsize = Max(nxtsize, MIN_EXTRA_JVL_ITEMS); /* but at least this */
3840 nxtsize * sizeof(JsonbValue));
3841 nxt->nitems = 1;
3842 nxt->maxitems = nxtsize;
3843 nxt->next = NULL;
3844 nxt->items[0] = *jbv;
3845 last->next = nxt;
3846 jvl->last = nxt;
3847 }
3848}
#define Max(x, y)
Definition c.h:1125
#define MIN_EXTRA_JVL_ITEMS
void * palloc(Size size)
Definition mcxt.c:1390
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 3803 of file jsonpath_exec.c.

3804{
3806
3807 /* Release any extra chunks */
3808 for (JsonValueList *chunk = jvl->next; chunk != NULL; chunk = nxt)
3809 {
3810 nxt = chunk->next;
3811 pfree(chunk);
3812 }
3813 /* ... and reset to empty */
3814 jvl->nitems = 0;
3815 Assert(jvl->maxitems == BASE_JVL_ITEMS);
3816 jvl->next = NULL;
3817 jvl->last = jvl;
3818}
#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 3869 of file jsonpath_exec.c.

3870{
3871#if BASE_JVL_ITEMS > 1
3872 /* We need not examine extra chunks in this case */
3873 return (jvl->nitems > 1);
3874#else
3875 return (jvl->nitems == 1 && jvl->next != NULL);
3876#endif
3877}

References fb().

Referenced by JsonPathQuery(), and JsonPathValue().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 3880 of file jsonpath_exec.c.

3881{
3882 Assert(jvl->nitems > 0);
3883 return &jvl->items[0];
3884}

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

3892{
3893 it->chunk = jvl;
3894 it->nextitem = 0;
3895}

References fb().

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

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( const JsonValueList jvl)
static

Definition at line 3851 of file jsonpath_exec.c.

3852{
3853 /* We need not examine extra chunks for this */
3854 return (jvl->nitems == 0);
3855}

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

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

References fb().

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

◆ JsonValueListNext()

static JsonbValue * JsonValueListNext ( JsonValueListIterator it)
static

Definition at line 3902 of file jsonpath_exec.c.

3903{
3904 if (it->chunk == NULL)
3905 return NULL;
3906 if (it->nextitem >= it->chunk->nitems)
3907 {
3908 it->chunk = it->chunk->next;
3909 if (it->chunk == NULL)
3910 return NULL;
3911 it->nextitem = 0;
3912 Assert(it->chunk->nitems > 0);
3913 }
3914 return &it->chunk->items[it->nextitem++];
3915}

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

3779{
3780 JsonBaseObjectInfo baseObject = cxt->baseObject;
3781
3782 cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
3783 (JsonbContainer *) jbv->val.binary.data;
3784 cxt->baseObject.id = id;
3785
3786 return baseObject;
3787}

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

3970{
3971 JsonbInState ps = {0};
3973 JsonbValue *jbv;
3974
3976
3978 while ((jbv = JsonValueListNext(&it)))
3980
3982
3983 return ps.result;
3984}
@ 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 408 of file jsonpath_exec.c.

409{
410 .InitOpaque = JsonTableInitOpaque,
411 .SetDocument = JsonTableSetDocument,
412 .SetNamespace = NULL,
413 .SetRowFilter = NULL,
414 .SetColumnFilter = NULL,
415 .FetchRow = JsonTableFetchRow,
416 .GetValue = JsonTableGetValue,
417 .DestroyOpaque = JsonTableDestroyOpaque
418};

Referenced by ExecInitTableFuncScan().