PostgreSQL Source Code  git master
jsonpath_exec.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "executor/execExpr.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/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
Include dependency graph for jsonpath_exec.c:

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

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

Variables

const TableFuncRoutine JsonbTableRoutine
 

Macro Definition Documentation

◆ jperIsError

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

Definition at line 143 of file jsonpath_exec.c.

◆ JSON_TABLE_EXEC_CONTEXT_MAGIC

#define JSON_TABLE_EXEC_CONTEXT_MAGIC   418352867

Definition at line 220 of file jsonpath_exec.c.

◆ jspAutoUnwrap

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

Definition at line 238 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 239 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 240 of file jsonpath_exec.c.

◆ jspStrictAbsenceOfErrors

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

Definition at line 237 of file jsonpath_exec.c.

◆ jspThrowErrors

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

Definition at line 241 of file jsonpath_exec.c.

◆ RETURN_ERROR

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

Definition at line 244 of file jsonpath_exec.c.

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 256 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

typedef enum JsonPathBool JsonPathBool

◆ JsonPathCountVarsCallback

typedef int(* JsonPathCountVarsCallback) (void *vars)

Definition at line 92 of file jsonpath_exec.c.

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathGetVarCallback

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

Definition at line 90 of file jsonpath_exec.c.

◆ JsonPathPredicateCallback

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

Definition at line 252 of file jsonpath_exec.c.

◆ JsonTableExecContext

◆ JsonTablePlanRowSource

◆ JsonTablePlanState

◆ JsonValueList

typedef struct JsonValueList JsonValueList

◆ JsonValueListIterator

Enumeration Type Documentation

◆ JsonPathBool

Enumerator
jpbFalse 
jpbTrue 
jpbUnknown 

Definition at line 128 of file jsonpath_exec.c.

129 {
130  jpbFalse = 0,
131  jpbTrue = 1,
132  jpbUnknown = 2
133 } JsonPathBool;
JsonPathBool
@ jpbUnknown
@ jpbFalse
@ jpbTrue

◆ JsonPathExecResult

Enumerator
jperOk 
jperNotFound 
jperError 

Definition at line 136 of file jsonpath_exec.c.

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

Function Documentation

◆ appendBoolResult()

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

Definition at line 2948 of file jsonpath_exec.c.

2950 {
2952  JsonbValue jbv;
2953 
2954  if (!jspGetNext(jsp, &next) && !found)
2955  return jperOk; /* found singleton boolean value */
2956 
2957  if (res == jpbUnknown)
2958  {
2959  jbv.type = jbvNull;
2960  }
2961  else
2962  {
2963  jbv.type = jbvBool;
2964  jbv.val.boolean = res == jpbTrue;
2965  }
2966 
2967  return executeNextItem(cxt, jsp, &next, &jbv, found, true);
2968 }
static int32 next
Definition: blutils.c:222
@ jbvBool
Definition: jsonb.h:231
@ jbvNull
Definition: jsonb.h:228
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1099
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264

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

Referenced by executeItemOptUnwrapTarget().

◆ binaryCompareStrings()

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

Definition at line 3271 of file jsonpath_exec.c.

3273 {
3274  int cmp;
3275 
3276  cmp = memcmp(s1, s2, Min(len1, len2));
3277 
3278  if (cmp != 0)
3279  return cmp;
3280 
3281  if (len1 == len2)
3282  return 0;
3283 
3284  return len1 < len2 ? -1 : 1;
3285 }
#define Min(x, y)
Definition: c.h:1004
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

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

Referenced by compareStrings().

◆ castTimeToTimeTz()

static Datum castTimeToTimeTz ( Datum  time,
bool  useTz 
)
static

Definition at line 3696 of file jsonpath_exec.c.

3697 {
3698  checkTimezoneIsUsedForCast(useTz, "time", "timetz");
3699 
3700  return DirectFunctionCall1(time_timetz, time);
3701 }
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2828
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
static void checkTimezoneIsUsedForCast(bool useTz, const char *type1, const char *type2)

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

Referenced by compareDatetime().

◆ checkTimezoneIsUsedForCast()

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

Definition at line 3684 of file jsonpath_exec.c.

3685 {
3686  if (!useTz)
3687  ereport(ERROR,
3688  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3689  errmsg("cannot convert value from %s to %s without time zone usage",
3690  type1, type2),
3691  errhint("Use *_tz() function for time zone support.")));
3692 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149

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

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

◆ cmpDateToTimestamp()

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

Definition at line 3708 of file jsonpath_exec.c.

3709 {
3710  return date_cmp_timestamp_internal(date1, ts2);
3711 }
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:743

References date_cmp_timestamp_internal().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 3717 of file jsonpath_exec.c.

3718 {
3719  checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
3720 
3721  return date_cmp_timestamptz_internal(date1, tstz2);
3722 }
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:823

References checkTimezoneIsUsedForCast(), and date_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

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

Definition at line 3728 of file jsonpath_exec.c.

3729 {
3730  checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
3731 
3732  return timestamp_cmp_timestamptz_internal(ts1, tstz2);
3733 }
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2306

References checkTimezoneIsUsedForCast(), and timestamp_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ compareDatetime()

static int compareDatetime ( Datum  val1,
Oid  typid1,
Datum  val2,
Oid  typid2,
bool  useTz,
bool cast_error 
)
static

Definition at line 3741 of file jsonpath_exec.c.

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

3360 {
3361  int cmp;
3362  bool res;
3363 
3364  if (jb1->type != jb2->type)
3365  {
3366  if (jb1->type == jbvNull || jb2->type == jbvNull)
3367 
3368  /*
3369  * Equality and order comparison of nulls to non-nulls returns
3370  * always false, but inequality comparison returns true.
3371  */
3372  return op == jpiNotEqual ? jpbTrue : jpbFalse;
3373 
3374  /* Non-null items of different types are not comparable. */
3375  return jpbUnknown;
3376  }
3377 
3378  switch (jb1->type)
3379  {
3380  case jbvNull:
3381  cmp = 0;
3382  break;
3383  case jbvBool:
3384  cmp = jb1->val.boolean == jb2->val.boolean ? 0 :
3385  jb1->val.boolean ? 1 : -1;
3386  break;
3387  case jbvNumeric:
3388  cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
3389  break;
3390  case jbvString:
3391  if (op == jpiEqual)
3392  return jb1->val.string.len != jb2->val.string.len ||
3393  memcmp(jb1->val.string.val,
3394  jb2->val.string.val,
3395  jb1->val.string.len) ? jpbFalse : jpbTrue;
3396 
3397  cmp = compareStrings(jb1->val.string.val, jb1->val.string.len,
3398  jb2->val.string.val, jb2->val.string.len);
3399  break;
3400  case jbvDatetime:
3401  {
3402  bool cast_error;
3403 
3404  cmp = compareDatetime(jb1->val.datetime.value,
3405  jb1->val.datetime.typid,
3406  jb2->val.datetime.value,
3407  jb2->val.datetime.typid,
3408  useTz,
3409  &cast_error);
3410 
3411  if (cast_error)
3412  return jpbUnknown;
3413  }
3414  break;
3415 
3416  case jbvBinary:
3417  case jbvArray:
3418  case jbvObject:
3419  return jpbUnknown; /* non-scalars are not comparable */
3420 
3421  default:
3422  elog(ERROR, "invalid jsonb value type %d", jb1->type);
3423  }
3424 
3425  switch (op)
3426  {
3427  case jpiEqual:
3428  res = (cmp == 0);
3429  break;
3430  case jpiNotEqual:
3431  res = (cmp != 0);
3432  break;
3433  case jpiLess:
3434  res = (cmp < 0);
3435  break;
3436  case jpiGreater:
3437  res = (cmp > 0);
3438  break;
3439  case jpiLessOrEqual:
3440  res = (cmp <= 0);
3441  break;
3442  case jpiGreaterOrEqual:
3443  res = (cmp >= 0);
3444  break;
3445  default:
3446  elog(ERROR, "unrecognized jsonpath operation: %d", op);
3447  return jpbUnknown;
3448  }
3449 
3450  return res ? jpbTrue : jpbFalse;
3451 }
@ jbvObject
Definition: jsonb.h:234
@ jbvNumeric
Definition: jsonb.h:230
@ jbvArray
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:236
@ jbvDatetime
Definition: jsonb.h:244
@ jbvString
Definition: jsonb.h:229
@ jpiNotEqual
Definition: jsonpath.h:73
@ jpiGreaterOrEqual
Definition: jsonpath.h:77
@ jpiGreater
Definition: jsonpath.h:75
@ jpiLess
Definition: jsonpath.h:74
@ jpiEqual
Definition: jsonpath.h:72
@ jpiLessOrEqual
Definition: jsonpath.h:76
static int compareStrings(const char *mbstr1, int mblen1, const char *mbstr2, int mblen2)
static int compareDatetime(Datum val1, Oid typid1, Datum val2, Oid typid2, bool useTz, bool *cast_error)
static int compareNumeric(Numeric a, Numeric b)

References cmp(), compareDatetime(), compareNumeric(), compareStrings(), elog, ERROR, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jpbFalse, jpbTrue, jpbUnknown, jpiEqual, jpiGreater, jpiGreaterOrEqual, jpiLess, jpiLessOrEqual, jpiNotEqual, res, JsonbValue::type, and JsonbValue::val.

Referenced by executeComparison().

◆ compareNumeric()

static int compareNumeric ( Numeric  a,
Numeric  b 
)
static

Definition at line 3455 of file jsonpath_exec.c.

3456 {
3458  NumericGetDatum(a),
3459  NumericGetDatum(b)));
3460 }
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2399
int b
Definition: isn.c:70
int a
Definition: isn.c:69
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73

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

Referenced by compareItems().

◆ compareStrings()

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

Definition at line 3292 of file jsonpath_exec.c.

3294 {
3295  if (GetDatabaseEncoding() == PG_SQL_ASCII ||
3297  {
3298  /*
3299  * It's known property of UTF-8 strings that their per-byte comparison
3300  * result matches codepoints comparison result. ASCII can be
3301  * considered as special case of UTF-8.
3302  */
3303  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
3304  }
3305  else
3306  {
3307  char *utf8str1,
3308  *utf8str2;
3309  int cmp,
3310  utf8len1,
3311  utf8len2;
3312 
3313  /*
3314  * We have to convert other encodings to UTF-8 first, then compare.
3315  * Input strings may be not null-terminated and pg_server_to_any() may
3316  * return them "as is". So, use strlen() only if there is real
3317  * conversion.
3318  */
3319  utf8str1 = pg_server_to_any(mbstr1, mblen1, PG_UTF8);
3320  utf8str2 = pg_server_to_any(mbstr2, mblen2, PG_UTF8);
3321  utf8len1 = (mbstr1 == utf8str1) ? mblen1 : strlen(utf8str1);
3322  utf8len2 = (mbstr2 == utf8str2) ? mblen2 : strlen(utf8str2);
3323 
3324  cmp = binaryCompareStrings(utf8str1, utf8len1, utf8str2, utf8len2);
3325 
3326  /*
3327  * If pg_server_to_any() did no real conversion, then we actually
3328  * compared original strings. So, we already done.
3329  */
3330  if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
3331  return cmp;
3332 
3333  /* Free memory if needed */
3334  if (mbstr1 != utf8str1)
3335  pfree(utf8str1);
3336  if (mbstr2 != utf8str2)
3337  pfree(utf8str2);
3338 
3339  /*
3340  * When all Unicode codepoints are equal, return result of binary
3341  * comparison. In some edge cases, same characters may have different
3342  * representations in encoding. Then our behavior could diverge from
3343  * standard. However, that allow us to do simple binary comparison
3344  * for "==" operator, which is performance critical in typical cases.
3345  * In future to implement strict standard conformance, we can do
3346  * normalization of input JSON strings.
3347  */
3348  if (cmp == 0)
3349  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
3350  else
3351  return cmp;
3352  }
3353 }
static int binaryCompareStrings(const char *s1, int len1, const char *s2, int len2)
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
void pfree(void *pointer)
Definition: mcxt.c:1521
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
@ PG_UTF8
Definition: pg_wchar.h:232

References binaryCompareStrings(), cmp(), GetDatabaseEncoding(), pfree(), pg_server_to_any(), PG_SQL_ASCII, and PG_UTF8.

Referenced by compareItems().

◆ copyJsonbValue()

static JsonbValue * copyJsonbValue ( JsonbValue src)
static

Definition at line 3463 of file jsonpath_exec.c.

3464 {
3465  JsonbValue *dst = palloc(sizeof(*dst));
3466 
3467  *dst = *src;
3468 
3469  return dst;
3470 }
void * palloc(Size size)
Definition: mcxt.c:1317

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

◆ CountJsonPathVars()

static int CountJsonPathVars ( void *  cxt)
static

Definition at line 3054 of file jsonpath_exec.c.

3055 {
3056  List *vars = (List *) cxt;
3057 
3058  return list_length(vars);
3059 }
static int list_length(const List *l)
Definition: pg_list.h:152
Definition: pg_list.h:54
Definition: regcomp.c:281

References list_length().

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

◆ countVariablesFromJsonb()

static int countVariablesFromJsonb ( void *  varsJsonb)
static

Definition at line 3221 of file jsonpath_exec.c.

3222 {
3223  Jsonb *vars = varsJsonb;
3224 
3225  if (vars && !JsonContainerIsObject(&vars->root))
3226  {
3227  ereport(ERROR,
3228  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3229  errmsg("\"vars\" argument is not an object"),
3230  errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object."));
3231  }
3232 
3233  /* count of base objects */
3234  return vars != NULL ? 1 : 0;
3235 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define JsonContainerIsObject(jc)
Definition: jsonb.h:208
Definition: jsonb.h:213

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

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

◆ executeAnyItem()

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

Definition at line 1952 of file jsonpath_exec.c.

1955 {
1957  JsonbIterator *it;
1958  int32 r;
1959  JsonbValue v;
1960 
1962 
1963  if (level > last)
1964  return res;
1965 
1966  it = JsonbIteratorInit(jbc);
1967 
1968  /*
1969  * Recursively iterate over jsonb objects/arrays
1970  */
1971  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1972  {
1973  if (r == WJB_KEY)
1974  {
1975  r = JsonbIteratorNext(&it, &v, true);
1976  Assert(r == WJB_VALUE);
1977  }
1978 
1979  if (r == WJB_VALUE || r == WJB_ELEM)
1980  {
1981 
1982  if (level >= first ||
1983  (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
1984  v.type != jbvBinary)) /* leaves only requested */
1985  {
1986  /* check expression */
1987  if (jsp)
1988  {
1989  if (ignoreStructuralErrors)
1990  {
1991  bool savedIgnoreStructuralErrors;
1992 
1993  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1994  cxt->ignoreStructuralErrors = true;
1995  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1996  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1997  }
1998  else
1999  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2000 
2001  if (jperIsError(res))
2002  break;
2003 
2004  if (res == jperOk && !found)
2005  break;
2006  }
2007  else if (found)
2008  JsonValueListAppend(found, copyJsonbValue(&v));
2009  else
2010  return jperOk;
2011  }
2012 
2013  if (level < last && v.type == jbvBinary)
2014  {
2016  (cxt, jsp, v.val.binary.data, found,
2017  level + 1, first, last,
2018  ignoreStructuralErrors, unwrapNext);
2019 
2020  if (jperIsError(res))
2021  break;
2022 
2023  if (res == jperOk && found == NULL)
2024  break;
2025  }
2026  }
2027  }
2028 
2029  return res;
2030 }
#define PG_UINT32_MAX
Definition: c.h:590
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
@ 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:817
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:853
static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
static void JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv)
#define jperIsError(jper)
static JsonbValue * copyJsonbValue(JsonbValue *src)
void check_stack_depth(void)
Definition: postgres.c:3540

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

Referenced by executeItemOptUnwrapTarget(), and executeItemUnwrapTargetArray().

◆ executeBinaryArithmExpr()

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

Definition at line 2123 of file jsonpath_exec.c.

2126 {
2127  JsonPathExecResult jper;
2128  JsonPathItem elem;
2129  JsonValueList lseq = {0};
2130  JsonValueList rseq = {0};
2131  JsonbValue *lval;
2132  JsonbValue *rval;
2133  Numeric res;
2134 
2135  jspGetLeftArg(jsp, &elem);
2136 
2137  /*
2138  * XXX: By standard only operands of multiplicative expressions are
2139  * unwrapped. We extend it to other binary arithmetic expressions too.
2140  */
2141  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
2142  if (jperIsError(jper))
2143  return jper;
2144 
2145  jspGetRightArg(jsp, &elem);
2146 
2147  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
2148  if (jperIsError(jper))
2149  return jper;
2150 
2151  if (JsonValueListLength(&lseq) != 1 ||
2152  !(lval = getScalar(JsonValueListHead(&lseq), jbvNumeric)))
2154  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2155  errmsg("left operand of jsonpath operator %s is not a single numeric value",
2156  jspOperationName(jsp->type)))));
2157 
2158  if (JsonValueListLength(&rseq) != 1 ||
2159  !(rval = getScalar(JsonValueListHead(&rseq), jbvNumeric)))
2161  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
2162  errmsg("right operand of jsonpath operator %s is not a single numeric value",
2163  jspOperationName(jsp->type)))));
2164 
2165  if (jspThrowErrors(cxt))
2166  {
2167  res = func(lval->val.numeric, rval->val.numeric, NULL);
2168  }
2169  else
2170  {
2171  bool error = false;
2172 
2173  res = func(lval->val.numeric, rval->val.numeric, &error);
2174 
2175  if (error)
2176  return jperError;
2177  }
2178 
2179  if (!jspGetNext(jsp, &elem) && !found)
2180  return jperOk;
2181 
2182  lval = palloc(sizeof(*lval));
2183  lval->type = jbvNumeric;
2184  lval->val.numeric = res;
2185 
2186  return executeNextItem(cxt, jsp, &elem, lval, found, false);
2187 }
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1166
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:843
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1188
#define RETURN_ERROR(throw_error)
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
static int JsonValueListLength(const JsonValueList *jvl)
static JsonPathExecResult executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonbValue * JsonValueListHead(JsonValueList *jvl)
static void error(void)
Definition: sql-dyntest.c:147
JsonPathItemType type
Definition: jsonpath.h:137

References ereport, errcode(), errmsg(), ERROR, error(), executeItemOptUnwrapResult(), executeNextItem(), getScalar(), jbvNumeric, jperError, jperIsError, jperOk, JsonValueListHead(), JsonValueListLength(), jspGetLeftArg(), jspGetNext(), jspGetRightArg(), jspOperationName(), jspThrowErrors, palloc(), res, RETURN_ERROR, JsonbValue::type, JsonPathItem::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ executeBoolItem()

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

Definition at line 1795 of file jsonpath_exec.c.

1797 {
1798  JsonPathItem larg;
1799  JsonPathItem rarg;
1800  JsonPathBool res;
1801  JsonPathBool res2;
1802 
1803  /* since this function recurses, it could be driven to stack overflow */
1805 
1806  if (!canHaveNext && jspHasNext(jsp))
1807  elog(ERROR, "boolean jsonpath item cannot have next item");
1808 
1809  switch (jsp->type)
1810  {
1811  case jpiAnd:
1812  jspGetLeftArg(jsp, &larg);
1813  res = executeBoolItem(cxt, &larg, jb, false);
1814 
1815  if (res == jpbFalse)
1816  return jpbFalse;
1817 
1818  /*
1819  * SQL/JSON says that we should check second arg in case of
1820  * jperError
1821  */
1822 
1823  jspGetRightArg(jsp, &rarg);
1824  res2 = executeBoolItem(cxt, &rarg, jb, false);
1825 
1826  return res2 == jpbTrue ? res : res2;
1827 
1828  case jpiOr:
1829  jspGetLeftArg(jsp, &larg);
1830  res = executeBoolItem(cxt, &larg, jb, false);
1831 
1832  if (res == jpbTrue)
1833  return jpbTrue;
1834 
1835  jspGetRightArg(jsp, &rarg);
1836  res2 = executeBoolItem(cxt, &rarg, jb, false);
1837 
1838  return res2 == jpbFalse ? res : res2;
1839 
1840  case jpiNot:
1841  jspGetArg(jsp, &larg);
1842 
1843  res = executeBoolItem(cxt, &larg, jb, false);
1844 
1845  if (res == jpbUnknown)
1846  return jpbUnknown;
1847 
1848  return res == jpbTrue ? jpbFalse : jpbTrue;
1849 
1850  case jpiIsUnknown:
1851  jspGetArg(jsp, &larg);
1852  res = executeBoolItem(cxt, &larg, jb, false);
1853  return res == jpbUnknown ? jpbTrue : jpbFalse;
1854 
1855  case jpiEqual:
1856  case jpiNotEqual:
1857  case jpiLess:
1858  case jpiGreater:
1859  case jpiLessOrEqual:
1860  case jpiGreaterOrEqual:
1861  jspGetLeftArg(jsp, &larg);
1862  jspGetRightArg(jsp, &rarg);
1863  return executePredicate(cxt, jsp, &larg, &rarg, jb, true,
1864  executeComparison, cxt);
1865 
1866  case jpiStartsWith: /* 'whole STARTS WITH initial' */
1867  jspGetLeftArg(jsp, &larg); /* 'whole' */
1868  jspGetRightArg(jsp, &rarg); /* 'initial' */
1869  return executePredicate(cxt, jsp, &larg, &rarg, jb, false,
1870  executeStartsWith, NULL);
1871 
1872  case jpiLikeRegex: /* 'expr LIKE_REGEX pattern FLAGS flags' */
1873  {
1874  /*
1875  * 'expr' is a sequence-returning expression. 'pattern' is a
1876  * regex string literal. SQL/JSON standard requires XQuery
1877  * regexes, but we use Postgres regexes here. 'flags' is a
1878  * string literal converted to integer flags at compile-time.
1879  */
1880  JsonLikeRegexContext lrcxt = {0};
1881 
1882  jspInitByBuffer(&larg, jsp->base,
1883  jsp->content.like_regex.expr);
1884 
1885  return executePredicate(cxt, jsp, &larg, NULL, jb, false,
1886  executeLikeRegex, &lrcxt);
1887  }
1888 
1889  case jpiExists:
1890  jspGetArg(jsp, &larg);
1891 
1892  if (jspStrictAbsenceOfErrors(cxt))
1893  {
1894  /*
1895  * In strict mode we must get a complete list of values to
1896  * check that there are no errors at all.
1897  */
1898  JsonValueList vals = {0};
1900  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1901  false, &vals);
1902 
1903  if (jperIsError(res))
1904  return jpbUnknown;
1905 
1906  return JsonValueListIsEmpty(&vals) ? jpbFalse : jpbTrue;
1907  }
1908  else
1909  {
1911  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1912  false, NULL);
1913 
1914  if (jperIsError(res))
1915  return jpbUnknown;
1916 
1917  return res == jperOk ? jpbTrue : jpbFalse;
1918  }
1919 
1920  default:
1921  elog(ERROR, "invalid boolean jsonpath item type: %d", jsp->type);
1922  return jpbUnknown;
1923  }
1924 }
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1081
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition: jsonpath.c:990
#define jspHasNext(jsp)
Definition: jsonpath.h:194
@ jpiExists
Definition: jsonpath.h:94
@ jpiNot
Definition: jsonpath.h:70
@ jpiAnd
Definition: jsonpath.h:68
@ jpiStartsWith
Definition: jsonpath.h:105
@ jpiOr
Definition: jsonpath.h:69
@ jpiLikeRegex
Definition: jsonpath.h:106
@ jpiIsUnknown
Definition: jsonpath.h:71
static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv, JsonbValue *rv, void *p)
static JsonPathBool executeBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool canHaveNext)
static JsonPathExecResult executeItemOptUnwrapResultNoThrow(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonPathBool executeStartsWith(JsonPathItem *jsp, JsonbValue *whole, JsonbValue *initial, void *param)
#define jspStrictAbsenceOfErrors(cxt)
static JsonPathBool executeLikeRegex(JsonPathItem *jsp, JsonbValue *str, JsonbValue *rarg, void *param)
static bool JsonValueListIsEmpty(JsonValueList *jvl)
static JsonPathBool executePredicate(JsonPathExecContext *cxt, JsonPathItem *pred, JsonPathItem *larg, JsonPathItem *rarg, JsonbValue *jb, bool unwrapRightArg, JsonPathPredicateCallback exec, void *param)
union JsonPathItem::@139 content
struct JsonPathItem::@139::@144 like_regex
char * base
Definition: jsonpath.h:146

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

Referenced by executeItemOptUnwrapTarget(), and executeNestedBoolItem().

◆ executeComparison()

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

Definition at line 3260 of file jsonpath_exec.c.

3261 {
3263 
3264  return compareItems(cmp->type, lv, rv, cxt->useTz);
3265 }
static JsonPathBool compareItems(int32 op, JsonbValue *jb1, JsonbValue *jb2, bool useTz)

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

Referenced by executeBoolItem().

◆ executeDateTimeMethod()

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

Definition at line 2357 of file jsonpath_exec.c.

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

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

Referenced by executeItemOptUnwrapTarget().

◆ executeItem()

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

Definition at line 734 of file jsonpath_exec.c.

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

References executeItemOptUnwrapTarget(), and jspAutoUnwrap.

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

◆ executeItemOptUnwrapResult()

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

Definition at line 1743 of file jsonpath_exec.c.

1746 {
1747  if (unwrap && jspAutoUnwrap(cxt))
1748  {
1749  JsonValueList seq = {0};
1751  JsonPathExecResult res = executeItem(cxt, jsp, jb, &seq);
1752  JsonbValue *item;
1753 
1754  if (jperIsError(res))
1755  return res;
1756 
1757  JsonValueListInitIterator(&seq, &it);
1758  while ((item = JsonValueListNext(&seq, &it)))
1759  {
1760  Assert(item->type != jbvArray);
1761 
1762  if (JsonbType(item) == jbvArray)
1763  executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1764  else
1765  JsonValueListAppend(found, item);
1766  }
1767 
1768  return jperOk;
1769  }
1770 
1771  return executeItem(cxt, jsp, jb, found);
1772 }
static int JsonbType(JsonbValue *jb)
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static void JsonValueListInitIterator(const JsonValueList *jvl, JsonValueListIterator *it)
static JsonbValue * JsonValueListNext(const JsonValueList *jvl, JsonValueListIterator *it)
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)

References Assert, executeItem(), executeItemUnwrapTargetArray(), jbvArray, jperIsError, jperOk, JsonbType(), JsonValueListAppend(), JsonValueListInitIterator(), JsonValueListNext(), jspAutoUnwrap, res, 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 1778 of file jsonpath_exec.c.

1782 {
1784  bool throwErrors = cxt->throwErrors;
1785 
1786  cxt->throwErrors = false;
1787  res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1788  cxt->throwErrors = throwErrors;
1789 
1790  return res;
1791 }

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

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

References JsonPathItem::anybounds, appendBoolResult(), JsonPathItem::args, JsonPathItem::array, Assert, JsonPathExecContext::baseObject, CHECK_FOR_INTERRUPTS, check_stack_depth(), construct_array_builtin(), JsonPathItem::content, CStringGetDatum(), JsonPathExecContext::current, date_out(), DatumGetCString(), DatumGetInt32(), DatumGetNumeric(), DirectFunctionCall1, DirectInputFunctionCallSafe(), elog, ereport, errcode(), errmsg(), ERROR, ErrorSaveContext::error_occurred, executeAnyItem(), executeBinaryArithmExpr(), executeBoolItem(), executeDateTimeMethod(), executeItemUnwrapTargetArray(), executeKeyValueMethod(), executeNestedBoolItem(), executeNextItem(), executeNumericItemMethod(), executeUnaryArithmExpr(), findJsonbValueFromContainer(), float8_numeric(), Float8GetDatum(), float8in_internal(), getArrayIndex(), getIthJsonbValueFromContainer(), getJsonPathItem(), i, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, Int32GetDatum(), int4_numeric(), int4in(), int64_to_numeric(), Int64GetDatum(), int8_numeric(), int8in(), InvalidOid, JB_FOBJECT, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, jpbTrue, jperError, jperIsError, jperNotFound, jperOk, jpiAbs, jpiAdd, jpiAnd, jpiAny, jpiAnyArray, jpiAnyKey, jpiBigint, jpiBool, jpiBoolean, jpiCeiling, jpiCurrent, jpiDate, jpiDatetime, jpiDecimal, jpiDiv, jpiDouble, jpiEqual, jpiExists, jpiFilter, jpiFloor, jpiGreater, jpiGreaterOrEqual, jpiIndexArray, jpiInteger, jpiIsUnknown, jpiKey, jpiKeyValue, jpiLast, jpiLess, jpiLessOrEqual, jpiLikeRegex, jpiMinus, jpiMod, jpiMul, jpiNot, jpiNotEqual, jpiNull, jpiNumber, jpiNumeric, jpiOr, jpiPlus, jpiRoot, jpiSize, jpiStartsWith, jpiString, jpiStringFunc, jpiSub, jpiTime, jpiTimestamp, jpiTimestampTz, jpiTimeTz, jpiType, jpiVariable, JsonbArraySize(), JsonbType(), JsonbTypeName(), jspAutoUnwrap, jspAutoWrap, jspGetArg(), jspGetArraySubscript(), jspGetLeftArg(), jspGetNext(), jspGetNumeric(), jspGetRightArg(), jspGetString(), jspHasNext, jspIgnoreStructuralErrors, jspOperationName(), jspThrowErrors, sort-test::key, numeric_abs(), numeric_add_opt_error(), numeric_ceil(), numeric_div_opt_error(), numeric_floor(), numeric_in(), numeric_int4_opt_error(), numeric_int8_opt_error(), numeric_is_inf(), numeric_is_nan(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_out(), numeric_sub_opt_error(), numeric_uminus(), NumericGetDatum(), numerictypmodin(), palloc(), parse_bool(), pfree(), pg_ltoa(), pnstrdup(), PointerGetDatum(), pstrdup(), range(), res, RETURN_ERROR, JsonPathExecContext::root, scale, setBaseObject(), size, time_out(), timestamp_out(), timestamptz_out(), timetz_out(), JsonbValue::type, JsonPathItem::type, JsonbValue::val, and val.

Referenced by executeAnyItem(), and executeItem().

◆ executeItemUnwrapTargetArray()

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

Definition at line 1692 of file jsonpath_exec.c.

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

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

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

◆ executeJsonPath()

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

Definition at line 678 of file jsonpath_exec.c.

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

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

2840 {
2843  JsonbContainer *jbc;
2844  JsonbValue key;
2845  JsonbValue val;
2846  JsonbValue idval;
2847  JsonbValue keystr;
2848  JsonbValue valstr;
2849  JsonbValue idstr;
2850  JsonbIterator *it;
2851  JsonbIteratorToken tok;
2852  int64 id;
2853  bool hasNext;
2854 
2855  if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
2857  (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
2858  errmsg("jsonpath item method .%s() can only be applied to an object",
2859  jspOperationName(jsp->type)))));
2860 
2861  jbc = jb->val.binary.data;
2862 
2863  if (!JsonContainerSize(jbc))
2864  return jperNotFound; /* no key-value pairs */
2865 
2866  hasNext = jspGetNext(jsp, &next);
2867 
2868  keystr.type = jbvString;
2869  keystr.val.string.val = "key";
2870  keystr.val.string.len = 3;
2871 
2872  valstr.type = jbvString;
2873  valstr.val.string.val = "value";
2874  valstr.val.string.len = 5;
2875 
2876  idstr.type = jbvString;
2877  idstr.val.string.val = "id";
2878  idstr.val.string.len = 2;
2879 
2880  /* construct object id from its base object and offset inside that */
2881  id = jb->type != jbvBinary ? 0 :
2882  (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
2883  id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
2884 
2885  idval.type = jbvNumeric;
2886  idval.val.numeric = int64_to_numeric(id);
2887 
2888  it = JsonbIteratorInit(jbc);
2889 
2890  while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
2891  {
2892  JsonBaseObjectInfo baseObject;
2893  JsonbValue obj;
2895  JsonbValue *keyval;
2896  Jsonb *jsonb;
2897 
2898  if (tok != WJB_KEY)
2899  continue;
2900 
2901  res = jperOk;
2902 
2903  if (!hasNext && !found)
2904  break;
2905 
2906  tok = JsonbIteratorNext(&it, &val, true);
2907  Assert(tok == WJB_VALUE);
2908 
2909  ps = NULL;
2911 
2912  pushJsonbValue(&ps, WJB_KEY, &keystr);
2914 
2915  pushJsonbValue(&ps, WJB_KEY, &valstr);
2917 
2918  pushJsonbValue(&ps, WJB_KEY, &idstr);
2919  pushJsonbValue(&ps, WJB_VALUE, &idval);
2920 
2921  keyval = pushJsonbValue(&ps, WJB_END_OBJECT, NULL);
2922 
2923  jsonb = JsonbValueToJsonb(keyval);
2924 
2925  JsonbInitBinary(&obj, jsonb);
2926 
2927  baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
2928 
2929  res = executeNextItem(cxt, jsp, &next, &obj, found, true);
2930 
2931  cxt->baseObject = baseObject;
2932 
2933  if (jperIsError(res))
2934  return res;
2935 
2936  if (res == jperOk && !found)
2937  break;
2938  }
2939 
2940  return res;
2941 }
struct parser_state ps
#define JsonContainerSize(jc)
Definition: jsonb.h:206
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566

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

Referenced by executeItemOptUnwrapTarget().

◆ executeLikeRegex()

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

Definition at line 2285 of file jsonpath_exec.c.

2287 {
2288  JsonLikeRegexContext *cxt = param;
2289 
2290  if (!(str = getScalar(str, jbvString)))
2291  return jpbUnknown;
2292 
2293  /* Cache regex text and converted flags. */
2294  if (!cxt->regex)
2295  {
2296  cxt->regex =
2298  jsp->content.like_regex.patternlen);
2299  (void) jspConvertRegexFlags(jsp->content.like_regex.flags,
2300  &(cxt->cflags), NULL);
2301  }
2302 
2303  if (RE_compile_and_execute(cxt->regex, str->val.string.val,
2304  str->val.string.len,
2305  cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
2306  return jpbTrue;
2307 
2308  return jpbFalse;
2309 }
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, JsonPathItem::content, cstring_to_text_with_len(), getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, jspConvertRegexFlags(), JsonPathItem::like_regex, 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 1931 of file jsonpath_exec.c.

1933 {
1934  JsonbValue *prev;
1935  JsonPathBool res;
1936 
1937  prev = cxt->current;
1938  cxt->current = jb;
1939  res = executeBoolItem(cxt, jsp, jb, false);
1940  cxt->current = prev;
1941 
1942  return res;
1943 }

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

Referenced by executeItemOptUnwrapTarget().

◆ executeNextItem()

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

Definition at line 1712 of file jsonpath_exec.c.

1715 {
1716  JsonPathItem elem;
1717  bool hasNext;
1718 
1719  if (!cur)
1720  hasNext = next != NULL;
1721  else if (next)
1722  hasNext = jspHasNext(cur);
1723  else
1724  {
1725  next = &elem;
1726  hasNext = jspGetNext(cur, next);
1727  }
1728 
1729  if (hasNext)
1730  return executeItem(cxt, next, v, found);
1731 
1732  if (found)
1733  JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1734 
1735  return jperOk;
1736 }
struct cursor * cur
Definition: ecpg.c:28

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

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

◆ executeNumericItemMethod()

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

Definition at line 2316 of file jsonpath_exec.c.

2319 {
2321  Datum datum;
2322 
2323  if (unwrap && JsonbType(jb) == jbvArray)
2324  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
2325 
2326  if (!(jb = getScalar(jb, jbvNumeric)))
2328  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
2329  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
2330  jspOperationName(jsp->type)))));
2331 
2332  datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
2333 
2334  if (!jspGetNext(jsp, &next) && !found)
2335  return jperOk;
2336 
2337  jb = palloc(sizeof(*jb));
2338  jb->type = jbvNumeric;
2339  jb->val.numeric = DatumGetNumeric(datum);
2340 
2341  return executeNextItem(cxt, jsp, &next, jb, found, false);
2342 }

References DatumGetNumeric(), DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, executeItemUnwrapTargetArray(), executeNextItem(), getScalar(), jbvArray, jbvNumeric, jperOk, JsonbType(), jspGetNext(), jspOperationName(), next, NumericGetDatum(), palloc(), RETURN_ERROR, JsonbValue::type, JsonPathItem::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ executePredicate()

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

Definition at line 2043 of file jsonpath_exec.c.

2047 {
2049  JsonValueListIterator lseqit;
2050  JsonValueList lseq = {0};
2051  JsonValueList rseq = {0};
2052  JsonbValue *lval;
2053  bool error = false;
2054  bool found = false;
2055 
2056  /* Left argument is always auto-unwrapped. */
2057  res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
2058  if (jperIsError(res))
2059  return jpbUnknown;
2060 
2061  if (rarg)
2062  {
2063  /* Right argument is conditionally auto-unwrapped. */
2064  res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
2065  unwrapRightArg, &rseq);
2066  if (jperIsError(res))
2067  return jpbUnknown;
2068  }
2069 
2070  JsonValueListInitIterator(&lseq, &lseqit);
2071  while ((lval = JsonValueListNext(&lseq, &lseqit)))
2072  {
2073  JsonValueListIterator rseqit;
2074  JsonbValue *rval;
2075  bool first = true;
2076 
2077  JsonValueListInitIterator(&rseq, &rseqit);
2078  if (rarg)
2079  rval = JsonValueListNext(&rseq, &rseqit);
2080  else
2081  rval = NULL;
2082 
2083  /* Loop over right arg sequence or do single pass otherwise */
2084  while (rarg ? (rval != NULL) : first)
2085  {
2086  JsonPathBool res = exec(pred, lval, rval, param);
2087 
2088  if (res == jpbUnknown)
2089  {
2090  if (jspStrictAbsenceOfErrors(cxt))
2091  return jpbUnknown;
2092 
2093  error = true;
2094  }
2095  else if (res == jpbTrue)
2096  {
2097  if (!jspStrictAbsenceOfErrors(cxt))
2098  return jpbTrue;
2099 
2100  found = true;
2101  }
2102 
2103  first = false;
2104  if (rarg)
2105  rval = JsonValueListNext(&rseq, &rseqit);
2106  }
2107  }
2108 
2109  if (found) /* possible only in strict mode */
2110  return jpbTrue;
2111 
2112  if (error) /* possible only in lax mode */
2113  return jpbUnknown;
2114 
2115  return jpbFalse;
2116 }
Definition: type.h:115

References error(), executeItemOptUnwrapResultNoThrow(), jpbFalse, jpbTrue, jpbUnknown, jperIsError, JsonValueListInitIterator(), JsonValueListNext(), jspStrictAbsenceOfErrors, and res.

Referenced by executeBoolItem().

◆ executeStartsWith()

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

Definition at line 2261 of file jsonpath_exec.c.

2263 {
2264  if (!(whole = getScalar(whole, jbvString)))
2265  return jpbUnknown; /* error */
2266 
2267  if (!(initial = getScalar(initial, jbvString)))
2268  return jpbUnknown; /* error */
2269 
2270  if (whole->val.string.len >= initial->val.string.len &&
2271  !memcmp(whole->val.string.val,
2272  initial->val.string.val,
2273  initial->val.string.len))
2274  return jpbTrue;
2275 
2276  return jpbFalse;
2277 }

References getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, and JsonbValue::val.

Referenced by executeBoolItem().

◆ executeUnaryArithmExpr()

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

Definition at line 2194 of file jsonpath_exec.c.

2196 {
2197  JsonPathExecResult jper;
2198  JsonPathExecResult jper2;
2199  JsonPathItem elem;
2200  JsonValueList seq = {0};
2202  JsonbValue *val;
2203  bool hasNext;
2204 
2205  jspGetArg(jsp, &elem);
2206  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
2207 
2208  if (jperIsError(jper))
2209  return jper;
2210 
2211  jper = jperNotFound;
2212 
2213  hasNext = jspGetNext(jsp, &elem);
2214 
2215  JsonValueListInitIterator(&seq, &it);
2216  while ((val = JsonValueListNext(&seq, &it)))
2217  {
2218  if ((val = getScalar(val, jbvNumeric)))
2219  {
2220  if (!found && !hasNext)
2221  return jperOk;
2222  }
2223  else
2224  {
2225  if (!found && !hasNext)
2226  continue; /* skip non-numerics processing */
2227 
2229  (errcode(ERRCODE_SQL_JSON_NUMBER_NOT_FOUND),
2230  errmsg("operand of unary jsonpath operator %s is not a numeric value",
2231  jspOperationName(jsp->type)))));
2232  }
2233 
2234  if (func)
2235  val->val.numeric =
2237  NumericGetDatum(val->val.numeric)));
2238 
2239  jper2 = executeNextItem(cxt, jsp, &elem, val, found, false);
2240 
2241  if (jperIsError(jper2))
2242  return jper2;
2243 
2244  if (jper2 == jperOk)
2245  {
2246  if (!found)
2247  return jperOk;
2248  jper = jperOk;
2249  }
2250  }
2251 
2252  return jper;
2253 }

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

Referenced by executeItemOptUnwrapTarget().

◆ getArrayIndex()

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

Definition at line 3477 of file jsonpath_exec.c.

3479 {
3480  JsonbValue *jbv;
3481  JsonValueList found = {0};
3482  JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
3483  Datum numeric_index;
3484  bool have_error = false;
3485 
3486  if (jperIsError(res))
3487  return res;
3488 
3489  if (JsonValueListLength(&found) != 1 ||
3490  !(jbv = getScalar(JsonValueListHead(&found), jbvNumeric)))
3492  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
3493  errmsg("jsonpath array subscript is not a single numeric value"))));
3494 
3495  numeric_index = DirectFunctionCall2(numeric_trunc,
3496  NumericGetDatum(jbv->val.numeric),
3497  Int32GetDatum(0));
3498 
3499  *index = numeric_int4_opt_error(DatumGetNumeric(numeric_index),
3500  &have_error);
3501 
3502  if (have_error)
3504  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
3505  errmsg("jsonpath array subscript is out of integer range"))));
3506 
3507  return jperOk;
3508 }
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:1599

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

Referenced by executeItemOptUnwrapTarget().

◆ getJsonPathItem()

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

Definition at line 2976 of file jsonpath_exec.c.

2978 {
2979  switch (item->type)
2980  {
2981  case jpiNull:
2982  value->type = jbvNull;
2983  break;
2984  case jpiBool:
2985  value->type = jbvBool;
2986  value->val.boolean = jspGetBool(item);
2987  break;
2988  case jpiNumeric:
2989  value->type = jbvNumeric;
2990  value->val.numeric = jspGetNumeric(item);
2991  break;
2992  case jpiString:
2993  value->type = jbvString;
2994  value->val.string.val = jspGetString(item,
2995  &value->val.string.len);
2996  break;
2997  case jpiVariable:
2998  getJsonPathVariable(cxt, item, value);
2999  return;
3000  default:
3001  elog(ERROR, "unexpected jsonpath item type");
3002  }
3003 }
bool jspGetBool(JsonPathItem *v)
Definition: jsonpath.c:1210
static void getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable, JsonbValue *value)

References elog, ERROR, getJsonPathVariable(), jbvBool, jbvNull, jbvNumeric, jbvString, jpiBool, jpiNull, jpiNumeric, jpiString, jpiVariable, jspGetBool(), jspGetNumeric(), jspGetString(), JsonPathItem::type, and value.

Referenced by executeItemOptUnwrapTarget().

◆ GetJsonPathVar()

static JsonbValue * GetJsonPathVar ( void *  cxt,
char *  varName,
int  varNameLen,
JsonbValue baseObject,
int *  baseObjectId 
)
static

Definition at line 3009 of file jsonpath_exec.c.

3011 {
3012  JsonPathVariable *var = NULL;
3013  List *vars = cxt;
3014  ListCell *lc;
3015  JsonbValue *result;
3016  int id = 1;
3017 
3018  foreach(lc, vars)
3019  {
3020  JsonPathVariable *curvar = lfirst(lc);
3021 
3022  if (curvar->namelen == varNameLen &&
3023  strncmp(curvar->name, varName, varNameLen) == 0)
3024  {
3025  var = curvar;
3026  break;
3027  }
3028 
3029  id++;
3030  }
3031 
3032  if (var == NULL)
3033  {
3034  *baseObjectId = -1;
3035  return NULL;
3036  }
3037 
3038  result = palloc(sizeof(JsonbValue));
3039  if (var->isnull)
3040  {
3041  *baseObjectId = 0;
3042  result->type = jbvNull;
3043  }
3044  else
3045  JsonItemFromDatum(var->value, var->typid, var->typmod, result);
3046 
3047  *baseObject = *result;
3048  *baseObjectId = id;
3049 
3050  return result;
3051 }
static void JsonItemFromDatum(Datum val, Oid typid, int32 typmod, JsonbValue *res)
#define lfirst(lc)
Definition: pg_list.h:172

References JsonPathVariable::isnull, jbvNull, JsonItemFromDatum(), lfirst, JsonPathVariable::name, JsonPathVariable::namelen, palloc(), JsonbValue::type, JsonPathVariable::typid, JsonPathVariable::typmod, and JsonPathVariable::value.

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

◆ getJsonPathVariable()

static void getJsonPathVariable ( JsonPathExecContext cxt,
JsonPathItem variable,
JsonbValue value 
)
static

Definition at line 3159 of file jsonpath_exec.c.

3161 {
3162  char *varName;
3163  int varNameLength;
3164  JsonbValue baseObject;
3165  int baseObjectId;
3166  JsonbValue *v;
3167 
3169  varName = jspGetString(variable, &varNameLength);
3170 
3171  if (cxt->vars == NULL ||
3172  (v = cxt->getVar(cxt->vars, varName, varNameLength,
3173  &baseObject, &baseObjectId)) == NULL)
3174  ereport(ERROR,
3175  (errcode(ERRCODE_UNDEFINED_OBJECT),
3176  errmsg("could not find jsonpath variable \"%s\"",
3177  pnstrdup(varName, varNameLength))));
3178 
3179  if (baseObjectId > 0)
3180  {
3181  *value = *v;
3182  setBaseObject(cxt, &baseObject, baseObjectId);
3183  }
3184 }
enum ECPGttype type

References Assert, ereport, errcode(), errmsg(), ERROR, JsonPathExecContext::getVar, jpiVariable, jspGetString(), pnstrdup(), setBaseObject(), variable::type, value, and JsonPathExecContext::vars.

Referenced by getJsonPathItem().

◆ getJsonPathVariableFromJsonb()

static JsonbValue * getJsonPathVariableFromJsonb ( void *  varsJsonb,
char *  varName,
int  varNameLength,
JsonbValue baseObject,
int *  baseObjectId 
)
static

Definition at line 3191 of file jsonpath_exec.c.

3193 {
3194  Jsonb *vars = varsJsonb;
3195  JsonbValue tmp;
3196  JsonbValue *result;
3197 
3198  tmp.type = jbvString;
3199  tmp.val.string.val = varName;
3200  tmp.val.string.len = varNameLength;
3201 
3202  result = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
3203 
3204  if (result == NULL)
3205  {
3206  *baseObjectId = -1;
3207  return NULL;
3208  }
3209 
3210  *baseObjectId = 1;
3211  JsonbInitBinary(baseObject, vars);
3212 
3213  return result;
3214 }

References findJsonbValueFromContainer(), JB_FOBJECT, jbvString, JsonbInitBinary(), JsonbValue::type, and JsonbValue::val.

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

◆ GetJsonTableExecContext()

static JsonTableExecContext* GetJsonTableExecContext ( TableFuncScanState state,
const char *  fname 
)
inlinestatic

Definition at line 4094 of file jsonpath_exec.c.

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

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

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

◆ getScalar()

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

Definition at line 3656 of file jsonpath_exec.c.

3657 {
3658  /* Scalars should be always extracted during jsonpath execution. */
3659  Assert(scalar->type != jbvBinary ||
3660  !JsonContainerIsScalar(scalar->val.binary.data));
3661 
3662  return scalar->type == type ? scalar : NULL;
3663 }
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
const char * type

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

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

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 426 of file jsonpath_exec.c.

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

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

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

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

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

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 432 of file jsonpath_exec.c.

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

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 496 of file jsonpath_exec.c.

497 {
498  return jsonb_path_match_internal(fcinfo, false);
499 }
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 455 of file jsonpath_exec.c.

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

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

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

◆ jsonb_path_match_opr()

Datum jsonb_path_match_opr ( PG_FUNCTION_ARGS  )

Definition at line 513 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 502 of file jsonpath_exec.c.

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

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 573 of file jsonpath_exec.c.

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

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_array_internal()

static Datum jsonb_path_query_array_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 590 of file jsonpath_exec.c.

591 {
592  Jsonb *jb = PG_GETARG_JSONB_P(0);
594  JsonValueList found = {0};
596  bool silent = PG_GETARG_BOOL(3);
597 
600  jb, !silent, &found, tz);
601 
603 }
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
static JsonbValue * wrapItemsInArray(const JsonValueList *items)

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

Referenced by jsonb_path_query_array(), and jsonb_path_query_array_tz().

◆ jsonb_path_query_array_tz()

Datum jsonb_path_query_array_tz ( PG_FUNCTION_ARGS  )

Definition at line 612 of file jsonpath_exec.c.

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

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 642 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_first_internal()

static Datum jsonb_path_query_first_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 648 of file jsonpath_exec.c.

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

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 525 of file jsonpath_exec.c.

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

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

Referenced by jsonb_path_query(), and jsonb_path_query_tz().

◆ jsonb_path_query_tz()

Datum jsonb_path_query_tz ( PG_FUNCTION_ARGS  )

Definition at line 579 of file jsonpath_exec.c.

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

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 3243 of file jsonpath_exec.c.

3244 {
3245  Assert(jb->type != jbvArray);
3246 
3247  if (jb->type == jbvBinary)
3248  {
3249  JsonbContainer *jbc = jb->val.binary.data;
3250 
3251  if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
3252  return JsonContainerSize(jbc);
3253  }
3254 
3255  return -1;
3256 }
#define JsonContainerIsArray(jc)
Definition: jsonb.h:209

References Assert, jbvArray, jbvBinary, JsonContainerIsArray, JsonContainerIsScalar, JsonContainerSize, JsonbValue::type, and JsonbValue::val.

Referenced by executeItemOptUnwrapTarget().

◆ JsonbInitBinary()

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

Definition at line 3619 of file jsonpath_exec.c.

3620 {
3621  jbv->type = jbvBinary;
3622  jbv->val.binary.data = &jb->root;
3623  jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
3624 
3625  return jbv;
3626 }
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

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

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

◆ JsonbType()

static int JsonbType ( JsonbValue jb)
static

Definition at line 3632 of file jsonpath_exec.c.

3633 {
3634  int type = jb->type;
3635 
3636  if (jb->type == jbvBinary)
3637  {
3638  JsonbContainer *jbc = (void *) jb->val.binary.data;
3639 
3640  /* Scalars should be always extracted during jsonpath execution. */
3642 
3643  if (JsonContainerIsObject(jbc))
3644  type = jbvObject;
3645  else if (JsonContainerIsArray(jbc))
3646  type = jbvArray;
3647  else
3648  elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
3649  }
3650 
3651  return type;
3652 }
uint32 header
Definition: jsonb.h:192

References Assert, elog, ERROR, JsonbContainer::header, jbvArray, jbvBinary, jbvObject, JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, type, JsonbValue::type, and JsonbValue::val.

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

◆ JsonbValueInitNumericDatum()

static void JsonbValueInitNumericDatum ( JsonbValue jbv,
Datum  num 
)
static

Definition at line 3149 of file jsonpath_exec.c.

3150 {
3151  jbv->type = jbvNumeric;
3152  jbv->val.numeric = DatumGetNumeric(num);
3153 }

References DatumGetNumeric(), jbvNumeric, JsonbValue::type, and JsonbValue::val.

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

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

Definition at line 3067 of file jsonpath_exec.c.

3068 {
3069  switch (typid)
3070  {
3071  case BOOLOID:
3072  res->type = jbvBool;
3073  res->val.boolean = DatumGetBool(val);
3074  break;
3075  case NUMERICOID:
3077  break;
3078  case INT2OID:
3080  break;
3081  case INT4OID:
3083  break;
3084  case INT8OID:
3086  break;
3087  case FLOAT4OID:
3089  break;
3090  case FLOAT8OID:
3092  break;
3093  case TEXTOID:
3094  case VARCHAROID:
3095  res->type = jbvString;
3096  res->val.string.val = VARDATA_ANY(val);
3097  res->val.string.len = VARSIZE_ANY_EXHDR(val);
3098  break;
3099  case DATEOID:
3100  case TIMEOID:
3101  case TIMETZOID:
3102  case TIMESTAMPOID:
3103  case TIMESTAMPTZOID:
3104  res->type = jbvDatetime;
3105  res->val.datetime.value = val;
3106  res->val.datetime.typid = typid;
3107  res->val.datetime.typmod = typmod;
3108  res->val.datetime.tz = 0;
3109  break;
3110  case JSONBOID:
3111  {
3112  JsonbValue *jbv = res;
3113  Jsonb *jb = DatumGetJsonbP(val);
3114 
3115  if (JsonContainerIsScalar(&jb->root))
3116  {
3117  bool result PG_USED_FOR_ASSERTS_ONLY;
3118 
3119  result = JsonbExtractScalar(&jb->root, jbv);
3120  Assert(result);
3121  }
3122  else
3123  JsonbInitBinary(jbv, jb);
3124  break;
3125  }
3126  case JSONOID:
3127  {
3128  text *txt = DatumGetTextP(val);
3129  char *str = text_to_cstring(txt);
3130  Jsonb *jb;
3131 
3133  CStringGetDatum(str)));
3134  pfree(str);
3135 
3136  JsonItemFromDatum(JsonbPGetDatum(jb), JSONBOID, -1, res);
3137  break;
3138  }
3139  default:
3140  ereport(ERROR,
3141  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3142  errmsg("could not convert value of type %s to jsonpath",
3143  format_type_be(typid)));
3144  }
3145 }
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4687
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4544
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:182
#define DatumGetTextP(X)
Definition: fmgr.h:332
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:73
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
static void JsonbValueInitNumericDatum(JsonbValue *jbv, Datum num)
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
#define VARDATA_ANY(PTR)
Definition: varatt.h:324

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

Referenced by GetJsonPathVar().

◆ JsonPathExists()

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

Definition at line 3906 of file jsonpath_exec.c.

3907 {
3909 
3910  res = executeJsonPath(jp, vars,
3912  DatumGetJsonbP(jb), !error, NULL, true);
3913 
3914  Assert(error || !jperIsError(res));
3915 
3916  if (error && jperIsError(res))
3917  *error = true;
3918 
3919  return res == jperOk;
3920 }
static JsonbValue * GetJsonPathVar(void *cxt, char *varName, int varNameLen, JsonbValue *baseObject, int *baseObjectId)
static int CountJsonPathVars(void *cxt)

References Assert, CountJsonPathVars(), DatumGetJsonbP(), error(), executeJsonPath(), GetJsonPathVar(), jperIsError, jperOk, and res.

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

3932 {
3933  JsonbValue *singleton;
3934  bool wrap;
3935  JsonValueList found = {0};
3937  int count;
3938 
3939  res = executeJsonPath(jp, vars,
3941  DatumGetJsonbP(jb), !error, &found, true);
3942  Assert(error || !jperIsError(res));
3943  if (error && jperIsError(res))
3944  {
3945  *error = true;
3946  *empty = false;
3947  return (Datum) 0;
3948  }
3949 
3950  /* WRAP or not? */
3951  count = JsonValueListLength(&found);
3952  singleton = count > 0 ? JsonValueListHead(&found) : NULL;
3953  if (singleton == NULL)
3954  wrap = false;
3955  else if (wrapper == JSW_NONE || wrapper == JSW_UNSPEC)
3956  wrap = false;
3957  else if (wrapper == JSW_UNCONDITIONAL)
3958  wrap = true;
3959  else if (wrapper == JSW_CONDITIONAL)
3960  wrap = count > 1 ||
3961  IsAJsonbScalar(singleton) ||
3962  (singleton->type == jbvBinary &&
3963  JsonContainerIsScalar(singleton->val.binary.data));
3964  else
3965  {
3966  elog(ERROR, "unrecognized json wrapper %d", (int) wrapper);
3967  wrap = false;
3968  }
3969 
3970  if (wrap)
3972 
3973  /* No wrapping means only one item is expected. */
3974  if (count > 1)
3975  {
3976  if (error)
3977  {
3978  *error = true;
3979  return (Datum) 0;
3980  }
3981 
3982  if (column_name)
3983  ereport(ERROR,
3984  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3985  errmsg("JSON path expression for column \"%s\" should return single item without wrapper",
3986  column_name),
3987  errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
3988  else
3989  ereport(ERROR,
3990  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3991  errmsg("JSON path expression in JSON_QUERY should return single item without wrapper"),
3992  errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array.")));
3993  }
3994 
3995  if (singleton)
3996  return JsonbPGetDatum(JsonbValueToJsonb(singleton));
3997 
3998  *empty = true;
3999  return PointerGetDatum(NULL);
4000 }
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297
@ JSW_UNCONDITIONAL
Definition: primnodes.h:1749
@ JSW_CONDITIONAL
Definition: primnodes.h:1748
@ JSW_UNSPEC
Definition: primnodes.h:1746
@ JSW_NONE
Definition: primnodes.h:1747

References Assert, CountJsonPathVars(), DatumGetJsonbP(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, error(), executeJsonPath(), GetJsonPathVar(), IsAJsonbScalar, jbvBinary, jperIsError, JsonbPGetDatum(), JsonbValueToJsonb(), JsonContainerIsScalar, JsonValueListHead(), JsonValueListLength(), JSW_CONDITIONAL, JSW_NONE, JSW_UNCONDITIONAL, JSW_UNSPEC, PointerGetDatum(), res, JsonbValue::type, JsonbValue::val, and wrapItemsInArray().

Referenced by ExecEvalJsonExprPath().

◆ JsonPathValue()

JsonbValue* JsonPathValue ( Datum  jb,
JsonPath jp,
bool