PostgreSQL Source Code git master
Loading...
Searching...
No Matches
jsonpath_exec.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "nodes/nodeFuncs.h"
#include "regex/regex.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/float.h"
#include "utils/formatting.h"
#include "utils/json.h"
#include "utils/jsonpath.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
Include dependency graph for jsonpath_exec.c:

Go to the source code of this file.

Data Structures

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

Macros

#define jperIsError(jper)   ((jper) == jperError)
 
#define BASE_JVL_ITEMS   2 /* number of items a base chunk holds */
 
#define MIN_EXTRA_JVL_ITEMS   16 /* min number of items an extra chunk holds */
 
#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867
 
#define jspStrictAbsenceOfErrors(cxt)   (!(cxt)->laxMode)
 
#define jspAutoUnwrap(cxt)   ((cxt)->laxMode)
 
#define jspAutoWrap(cxt)   ((cxt)->laxMode)
 
#define jspIgnoreStructuralErrors(cxt)   ((cxt)->ignoreStructuralErrors)
 
#define jspThrowErrors(cxt)   ((cxt)->throwErrors)
 
#define RETURN_ERROR(throw_error)
 

Typedefs

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

Enumerations

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

Functions

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

Variables

const TableFuncRoutine JsonbTableRoutine
 

Macro Definition Documentation

◆ BASE_JVL_ITEMS

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

Definition at line 168 of file jsonpath_exec.c.

◆ jperIsError

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

Definition at line 142 of file jsonpath_exec.c.

◆ JSON_TABLE_EXEC_CONTEXT_MAGIC

#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867

Definition at line 246 of file jsonpath_exec.c.

◆ jspAutoUnwrap

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

Definition at line 264 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 265 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 266 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

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

Definition at line 263 of file jsonpath_exec.c.

◆ jspThrowErrors

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

Definition at line 267 of file jsonpath_exec.c.

◆ MIN_EXTRA_JVL_ITEMS

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

Definition at line 169 of file jsonpath_exec.c.

◆ RETURN_ERROR

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

Definition at line 270 of file jsonpath_exec.c.

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

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 282 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

◆ JsonPathCountVarsCallback

typedef int(* JsonPathCountVarsCallback) (void *vars)

Definition at line 91 of file jsonpath_exec.c.

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathGetVarCallback

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

Definition at line 89 of file jsonpath_exec.c.

◆ JsonPathPredicateCallback

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

Definition at line 278 of file jsonpath_exec.c.

◆ JsonTableExecContext

◆ JsonTablePlanRowSource

◆ JsonTablePlanState

◆ JsonValueList

◆ JsonValueListIterator

Enumeration Type Documentation

◆ JsonPathBool

Enumerator
jpbFalse 
jpbTrue 
jpbUnknown 

Definition at line 127 of file jsonpath_exec.c.

128{
129 jpbFalse = 0,
130 jpbTrue = 1,
131 jpbUnknown = 2
JsonPathBool
@ jpbUnknown
@ jpbFalse
@ jpbTrue

◆ JsonPathExecResult

Enumerator
jperOk 
jperNotFound 
jperError 

Definition at line 135 of file jsonpath_exec.c.

136{
137 jperOk = 0,
138 jperNotFound = 1,
139 jperError = 2
JsonPathExecResult
@ jperNotFound
@ jperOk

Function Documentation

◆ appendBoolResult()

static JsonPathExecResult appendBoolResult ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonValueList found,
JsonPathBool  res 
)
static

Definition at line 3207 of file jsonpath_exec.c.

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

3532{
3533 int cmp;
3534
3535 cmp = memcmp(s1, s2, Min(len1, len2));
3536
3537 if (cmp != 0)
3538 return cmp;
3539
3540 if (len1 == len2)
3541 return 0;
3542
3543 return len1 < len2 ? -1 : 1;
3544}
#define Min(x, y)
Definition c.h:1091
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)

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

Referenced by compareStrings().

◆ castTimeToTimeTz()

static Datum castTimeToTimeTz ( Datum  time,
bool  useTz 
)
static

Definition at line 4005 of file jsonpath_exec.c.

4006{
4007 checkTimezoneIsUsedForCast(useTz, "time", "timetz");
4008
4009 return DirectFunctionCall1(time_timetz, time);
4010}
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 3993 of file jsonpath_exec.c.

3994{
3995 if (!useTz)
3996 ereport(ERROR,
3998 errmsg("cannot convert value from %s to %s without time zone usage",
3999 type1, type2),
4000 errhint("Use *_tz() function for time zone support.")));
4001}
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 4017 of file jsonpath_exec.c.

4018{
4020}
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 4026 of file jsonpath_exec.c.

4027{
4028 checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
4029
4031}
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 4037 of file jsonpath_exec.c.

4038{
4039 checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
4040
4042}
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 4050 of file jsonpath_exec.c.

4052{
4054
4055 *cast_error = false;
4056
4057 switch (typid1)
4058 {
4059 case DATEOID:
4060 switch (typid2)
4061 {
4062 case DATEOID:
4063 cmpfunc = date_cmp;
4064
4065 break;
4066
4067 case TIMESTAMPOID:
4070 useTz);
4071
4072 case TIMESTAMPTZOID:
4075 useTz);
4076
4077 case TIMEOID:
4078 case TIMETZOID:
4079 *cast_error = true; /* uncomparable types */
4080 return 0;
4081
4082 default:
4083 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4084 typid2);
4085 }
4086 break;
4087
4088 case TIMEOID:
4089 switch (typid2)
4090 {
4091 case TIMEOID:
4092 cmpfunc = time_cmp;
4093
4094 break;
4095
4096 case TIMETZOID:
4097 val1 = castTimeToTimeTz(val1, useTz);
4099
4100 break;
4101
4102 case DATEOID:
4103 case TIMESTAMPOID:
4104 case TIMESTAMPTZOID:
4105 *cast_error = true; /* uncomparable types */
4106 return 0;
4107
4108 default:
4109 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4110 typid2);
4111 }
4112 break;
4113
4114 case TIMETZOID:
4115 switch (typid2)
4116 {
4117 case TIMEOID:
4118 val2 = castTimeToTimeTz(val2, useTz);
4120
4121 break;
4122
4123 case TIMETZOID:
4125
4126 break;
4127
4128 case DATEOID:
4129 case TIMESTAMPOID:
4130 case TIMESTAMPTZOID:
4131 *cast_error = true; /* uncomparable types */
4132 return 0;
4133
4134 default:
4135 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4136 typid2);
4137 }
4138 break;
4139
4140 case TIMESTAMPOID:
4141 switch (typid2)
4142 {
4143 case DATEOID:
4146 useTz);
4147
4148 case TIMESTAMPOID:
4150
4151 break;
4152
4153 case TIMESTAMPTZOID:
4156 useTz);
4157
4158 case TIMEOID:
4159 case TIMETZOID:
4160 *cast_error = true; /* uncomparable types */
4161 return 0;
4162
4163 default:
4164 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4165 typid2);
4166 }
4167 break;
4168
4169 case TIMESTAMPTZOID:
4170 switch (typid2)
4171 {
4172 case DATEOID:
4175 useTz);
4176
4177 case TIMESTAMPOID:
4180 useTz);
4181
4182 case TIMESTAMPTZOID:
4184
4185 break;
4186
4187 case TIMEOID:
4188 case TIMETZOID:
4189 *cast_error = true; /* uncomparable types */
4190 return 0;
4191
4192 default:
4193 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
4194 typid2);
4195 }
4196 break;
4197
4198 default:
4199 elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
4200 }
4201
4202 if (*cast_error)
4203 return 0; /* cast error */
4204
4206}
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 3618 of file jsonpath_exec.c.

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

3715{
3718 NumericGetDatum(b)));
3719}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition numeric.c:2417
int b
Definition isn.c:74
int a
Definition isn.c:73
static Datum NumericGetDatum(Numeric X)
Definition numeric.h:76

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

Referenced by compareItems().

◆ compareStrings()

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

Definition at line 3551 of file jsonpath_exec.c.

3553{
3556 {
3557 /*
3558 * It's known property of UTF-8 strings that their per-byte comparison
3559 * result matches codepoints comparison result. ASCII can be
3560 * considered as special case of UTF-8.
3561 */
3563 }
3564 else
3565 {
3566 char *utf8str1,
3567 *utf8str2;
3568 int cmp,
3569 utf8len1,
3570 utf8len2;
3571
3572 /*
3573 * We have to convert other encodings to UTF-8 first, then compare.
3574 * Input strings may be not null-terminated and pg_server_to_any() may
3575 * return them "as is". So, use strlen() only if there is real
3576 * conversion.
3577 */
3582
3584
3585 /*
3586 * If pg_server_to_any() did no real conversion, then we actually
3587 * compared original strings. So, we already done.
3588 */
3589 if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
3590 return cmp;
3591
3592 /* Free memory if needed */
3593 if (mbstr1 != utf8str1)
3594 pfree(utf8str1);
3595 if (mbstr2 != utf8str2)
3596 pfree(utf8str2);
3597
3598 /*
3599 * When all Unicode codepoints are equal, return result of binary
3600 * comparison. In some edge cases, same characters may have different
3601 * representations in encoding. Then our behavior could diverge from
3602 * standard. However, that allow us to do simple binary comparison
3603 * for "==" operator, which is performance critical in typical cases.
3604 * In future to implement strict standard conformance, we can do
3605 * normalization of input JSON strings.
3606 */
3607 if (cmp == 0)
3609 else
3610 return cmp;
3611 }
3612}
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 3722 of file jsonpath_exec.c.

3723{
3725
3726 *dst = *src;
3727
3728 return dst;
3729}
#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 3313 of file jsonpath_exec.c.

3314{
3315 List *vars = (List *) cxt;
3316
3317 return list_length(vars);
3318}
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 3480 of file jsonpath_exec.c.

3481{
3482 Jsonb *vars = varsJsonb;
3483
3484 if (vars && !JsonContainerIsObject(&vars->root))
3485 {
3486 ereport(ERROR,
3488 errmsg("\"vars\" argument is not an object"),
3489 errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3490 }
3491
3492 /* count of base objects */
3493 return vars != NULL ? 1 : 0;
3494}
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define JsonContainerIsObject(jc)
Definition jsonb.h:210
Definition jsonb.h:215

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

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

◆ executeAnyItem()

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

Definition at line 1988 of file jsonpath_exec.c.

1991{
1994 int32 r;
1995 JsonbValue v;
1996
1998
1999 if (level > last)
2000 return res;
2001
2002 it = JsonbIteratorInit(jbc);
2003
2004 /*
2005 * Recursively iterate over jsonb objects/arrays
2006 */
2007 while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
2008 {
2009 if (r == WJB_KEY)
2010 {
2011 r = JsonbIteratorNext(&it, &v, true);
2012 Assert(r == WJB_VALUE);
2013 }
2014
2015 if (r == WJB_VALUE || r == WJB_ELEM)
2016 {
2017
2018 if (level >= first ||
2019 (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
2020 v.type != jbvBinary)) /* leaves only requested */
2021 {
2022 /* check expression */
2023 if (jsp)
2024 {
2025 if (ignoreStructuralErrors)
2026 {
2028
2030 cxt->ignoreStructuralErrors = true;
2031 res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2033 }
2034 else
2035 res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2036
2037 if (jperIsError(res))
2038 break;
2039
2040 if (res == jperOk && !found)
2041 break;
2042 }
2043 else if (found)
2044 JsonValueListAppend(found, &v);
2045 else
2046 return jperOk;
2047 }
2048
2049 if (level < last && v.type == jbvBinary)
2050 {
2051 res = executeAnyItem
2052 (cxt, jsp, v.val.binary.data, found,
2053 level + 1, first, last,
2054 ignoreStructuralErrors, unwrapNext);
2055
2056 if (jperIsError(res))
2057 break;
2058
2059 if (res == jperOk && found == NULL)
2060 break;
2061 }
2062 }
2063 }
2064
2065 return res;
2066}
#define PG_UINT32_MAX
Definition c.h:674
#define Assert(condition)
Definition c.h:943
int32_t int32
Definition c.h:620
@ WJB_KEY
Definition jsonb.h:23
@ WJB_DONE
Definition jsonb.h:22
@ WJB_VALUE
Definition jsonb.h:24
@ WJB_ELEM
Definition jsonb.h:25
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition jsonb_util.c:935
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition jsonb_util.c:973
static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
#define jperIsError(jper)
static void JsonValueListAppend(JsonValueList *jvl, const JsonbValue *jbv)
void check_stack_depth(void)
Definition stack_depth.c:95
char * val
Definition jsonb.h:266

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

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

◆ executeBinaryArithmExpr()

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

Definition at line 2173 of file jsonpath_exec.c.

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

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

Referenced by executeItemOptUnwrapTarget().

◆ executeBoolItem()

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

Definition at line 1824 of file jsonpath_exec.c.

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

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

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

◆ executeComparison()

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

Definition at line 3519 of file jsonpath_exec.c.

3520{
3522
3523 return compareItems(cmp->type, lv, rv, cxt->useTz);
3524}
static JsonPathBool compareItems(int32 op, JsonbValue *jb1, JsonbValue *jb2, bool useTz)

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

Referenced by executeBoolItem().

◆ executeDateTimeMethod()

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

Definition at line 2445 of file jsonpath_exec.c.

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

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

Referenced by executeItemOptUnwrapTarget().

◆ executeItem()

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

Definition at line 777 of file jsonpath_exec.c.

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

References executeItemOptUnwrapTarget(), fb(), and jspAutoUnwrap.

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

◆ executeItemOptUnwrapResult()

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

Definition at line 1763 of file jsonpath_exec.c.

1766{
1767 if (unwrap && jspAutoUnwrap(cxt))
1768 {
1772 JsonbValue *item;
1773
1775
1776 res = executeItem(cxt, jsp, jb, &seq);
1777
1778 if (jperIsError(res))
1779 {
1781 return res;
1782 }
1783
1785 while ((item = JsonValueListNext(&it)))
1786 {
1787 Assert(item->type != jbvArray);
1788
1789 if (JsonbType(item) == jbvArray)
1790 executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1791 else
1792 JsonValueListAppend(found, item);
1793 }
1794
1796
1797 return jperOk;
1798 }
1799
1800 return executeItem(cxt, jsp, jb, found);
1801}
static JsonbValue * JsonValueListNext(JsonValueListIterator *it)
static int JsonbType(JsonbValue *jb)
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
static void JsonValueListInitIterator(JsonValueList *jvl, JsonValueListIterator *it)

References Assert, executeItem(), executeItemUnwrapTargetArray(), fb(), jbvArray, jperIsError, jperOk, JsonbType(), JsonValueListAppend(), JsonValueListClear(), JsonValueListInit(), JsonValueListInitIterator(), JsonValueListNext(), jspAutoUnwrap, and JsonbValue::type.

Referenced by executeBinaryArithmExpr(), executeItemOptUnwrapResultNoThrow(), and executeUnaryArithmExpr().

◆ executeItemOptUnwrapResultNoThrow()

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

Definition at line 1807 of file jsonpath_exec.c.

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

References executeItemOptUnwrapResult(), fb(), and JsonPathExecContext::throwErrors.

Referenced by executeBoolItem(), and executePredicate().

◆ executeItemOptUnwrapTarget()

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

Definition at line 789 of file jsonpath_exec.c.

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

Referenced by executeAnyItem(), and executeItem().

◆ executeItemUnwrapTargetArray()

static JsonPathExecResult executeItemUnwrapTargetArray ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb,
JsonValueList found,
bool  unwrapElements 
)
static

Definition at line 1712 of file jsonpath_exec.c.

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

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

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

◆ executeJsonPath()

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

Definition at line 715 of file jsonpath_exec.c.

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

References Assert, JsonPathExecContext::baseObject, JsonPathExecContext::current, executeItem(), fb(), JsonPathExecContext::getVar, JsonPath::header, JsonBaseObjectInfo::id, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, JsonBaseObjectInfo::jbc, jperIsError, jperNotFound, jperOk, JsonbExtractScalar(), JsonbInitBinary(), JSONPATH_LAX, JsonValueListClear(), JsonValueListInit(), JsonValueListIsEmpty(), jspInit(), jspStrictAbsenceOfErrors, JsonPathExecContext::lastGeneratedObjectId, JsonPathExecContext::laxMode, result, JsonPathExecContext::root, Jsonb::root, JsonPathExecContext::throwErrors, JsonPathExecContext::useTz, and JsonPathExecContext::vars.

Referenced by jsonb_path_exists_internal(), jsonb_path_match_internal(), jsonb_path_query_array_internal(), jsonb_path_query_first_internal(), jsonb_path_query_internal(), JsonPathExists(), JsonPathQuery(), JsonPathValue(), and JsonTableResetRowPattern().

◆ executeKeyValueMethod()

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

Definition at line 3097 of file jsonpath_exec.c.

3099{
3102 JsonbContainer *jbc;
3111 int64 id;
3112 bool hasNext;
3113
3114 if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
3117 errmsg("jsonpath item method .%s() can only be applied to an object",
3118 jspOperationName(jsp->type)))));
3119
3120 jbc = jb->val.binary.data;
3121
3122 if (!JsonContainerSize(jbc))
3123 return jperNotFound; /* no key-value pairs */
3124
3126
3127 keystr.type = jbvString;
3128 keystr.val.string.val = "key";
3129 keystr.val.string.len = 3;
3130
3131 valstr.type = jbvString;
3132 valstr.val.string.val = "value";
3133 valstr.val.string.len = 5;
3134
3135 idstr.type = jbvString;
3136 idstr.val.string.val = "id";
3137 idstr.val.string.len = 2;
3138
3139 /* construct object id from its base object and offset inside that */
3140 id = jb->type != jbvBinary ? 0 :
3141 (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
3142 id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
3143
3144 idval.type = jbvNumeric;
3145 idval.val.numeric = int64_to_numeric(id);
3146
3147 it = JsonbIteratorInit(jbc);
3148
3149 while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
3150 {
3151 JsonBaseObjectInfo baseObject;
3152 JsonbValue obj;
3154 Jsonb *jsonb;
3155
3156 if (tok != WJB_KEY)
3157 continue;
3158
3159 res = jperOk;
3160
3161 if (!hasNext && !found)
3162 break;
3163
3164 tok = JsonbIteratorNext(&it, &val, true);
3165 Assert(tok == WJB_VALUE);
3166
3167 memset(&ps, 0, sizeof(ps));
3168
3170
3172 pushJsonbValue(&ps, WJB_VALUE, &key);
3173
3176
3179
3181
3182 jsonb = JsonbValueToJsonb(ps.result);
3183
3184 JsonbInitBinary(&obj, jsonb);
3185
3186 baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
3187
3188 res = executeNextItem(cxt, jsp, &next, &obj, found);
3189
3190 cxt->baseObject = baseObject;
3191
3192 if (jperIsError(res))
3193 return res;
3194
3195 if (res == jperOk && !found)
3196 break;
3197 }
3198
3199 return res;
3200}
#define INT64CONST(x)
Definition c.h:630
struct parser_state ps
#define JsonContainerSize(jc)
Definition jsonb.h:208
JsonbIteratorToken
Definition jsonb.h:21
@ WJB_END_OBJECT
Definition jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition jsonb.h:28
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition jsonb_util.c:583
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition jsonb_util.c:96

References Assert, JsonPathExecContext::baseObject, ereport, errcode(), errmsg, ERROR, executeNextItem(), fb(), JsonBaseObjectInfo::id, int64_to_numeric(), INT64CONST, JsonBaseObjectInfo::jbc, jbvBinary, jbvNumeric, jbvObject, jbvString, jperIsError, jperNotFound, jperOk, JsonbInitBinary(), JsonbIteratorInit(), JsonbIteratorNext(), JsonbType(), JsonbValueToJsonb(), JsonContainerSize, jspGetNext(), jspOperationName(), JsonPathExecContext::lastGeneratedObjectId, next, ps, pushJsonbValue(), RETURN_ERROR, setBaseObject(), val, WJB_BEGIN_OBJECT, WJB_DONE, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by executeItemOptUnwrapTarget().

◆ executeLikeRegex()

static JsonPathBool executeLikeRegex ( JsonPathItem jsp,
JsonbValue str,
JsonbValue rarg,
void param 
)
static

Definition at line 2373 of file jsonpath_exec.c.

2375{
2376 JsonLikeRegexContext *cxt = param;
2377
2378 if (!(str = getScalar(str, jbvString)))
2379 return jpbUnknown;
2380
2381 /* Cache regex text and converted flags. */
2382 if (!cxt->regex)
2383 {
2384 cxt->regex =
2385 cstring_to_text_with_len(jsp->content.like_regex.pattern,
2386 jsp->content.like_regex.patternlen);
2387 (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2388 &(cxt->cflags), NULL);
2389 }
2390
2391 if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2392 str->val.string.len,
2394 return jpbTrue;
2395
2396 return jpbFalse;
2397}
const char * str
bool jspConvertRegexFlags(uint32 xflags, int *result, struct Node *escontext)
bool RE_compile_and_execute(text *text_re, char *dat, int dat_len, int cflags, Oid collation, int nmatch, regmatch_t *pmatch)
Definition regexp.c:358

References JsonLikeRegexContext::cflags, cstring_to_text_with_len(), fb(), getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, jspConvertRegexFlags(), RE_compile_and_execute(), JsonLikeRegexContext::regex, and str.

Referenced by executeBoolItem().

◆ executeNestedBoolItem()

static JsonPathBool executeNestedBoolItem ( JsonPathExecContext cxt,
JsonPathItem jsp,
JsonbValue jb 
)
static

Definition at line 1967 of file jsonpath_exec.c.

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

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

Referenced by executeItemOptUnwrapTarget().

◆ executeNextItem()

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

Definition at line 1732 of file jsonpath_exec.c.

1735{
1736 JsonPathItem elem;
1737 bool hasNext;
1738
1739 if (!cur)
1740 hasNext = next != NULL;
1741 else if (next)
1743 else
1744 {
1745 next = &elem;
1747 }
1748
1749 if (hasNext)
1750 return executeItem(cxt, next, v, found);
1751
1752 if (found)
1753 JsonValueListAppend(found, v);
1754
1755 return jperOk;
1756}
struct cursor * cur
Definition ecpg.c:29

References cur, executeItem(), fb(), jperOk, JsonValueListAppend(), jspGetNext(), jspHasNext, and next.

Referenced by appendBoolResult(), executeBinaryArithmExpr(), executeDateTimeMethod(), executeItemOptUnwrapTarget(), executeKeyValueMethod(), executeNumericItemMethod(), executeStringInternalMethod(), and executeUnaryArithmExpr().

◆ executeNumericItemMethod()

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

Definition at line 2404 of file jsonpath_exec.c.

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

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

Referenced by executeItemOptUnwrapTarget().

◆ executePredicate()

static JsonPathBool executePredicate ( JsonPathExecContext cxt,
JsonPathItem pred,
JsonPathItem larg,
JsonPathItem rarg,
JsonbValue jb,
bool  unwrapRightArg,
JsonPathPredicateCallback  exec,
void param 
)
static

Definition at line 2079 of file jsonpath_exec.c.

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

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

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

Referenced by executeBoolItem().

◆ executeStringInternalMethod()

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

Definition at line 2905 of file jsonpath_exec.c.

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

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

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

Referenced by executeItemOptUnwrapTarget().

◆ getArrayIndex()

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

Definition at line 3736 of file jsonpath_exec.c.

3738{
3739 JsonbValue *jbv;
3740 JsonValueList found;
3744
3745 JsonValueListInit(&found);
3746
3747 res = executeItem(cxt, jsp, jb, &found);
3748
3749 if (jperIsError(res))
3750 {
3751 JsonValueListClear(&found);
3752 return res;
3753 }
3754
3755 if (!JsonValueListIsSingleton(&found) ||
3757 {
3758 JsonValueListClear(&found);
3761 errmsg("jsonpath array subscript is not a single numeric value"))));
3762 }
3763
3765 NumericGetDatum(jbv->val.numeric),
3766 Int32GetDatum(0));
3767
3769 (Node *) &escontext);
3770
3771 JsonValueListClear(&found);
3772
3773 if (escontext.error_occurred)
3776 errmsg("jsonpath array subscript is out of integer range"))));
3777
3778 return jperOk;
3779}
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition numeric.c:1582

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

Referenced by executeItemOptUnwrapTarget().

◆ getJsonPathItem()

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

Definition at line 3235 of file jsonpath_exec.c.

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

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

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

3452{
3453 Jsonb *vars = varsJsonb;
3454 JsonbValue tmp;
3456
3457 tmp.type = jbvString;
3458 tmp.val.string.val = varName;
3459 tmp.val.string.len = varNameLength;
3460
3462
3463 if (result == NULL)
3464 {
3465 *baseObjectId = -1;
3466 return NULL;
3467 }
3468
3469 *baseObjectId = 1;
3470 JsonbInitBinary(baseObject, vars);
3471
3472 return result;
3473}

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

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

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

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

◆ getScalar()

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

Definition at line 3963 of file jsonpath_exec.c.

3964{
3965 /* Scalars should be always extracted during jsonpath execution. */
3966 Assert(scalar->type != jbvBinary ||
3967 !JsonContainerIsScalar(scalar->val.binary.data));
3968
3969 return scalar->type == type ? scalar : NULL;
3970}
#define JsonContainerIsScalar(jc)
Definition jsonb.h:209
const char * type

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

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

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 455 of file jsonpath_exec.c.

456{
457 return jsonb_path_exists_internal(fcinfo, false);
458}
static Datum jsonb_path_exists_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_exists_internal().

◆ jsonb_path_exists_internal()

static Datum jsonb_path_exists_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 427 of file jsonpath_exec.c.

428{
432 Jsonb *vars = NULL;
433 bool silent = true;
434
435 if (PG_NARGS() == 4)
436 {
439 }
440
443 jb, !silent, NULL, tz);
444
447
448 if (jperIsError(res))
450
451 PG_RETURN_BOOL(res == jperOk);
452}
#define PG_FREE_IF_COPY(ptr, n)
Definition fmgr.h:260
#define PG_NARGS()
Definition fmgr.h:203
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define PG_GETARG_JSONB_P(x)
Definition jsonb.h:418
#define PG_GETARG_JSONPATH_P(x)
Definition jsonpath.h:46
static int countVariablesFromJsonb(void *varsJsonb)
static JsonbValue * getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, int varNameLength, JsonbValue *baseObject, int *baseObjectId)
static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars, JsonPathGetVarCallback getVar, JsonPathCountVarsCallback countVars, Jsonb *json, bool throwErrors, JsonValueList *result, bool useTz)

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

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

◆ jsonb_path_exists_opr()

Datum jsonb_path_exists_opr ( PG_FUNCTION_ARGS  )

Definition at line 472 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 461 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 527 of file jsonpath_exec.c.

528{
529 return jsonb_path_match_internal(fcinfo, false);
530}
static Datum jsonb_path_match_internal(FunctionCallInfo fcinfo, bool tz)

References jsonb_path_match_internal().

◆ jsonb_path_match_internal()

static Datum jsonb_path_match_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 484 of file jsonpath_exec.c.

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

References countVariablesFromJsonb(), ereport, errcode(), errmsg, ERROR, executeJsonPath(), fb(), getJsonPathVariableFromJsonb(), jbvBool, jbvNull, JsonValueListHead(), JsonValueListInit(), JsonValueListIsSingleton(), PG_FREE_IF_COPY, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_GETARG_JSONPATH_P, PG_NARGS, PG_RETURN_BOOL, and PG_RETURN_NULL.

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

◆ jsonb_path_match_opr()

Datum jsonb_path_match_opr ( PG_FUNCTION_ARGS  )

Definition at line 544 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 533 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 606 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ jsonb_path_query_array()

Datum jsonb_path_query_array ( PG_FUNCTION_ARGS  )

Definition at line 641 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_array_internal()

static Datum jsonb_path_query_array_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

◆ jsonb_path_query_array_tz()

Datum jsonb_path_query_array_tz ( PG_FUNCTION_ARGS  )

Definition at line 647 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 679 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_first_internal()

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 685 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 556 of file jsonpath_exec.c.

557{
560 JsonbValue *v;
561
562 if (SRF_IS_FIRSTCALL())
563 {
564 JsonPath *jp;
565 Jsonb *jb;
566 Jsonb *vars;
567 bool silent;
568 MemoryContext oldcontext;
569 JsonValueList *found;
570
572 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
573
578
580 JsonValueListInit(found);
581
584 jb, !silent, found, tz);
585
587 JsonValueListInitIterator(found, iter);
588
589 funcctx->user_fctx = iter;
590
591 MemoryContextSwitchTo(oldcontext);
592 }
593
595 iter = funcctx->user_fctx;
596
597 v = JsonValueListNext(iter);
598
599 if (v == NULL)
601
603}
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
#define PG_GETARG_JSONB_P_COPY(x)
Definition jsonb.h:419
static Datum JsonbPGetDatum(const Jsonb *p)
Definition jsonb.h:413
#define PG_GETARG_JSONPATH_P_COPY(x)
Definition jsonpath.h:47

References countVariablesFromJsonb(), executeJsonPath(), fb(), getJsonPathVariableFromJsonb(), JsonbPGetDatum(), JsonbValueToJsonb(), JsonValueListInit(), JsonValueListInitIterator(), JsonValueListNext(), MemoryContextSwitchTo(), palloc_object, PG_GETARG_BOOL, PG_GETARG_JSONB_P_COPY, PG_GETARG_JSONPATH_P_COPY, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, and SRF_RETURN_NEXT.

Referenced by jsonb_path_query(), and jsonb_path_query_tz().

◆ jsonb_path_query_tz()

Datum jsonb_path_query_tz ( PG_FUNCTION_ARGS  )

Definition at line 612 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3502 of file jsonpath_exec.c.

3503{
3504 Assert(jb->type != jbvArray);
3505
3506 if (jb->type == jbvBinary)
3507 {
3508 JsonbContainer *jbc = jb->val.binary.data;
3509
3511 return JsonContainerSize(jbc);
3512 }
3513
3514 return -1;
3515}
#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 3926 of file jsonpath_exec.c.

3927{
3928 jbv->type = jbvBinary;
3929 jbv->val.binary.data = &jb->root;
3930 jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3931
3932 return jbv;
3933}
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 3939 of file jsonpath_exec.c.

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

3409{
3410 jbv->type = jbvNumeric;
3411 jbv->val.numeric = DatumGetNumeric(num);
3412}

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

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

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

Definition at line 3326 of file jsonpath_exec.c.

3327{
3328 switch (typid)
3329 {
3330 case BOOLOID:
3331 res->type = jbvBool;
3332 res->val.boolean = DatumGetBool(val);
3333 break;
3334 case NUMERICOID:
3336 break;
3337 case INT2OID:
3339 break;
3340 case INT4OID:
3342 break;
3343 case INT8OID:
3345 break;
3346 case FLOAT4OID:
3348 break;
3349 case FLOAT8OID:
3351 break;
3352 case TEXTOID:
3353 case VARCHAROID:
3354 res->type = jbvString;
3355 res->val.string.val = VARDATA_ANY(DatumGetPointer(val));
3356 res->val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(val));
3357 break;
3358 case DATEOID:
3359 case TIMEOID:
3360 case TIMETZOID:
3361 case TIMESTAMPOID:
3362 case TIMESTAMPTZOID:
3363 res->type = jbvDatetime;
3364 res->val.datetime.value = val;
3365 res->val.datetime.typid = typid;
3366 res->val.datetime.typmod = typmod;
3367 res->val.datetime.tz = 0;
3368 break;
3369 case JSONBOID:
3370 {
3371 JsonbValue *jbv = res;
3373
3374 if (JsonContainerIsScalar(&jb->root))
3375 {
3377
3378 result = JsonbExtractScalar(&jb->root, jbv);
3379 Assert(result);
3380 }
3381 else
3383 break;
3384 }
3385 case JSONOID:
3386 {
3388 char *str = text_to_cstring(txt);
3389 Jsonb *jb;
3390
3393 pfree(str);
3394
3396 break;
3397 }
3398 default:
3399 ereport(ERROR,
3401 errmsg("could not convert value of type %s to jsonpath",
3402 format_type_be(typid)));
3403 }
3404}
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4637
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4489
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
#define DatumGetTextP(X)
Definition fmgr.h:333
char * format_type_be(Oid type_oid)
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition jsonb.c:64
static Jsonb * DatumGetJsonbP(Datum d)
Definition jsonb.h:401
static void JsonbValueInitNumericDatum(JsonbValue *jbv, Datum num)
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486

References Assert, CStringGetDatum(), DatumGetBool(), DatumGetJsonbP(), DatumGetPointer(), DatumGetTextP, DirectFunctionCall1, ereport, errcode(), errmsg, ERROR, fb(), float4_numeric(), float8_numeric(), format_type_be(), int2_numeric(), int4_numeric(), int8_numeric(), jbvBool, jbvDatetime, jbvString, jsonb_in(), JsonbExtractScalar(), JsonbInitBinary(), JsonbPGetDatum(), JsonbValueInitNumericDatum(), JsonContainerIsScalar, JsonItemFromDatum(), pfree(), PG_USED_FOR_ASSERTS_ONLY, result, str, text_to_cstring(), JsonbValue::type, JsonbValue::val, val, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Referenced by GetJsonPathVar(), and JsonItemFromDatum().

◆ JsonPathExists()

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

Definition at line 4215 of file jsonpath_exec.c.

4216{
4218
4219 res = executeJsonPath(jp, vars,
4221 DatumGetJsonbP(jb), !error, NULL, true);
4222
4223 Assert(error || !jperIsError(res));
4224
4225 if (error && jperIsError(res))
4226 *error = true;
4227
4228 return res == jperOk;
4229}
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 4238 of file jsonpath_exec.c.

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

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

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

4498{
4500 GetJsonTableExecContext(state, "JsonTableDestroyOpaque");
4501
4502 /* not valid anymore */
4503 cxt->magic = 0;
4504
4505 state->opaque = NULL;
4506}
static JsonTableExecContext * GetJsonTableExecContext(TableFuncScanState *state, const char *fname)

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

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 4760 of file jsonpath_exec.c.

4761{
4763 GetJsonTableExecContext(state, "JsonTableFetchRow");
4764
4766}
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 4776 of file jsonpath_exec.c.

4778{
4780 GetJsonTableExecContext(state, "JsonTableGetValue");
4781 ExprContext *econtext = state->ss.ps.ps_ExprContext;
4782 ExprState *estate = list_nth(state->colvalexprs, colnum);
4783 JsonTablePlanState *planstate = cxt->colplanstates[colnum];
4784 JsonTablePlanRowSource *current = &planstate->current;
4785 Datum result;
4786
4787 /* Row pattern value is NULL */
4788 if (current->isnull)
4789 {
4790 result = (Datum) 0;
4791 *isnull = true;
4792 }
4793 /* Evaluate JsonExpr. */
4794 else if (estate)
4795 {
4797 bool saved_caseIsNull = econtext->caseValue_isNull;
4798
4799 /* Pass the row pattern value via CaseTestExpr. */
4800 econtext->caseValue_datum = current->value;
4801 econtext->caseValue_isNull = false;
4802
4803 result = ExecEvalExpr(estate, econtext, isnull);
4804
4805 econtext->caseValue_datum = saved_caseValue;
4807 }
4808 /* ORDINAL column */
4809 else
4810 {
4811 result = Int32GetDatum(planstate->ordinal);
4812 *isnull = false;
4813 }
4814
4815 return result;
4816}
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:403
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
bool caseValue_isNull
Definition execnodes.h:314
Datum caseValue_datum
Definition execnodes.h:312
JsonTablePlanState ** colplanstates
JsonTablePlanRowSource current

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

◆ JsonTableInitOpaque()

static void JsonTableInitOpaque ( TableFuncScanState state,
int  natts 
)
static

Definition at line 4433 of file jsonpath_exec.c.

4434{
4436 PlanState *ps = &state->ss.ps;
4438 TableFunc *tf = tfs->tablefunc;
4439 JsonTablePlan *rootplan = (JsonTablePlan *) tf->plan;
4440 JsonExpr *je = castNode(JsonExpr, tf->docexpr);
4441 List *args = NIL;
4442
4444 cxt->magic = JSON_TABLE_EXEC_CONTEXT_MAGIC;
4445
4446 /*
4447 * Evaluate JSON_TABLE() PASSING arguments to be passed to the jsonpath
4448 * executor via JsonPathVariables.
4449 */
4450 if (state->passingvalexprs)
4451 {
4454
4455 Assert(list_length(state->passingvalexprs) ==
4456 list_length(je->passing_names));
4457 forboth(exprlc, state->passingvalexprs,
4458 namelc, je->passing_names)
4459 {
4463
4464 var->name = pstrdup(name->sval);
4465 var->namelen = strlen(var->name);
4466 var->typid = exprType((Node *) state->expr);
4467 var->typmod = exprTypmod((Node *) state->expr);
4468
4469 /*
4470 * Evaluate the expression and save the value to be returned by
4471 * GetJsonPathVar().
4472 */
4473 var->value = ExecEvalExpr(state, ps->ps_ExprContext,
4474 &var->isnull);
4475
4476 args = lappend(args, var);
4477 }
4478 }
4479
4480 cxt->colplanstates = palloc_array(JsonTablePlanState *, list_length(tf->colvalexprs));
4481
4482 /*
4483 * Initialize plan for the root path and, recursively, also any child
4484 * plans that compute the NESTED paths.
4485 */
4486 cxt->rootplanstate = JsonTableInitPlan(cxt, rootplan, NULL, args,
4488
4489 state->opaque = cxt;
4490}
#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:182
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define NIL
Definition pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
Definition value.h:64
const char * name

References Assert, castNode, JsonTableExecContext::colplanstates, CurrentMemoryContext, TableFunc::docexpr, ExecEvalExpr(), exprType(), exprTypmod(), fb(), forboth, JsonPathVariable::isnull, JSON_TABLE_EXEC_CONTEXT_MAGIC, JsonTableInitPlan(), lappend(), lfirst_node, list_length(), JsonTableExecContext::magic, name, JsonPathVariable::name, JsonPathVariable::namelen, NIL, palloc0_object, palloc_array, palloc_object, ps, pstrdup(), JsonTableExecContext::rootplanstate, JsonPathVariable::typid, JsonPathVariable::typmod, and JsonPathVariable::value.

◆ JsonTableInitPlan()

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

Definition at line 4514 of file jsonpath_exec.c.

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

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

Referenced by JsonTableInitOpaque(), and JsonTableInitPlan().

◆ JsonTablePlanJoinNextRow()

static bool JsonTablePlanJoinNextRow ( JsonTablePlanState planstate)
static

Definition at line 4733 of file jsonpath_exec.c.

4734{
4735
4736 /* Fetch row from left sibling. */
4737 if (!JsonTablePlanNextRow(planstate->left))
4738 {
4739 /*
4740 * Left sibling ran out of rows, so start fetching from the right
4741 * sibling.
4742 */
4743 if (!JsonTablePlanNextRow(planstate->right))
4744 {
4745 /* Right sibling ran out of rows too, so there are no more rows. */
4746 return false;
4747 }
4748 }
4749
4750 return true;
4751}

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

Referenced by JsonTablePlanNextRow().

◆ JsonTablePlanNextRow()

static bool JsonTablePlanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4615 of file jsonpath_exec.c.

4616{
4617 if (IsA(planstate->plan, JsonTablePathScan))
4618 return JsonTablePlanScanNextRow(planstate);
4619 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4620 return JsonTablePlanJoinNextRow(planstate);
4621 else
4622 elog(ERROR, "invalid JsonTablePlan %d", (int) planstate->plan->type);
4623
4624 Assert(false);
4625 /* Appease compiler */
4626 return false;
4627}
static bool JsonTablePlanScanNextRow(JsonTablePlanState *planstate)
static bool JsonTablePlanJoinNextRow(JsonTablePlanState *planstate)

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

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

◆ JsonTablePlanScanNextRow()

static bool JsonTablePlanScanNextRow ( JsonTablePlanState planstate)
static

Definition at line 4642 of file jsonpath_exec.c.

4643{
4644 JsonbValue *jbv;
4646
4647 /*
4648 * If planstate already has an active row and there is a nested plan,
4649 * check if it has an active row to join with the former.
4650 */
4651 if (!planstate->current.isnull)
4652 {
4653 if (planstate->nested && JsonTablePlanNextRow(planstate->nested))
4654 return true;
4655 }
4656
4657 /* Fetch new row from the list of found values to set as active. */
4658 jbv = JsonValueListNext(&planstate->iter);
4659
4660 /* End of list? */
4661 if (jbv == NULL)
4662 {
4663 planstate->current.value = PointerGetDatum(NULL);
4664 planstate->current.isnull = true;
4665 return false;
4666 }
4667
4668 /*
4669 * Set current row item for subsequent JsonTableGetValue() calls for
4670 * evaluating individual columns.
4671 */
4672 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4674 planstate->current.isnull = false;
4676
4677 /* Next row! */
4678 planstate->ordinal++;
4679
4680 /* Process nested plan(s), if any. */
4681 if (planstate->nested)
4682 {
4683 /* Re-evaluate the nested path using the above parent row. */
4684 JsonTableResetNestedPlan(planstate->nested);
4685
4686 /*
4687 * Now fetch the nested plan's current row to be joined against the
4688 * parent row. Any further nested plans' paths will be re-evaluated
4689 * recursively, level at a time, after setting each nested plan's
4690 * current row.
4691 */
4692 (void) JsonTablePlanNextRow(planstate->nested);
4693 }
4694
4695 /* There are more rows. */
4696 return true;
4697}
static void JsonTableResetNestedPlan(JsonTablePlanState *planstate)
JsonValueListIterator iter

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

Referenced by JsonTablePlanNextRow().

◆ JsonTableResetNestedPlan()

static void JsonTableResetNestedPlan ( JsonTablePlanState planstate)
static

Definition at line 4704 of file jsonpath_exec.c.

4705{
4706 /* This better be a child plan. */
4707 Assert(planstate->parent != NULL);
4708 if (IsA(planstate->plan, JsonTablePathScan))
4709 {
4710 JsonTablePlanState *parent = planstate->parent;
4711
4712 if (!parent->current.isnull)
4713 JsonTableResetRowPattern(planstate, parent->current.value);
4714
4715 /*
4716 * If this plan itself has a child nested plan, it will be reset when
4717 * the caller calls JsonTablePlanNextRow() on this plan.
4718 */
4719 }
4720 else if (IsA(planstate->plan, JsonTableSiblingJoin))
4721 {
4722 JsonTableResetNestedPlan(planstate->left);
4723 JsonTableResetNestedPlan(planstate->right);
4724 }
4725}
static void JsonTableResetRowPattern(JsonTablePlanState *planstate, Datum item)

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

Referenced by JsonTablePlanScanNextRow(), and JsonTableResetNestedPlan().

◆ JsonTableResetRowPattern()

static void JsonTableResetRowPattern ( JsonTablePlanState planstate,
Datum  item 
)
static

Definition at line 4575 of file jsonpath_exec.c.

4576{
4577 JsonTablePathScan *scan = castNode(JsonTablePathScan, planstate->plan);
4580 Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
4581
4582 JsonValueListClear(&planstate->found);
4583
4584 MemoryContextResetOnly(planstate->mcxt);
4585
4586 oldcxt = MemoryContextSwitchTo(planstate->mcxt);
4587
4588 res = executeJsonPath(planstate->path, planstate->args,
4590 js, scan->errorOnError,
4591 &planstate->found,
4592 true);
4593
4595
4596 if (jperIsError(res))
4597 {
4598 Assert(!scan->errorOnError);
4599 JsonValueListClear(&planstate->found);
4600 }
4601
4602 /* Reset plan iterator to the beginning of the item list */
4603 JsonValueListInitIterator(&planstate->found, &planstate->iter);
4604 planstate->current.value = PointerGetDatum(NULL);
4605 planstate->current.isnull = true;
4606 planstate->ordinal = 0;
4607}
void MemoryContextResetOnly(MemoryContext context)
Definition mcxt.c:425

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

Referenced by JsonTableResetNestedPlan(), and JsonTableSetDocument().

◆ JsonTableSetDocument()

static void JsonTableSetDocument ( TableFuncScanState state,
Datum  value 
)
static

◆ JsonValueListAppend()

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

Definition at line 3826 of file jsonpath_exec.c.

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

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

3875{
3876#if BASE_JVL_ITEMS > 1
3877 /* We need not examine extra chunks in this case */
3878 return (jvl->nitems > 1);
3879#else
3880 return (jvl->nitems == 1 && jvl->next != NULL);
3881#endif
3882}

References fb().

Referenced by JsonPathQuery(), and JsonPathValue().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 3885 of file jsonpath_exec.c.

3886{
3887 Assert(jvl->nitems > 0);
3888 return &jvl->items[0];
3889}

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

3897{
3898 it->chunk = jvl;
3899 it->nextitem = 0;
3900}

References fb().

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

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( const JsonValueList jvl)
static

Definition at line 3856 of file jsonpath_exec.c.

3857{
3858 /* We need not examine extra chunks for this */
3859 return (jvl->nitems == 0);
3860}

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

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

References fb().

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

◆ JsonValueListNext()

static JsonbValue * JsonValueListNext ( JsonValueListIterator it)
static

Definition at line 3907 of file jsonpath_exec.c.

3908{
3909 if (it->chunk == NULL)
3910 return NULL;
3911 if (it->nextitem >= it->chunk->nitems)
3912 {
3913 it->chunk = it->chunk->next;
3914 if (it->chunk == NULL)
3915 return NULL;
3916 it->nextitem = 0;
3917 Assert(it->chunk->nitems > 0);
3918 }
3919 return &it->chunk->items[it->nextitem++];
3920}

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

3784{
3785 JsonBaseObjectInfo baseObject = cxt->baseObject;
3786
3787 cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
3788 (JsonbContainer *) jbv->val.binary.data;
3789 cxt->baseObject.id = id;
3790
3791 return baseObject;
3792}

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

3975{
3976 JsonbInState ps = {0};
3978 JsonbValue *jbv;
3979
3981
3983 while ((jbv = JsonValueListNext(&it)))
3985
3987
3988 return ps.result;
3989}
@ WJB_END_ARRAY
Definition jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition jsonb.h:26

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

Referenced by jsonb_path_query_array_internal(), and JsonPathQuery().

Variable Documentation

◆ JsonbTableRoutine

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

Definition at line 400 of file jsonpath_exec.c.

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

Referenced by ExecInitTableFuncScan().