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 "lib/stringinfo.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "regex/regex.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/datum.h"
#include "utils/float.h"
#include "utils/formatting.h"
#include "utils/guc.h"
#include "utils/json.h"
#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
#include "utils/varlena.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  JsonTableScanState
 
struct  JsonTableJoinState
 
struct  JsonTableContext
 

Macros

#define jperIsError(jper)   ((jper) == jperError)
 
#define JSON_TABLE_CONTEXT_MAGIC   418352867
 
#define jspStrictAbsenseOfErrors(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 int(* JsonPathVarCallback) (void *vars, char *varName, int varNameLen, JsonbValue *val, JsonbValue *baseObject)
 
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 JsonTableScanState JsonTableScanState
 
typedef struct JsonTableJoinState JsonTableJoinState
 
typedef struct JsonTableContext JsonTableContext
 
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, JsonPathVarCallback getVar, 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 void getJsonPathVariable (JsonPathExecContext *cxt, JsonPathItem *variable, JsonbValue *value)
 
static int getJsonPathVariableFromJsonb (void *varsJsonb, char *varName, int varNameLen, JsonbValue *val, JsonbValue *baseObject)
 
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 int JsonbType (JsonbValue *jb)
 
static JsonbValueJsonbInitBinary (JsonbValue *jbv, Jsonb *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 *have_error)
 
static JsonTableJoinStateJsonTableInitPlanState (JsonTableContext *cxt, Node *plan, JsonTableScanState *parent)
 
static bool JsonTableNextRow (JsonTableScanState *scan)
 
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 void checkTimezoneIsUsedForCast (bool useTz, const char *type1, const char *type2)
 
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, List *vars, bool *error)
 
Datum JsonPathQuery (Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, bool *error, List *vars)
 
JsonbValueJsonPathValue (Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars)
 
static void JsonbValueInitNumericDatum (JsonbValue *jbv, Datum num)
 
void JsonItemFromDatum (Datum val, Oid typid, int32 typmod, JsonbValue *res)
 
static JsonTableContextGetJsonTableContext (TableFuncScanState *state, const char *fname)
 
static void JsonTableInitScanState (JsonTableContext *cxt, JsonTableScanState *scan, JsonTableParent *node, JsonTableScanState *parent, List *args, MemoryContext mcxt)
 
static void JsonTableInitOpaque (TableFuncScanState *state, int natts)
 
static void JsonTableRescan (JsonTableScanState *scan)
 
static void JsonTableResetContextItem (JsonTableScanState *scan, Datum item)
 
static void JsonTableSetDocument (TableFuncScanState *state, Datum value)
 
static void JsonTableRescanRecursive (JsonTableJoinState *state)
 
static bool JsonTableNextJoinRow (JsonTableJoinState *state)
 
static void JsonTableJoinReset (JsonTableJoinState *state)
 
static bool JsonTableFetchRow (TableFuncScanState *state)
 
static Datum JsonTableGetValue (TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
 
static void JsonTableDestroyOpaque (TableFuncScanState *state)
 

Variables

const TableFuncRoutine JsonbTableRoutine
 

Macro Definition Documentation

◆ jperIsError

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

Definition at line 144 of file jsonpath_exec.c.

◆ JSON_TABLE_CONTEXT_MAGIC

#define JSON_TABLE_CONTEXT_MAGIC   418352867

Definition at line 201 of file jsonpath_exec.c.

◆ jspAutoUnwrap

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

Definition at line 217 of file jsonpath_exec.c.

◆ jspAutoWrap

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

Definition at line 218 of file jsonpath_exec.c.

◆ jspIgnoreStructuralErrors

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

Definition at line 219 of file jsonpath_exec.c.

◆ jspStrictAbsenseOfErrors

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

Definition at line 216 of file jsonpath_exec.c.

◆ jspThrowErrors

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

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

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 235 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

typedef enum JsonPathBool JsonPathBool

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathPredicateCallback

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

Definition at line 231 of file jsonpath_exec.c.

◆ JsonPathVarCallback

typedef int(* JsonPathVarCallback) (void *vars, char *varName, int varNameLen, JsonbValue *val, JsonbValue *baseObject)

Definition at line 93 of file jsonpath_exec.c.

◆ JsonTableContext

◆ JsonTableJoinState

Definition at line 93 of file jsonpath_exec.c.

◆ JsonTableScanState

Definition at line 93 of file jsonpath_exec.c.

◆ JsonValueList

typedef struct JsonValueList JsonValueList

◆ JsonValueListIterator

Enumeration Type Documentation

◆ JsonPathBool

Enumerator
jpbFalse 
jpbTrue 
jpbUnknown 

Definition at line 129 of file jsonpath_exec.c.

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

◆ JsonPathExecResult

Enumerator
jperOk 
jperNotFound 
jperError 

Definition at line 137 of file jsonpath_exec.c.

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

Function Documentation

◆ appendBoolResult()

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

Definition at line 2118 of file jsonpath_exec.c.

2120 {
2122  JsonbValue jbv;
2123 
2124  if (!jspGetNext(jsp, &next) && !found)
2125  return jperOk; /* found singleton boolean value */
2126 
2127  if (res == jpbUnknown)
2128  {
2129  jbv.type = jbvNull;
2130  }
2131  else
2132  {
2133  jbv.type = jbvBool;
2134  jbv.val.boolean = res == jpbTrue;
2135  }
2136 
2137  return executeNextItem(cxt, jsp, &next, &jbv, found, true);
2138 }
static int32 next
Definition: blutils.c:219
@ jbvBool
Definition: jsonb.h:239
@ jbvNull
Definition: jsonb.h:236
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:943
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
enum jbvType type
Definition: jsonb.h:263
char * val
Definition: jsonb.h:272

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

2275 {
2276  int cmp;
2277 
2278  cmp = memcmp(s1, s2, Min(len1, len2));
2279 
2280  if (cmp != 0)
2281  return cmp;
2282 
2283  if (len1 == len2)
2284  return 0;
2285 
2286  return len1 < len2 ? -1 : 1;
2287 }
#define Min(x, y)
Definition: c.h:986
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:747

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

Referenced by compareStrings().

◆ castTimeToTimeTz()

static Datum castTimeToTimeTz ( Datum  time,
bool  useTz 
)
static

Definition at line 2698 of file jsonpath_exec.c.

2699 {
2700  checkTimezoneIsUsedForCast(useTz, "time", "timetz");
2701 
2702  return DirectFunctionCall1(time_timetz, time);
2703 }
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2790
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
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 2686 of file jsonpath_exec.c.

2687 {
2688  if (!useTz)
2689  ereport(ERROR,
2690  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2691  errmsg("cannot convert value from %s to %s without time zone usage",
2692  type1, type2),
2693  errhint("Use *_tz() function for time zone support.")));
2694 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143

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

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

◆ cmpDateToTimestamp()

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

Definition at line 2710 of file jsonpath_exec.c.

2711 {
2712  return date_cmp_timestamp_internal(date1, ts2);
2713 }
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:736

References date_cmp_timestamp_internal().

Referenced by compareDatetime().

◆ cmpDateToTimestampTz()

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

Definition at line 2719 of file jsonpath_exec.c.

2720 {
2721  checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
2722 
2723  return date_cmp_timestamptz_internal(date1, tstz2);
2724 }
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:816

References checkTimezoneIsUsedForCast(), and date_cmp_timestamptz_internal().

Referenced by compareDatetime().

◆ cmpTimestampToTimestampTz()

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

Definition at line 2730 of file jsonpath_exec.c.

2731 {
2732  checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
2733 
2734  return timestamp_cmp_timestamptz_internal(ts1, tstz2);
2735 }
int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2)
Definition: timestamp.c:2226

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 have_error 
)
static

Definition at line 2743 of file jsonpath_exec.c.

2745 {
2746  PGFunction cmpfunc;
2747 
2748  *cast_error = false;
2749 
2750  switch (typid1)
2751  {
2752  case DATEOID:
2753  switch (typid2)
2754  {
2755  case DATEOID:
2756  cmpfunc = date_cmp;
2757 
2758  break;
2759 
2760  case TIMESTAMPOID:
2761  return cmpDateToTimestamp(DatumGetDateADT(val1),
2762  DatumGetTimestamp(val2),
2763  useTz);
2764 
2765  case TIMESTAMPTZOID:
2767  DatumGetTimestampTz(val2),
2768  useTz);
2769 
2770  case TIMEOID:
2771  case TIMETZOID:
2772  *cast_error = true; /* uncomparable types */
2773  return 0;
2774 
2775  default:
2776  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
2777  typid2);
2778  }
2779  break;
2780 
2781  case TIMEOID:
2782  switch (typid2)
2783  {
2784  case TIMEOID:
2785  cmpfunc = time_cmp;
2786 
2787  break;
2788 
2789  case TIMETZOID:
2790  val1 = castTimeToTimeTz(val1, useTz);
2791  cmpfunc = timetz_cmp;
2792 
2793  break;
2794 
2795  case DATEOID:
2796  case TIMESTAMPOID:
2797  case TIMESTAMPTZOID:
2798  *cast_error = true; /* uncomparable types */
2799  return 0;
2800 
2801  default:
2802  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
2803  typid2);
2804  }
2805  break;
2806 
2807  case TIMETZOID:
2808  switch (typid2)
2809  {
2810  case TIMEOID:
2811  val2 = castTimeToTimeTz(val2, useTz);
2812  cmpfunc = timetz_cmp;
2813 
2814  break;
2815 
2816  case TIMETZOID:
2817  cmpfunc = timetz_cmp;
2818 
2819  break;
2820 
2821  case DATEOID:
2822  case TIMESTAMPOID:
2823  case TIMESTAMPTZOID:
2824  *cast_error = true; /* uncomparable types */
2825  return 0;
2826 
2827  default:
2828  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
2829  typid2);
2830  }
2831  break;
2832 
2833  case TIMESTAMPOID:
2834  switch (typid2)
2835  {
2836  case DATEOID:
2837  return -cmpDateToTimestamp(DatumGetDateADT(val2),
2838  DatumGetTimestamp(val1),
2839  useTz);
2840 
2841  case TIMESTAMPOID:
2842  cmpfunc = timestamp_cmp;
2843 
2844  break;
2845 
2846  case TIMESTAMPTZOID:
2848  DatumGetTimestampTz(val2),
2849  useTz);
2850 
2851  case TIMEOID:
2852  case TIMETZOID:
2853  *cast_error = true; /* uncomparable types */
2854  return 0;
2855 
2856  default:
2857  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
2858  typid2);
2859  }
2860  break;
2861 
2862  case TIMESTAMPTZOID:
2863  switch (typid2)
2864  {
2865  case DATEOID:
2866  return -cmpDateToTimestampTz(DatumGetDateADT(val2),
2867  DatumGetTimestampTz(val1),
2868  useTz);
2869 
2870  case TIMESTAMPOID:
2872  DatumGetTimestampTz(val1),
2873  useTz);
2874 
2875  case TIMESTAMPTZOID:
2876  cmpfunc = timestamp_cmp;
2877 
2878  break;
2879 
2880  case TIMEOID:
2881  case TIMETZOID:
2882  *cast_error = true; /* uncomparable types */
2883  return 0;
2884 
2885  default:
2886  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u",
2887  typid2);
2888  }
2889  break;
2890 
2891  default:
2892  elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", typid1);
2893  }
2894 
2895  if (*cast_error)
2896  return 0; /* cast error */
2897 
2898  return DatumGetInt32(DirectFunctionCall2(cmpfunc, val1, val2));
2899 }
Datum timestamp_cmp(PG_FUNCTION_ARGS)
Definition: timestamp.c:2171
Datum date_cmp(PG_FUNCTION_ARGS)
Definition: date.c:430
Datum time_cmp(PG_FUNCTION_ARGS)
Definition: date.c:1722
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition: date.c:2498
#define DatumGetDateADT(X)
Definition: date.h:53
#define elog(elevel,...)
Definition: elog.h:218
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:633
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)
#define DatumGetInt32(X)
Definition: postgres.h:516
#define DatumGetTimestamp(X)
Definition: timestamp.h:27
#define DatumGetTimestampTz(X)
Definition: timestamp.h:28

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

2362 {
2363  int cmp;
2364  bool res;
2365 
2366  if (jb1->type != jb2->type)
2367  {
2368  if (jb1->type == jbvNull || jb2->type == jbvNull)
2369 
2370  /*
2371  * Equality and order comparison of nulls to non-nulls returns
2372  * always false, but inequality comparison returns true.
2373  */
2374  return op == jpiNotEqual ? jpbTrue : jpbFalse;
2375 
2376  /* Non-null items of different types are not comparable. */
2377  return jpbUnknown;
2378  }
2379 
2380  switch (jb1->type)
2381  {
2382  case jbvNull:
2383  cmp = 0;
2384  break;
2385  case jbvBool:
2386  cmp = jb1->val.boolean == jb2->val.boolean ? 0 :
2387  jb1->val.boolean ? 1 : -1;
2388  break;
2389  case jbvNumeric:
2390  cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
2391  break;
2392  case jbvString:
2393  if (op == jpiEqual)
2394  return jb1->val.string.len != jb2->val.string.len ||
2395  memcmp(jb1->val.string.val,
2396  jb2->val.string.val,
2397  jb1->val.string.len) ? jpbFalse : jpbTrue;
2398 
2399  cmp = compareStrings(jb1->val.string.val, jb1->val.string.len,
2400  jb2->val.string.val, jb2->val.string.len);
2401  break;
2402  case jbvDatetime:
2403  {
2404  bool cast_error;
2405 
2406  cmp = compareDatetime(jb1->val.datetime.value,
2407  jb1->val.datetime.typid,
2408  jb2->val.datetime.value,
2409  jb2->val.datetime.typid,
2410  useTz,
2411  &cast_error);
2412 
2413  if (cast_error)
2414  return jpbUnknown;
2415  }
2416  break;
2417 
2418  case jbvBinary:
2419  case jbvArray:
2420  case jbvObject:
2421  return jpbUnknown; /* non-scalars are not comparable */
2422 
2423  default:
2424  elog(ERROR, "invalid jsonb value type %d", jb1->type);
2425  }
2426 
2427  switch (op)
2428  {
2429  case jpiEqual:
2430  res = (cmp == 0);
2431  break;
2432  case jpiNotEqual:
2433  res = (cmp != 0);
2434  break;
2435  case jpiLess:
2436  res = (cmp < 0);
2437  break;
2438  case jpiGreater:
2439  res = (cmp > 0);
2440  break;
2441  case jpiLessOrEqual:
2442  res = (cmp <= 0);
2443  break;
2444  case jpiGreaterOrEqual:
2445  res = (cmp >= 0);
2446  break;
2447  default:
2448  elog(ERROR, "unrecognized jsonpath operation: %d", op);
2449  return jpbUnknown;
2450  }
2451 
2452  return res ? jpbTrue : jpbFalse;
2453 }
@ jbvObject
Definition: jsonb.h:242
@ jbvNumeric
Definition: jsonb.h:238
@ jbvArray
Definition: jsonb.h:241
@ jbvBinary
Definition: jsonb.h:244
@ jbvDatetime
Definition: jsonb.h:252
@ jbvString
Definition: jsonb.h:237
@ jpiNotEqual
Definition: jsonpath.h:57
@ jpiGreaterOrEqual
Definition: jsonpath.h:61
@ jpiGreater
Definition: jsonpath.h:59
@ jpiLess
Definition: jsonpath.h:58
@ jpiEqual
Definition: jsonpath.h:56
@ jpiLessOrEqual
Definition: jsonpath.h:60
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 *have_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 2457 of file jsonpath_exec.c.

2458 {
2460  NumericGetDatum(a),
2461  NumericGetDatum(b)));
2462 }
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2316
int b
Definition: isn.c:70
int a
Definition: isn.c:69
#define NumericGetDatum(X)
Definition: numeric.h:61

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

2296 {
2297  if (GetDatabaseEncoding() == PG_SQL_ASCII ||
2299  {
2300  /*
2301  * It's known property of UTF-8 strings that their per-byte comparison
2302  * result matches codepoints comparison result. ASCII can be
2303  * considered as special case of UTF-8.
2304  */
2305  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
2306  }
2307  else
2308  {
2309  char *utf8str1,
2310  *utf8str2;
2311  int cmp,
2312  utf8len1,
2313  utf8len2;
2314 
2315  /*
2316  * We have to convert other encodings to UTF-8 first, then compare.
2317  * Input strings may be not null-terminated and pg_server_to_any() may
2318  * return them "as is". So, use strlen() only if there is real
2319  * conversion.
2320  */
2321  utf8str1 = pg_server_to_any(mbstr1, mblen1, PG_UTF8);
2322  utf8str2 = pg_server_to_any(mbstr2, mblen2, PG_UTF8);
2323  utf8len1 = (mbstr1 == utf8str1) ? mblen1 : strlen(utf8str1);
2324  utf8len2 = (mbstr2 == utf8str2) ? mblen2 : strlen(utf8str2);
2325 
2326  cmp = binaryCompareStrings(utf8str1, utf8len1, utf8str2, utf8len2);
2327 
2328  /*
2329  * If pg_server_to_any() did no real conversion, then we actually
2330  * compared original strings. So, we already done.
2331  */
2332  if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
2333  return cmp;
2334 
2335  /* Free memory if needed */
2336  if (mbstr1 != utf8str1)
2337  pfree(utf8str1);
2338  if (mbstr2 != utf8str2)
2339  pfree(utf8str2);
2340 
2341  /*
2342  * When all Unicode codepoints are equal, return result of binary
2343  * comparison. In some edge cases, same characters may have different
2344  * representations in encoding. Then our behavior could diverge from
2345  * standard. However, that allow us to do simple binary comparison
2346  * for "==" operator, which is performance critical in typical cases.
2347  * In future to implement strict standard conformance, we can do
2348  * normalization of input JSON strings.
2349  */
2350  if (cmp == 0)
2351  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
2352  else
2353  return cmp;
2354  }
2355 }
static int binaryCompareStrings(const char *s1, int len1, const char *s2, int len2)
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
void pfree(void *pointer)
Definition: mcxt.c:1175
@ PG_SQL_ASCII
Definition: pg_wchar.h:224
@ PG_UTF8
Definition: pg_wchar.h:230

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

2466 {
2467  JsonbValue *dst = palloc(sizeof(*dst));
2468 
2469  *dst = *src;
2470 
2471  return dst;
2472 }
void * palloc(Size size)
Definition: mcxt.c:1068

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

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

1451 {
1453  JsonbIterator *it;
1454  int32 r;
1455  JsonbValue v;
1456 
1458 
1459  if (level > last)
1460  return res;
1461 
1462  it = JsonbIteratorInit(jbc);
1463 
1464  /*
1465  * Recursively iterate over jsonb objects/arrays
1466  */
1467  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1468  {
1469  if (r == WJB_KEY)
1470  {
1471  r = JsonbIteratorNext(&it, &v, true);
1472  Assert(r == WJB_VALUE);
1473  }
1474 
1475  if (r == WJB_VALUE || r == WJB_ELEM)
1476  {
1477 
1478  if (level >= first ||
1479  (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
1480  v.type != jbvBinary)) /* leaves only requested */
1481  {
1482  /* check expression */
1483  if (jsp)
1484  {
1485  if (ignoreStructuralErrors)
1486  {
1487  bool savedIgnoreStructuralErrors;
1488 
1489  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1490  cxt->ignoreStructuralErrors = true;
1491  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1492  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1493  }
1494  else
1495  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1496 
1497  if (jperIsError(res))
1498  break;
1499 
1500  if (res == jperOk && !found)
1501  break;
1502  }
1503  else if (found)
1504  JsonValueListAppend(found, copyJsonbValue(&v));
1505  else
1506  return jperOk;
1507  }
1508 
1509  if (level < last && v.type == jbvBinary)
1510  {
1512  (cxt, jsp, v.val.binary.data, found,
1513  level + 1, first, last,
1514  ignoreStructuralErrors, unwrapNext);
1515 
1516  if (jperIsError(res))
1517  break;
1518 
1519  if (res == jperOk && found == NULL)
1520  break;
1521  }
1522  }
1523  }
1524 
1525  return res;
1526 }
#define PG_UINT32_MAX
Definition: c.h:525
signed int int32
Definition: c.h:429
@ 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:819
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:855
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)
Assert(fmt[strlen(fmt) - 1] !='\n')
void check_stack_depth(void)
Definition: postgres.c:3500

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

1622 {
1623  JsonPathExecResult jper;
1624  JsonPathItem elem;
1625  JsonValueList lseq = {0};
1626  JsonValueList rseq = {0};
1627  JsonbValue *lval;
1628  JsonbValue *rval;
1629  Numeric res;
1630 
1631  jspGetLeftArg(jsp, &elem);
1632 
1633  /*
1634  * XXX: By standard only operands of multiplicative expressions are
1635  * unwrapped. We extend it to other binary arithmetic expressions too.
1636  */
1637  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
1638  if (jperIsError(jper))
1639  return jper;
1640 
1641  jspGetRightArg(jsp, &elem);
1642 
1643  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
1644  if (jperIsError(jper))
1645  return jper;
1646 
1647  if (JsonValueListLength(&lseq) != 1 ||
1648  !(lval = getScalar(JsonValueListHead(&lseq), jbvNumeric)))
1650  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
1651  errmsg("left operand of jsonpath operator %s is not a single numeric value",
1652  jspOperationName(jsp->type)))));
1653 
1654  if (JsonValueListLength(&rseq) != 1 ||
1655  !(rval = getScalar(JsonValueListHead(&rseq), jbvNumeric)))
1657  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
1658  errmsg("right operand of jsonpath operator %s is not a single numeric value",
1659  jspOperationName(jsp->type)))));
1660 
1661  if (jspThrowErrors(cxt))
1662  {
1663  res = func(lval->val.numeric, rval->val.numeric, NULL);
1664  }
1665  else
1666  {
1667  bool error = false;
1668 
1669  res = func(lval->val.numeric, rval->val.numeric, &error);
1670 
1671  if (error)
1672  return jperError;
1673  }
1674 
1675  if (!jspGetNext(jsp, &elem) && !found)
1676  return jperOk;
1677 
1678  lval = palloc(sizeof(*lval));
1679  lval->type = jbvNumeric;
1680  lval->val.numeric = res;
1681 
1682  return executeNextItem(cxt, jsp, &elem, lval, found, false);
1683 }
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:998
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:724
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1019
#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:110

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

1296 {
1297  JsonPathItem larg;
1298  JsonPathItem rarg;
1299  JsonPathBool res;
1300  JsonPathBool res2;
1301 
1302  if (!canHaveNext && jspHasNext(jsp))
1303  elog(ERROR, "boolean jsonpath item cannot have next item");
1304 
1305  switch (jsp->type)
1306  {
1307  case jpiAnd:
1308  jspGetLeftArg(jsp, &larg);
1309  res = executeBoolItem(cxt, &larg, jb, false);
1310 
1311  if (res == jpbFalse)
1312  return jpbFalse;
1313 
1314  /*
1315  * SQL/JSON says that we should check second arg in case of
1316  * jperError
1317  */
1318 
1319  jspGetRightArg(jsp, &rarg);
1320  res2 = executeBoolItem(cxt, &rarg, jb, false);
1321 
1322  return res2 == jpbTrue ? res : res2;
1323 
1324  case jpiOr:
1325  jspGetLeftArg(jsp, &larg);
1326  res = executeBoolItem(cxt, &larg, jb, false);
1327 
1328  if (res == jpbTrue)
1329  return jpbTrue;
1330 
1331  jspGetRightArg(jsp, &rarg);
1332  res2 = executeBoolItem(cxt, &rarg, jb, false);
1333 
1334  return res2 == jpbFalse ? res : res2;
1335 
1336  case jpiNot:
1337  jspGetArg(jsp, &larg);
1338 
1339  res = executeBoolItem(cxt, &larg, jb, false);
1340 
1341  if (res == jpbUnknown)
1342  return jpbUnknown;
1343 
1344  return res == jpbTrue ? jpbFalse : jpbTrue;
1345 
1346  case jpiIsUnknown:
1347  jspGetArg(jsp, &larg);
1348  res = executeBoolItem(cxt, &larg, jb, false);
1349  return res == jpbUnknown ? jpbTrue : jpbFalse;
1350 
1351  case jpiEqual:
1352  case jpiNotEqual:
1353  case jpiLess:
1354  case jpiGreater:
1355  case jpiLessOrEqual:
1356  case jpiGreaterOrEqual:
1357  jspGetLeftArg(jsp, &larg);
1358  jspGetRightArg(jsp, &rarg);
1359  return executePredicate(cxt, jsp, &larg, &rarg, jb, true,
1360  executeComparison, cxt);
1361 
1362  case jpiStartsWith: /* 'whole STARTS WITH initial' */
1363  jspGetLeftArg(jsp, &larg); /* 'whole' */
1364  jspGetRightArg(jsp, &rarg); /* 'initial' */
1365  return executePredicate(cxt, jsp, &larg, &rarg, jb, false,
1366  executeStartsWith, NULL);
1367 
1368  case jpiLikeRegex: /* 'expr LIKE_REGEX pattern FLAGS flags' */
1369  {
1370  /*
1371  * 'expr' is a sequence-returning expression. 'pattern' is a
1372  * regex string literal. SQL/JSON standard requires XQuery
1373  * regexes, but we use Postgres regexes here. 'flags' is a
1374  * string literal converted to integer flags at compile-time.
1375  */
1376  JsonLikeRegexContext lrcxt = {0};
1377 
1378  jspInitByBuffer(&larg, jsp->base,
1379  jsp->content.like_regex.expr);
1380 
1381  return executePredicate(cxt, jsp, &larg, NULL, jb, false,
1382  executeLikeRegex, &lrcxt);
1383  }
1384 
1385  case jpiExists:
1386  jspGetArg(jsp, &larg);
1387 
1388  if (jspStrictAbsenseOfErrors(cxt))
1389  {
1390  /*
1391  * In strict mode we must get a complete list of values to
1392  * check that there are no errors at all.
1393  */
1394  JsonValueList vals = {0};
1396  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1397  false, &vals);
1398 
1399  if (jperIsError(res))
1400  return jpbUnknown;
1401 
1402  return JsonValueListIsEmpty(&vals) ? jpbFalse : jpbTrue;
1403  }
1404  else
1405  {
1407  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1408  false, NULL);
1409 
1410  if (jperIsError(res))
1411  return jpbUnknown;
1412 
1413  return res == jperOk ? jpbTrue : jpbFalse;
1414  }
1415 
1416  default:
1417  elog(ERROR, "invalid boolean jsonpath item type: %d", jsp->type);
1418  return jpbUnknown;
1419  }
1420 }
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:929
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition: jsonpath.c:849
#define jspHasNext(jsp)
Definition: jsonpath.h:167
@ jpiExists
Definition: jsonpath.h:78
@ jpiNot
Definition: jsonpath.h:54
@ jpiAnd
Definition: jsonpath.h:52
@ jpiStartsWith
Definition: jsonpath.h:89
@ jpiOr
Definition: jsonpath.h:53
@ jpiLikeRegex
Definition: jsonpath.h:90
@ jpiIsUnknown
Definition: jsonpath.h:55
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 jspStrictAbsenseOfErrors(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)
char * base
Definition: jsonpath.h:119
struct JsonPathItem::@136::@141 like_regex
union JsonPathItem::@136 content

References JsonPathItem::base, 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(), jspStrictAbsenseOfErrors, 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 2262 of file jsonpath_exec.c.

2263 {
2265 
2266  return compareItems(cmp->type, lv, rv, cxt->useTz);
2267 }
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 1847 of file jsonpath_exec.c.

1849 {
1850  JsonbValue jbvbuf;
1851  Datum value;
1852  text *datetime;
1853  Oid collid;
1854  Oid typid;
1855  int32 typmod = -1;
1856  int tz = 0;
1857  bool hasNext;
1859  JsonPathItem elem;
1860 
1861  if (!(jb = getScalar(jb, jbvString)))
1863  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
1864  errmsg("jsonpath item method .%s() can only be applied to a string",
1865  jspOperationName(jsp->type)))));
1866 
1867  datetime = cstring_to_text_with_len(jb->val.string.val,
1868  jb->val.string.len);
1869 
1870  /*
1871  * At some point we might wish to have callers supply the collation to
1872  * use, but right now it's unclear that they'd be able to do better than
1873  * DEFAULT_COLLATION_OID anyway.
1874  */
1875  collid = DEFAULT_COLLATION_OID;
1876 
1877  if (jsp->content.arg)
1878  {
1879  text *template;
1880  char *template_str;
1881  int template_len;
1882  bool have_error = false;
1883 
1884  jspGetArg(jsp, &elem);
1885 
1886  if (elem.type != jpiString)
1887  elog(ERROR, "invalid jsonpath item type for .datetime() argument");
1888 
1889  template_str = jspGetString(&elem, &template_len);
1890 
1891  template = cstring_to_text_with_len(template_str,
1892  template_len);
1893 
1894  value = parse_datetime(datetime, template, collid, true,
1895  &typid, &typmod, &tz,
1896  jspThrowErrors(cxt) ? NULL : &have_error);
1897 
1898  if (have_error)
1899  res = jperError;
1900  else
1901  res = jperOk;
1902  }
1903  else
1904  {
1905  /*
1906  * According to SQL/JSON standard enumerate ISO formats for: date,
1907  * timetz, time, timestamptz, timestamp.
1908  *
1909  * We also support ISO 8601 for timestamps, because to_json[b]()
1910  * functions use this format.
1911  */
1912  static const char *fmt_str[] =
1913  {
1914  "yyyy-mm-dd",
1915  "HH24:MI:SSTZH:TZM",
1916  "HH24:MI:SSTZH",
1917  "HH24:MI:SS",
1918  "yyyy-mm-dd HH24:MI:SSTZH:TZM",
1919  "yyyy-mm-dd HH24:MI:SSTZH",
1920  "yyyy-mm-dd HH24:MI:SS",
1921  "yyyy-mm-dd\"T\"HH24:MI:SSTZH:TZM",
1922  "yyyy-mm-dd\"T\"HH24:MI:SSTZH",
1923  "yyyy-mm-dd\"T\"HH24:MI:SS"
1924  };
1925 
1926  /* cache for format texts */
1927  static text *fmt_txt[lengthof(fmt_str)] = {0};
1928  int i;
1929 
1930  /* loop until datetime format fits */
1931  for (i = 0; i < lengthof(fmt_str); i++)
1932  {
1933  bool have_error = false;
1934 
1935  if (!fmt_txt[i])
1936  {
1937  MemoryContext oldcxt =
1939 
1940  fmt_txt[i] = cstring_to_text(fmt_str[i]);
1941  MemoryContextSwitchTo(oldcxt);
1942  }
1943 
1944  value = parse_datetime(datetime, fmt_txt[i], collid, true,
1945  &typid, &typmod, &tz,
1946  &have_error);
1947 
1948  if (!have_error)
1949  {
1950  res = jperOk;
1951  break;
1952  }
1953  }
1954 
1955  if (res == jperNotFound)
1957  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
1958  errmsg("datetime format is not recognized: \"%s\"",
1959  text_to_cstring(datetime)),
1960  errhint("Use a datetime template argument to specify the input data format."))));
1961  }
1962 
1963  pfree(datetime);
1964 
1965  if (jperIsError(res))
1966  return res;
1967 
1968  hasNext = jspGetNext(jsp, &elem);
1969 
1970  if (!hasNext && !found)
1971  return res;
1972 
1973  jb = hasNext ? &jbvbuf : palloc(sizeof(*jb));
1974 
1975  jb->type = jbvDatetime;
1976  jb->val.datetime.value = value;
1977  jb->val.datetime.typid = typid;
1978  jb->val.datetime.typmod = typmod;
1979  jb->val.datetime.tz = tz;
1980 
1981  return executeNextItem(cxt, jsp, &elem, jb, found, hasNext);
1982 }
#define lengthof(array)
Definition: c.h:734
Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict, Oid *typid, int32 *typmod, int *tz, bool *have_error)
Definition: formatting.c:4324
static struct @151 value
int i
Definition: isn.c:73
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1056
@ jpiString
Definition: jsonpath.h:49
MemoryContext TopMemoryContext
Definition: mcxt.c:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uintptr_t Datum
Definition: postgres.h:411
unsigned int Oid
Definition: postgres_ext.h:31
int32 arg
Definition: jsonpath.h:131
Definition: c.h:622
char * text_to_cstring(const text *t)
Definition: varlena.c:221
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200
text * cstring_to_text(const char *s)
Definition: varlena.c:188

References JsonPathItem::arg, JsonPathItem::content, cstring_to_text(), cstring_to_text_with_len(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, executeNextItem(), getScalar(), i, jbvDatetime, jbvString, jperError, jperIsError, jperNotFound, jperOk, jpiString, jspGetArg(), jspGetNext(), jspGetString(), jspOperationName(), jspThrowErrors, lengthof, MemoryContextSwitchTo(), palloc(), parse_datetime(), pfree(), res, RETURN_ERROR, text_to_cstring(), TopMemoryContext, JsonbValue::type, JsonPathItem::type, JsonbValue::val, and value.

Referenced by executeItemOptUnwrapTarget().

◆ executeItem()

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

Definition at line 671 of file jsonpath_exec.c.

673 {
674  return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
675 }
#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 1242 of file jsonpath_exec.c.

1245 {
1246  if (unwrap && jspAutoUnwrap(cxt))
1247  {
1248  JsonValueList seq = {0};
1250  JsonPathExecResult res = executeItem(cxt, jsp, jb, &seq);
1251  JsonbValue *item;
1252 
1253  if (jperIsError(res))
1254  return res;
1255 
1256  JsonValueListInitIterator(&seq, &it);
1257  while ((item = JsonValueListNext(&seq, &it)))
1258  {
1259  Assert(item->type != jbvArray);
1260 
1261  if (JsonbType(item) == jbvArray)
1262  executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1263  else
1264  JsonValueListAppend(found, item);
1265  }
1266 
1267  return jperOk;
1268  }
1269 
1270  return executeItem(cxt, jsp, jb, found);
1271 }
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 1277 of file jsonpath_exec.c.

1281 {
1283  bool throwErrors = cxt->throwErrors;
1284 
1285  cxt->throwErrors = false;
1286  res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1287  cxt->throwErrors = throwErrors;
1288 
1289  return res;
1290 }

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

685 {
686  JsonPathItem elem;
688  JsonBaseObjectInfo baseObject;
689 
692 
693  switch (jsp->type)
694  {
695  /* all boolean item types: */
696  case jpiAnd:
697  case jpiOr:
698  case jpiNot:
699  case jpiIsUnknown:
700  case jpiEqual:
701  case jpiNotEqual:
702  case jpiLess:
703  case jpiGreater:
704  case jpiLessOrEqual:
705  case jpiGreaterOrEqual:
706  case jpiExists:
707  case jpiStartsWith:
708  case jpiLikeRegex:
709  {
710  JsonPathBool st = executeBoolItem(cxt, jsp, jb, true);
711 
712  res = appendBoolResult(cxt, jsp, found, st);
713  break;
714  }
715 
716  case jpiKey:
717  if (JsonbType(jb) == jbvObject)
718  {
719  JsonbValue *v;
720  JsonbValue key;
721 
722  key.type = jbvString;
723  key.val.string.val = jspGetString(jsp, &key.val.string.len);
724 
725  v = findJsonbValueFromContainer(jb->val.binary.data,
726  JB_FOBJECT, &key);
727 
728  if (v != NULL)
729  {
730  res = executeNextItem(cxt, jsp, NULL,
731  v, found, false);
732 
733  /* free value if it was not added to found list */
734  if (jspHasNext(jsp) || !found)
735  pfree(v);
736  }
737  else if (!jspIgnoreStructuralErrors(cxt))
738  {
739  Assert(found);
740 
741  if (!jspThrowErrors(cxt))
742  return jperError;
743 
744  ereport(ERROR,
745  (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND), \
746  errmsg("JSON object does not contain key \"%s\"",
747  pnstrdup(key.val.string.val,
748  key.val.string.len))));
749  }
750  }
751  else if (unwrap && JsonbType(jb) == jbvArray)
752  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
753  else if (!jspIgnoreStructuralErrors(cxt))
754  {
755  Assert(found);
757  (errcode(ERRCODE_SQL_JSON_MEMBER_NOT_FOUND),
758  errmsg("jsonpath member accessor can only be applied to an object"))));
759  }
760  break;
761 
762  case jpiRoot:
763  jb = cxt->root;
764  baseObject = setBaseObject(cxt, jb, 0);
765  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
766  cxt->baseObject = baseObject;
767  break;
768 
769  case jpiCurrent:
770  res = executeNextItem(cxt, jsp, NULL, cxt->current,
771  found, true);
772  break;
773 
774  case jpiAnyArray:
775  if (JsonbType(jb) == jbvArray)
776  {
777  bool hasNext = jspGetNext(jsp, &elem);
778 
779  res = executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL,
780  jb, found, jspAutoUnwrap(cxt));
781  }
782  else if (jspAutoWrap(cxt))
783  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
784  else if (!jspIgnoreStructuralErrors(cxt))
786  (errcode(ERRCODE_SQL_JSON_ARRAY_NOT_FOUND),
787  errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
788  break;
789 
790  case jpiIndexArray:
791  if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
792  {
793  int innermostArraySize = cxt->innermostArraySize;
794  int i;
795  int size = JsonbArraySize(jb);
796  bool singleton = size < 0;
797  bool hasNext = jspGetNext(jsp, &elem);
798 
799  if (singleton)
800  size = 1;
801 
802  cxt->innermostArraySize = size; /* for LAST evaluation */
803 
804  for (i = 0; i < jsp->content.array.nelems; i++)
805  {
806  JsonPathItem from;
807  JsonPathItem to;
808  int32 index;
809  int32 index_from;
810  int32 index_to;
811  bool range = jspGetArraySubscript(jsp, &from,
812  &to, i);
813 
814  res = getArrayIndex(cxt, &from, jb, &index_from);
815 
816  if (jperIsError(res))
817  break;
818 
819  if (range)
820  {
821  res = getArrayIndex(cxt, &to, jb, &index_to);
822 
823  if (jperIsError(res))
824  break;
825  }
826  else
827  index_to = index_from;
828 
829  if (!jspIgnoreStructuralErrors(cxt) &&
830  (index_from < 0 ||
831  index_from > index_to ||
832  index_to >= size))
834  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
835  errmsg("jsonpath array subscript is out of bounds"))));
836 
837  if (index_from < 0)
838  index_from = 0;
839 
840  if (index_to >= size)
841  index_to = size - 1;
842 
843  res = jperNotFound;
844 
845  for (index = index_from; index <= index_to; index++)
846  {
847  JsonbValue *v;
848  bool copy;
849 
850  if (singleton)
851  {
852  v = jb;
853  copy = true;
854  }
855  else
856  {
857  v = getIthJsonbValueFromContainer(jb->val.binary.data,
858  (uint32) index);
859 
860  if (v == NULL)
861  continue;
862 
863  copy = false;
864  }
865 
866  if (!hasNext && !found)
867  return jperOk;
868 
869  res = executeNextItem(cxt, jsp, &elem, v, found,
870  copy);
871 
872  if (jperIsError(res))
873  break;
874 
875  if (res == jperOk && !found)
876  break;
877  }
878 
879  if (jperIsError(res))
880  break;
881 
882  if (res == jperOk && !found)
883  break;
884  }
885 
886  cxt->innermostArraySize = innermostArraySize;
887  }
888  else if (!jspIgnoreStructuralErrors(cxt))
889  {
891  (errcode(ERRCODE_SQL_JSON_ARRAY_NOT_FOUND),
892  errmsg("jsonpath array accessor can only be applied to an array"))));
893  }
894  break;
895 
896  case jpiLast:
897  {
898  JsonbValue tmpjbv;
899  JsonbValue *lastjbv;
900  int last;
901  bool hasNext = jspGetNext(jsp, &elem);
902 
903  if (cxt->innermostArraySize < 0)
904  elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
905 
906  if (!hasNext && !found)
907  {
908  res = jperOk;
909  break;
910  }
911 
912  last = cxt->innermostArraySize - 1;
913 
914  lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
915 
916  lastjbv->type = jbvNumeric;
917  lastjbv->val.numeric = int64_to_numeric(last);
918 
919  res = executeNextItem(cxt, jsp, &elem,
920  lastjbv, found, hasNext);
921  }
922  break;
923 
924  case jpiAnyKey:
925  if (JsonbType(jb) == jbvObject)
926  {
927  bool hasNext = jspGetNext(jsp, &elem);
928 
929  if (jb->type != jbvBinary)
930  elog(ERROR, "invalid jsonb object type: %d", jb->type);
931 
932  return executeAnyItem
933  (cxt, hasNext ? &elem : NULL,
934  jb->val.binary.data, found, 1, 1, 1,
935  false, jspAutoUnwrap(cxt));
936  }
937  else if (unwrap && JsonbType(jb) == jbvArray)
938  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
939  else if (!jspIgnoreStructuralErrors(cxt))
940  {
941  Assert(found);
943  (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
944  errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
945  }
946  break;
947 
948  case jpiAdd:
949  return executeBinaryArithmExpr(cxt, jsp, jb,
950  numeric_add_opt_error, found);
951 
952  case jpiSub:
953  return executeBinaryArithmExpr(cxt, jsp, jb,
954  numeric_sub_opt_error, found);
955 
956  case jpiMul:
957  return executeBinaryArithmExpr(cxt, jsp, jb,
958  numeric_mul_opt_error, found);
959 
960  case jpiDiv:
961  return executeBinaryArithmExpr(cxt, jsp, jb,
962  numeric_div_opt_error, found);
963 
964  case jpiMod:
965  return executeBinaryArithmExpr(cxt, jsp, jb,
966  numeric_mod_opt_error, found);
967 
968  case jpiPlus:
969  return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
970 
971  case jpiMinus:
972  return executeUnaryArithmExpr(cxt, jsp, jb, numeric_uminus,
973  found);
974 
975  case jpiFilter:
976  {
977  JsonPathBool st;
978 
979  if (unwrap && JsonbType(jb) == jbvArray)
980  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
981  false);
982 
983  jspGetArg(jsp, &elem);
984  st = executeNestedBoolItem(cxt, &elem, jb);
985  if (st != jpbTrue)
986  res = jperNotFound;
987  else
988  res = executeNextItem(cxt, jsp, NULL,
989  jb, found, true);
990  break;
991  }
992 
993  case jpiAny:
994  {
995  bool hasNext = jspGetNext(jsp, &elem);
996 
997  /* first try without any intermediate steps */
998  if (jsp->content.anybounds.first == 0)
999  {
1000  bool savedIgnoreStructuralErrors;
1001 
1002  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1003  cxt->ignoreStructuralErrors = true;
1004  res = executeNextItem(cxt, jsp, &elem,
1005  jb, found, true);
1006  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1007 
1008  if (res == jperOk && !found)
1009  break;
1010  }
1011 
1012  if (jb->type == jbvBinary)
1014  (cxt, hasNext ? &elem : NULL,
1015  jb->val.binary.data, found,
1016  1,
1017  jsp->content.anybounds.first,
1018  jsp->content.anybounds.last,
1019  true, jspAutoUnwrap(cxt));
1020  break;
1021  }
1022 
1023  case jpiNull:
1024  case jpiBool:
1025  case jpiNumeric:
1026  case jpiString:
1027  case jpiVariable:
1028  {
1029  JsonbValue vbuf;
1030  JsonbValue *v;
1031  bool hasNext = jspGetNext(jsp, &elem);
1032 
1033  if (!hasNext && !found)
1034  {
1035  res = jperOk; /* skip evaluation */
1036  break;
1037  }
1038 
1039  v = hasNext ? &vbuf : palloc(sizeof(*v));
1040 
1041  baseObject = cxt->baseObject;
1042  getJsonPathItem(cxt, jsp, v);
1043 
1044  res = executeNextItem(cxt, jsp, &elem,
1045  v, found, hasNext);
1046  cxt->baseObject = baseObject;
1047  }
1048  break;
1049 
1050  case jpiType:
1051  {
1052  JsonbValue *jbv = palloc(sizeof(*jbv));
1053 
1054  jbv->type = jbvString;
1055  jbv->val.string.val = pstrdup(JsonbTypeName(jb));
1056  jbv->val.string.len = strlen(jbv->val.string.val);
1057 
1058  res = executeNextItem(cxt, jsp, NULL, jbv,
1059  found, false);
1060  }
1061  break;
1062 
1063  case jpiSize:
1064  {
1065  int size = JsonbArraySize(jb);
1066 
1067  if (size < 0)
1068  {
1069  if (!jspAutoWrap(cxt))
1070  {
1071  if (!jspIgnoreStructuralErrors(cxt))
1073  (errcode(ERRCODE_SQL_JSON_ARRAY_NOT_FOUND),
1074  errmsg("jsonpath item method .%s() can only be applied to an array",
1075  jspOperationName(jsp->type)))));
1076  break;
1077  }
1078 
1079  size = 1;
1080  }
1081 
1082  jb = palloc(sizeof(*jb));
1083 
1084  jb->type = jbvNumeric;
1085  jb->val.numeric = int64_to_numeric(size);
1086 
1087  res = executeNextItem(cxt, jsp, NULL, jb, found, false);
1088  }
1089  break;
1090 
1091  case jpiAbs:
1092  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_abs,
1093  found);
1094 
1095  case jpiFloor:
1096  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_floor,
1097  found);
1098 
1099  case jpiCeiling:
1100  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_ceil,
1101  found);
1102 
1103  case jpiDouble:
1104  {
1105  JsonbValue jbv;
1106 
1107  if (unwrap && JsonbType(jb) == jbvArray)
1108  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
1109  false);
1110 
1111  if (jb->type == jbvNumeric)
1112  {
1114  NumericGetDatum(jb->val.numeric)));
1115  double val;
1116  bool have_error = false;
1117 
1119  NULL,
1120  "double precision",
1121  tmp,
1122  &have_error);
1123 
1124  if (have_error || isinf(val) || isnan(val))
1126  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1127  errmsg("numeric argument of jsonpath item method .%s() is out of range for type double precision",
1128  jspOperationName(jsp->type)))));
1129  res = jperOk;
1130  }
1131  else if (jb->type == jbvString)
1132  {
1133  /* cast string as double */
1134  double val;
1135  char *tmp = pnstrdup(jb->val.string.val,
1136  jb->val.string.len);
1137  bool have_error = false;
1138 
1140  NULL,
1141  "double precision",
1142  tmp,
1143  &have_error);
1144 
1145  if (have_error || isinf(val) || isnan(val))
1147  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1148  errmsg("string argument of jsonpath item method .%s() is not a valid representation of a double precision number",
1149  jspOperationName(jsp->type)))));
1150 
1151  jb = &jbv;
1152  jb->type = jbvNumeric;
1154  Float8GetDatum(val)));
1155  res = jperOk;
1156  }
1157 
1158  if (res == jperNotFound)
1160  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1161  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1162  jspOperationName(jsp->type)))));
1163 
1164  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1165  }
1166  break;
1167 
1168  case jpiDatetime:
1169  if (unwrap && JsonbType(jb) == jbvArray)
1170  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1171 
1172  return executeDateTimeMethod(cxt, jsp, jb, found);
1173 
1174  case jpiKeyValue:
1175  if (unwrap && JsonbType(jb) == jbvArray)
1176  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1177 
1178  return executeKeyValueMethod(cxt, jsp, jb, found);
1179 
1180  default:
1181  elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
1182  }
1183 
1184  return res;
1185 }
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4392
Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3285
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3061
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4137
Datum numeric_uminus(PG_FUNCTION_ARGS)
Definition: numeric.c:1339
Datum numeric_ceil(PG_FUNCTION_ARGS)
Definition: numeric.c:1558
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:735
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2862
Numeric numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2940
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition: numeric.c:1312
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2784
Datum numeric_floor(PG_FUNCTION_ARGS)
Definition: numeric.c:1586
unsigned int uint32
Definition: c.h:441
double float8in_internal_opt_error(char *num, char **endptr_p, const char *type_name, const char *orig_string, bool *have_error)
Definition: float.c:380
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1692
long val
Definition: informix.c:664
const char * JsonbTypeName(JsonbValue *jbv)
Definition: jsonb.c:178
#define JB_FOBJECT
Definition: jsonb.h:210
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:470
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:346
bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to, int i)
Definition: jsonpath.c:1068
@ jpiAdd
Definition: jsonpath.h:62
@ jpiAbs
Definition: jsonpath.h:81
@ jpiIndexArray
Definition: jsonpath.h:71
@ jpiAny
Definition: jsonpath.h:72
@ jpiDatetime
Definition: jsonpath.h:85
@ jpiBool
Definition: jsonpath.h:51
@ jpiType
Definition: jsonpath.h:79
@ jpiFloor
Definition: jsonpath.h:82
@ jpiAnyArray
Definition: jsonpath.h:69
@ jpiSize
Definition: jsonpath.h:80
@ jpiSub
Definition: jsonpath.h:63
@ jpiMul
Definition: jsonpath.h:64
@ jpiVariable
Definition: jsonpath.h:76
@ jpiPlus
Definition: jsonpath.h:67
@ jpiDouble
Definition: jsonpath.h:84
@ jpiMod
Definition: jsonpath.h:66
@ jpiRoot
Definition: jsonpath.h:75
@ jpiFilter
Definition: jsonpath.h:77
@ jpiNull
Definition: jsonpath.h:48
@ jpiCurrent
Definition: jsonpath.h:74
@ jpiKey
Definition: jsonpath.h:73
@ jpiDiv
Definition: jsonpath.h:65
@ jpiLast
Definition: jsonpath.h:88
@ jpiMinus
Definition: jsonpath.h:68
@ jpiCeiling
Definition: jsonpath.h:83
@ jpiKeyValue
Definition: jsonpath.h:86
@ jpiNumeric
Definition: jsonpath.h:50
@ jpiAnyKey
Definition: jsonpath.h:70
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:1316
char * pstrdup(const char *in)
Definition: mcxt.c:1305
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define DatumGetNumeric(X)
Definition: numeric.h:59
#define DatumGetCString(X)
Definition: postgres.h:610
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
JsonbValue * current
JsonBaseObjectInfo baseObject
struct JsonPathItem::@136::@139 anybounds
struct JsonPathItem::@136::@138 array
Definition: type.h:90

References JsonPathItem::anybounds, appendBoolResult(), JsonPathItem::array, Assert(), JsonPathExecContext::baseObject, CHECK_FOR_INTERRUPTS, check_stack_depth(), JsonPathItem::content, JsonPathExecContext::current, DatumGetCString, DatumGetNumeric, DirectFunctionCall1, elog, ereport, errcode(), errmsg(), ERROR, executeAnyItem(), executeBinaryArithmExpr(), executeBoolItem(), executeDateTimeMethod(), executeItemUnwrapTargetArray(), executeKeyValueMethod(), executeNestedBoolItem(), executeNextItem(), executeNumericItemMethod(), executeUnaryArithmExpr(), findJsonbValueFromContainer(), float8_numeric(), Float8GetDatum(), float8in_internal_opt_error(), getArrayIndex(), getIthJsonbValueFromContainer(), getJsonPathItem(), i, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, int64_to_numeric(), JB_FOBJECT, jbvArray, jbvBinary, jbvNumeric, jbvObject, jbvString, jpbTrue, jperError, jperIsError, jperNotFound, jperOk, jpiAbs, jpiAdd, jpiAnd, jpiAny, jpiAnyArray, jpiAnyKey, jpiBool, jpiCeiling, jpiCurrent, jpiDatetime, jpiDiv, jpiDouble, jpiEqual, jpiExists, jpiFilter, jpiFloor, jpiGreater, jpiGreaterOrEqual, jpiIndexArray, jpiIsUnknown, jpiKey, jpiKeyValue, jpiLast, jpiLess, jpiLessOrEqual, jpiLikeRegex, jpiMinus, jpiMod, jpiMul, jpiNot, jpiNotEqual, jpiNull, jpiNumeric, jpiOr, jpiPlus, jpiRoot, jpiSize, jpiStartsWith, jpiString, jpiSub, jpiType, jpiVariable, JsonbArraySize(), JsonbType(), JsonbTypeName(), jspAutoUnwrap, jspAutoWrap, jspGetArg(), jspGetArraySubscript(), jspGetNext(), jspGetString(), jspHasNext, jspIgnoreStructuralErrors, jspOperationName(), jspThrowErrors, sort-test::key, numeric_abs(), numeric_add_opt_error(), numeric_ceil(), numeric_div_opt_error(), numeric_floor(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_out(), numeric_sub_opt_error(), numeric_uminus(), NumericGetDatum, palloc(), pfree(), pnstrdup(), pstrdup(), range(), res, RETURN_ERROR, JsonPathExecContext::root, setBaseObject(), 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 1191 of file jsonpath_exec.c.

1194 {
1195  if (jb->type != jbvBinary)
1196  {
1197  Assert(jb->type != jbvArray);
1198  elog(ERROR, "invalid jsonb array value type: %d", jb->type);
1199  }
1200 
1201  return executeAnyItem
1202  (cxt, jsp, jb->val.binary.data, found, 1, 1, 1,
1203  false, unwrapElements);
1204 }

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,
JsonPathVarCallback  getVar,
Jsonb json,
bool  throwErrors,
JsonValueList result,
bool  useTz 
)
static

Definition at line 616 of file jsonpath_exec.c.

619 {
622  JsonPathItem jsp;
623  JsonbValue jbv;
624 
625  jspInit(&jsp, path);
626 
627  if (!JsonbExtractScalar(&json->root, &jbv))
628  JsonbInitBinary(&jbv, json);
629 
630  cxt.vars = vars;
631  cxt.getVar = getVar;
632  cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
634  cxt.root = &jbv;
635  cxt.current = &jbv;
636  cxt.baseObject.jbc = NULL;
637  cxt.baseObject.id = 0;
638  /* 1 + number of base objects in vars */
639  cxt.lastGeneratedObjectId = 1 + getVar(vars, NULL, 0, NULL, NULL);
640  cxt.innermostArraySize = -1;
641  cxt.throwErrors = throwErrors;
642  cxt.useTz = useTz;
643 
644  if (jspStrictAbsenseOfErrors(&cxt) && !result)
645  {
646  /*
647  * In strict mode we must get a complete list of values to check that
648  * there are no errors at all.
649  */
650  JsonValueList vals = {0};
651 
652  res = executeItem(&cxt, &jsp, &jbv, &vals);
653 
654  if (jperIsError(res))
655  return res;
656 
657  return JsonValueListIsEmpty(&vals) ? jperNotFound : jperOk;
658  }
659 
660  res = executeItem(&cxt, &jsp, &jbv, result);
661 
662  Assert(!throwErrors || !jperIsError(res));
663 
664  return res;
665 }
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:2034
void jspInit(JsonPathItem *v, JsonPath *js)
Definition: jsonpath.c:839
#define JSONPATH_LAX
Definition: jsonpath.h:32
static JsonbValue * JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
JsonbContainer * jbc
Definition: jsonpath_exec.c:89
JsonPathVarCallback getVar
uint32 header
Definition: jsonpath.h:27
JsonbContainer root
Definition: jsonb.h:223
Definition: regcomp.c:238

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(), jspStrictAbsenseOfErrors, 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 JsonTableResetContextItem().

◆ executeKeyValueMethod()

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

Definition at line 2008 of file jsonpath_exec.c.

2010 {
2013  JsonbContainer *jbc;
2014  JsonbValue key;
2015  JsonbValue val;
2016  JsonbValue idval;
2017  JsonbValue keystr;
2018  JsonbValue valstr;
2019  JsonbValue idstr;
2020  JsonbIterator *it;
2021  JsonbIteratorToken tok;
2022  int64 id;
2023  bool hasNext;
2024 
2025  if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
2027  (errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
2028  errmsg("jsonpath item method .%s() can only be applied to an object",
2029  jspOperationName(jsp->type)))));
2030 
2031  jbc = jb->val.binary.data;
2032 
2033  if (!JsonContainerSize(jbc))
2034  return jperNotFound; /* no key-value pairs */
2035 
2036  hasNext = jspGetNext(jsp, &next);
2037 
2038  keystr.type = jbvString;
2039  keystr.val.string.val = "key";
2040  keystr.val.string.len = 3;
2041 
2042  valstr.type = jbvString;
2043  valstr.val.string.val = "value";
2044  valstr.val.string.len = 5;
2045 
2046  idstr.type = jbvString;
2047  idstr.val.string.val = "id";
2048  idstr.val.string.len = 2;
2049 
2050  /* construct object id from its base object and offset inside that */
2051  id = jb->type != jbvBinary ? 0 :
2052  (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
2053  id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
2054 
2055  idval.type = jbvNumeric;
2056  idval.val.numeric = int64_to_numeric(id);
2057 
2058  it = JsonbIteratorInit(jbc);
2059 
2060  while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
2061  {
2062  JsonBaseObjectInfo baseObject;
2063  JsonbValue obj;
2064  JsonbParseState *ps;
2065  JsonbValue *keyval;
2066  Jsonb *jsonb;
2067 
2068  if (tok != WJB_KEY)
2069  continue;
2070 
2071  res = jperOk;
2072 
2073  if (!hasNext && !found)
2074  break;
2075 
2076  tok = JsonbIteratorNext(&it, &val, true);
2077  Assert(tok == WJB_VALUE);
2078 
2079  ps = NULL;
2080  pushJsonbValue(&ps, WJB_BEGIN_OBJECT, NULL);
2081 
2082  pushJsonbValue(&ps, WJB_KEY, &keystr);
2083  pushJsonbValue(&ps, WJB_VALUE, &key);
2084 
2085  pushJsonbValue(&ps, WJB_KEY, &valstr);
2086  pushJsonbValue(&ps, WJB_VALUE, &val);
2087 
2088  pushJsonbValue(&ps, WJB_KEY, &idstr);
2089  pushJsonbValue(&ps, WJB_VALUE, &idval);
2090 
2091  keyval = pushJsonbValue(&ps, WJB_END_OBJECT, NULL);
2092 
2093  jsonb = JsonbValueToJsonb(keyval);
2094 
2095  JsonbInitBinary(&obj, jsonb);
2096 
2097  baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
2098 
2099  res = executeNextItem(cxt, jsp, &next, &obj, found, true);
2100 
2101  cxt->baseObject = baseObject;
2102 
2103  if (jperIsError(res))
2104  return res;
2105 
2106  if (res == jperOk && !found)
2107  break;
2108  }
2109 
2110  return res;
2111 }
#define JsonContainerSize(jc)
Definition: jsonb.h:214
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:94
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:568
Definition: jsonb.h:221

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

1783 {
1784  JsonLikeRegexContext *cxt = param;
1785 
1786  if (!(str = getScalar(str, jbvString)))
1787  return jpbUnknown;
1788 
1789  /* Cache regex text and converted flags. */
1790  if (!cxt->regex)
1791  {
1792  cxt->regex =
1794  jsp->content.like_regex.patternlen);
1795  cxt->cflags = jspConvertRegexFlags(jsp->content.like_regex.flags);
1796  }
1797 
1798  if (RE_compile_and_execute(cxt->regex, str->val.string.val,
1799  str->val.string.len,
1800  cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
1801  return jpbTrue;
1802 
1803  return jpbFalse;
1804 }
int jspConvertRegexFlags(uint32 xflags)
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:344

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 generate_unaccent_rules::str.

Referenced by executeBoolItem().

◆ executeNestedBoolItem()

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

Definition at line 1427 of file jsonpath_exec.c.

1429 {
1430  JsonbValue *prev;
1431  JsonPathBool res;
1432 
1433  prev = cxt->current;
1434  cxt->current = jb;
1435  res = executeBoolItem(cxt, jsp, jb, false);
1436  cxt->current = prev;
1437 
1438  return res;
1439 }

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

1214 {
1215  JsonPathItem elem;
1216  bool hasNext;
1217 
1218  if (!cur)
1219  hasNext = next != NULL;
1220  else if (next)
1221  hasNext = jspHasNext(cur);
1222  else
1223  {
1224  next = &elem;
1225  hasNext = jspGetNext(cur, next);
1226  }
1227 
1228  if (hasNext)
1229  return executeItem(cxt, next, v, found);
1230 
1231  if (found)
1232  JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1233 
1234  return jperOk;
1235 }
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 1811 of file jsonpath_exec.c.

1814 {
1816  Datum datum;
1817 
1818  if (unwrap && JsonbType(jb) == jbvArray)
1819  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1820 
1821  if (!(jb = getScalar(jb, jbvNumeric)))
1823  (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
1824  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
1825  jspOperationName(jsp->type)))));
1826 
1827  datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
1828 
1829  if (!jspGetNext(jsp, &next) && !found)
1830  return jperOk;
1831 
1832  jb = palloc(sizeof(*jb));
1833  jb->type = jbvNumeric;
1834  jb->val.numeric = DatumGetNumeric(datum);
1835 
1836  return executeNextItem(cxt, jsp, &next, jb, found, false);
1837 }

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

1543 {
1545  JsonValueListIterator lseqit;
1546  JsonValueList lseq = {0};
1547  JsonValueList rseq = {0};
1548  JsonbValue *lval;
1549  bool error = false;
1550  bool found = false;
1551 
1552  /* Left argument is always auto-unwrapped. */
1553  res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
1554  if (jperIsError(res))
1555  return jpbUnknown;
1556 
1557  if (rarg)
1558  {
1559  /* Right argument is conditionally auto-unwrapped. */
1560  res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
1561  unwrapRightArg, &rseq);
1562  if (jperIsError(res))
1563  return jpbUnknown;
1564  }
1565 
1566  JsonValueListInitIterator(&lseq, &lseqit);
1567  while ((lval = JsonValueListNext(&lseq, &lseqit)))
1568  {
1569  JsonValueListIterator rseqit;
1570  JsonbValue *rval;
1571  bool first = true;
1572 
1573  JsonValueListInitIterator(&rseq, &rseqit);
1574  if (rarg)
1575  rval = JsonValueListNext(&rseq, &rseqit);
1576  else
1577  rval = NULL;
1578 
1579  /* Loop over right arg sequence or do single pass otherwise */
1580  while (rarg ? (rval != NULL) : first)
1581  {
1582  JsonPathBool res = exec(pred, lval, rval, param);
1583 
1584  if (res == jpbUnknown)
1585  {
1586  if (jspStrictAbsenseOfErrors(cxt))
1587  return jpbUnknown;
1588 
1589  error = true;
1590  }
1591  else if (res == jpbTrue)
1592  {
1593  if (!jspStrictAbsenseOfErrors(cxt))
1594  return jpbTrue;
1595 
1596  found = true;
1597  }
1598 
1599  first = false;
1600  if (rarg)
1601  rval = JsonValueListNext(&rseq, &rseqit);
1602  }
1603  }
1604 
1605  if (found) /* possible only in strict mode */
1606  return jpbTrue;
1607 
1608  if (error) /* possible only in lax mode */
1609  return jpbUnknown;
1610 
1611  return jpbFalse;
1612 }
Definition: type.h:110

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

Referenced by executeBoolItem().

◆ executeStartsWith()

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

Definition at line 1757 of file jsonpath_exec.c.

1759 {
1760  if (!(whole = getScalar(whole, jbvString)))
1761  return jpbUnknown; /* error */
1762 
1763  if (!(initial = getScalar(initial, jbvString)))
1764  return jpbUnknown; /* error */
1765 
1766  if (whole->val.string.len >= initial->val.string.len &&
1767  !memcmp(whole->val.string.val,
1768  initial->val.string.val,
1769  initial->val.string.len))
1770  return jpbTrue;
1771 
1772  return jpbFalse;
1773 }

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

1692 {
1693  JsonPathExecResult jper;
1694  JsonPathExecResult jper2;
1695  JsonPathItem elem;
1696  JsonValueList seq = {0};
1698  JsonbValue *val;
1699  bool hasNext;
1700 
1701  jspGetArg(jsp, &elem);
1702  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
1703 
1704  if (jperIsError(jper))
1705  return jper;
1706 
1707  jper = jperNotFound;
1708 
1709  hasNext = jspGetNext(jsp, &elem);
1710 
1711  JsonValueListInitIterator(&seq, &it);
1712  while ((val = JsonValueListNext(&seq, &it)))
1713  {
1714  if ((val = getScalar(val, jbvNumeric)))
1715  {
1716  if (!found && !hasNext)
1717  return jperOk;
1718  }
1719  else
1720  {
1721  if (!found && !hasNext)
1722  continue; /* skip non-numerics processing */
1723 
1725  (errcode(ERRCODE_SQL_JSON_NUMBER_NOT_FOUND),
1726  errmsg("operand of unary jsonpath operator %s is not a numeric value",
1727  jspOperationName(jsp->type)))));
1728  }
1729 
1730  if (func)
1731  val->val.numeric =
1733  NumericGetDatum(val->val.numeric)));
1734 
1735  jper2 = executeNextItem(cxt, jsp, &elem, val, found, false);
1736 
1737  if (jperIsError(jper2))
1738  return jper2;
1739 
1740  if (jper2 == jperOk)
1741  {
1742  if (!found)
1743  return jperOk;
1744  jper = jperOk;
1745  }
1746  }
1747 
1748  return jper;
1749 }

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

2481 {
2482  JsonbValue *jbv;
2483  JsonValueList found = {0};
2484  JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
2485  Datum numeric_index;
2486  bool have_error = false;
2487 
2488  if (jperIsError(res))
2489  return res;
2490 
2491  if (JsonValueListLength(&found) != 1 ||
2492  !(jbv = getScalar(JsonValueListHead(&found), jbvNumeric)))
2494  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
2495  errmsg("jsonpath array subscript is not a single numeric value"))));
2496 
2497  numeric_index = DirectFunctionCall2(numeric_trunc,
2498  NumericGetDatum(jbv->val.numeric),
2499  Int32GetDatum(0));
2500 
2501  *index = numeric_int4_opt_error(DatumGetNumeric(numeric_index),
2502  &have_error);
2503 
2504  if (have_error)
2506  (errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
2507  errmsg("jsonpath array subscript is out of integer range"))));
2508 
2509  return jperOk;
2510 }
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4223
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:1511
#define Int32GetDatum(X)
Definition: postgres.h:523

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

2148 {
2149  switch (item->type)
2150  {
2151  case jpiNull:
2152  value->type = jbvNull;
2153  break;
2154  case jpiBool:
2155  value->type = jbvBool;
2156  value->val.boolean = jspGetBool(item);
2157  break;
2158  case jpiNumeric:
2159  value->type = jbvNumeric;
2160  value->val.numeric = jspGetNumeric(item);
2161  break;
2162  case jpiString:
2163  value->type = jbvString;
2164  value->val.string.val = jspGetString(item,
2165  &value->val.string.len);
2166  break;
2167  case jpiVariable:
2168  getJsonPathVariable(cxt, item, value);
2169  return;
2170  default:
2171  elog(ERROR, "unexpected jsonpath item type");
2172  }
2173 }
bool jspGetBool(JsonPathItem *v)
Definition: jsonpath.c:1040
Numeric jspGetNumeric(JsonPathItem *v)
Definition: jsonpath.c:1048
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().

◆ getJsonPathVariable()

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

Definition at line 2179 of file jsonpath_exec.c.

2181 {
2182  char *varName;
2183  int varNameLength;
2184  JsonbValue baseObject;
2185  int baseObjectId;
2186 
2188  varName = jspGetString(variable, &varNameLength);
2189 
2190  if (!cxt->vars ||
2191  (baseObjectId = cxt->getVar(cxt->vars, varName, varNameLength, value,
2192  &baseObject)) < 0)
2193  ereport(ERROR,
2194  (errcode(ERRCODE_UNDEFINED_OBJECT),
2195  errmsg("could not find jsonpath variable \"%s\"",
2196  pnstrdup(varName, varNameLength))));
2197 
2198  if (baseObjectId > 0)
2199  setBaseObject(cxt, &baseObject, baseObjectId);
2200 }
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 int getJsonPathVariableFromJsonb ( void *  varsJsonb,
char *  varName,
int  varNameLen,
JsonbValue val,
JsonbValue baseObject 
)
static

Definition at line 2203 of file jsonpath_exec.c.

2205 {
2206  Jsonb *vars = varsJsonb;
2207  JsonbValue tmp;
2208  JsonbValue *v;
2209 
2210  if (!varName)
2211  {
2212  if (vars && !JsonContainerIsObject(&vars->root))
2213  {
2214  ereport(ERROR,
2215  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2216  errmsg("\"vars\" argument is not an object"),
2217  errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object.")));
2218  }
2219 
2220  return vars ? 1 : 0; /* count of base objects */
2221  }
2222 
2223  tmp.type = jbvString;
2224  tmp.val.string.val = varName;
2225  tmp.val.string.len = varNameLength;
2226 
2227  v = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
2228 
2229  if (!v)
2230  return -1;
2231 
2232  *value = *v;
2233  pfree(v);
2234 
2235  JsonbInitBinary(baseObject, vars);
2236  return 1;
2237 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216

References ereport, errcode(), errdetail(), errmsg(), ERROR, findJsonbValueFromContainer(), JB_FOBJECT, jbvString, JsonbInitBinary(), JsonContainerIsObject, pfree(), JsonbValue::type, JsonbValue::val, and value.

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().

◆ GetJsonTableContext()

static JsonTableContext* GetJsonTableContext ( TableFuncScanState state,
const char *  fname 
)
inlinestatic

Definition at line 3149 of file jsonpath_exec.c.

3150 {
3151  JsonTableContext *result;
3152 
3153  if (!IsA(state, TableFuncScanState))
3154  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
3155  result = (JsonTableContext *) state->opaque;
3156  if (result->magic != JSON_TABLE_CONTEXT_MAGIC)
3157  elog(ERROR, "%s called with invalid TableFuncScanState", fname);
3158 
3159  return result;
3160 }
#define JSON_TABLE_CONTEXT_MAGIC
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
Definition: regguts.h:318

References elog, ERROR, if(), IsA, JSON_TABLE_CONTEXT_MAGIC, and JsonTableContext::magic.

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

◆ getScalar()

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

Definition at line 2658 of file jsonpath_exec.c.

2659 {
2660  /* Scalars should be always extracted during jsonpath execution. */
2661  Assert(scalar->type != jbvBinary ||
2662  !JsonContainerIsScalar(scalar->val.binary.data));
2663 
2664  return scalar->type == type ? scalar : NULL;
2665 }
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215

References Assert(), jbvBinary, JsonContainerIsScalar, generate_unaccent_rules::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 371 of file jsonpath_exec.c.

372 {
373  return jsonb_path_exists_internal(fcinfo, false);
374 }
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 344 of file jsonpath_exec.c.

345 {
346  Jsonb *jb = PG_GETARG_JSONB_P(0);
349  Jsonb *vars = NULL;
350  bool silent = true;
351 
352  if (PG_NARGS() == 4)
353  {
354  vars = PG_GETARG_JSONB_P(2);
355  silent = PG_GETARG_BOOL(3);
356  }
357 
359  jb, !silent, NULL, tz);
360 
361  PG_FREE_IF_COPY(jb, 0);
362  PG_FREE_IF_COPY(jp, 1);
363 
364  if (jperIsError(res))
365  PG_RETURN_NULL();
366 
368 }
#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:74
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:37
static int getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, int varNameLen, JsonbValue *val, JsonbValue *baseObject)
static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars, JsonPathVarCallback getVar, Jsonb *json, bool throwErrors, JsonValueList *result, bool useTz)

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

389 {
390  /* just call the other one -- it can handle both cases */
391  return jsonb_path_exists_internal(fcinfo, false);
392 }

References jsonb_path_exists_internal().

◆ jsonb_path_exists_tz()

Datum jsonb_path_exists_tz ( PG_FUNCTION_ARGS  )

Definition at line 377 of file jsonpath_exec.c.

378 {
379  return jsonb_path_exists_internal(fcinfo, true);
380 }

References jsonb_path_exists_internal().

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 440 of file jsonpath_exec.c.

441 {
442  return jsonb_path_match_internal(fcinfo, false);
443 }
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 400 of file jsonpath_exec.c.

401 {
402  Jsonb *jb = PG_GETARG_JSONB_P(0);
404  JsonValueList found = {0};
405  Jsonb *vars = NULL;
406  bool silent = true;
407 
408  if (PG_NARGS() == 4)
409  {
410  vars = PG_GETARG_JSONB_P(2);
411  silent = PG_GETARG_BOOL(3);
412  }
413 
415  jb, !silent, &found, tz);
416 
417  PG_FREE_IF_COPY(jb, 0);
418  PG_FREE_IF_COPY(jp, 1);
419 
420  if (JsonValueListLength(&found) == 1)
421  {
422  JsonbValue *jbv = JsonValueListHead(&found);
423 
424  if (jbv->type == jbvBool)
425  PG_RETURN_BOOL(jbv->val.boolean);
426 
427  if (jbv->type == jbvNull)
428  PG_RETURN_NULL();
429  }
430 
431  if (!silent)
432  ereport(ERROR,
433  (errcode(ERRCODE_SINGLETON_SQL_JSON_ITEM_REQUIRED),
434  errmsg("single boolean result is expected")));
435 
436  PG_RETURN_NULL();
437 }

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

458 {
459  /* just call the other one -- it can handle both cases */
460  return jsonb_path_match_internal(fcinfo, false);
461 }

References jsonb_path_match_internal().

◆ jsonb_path_match_tz()

Datum jsonb_path_match_tz ( PG_FUNCTION_ARGS  )

Definition at line 446 of file jsonpath_exec.c.

447 {
448  return jsonb_path_match_internal(fcinfo, true);
449 }

References jsonb_path_match_internal().

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 516 of file jsonpath_exec.c.

517 {
518  return jsonb_path_query_internal(fcinfo, false);
519 }
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 548 of file jsonpath_exec.c.

549 {
550  return jsonb_path_query_array_internal(fcinfo, false);
551 }
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 533 of file jsonpath_exec.c.

534 {
535  Jsonb *jb = PG_GETARG_JSONB_P(0);
537  JsonValueList found = {0};
539  bool silent = PG_GETARG_BOOL(3);
540 
542  jb, !silent, &found, tz);
543 
545 }
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
static JsonbValue * wrapItemsInArray(const JsonValueList *items)

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

555 {
556  return jsonb_path_query_array_internal(fcinfo, true);
557 }

References jsonb_path_query_array_internal().

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 583 of file jsonpath_exec.c.

584 {
585  return jsonb_path_query_first_internal(fcinfo, false);
586 }
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

Definition at line 565 of file jsonpath_exec.c.

566 {
567  Jsonb *jb = PG_GETARG_JSONB_P(0);
569  JsonValueList found = {0};
571  bool silent = PG_GETARG_BOOL(3);
572 
574  jb, !silent, &found, tz);
575 
576  if (JsonValueListLength(&found) >= 1)
578  else
579  PG_RETURN_NULL();
580 }

References executeJsonPath(), getJsonPathVariableFromJsonb(), JsonbValueToJsonb(), JsonValueListHead(), JsonValueListLength(), PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_GETARG_JSONPATH_P, PG_RETURN_JSONB_P, and PG_RETURN_NULL.

Referenced by jsonb_path_query_first(), and jsonb_path_query_first_tz().

◆ jsonb_path_query_first_tz()

Datum jsonb_path_query_first_tz ( PG_FUNCTION_ARGS  )

Definition at line 589 of file jsonpath_exec.c.

590 {
591  return jsonb_path_query_first_internal(fcinfo, true);
592 }

References jsonb_path_query_first_internal().

◆ jsonb_path_query_internal()

static Datum jsonb_path_query_internal ( FunctionCallInfo  fcinfo,
bool  tz 
)
static

Definition at line 469 of file jsonpath_exec.c.

470 {
471  FuncCallContext *funcctx;
472  List *found;
473  JsonbValue *v;
474  ListCell *c;
475 
476  if (SRF_IS_FIRSTCALL())
477  {
478  JsonPath *jp;
479  Jsonb *jb;
480  MemoryContext oldcontext;
481  Jsonb *vars;
482  bool silent;
483  JsonValueList found = {0};
484 
485  funcctx = SRF_FIRSTCALL_INIT();
486  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
487 
488  jb = PG_GETARG_JSONB_P_COPY(0);
491  silent = PG_GETARG_BOOL(3);
492 
494  jb, !silent, &found, tz);
495 
496  funcctx->user_fctx = JsonValueListGetList(&found);
497 
498  MemoryContextSwitchTo(oldcontext);
499  }
500 
501  funcctx = SRF_PERCALL_SETUP();
502  found = funcctx->user_fctx;
503 
504  c = list_head(found);
505 
506  if (c == NULL)
507  SRF_RETURN_DONE(funcctx);
508 
509  v = lfirst(c);
510  funcctx->user_fctx = list_delete_first(found);
511 
513 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:299
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:303
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:305
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:301
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:323
#define PG_GETARG_JSONB_P_COPY(x)
Definition: jsonb.h:75
#define JsonbPGetDatum(p)
Definition: jsonb.h:73
#define PG_GETARG_JSONPATH_P_COPY(x)
Definition: jsonpath.h:38
static List * JsonValueListGetList(JsonValueList *jvl)
List * list_delete_first(List *list)
Definition: list.c:902
#define lfirst(lc)
Definition: pg_list.h:169
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
char * c
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
Definition: pg_list.h:51

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

523 {
524  return jsonb_path_query_internal(fcinfo, true);
525 }

References jsonb_path_query_internal().

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 2245 of file jsonpath_exec.c.

2246 {
2247  Assert(jb->type != jbvArray);
2248 
2249  if (jb->type == jbvBinary)
2250  {
2251  JsonbContainer *jbc = jb->val.binary.data;
2252 
2253  if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
2254  return JsonContainerSize(jbc);
2255  }
2256 
2257  return -1;
2258 }
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217

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

2622 {
2623  jbv->type = jbvBinary;
2624  jbv->val.binary.data = &jb->root;
2625  jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
2626 
2627  return jbv;
2628 }
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354

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

2635 {
2636  int type = jb->type;
2637 
2638  if (jb->type == jbvBinary)
2639  {
2640  JsonbContainer *jbc = (void *) jb->val.binary.data;
2641 
2642  /* Scalars should be always extracted during jsonpath execution. */
2644 
2645  if (JsonContainerIsObject(jbc))
2646  type = jbvObject;
2647  else if (JsonContainerIsArray(jbc))
2648  type = jbvArray;
2649  else
2650  elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
2651  }
2652 
2653  return type;
2654 }
uint32 header
Definition: jsonb.h:200

References Assert(), elog, ERROR, JsonbContainer::header, jbvArray, jbvBinary, jbvObject, JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, generate_unaccent_rules::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 3055 of file jsonpath_exec.c.

3056 {
3057  jbv->type = jbvNumeric;
3058  jbv->val.numeric = DatumGetNumeric(num);
3059 }

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

Referenced by JsonItemFromDatum().

◆ JsonItemFromDatum()

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

Definition at line 3062 of file jsonpath_exec.c.

3063 {
3064  switch (typid)
3065  {
3066  case BOOLOID:
3067  res->type = jbvBool;
3068  res->val.boolean = DatumGetBool(val);
3069  break;
3070  case NUMERICOID:
3072  break;
3073  case INT2OID:
3075  break;
3076  case INT4OID:
3078  break;
3079  case INT8OID:
3081  break;
3082  case FLOAT4OID:
3084  break;
3085  case FLOAT8OID:
3087  break;
3088  case TEXTOID:
3089  case VARCHAROID:
3090  res->type = jbvString;
3091  res->val.string.val = VARDATA_ANY(val);
3092  res->val.string.len = VARSIZE_ANY_EXHDR(val);
3093  break;
3094  case DATEOID:
3095  case TIMEOID:
3096  case TIMETZOID:
3097  case TIMESTAMPOID:
3098  case TIMESTAMPTZOID:
3099  res->type = jbvDatetime;
3100  res->val.datetime.value = val;
3101  res->val.datetime.typid = typid;
3102  res->val.datetime.typmod = typmod;
3103  res->val.datetime.tz = 0;
3104  break;
3105  case JSONBOID:
3106  {
3107  JsonbValue *jbv = res;
3108  Jsonb *jb = DatumGetJsonbP(val);
3109 
3110  if (JsonContainerIsScalar(&jb->root))
3111  {
3113 
3114  res = JsonbExtractScalar(&jb->root, jbv);
3115  Assert(res);
3116  }
3117  else
3118  JsonbInitBinary(jbv, jb);
3119  break;
3120  }
3121  case JSONOID:
3122  {
3123  text *txt = DatumGetTextP(val);
3124  char *str = text_to_cstring(txt);
3125  Jsonb *jb =
3127  CStringGetDatum(str)));
3128 
3129  pfree(str);
3130 
3131  JsonItemFromDatum(JsonbPGetDatum(jb), JSONBOID, -1, res);
3132  break;
3133  }
3134  default:
3135  ereport(ERROR,
3136  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3137  errmsg("only bool, numeric, and text types could be "
3138  "casted to supported jsonpath types.")));
3139  }
3140 }
Datum float4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4485
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4215
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4343
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:4303
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:155
#define DatumGetTextP(X)
Definition: fmgr.h:332
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:76
#define DatumGetJsonbP(d)
Definition: jsonb.h:71
void JsonItemFromDatum(Datum val, Oid typid, int32 typmod, JsonbValue *res)
static void JsonbValueInitNumericDatum(JsonbValue *jbv, Datum num)
#define CStringGetDatum(X)
Definition: postgres.h:622
#define DatumGetBool(X)
Definition: postgres.h:437
#define VARDATA_ANY(PTR)
Definition: postgres.h:361

References Assert(), CStringGetDatum, DatumGetBool, DatumGetJsonbP, DatumGetTextP, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, float4_numeric(), float8_numeric(), 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, generate_unaccent_rules::str, text_to_cstring(), val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by EvalJsonPathVar().

◆ JsonPathExists()

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

Definition at line 2904 of file jsonpath_exec.c.

2905 {
2907  DatumGetJsonbP(jb), !error, NULL,
2908  true);
2909 
2910  Assert(error || !jperIsError(res));
2911 
2912  if (error && jperIsError(res))
2913  *error = true;
2914 
2915  return res == jperOk;
2916 }
int EvalJsonPathVar(void *cxt, char *varName, int varNameLen, JsonbValue *val, JsonbValue *baseObject)

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

Referenced by ExecEvalJsonExpr().

◆ JsonPathQuery()

Datum JsonPathQuery ( Datum  jb,
JsonPath jp,
JsonWrapper  wrapper,
bool empty,
bool error,
List vars 
)

Definition at line 2919 of file jsonpath_exec.c.

2921 {
2922  JsonbValue *first;
2923  bool wrap;
2924  JsonValueList found = {0};
2926  int count;
2927 
2929  &found, true);
2930 
2931  Assert(error || !jperIsError(res));
2932 
2933  if (error && jperIsError(res))
2934  {
2935  *error = true;
2936  *empty = false;
2937  return (Datum) 0;
2938  }
2939 
2940  count = JsonValueListLength(&found);
2941 
2942  first = count ? JsonValueListHead(&found) : NULL;
2943 
2944  if (!first)
2945  wrap = false;
2946  else if (wrapper == JSW_NONE)
2947  wrap = false;
2948  else if (wrapper == JSW_UNCONDITIONAL)
2949  wrap = true;
2950  else if (wrapper == JSW_CONDITIONAL)
2951  wrap = count > 1 ||
2952  IsAJsonbScalar(first) ||
2953  (first->type == jbvBinary &&
2954  JsonContainerIsScalar(first->val.binary.data));
2955  else
2956  {
2957  elog(ERROR, "unrecognized json wrapper %d", wrapper);
2958  wrap = false;
2959  }
2960 
2961  if (wrap)
2963 
2964  if (count > 1)
2965  {
2966  if (error)
2967  {
2968  *error = true;
2969  return (Datum) 0;
2970  }
2971 
2972  ereport(ERROR,
2973  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
2974  errmsg("JSON path expression in JSON_QUERY should return "
2975  "singleton item without wrapper"),
2976  errhint("use WITH WRAPPER clause to wrap SQL/JSON item "
2977  "sequence into array")));
2978  }
2979 
2980  if (first)
2981  return JsonbPGetDatum(JsonbValueToJsonb(first));
2982 
2983  *empty = true;
2984  return PointerGetDatum(NULL);
2985 }
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
#define PointerGetDatum(X)
Definition: postgres.h:600
@ JSW_UNCONDITIONAL
Definition: primnodes.h:1309
@ JSW_CONDITIONAL
Definition: primnodes.h:1308
@ JSW_NONE
Definition: primnodes.h:1307

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

Referenced by ExecEvalJsonExpr().

◆ JsonPathValue()

JsonbValue* JsonPathValue ( Datum  jb,
JsonPath jp,
bool empty,
bool error,
List vars 
)

Definition at line 2988 of file jsonpath_exec.c.

2989 {
2990  JsonbValue *res;
2991  JsonValueList found = {0};
2993  int count;
2994 
2996  &found, true);
2997 
2998  Assert(error || !jperIsError(jper));
2999 
3000  if (error && jperIsError(jper))
3001  {
3002  *error = true;
3003  *empty = false;
3004  return NULL;
3005  }
3006 
3007  count = JsonValueListLength(&found);
3008 
3009  *empty = !count;
3010 
3011  if (*empty)
3012  return NULL;
3013 
3014  if (count > 1)
3015  {
3016  if (error)
3017  {
3018  *error = true;
3019  return NULL;
3020  }
3021 
3022  ereport(ERROR,
3023  (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
3024  errmsg("JSON path expression in JSON_VALUE should return "
3025  "singleton scalar item")));
3026  }
3027 
3028  res = JsonValueListHead(&found);
3029 
3030  if (res->type == jbvBinary &&
3031  JsonContainerIsScalar(res->val.binary.data))
3032  JsonbExtractScalar(res->val.binary.data, res);
3033 
3034  if (!IsAJsonbScalar(res))
3035  {
3036  if (error)
3037  {
3038  *error = true;
3039  return NULL;
3040  }
3041 
3042  ereport(ERROR,
3043  (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
3044  errmsg("JSON path expression in JSON_VALUE should return "
3045  "singleton scalar item")));
3046  }
3047 
3048  if (res->type == jbvNull)
3049  return NULL;
3050 
3051  return res;
3052 }
int binary
Definition: libpq-int.h:180

References Assert(), pg_result::binary, DatumGetJsonbP, ereport, errcode(), errmsg(), ERROR, error(), EvalJsonPathVar(), executeJsonPath(), IsAJsonbScalar, jbvBinary, jbvNull, jperIsError, JsonbExtractScalar(), JsonContainerIsScalar, JsonValueListHead(), JsonValueListLength(), PG_USED_FOR_ASSERTS_ONLY, and res.

Referenced by ExecEvalJsonExpr().

◆ JsonTableDestroyOpaque()

static void JsonTableDestroyOpaque ( TableFuncScanState state)
static

Definition at line 3543 of file jsonpath_exec.c.

3544 {
3545  JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableDestroyOpaque");
3546 
3547  /* not valid anymore */
3548  cxt->magic = 0;
3549 
3550  state->opaque = NULL;
3551 }
static JsonTableContext * GetJsonTableContext(TableFuncScanState *state, const char *fname)

References GetJsonTableContext(), and JsonTableContext::magic.

◆ JsonTableFetchRow()

static bool JsonTableFetchRow ( TableFuncScanState state)
static

Definition at line 3494 of file jsonpath_exec.c.

3495 {
3496  JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableFetchRow");
3497 
3498  if (cxt->empty)
3499  return false;
3500 
3501  return JsonTableNextRow(&cxt->root);
3502 }
static bool JsonTableNextRow(JsonTableScanState *scan)
JsonTableScanState root

References JsonTableContext::empty, GetJsonTableContext(), JsonTableNextRow(), and JsonTableContext::root.

◆ JsonTableGetValue()

static Datum JsonTableGetValue ( TableFuncScanState state,
int  colnum,
Oid  typid,
int32  typmod,
bool isnull 
)
static

Definition at line 3512 of file jsonpath_exec.c.

3514 {
3515  JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableGetValue");
3516  ExprContext *econtext = state->ss.ps.ps_ExprContext;
3517  ExprState *estate = cxt->colexprs[colnum].expr;
3518  JsonTableScanState *scan = cxt->colexprs[colnum].scan;
3519  Datum result;
3520 
3521  if (scan->currentIsNull) /* NULL from outer/union join */
3522  {
3523  result = (Datum) 0;
3524  *isnull = true;
3525  }
3526  else if (estate) /* regular column */
3527  {
3528  result = ExecEvalExpr(estate, econtext, isnull);
3529  }
3530  else
3531  {
3532  result = Int32GetDatum(scan->ordinal); /* ordinality column */
3533  *isnull = false;
3534  }
3535 
3536  return result;
3537 }
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:320
ExprState * expr
struct JsonTableContext::@27 * colexprs
JsonTableScanState * scan

References JsonTableContext::colexprs, JsonTableScanState::currentIsNull, ExecEvalExpr(), JsonTableContext::expr, GetJsonTableContext(), Int32GetDatum, JsonTableScanState::ordinal, and JsonTableContext::scan.

◆ JsonTableInitOpaque()

static void JsonTableInitOpaque ( TableFuncScanState state,
int  natts 
)
static

Definition at line 3220 of file jsonpath_exec.c.

3221 {
3222  JsonTableContext *cxt;
3223  PlanState *ps = &state->ss.ps;
3225  TableFunc *tf = tfs->tablefunc;
3226  JsonExpr *ci = castNode(JsonExpr, tf->docexpr);
3228  List *args = NIL;
3229  ListCell *lc;
3230  int i;
3231 
3232  cxt = palloc0(sizeof(JsonTableContext));
3234 
3235  if (ci->passing_values)
3236  {
3237  ListCell *exprlc;
3238  ListCell *namelc;
3239 
3240  forboth(exprlc, ci->passing_values,
3241  namelc, ci->passing_names)
3242  {
3243  Expr *expr = (Expr *) lfirst(exprlc);
3244  String *name = lfirst_node(String, namelc);
3245  JsonPathVariableEvalContext *var = palloc(sizeof(*var));
3246 
3247  var->name = pstrdup(name->sval);
3248  var->typid = exprType((Node *) expr);
3249  var->typmod = exprTypmod((Node *) expr);
3250  var->estate = ExecInitExpr(expr, ps);
3251  var->econtext = ps->ps_ExprContext;
3252  var->mcxt = CurrentMemoryContext;
3253  var->evaluated = false;
3254  var->value = (Datum) 0;
3255  var->isnull = true;
3256 
3257  args = lappend(args, var);
3258  }
3259  }
3260 
3261  cxt->colexprs = palloc(sizeof(*cxt->colexprs) *
3262  list_length(tf->colvalexprs));
3263 
3264  JsonTableInitScanState(cxt, &cxt->root, root, NULL, args,
3266 
3267  i = 0;
3268 
3269  foreach(lc, tf->colvalexprs)
3270  {
3271  Expr *expr = lfirst(lc);
3272 
3273  cxt->colexprs[i].expr =
3274  ExecInitExprWithCaseValue(expr, ps,
3275  &cxt->colexprs[i].scan->current,
3276  &cxt->colexprs[i].scan->currentIsNull);
3277 
3278  i++;
3279  }
3280 
3281  state->opaque = cxt;
3282 }
const char * name
Definition: encode.c:561
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:160
ExprState * ExecInitExprWithCaseValue(Expr *node, PlanState *parent, Datum *caseval, bool *casenull)
Definition: execExpr.c:184
static void JsonTableInitScanState(JsonTableContext *cxt, JsonTableScanState *scan, JsonTableParent *node, JsonTableScanState *parent, List *args, MemoryContext mcxt)
List * lappend(List *list, void *datum)
Definition: list.c:336
void * palloc0(Size size)
Definition: mcxt.c:1099
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:286
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
List * passing_values
Definition: primnodes.h:1459
List * passing_names
Definition: primnodes.h:1458
struct ExprState * estate
Definition: jsonpath.h:266
struct ExprContext * econtext
Definition: jsonpath.h:265
Definition: nodes.h:574
Plan * plan
Definition: execnodes.h:998
ExprContext * ps_ExprContext
Definition: execnodes.h:1037
Definition: value.h:58
TableFunc * tablefunc
Definition: plannodes.h:591
List * colvalexprs
Definition: primnodes.h:102
Node * docexpr
Definition: primnodes.h:94
Node * plan
Definition: primnodes.h:104

References generate_unaccent_rules::args, castNode, JsonTableContext::colexprs, TableFunc::colvalexprs, JsonTableScanState::current, JsonTableScanState::currentIsNull, CurrentMemoryContext, TableFunc::docexpr, JsonPathVariableEvalContext::econtext, JsonPathVariableEvalContext::estate, JsonPathVariableEvalContext::evaluated, ExecInitExpr(), ExecInitExprWithCaseValue(), JsonTableContext::expr, exprType(), exprTypmod(), forboth, i, JsonPathVariableEvalContext::isnull, JSON_TABLE_CONTEXT_MAGIC, JsonTableInitScanState(), lappend(), lfirst, lfirst_node, list_length(), JsonTableContext::magic, JsonPathVariableEvalContext::mcxt, name, JsonPathVariableEvalContext::name, NIL, palloc(), palloc0(), JsonExpr::passing_names, JsonExpr::passing_values, PlanState::plan, TableFunc::plan, PlanState::ps_ExprContext, pstrdup(), JsonTableContext::root, JsonTableContext::scan, TableFuncScan::tablefunc, JsonPathVariableEvalContext::typid, JsonPathVariableEvalContext::typmod, and JsonPathVariableEvalContext::value.

◆ JsonTableInitPlanState()

static JsonTableJoinState * JsonTableInitPlanState ( JsonTableContext cxt,
Node plan,
JsonTableScanState parent 
)
static

Definition at line 3188 of file jsonpath_exec.c.

3190 {
3191  JsonTableJoinState *state = palloc0(sizeof(*state));
3192 
3193  if (IsA(plan, JsonTableSibling))
3194  {
3196 
3197  state->is_join = true;
3198  state->u.join.cross = join->cross;
3199  state->u.join.left = JsonTableInitPlanState(cxt, join->larg, parent);
3200  state->u.join.right = JsonTableInitPlanState(cxt, join->rarg, parent);
3201  }
3202  else
3203  {
3204  JsonTableParent *node = castNode(JsonTableParent, plan);
3205 
3206  state->is_join = false;
3207 
3208  JsonTableInitScanState(cxt, &state->u.scan, node, parent,
3209  parent->args, parent->mcxt);
3210  }
3211 
3212  return state;
3213 }
static JsonTableJoinState * JsonTableInitPlanState(JsonTableContext *cxt, Node *plan, JsonTableScanState *parent)
MemoryContext mcxt

References JsonTableScanState::args, castNode, JsonTableSibling::cross, IsA, JsonTableInitScanState(), JsonTableSibling::larg, JsonTableScanState::mcxt, palloc0(), and JsonTableSibling::rarg.

Referenced by JsonTableInitScanState().

◆ JsonTableInitScanState()

static void JsonTableInitScanState ( JsonTableContext cxt,
JsonTableScanState scan,
JsonTableParent node,
JsonTableScanState parent,
List args,
MemoryContext  mcxt 
)
static

Definition at line 3164 of file jsonpath_exec.c.

3167 {
3168  int i;
3169 
3170  scan->parent = parent;
3171  scan->outerJoin = node->outerJoin;
3172  scan->errorOnError = node->errorOnError;
3173  scan->path = DatumGetJsonPathP(node->path->constvalue);
3174  scan->args = args;
3175  scan->mcxt = AllocSetContextCreate(mcxt, "JsonTableContext",
3177  scan->nested = node->child ?
3178  JsonTableInitPlanState(cxt, node->child, scan) : NULL;
3179  scan->current = PointerGetDatum(NULL);
3180  scan->currentIsNull = true;
3181 
3182  for (i = node->colMin; i <= node->colMax; i++)
3183  cxt->colexprs[i].scan = scan;
3184 }
#define DatumGetJsonPathP(d)
Definition: jsonpath.h:35
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
Datum constvalue
Definition: primnodes.h:228
JsonTableJoinState * nested
JsonTableScanState * parent

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, generate_unaccent_rules::args, JsonTableScanState::args, JsonTableParent::child, JsonTableContext::colexprs, JsonTableParent::colMin, Const::constvalue, JsonTableScanState::current, JsonTableScanState::currentIsNull, DatumGetJsonPathP, JsonTableScanState::errorOnError, JsonTableParent::errorOnError, i, JsonTableInitPlanState(), JsonTableScanState::mcxt, JsonTableScanState::nested, JsonTableScanState::outerJoin, JsonTableParent::outerJoin, JsonTableScanState::parent, JsonTableScanState::path, JsonTableParent::path, PointerGetDatum, and JsonTableContext::scan.

Referenced by JsonTableInitOpaque(), and JsonTableInitPlanState().

◆ JsonTableJoinReset()

static void JsonTableJoinReset ( JsonTableJoinState state)
static

Definition at line 3410 of file jsonpath_exec.c.

3411 {
3412  if (state->is_join)
3413  {
3414  JsonTableJoinReset(state->u.join.left);
3415  JsonTableJoinReset(state->u.join.right);
3416  state->u.join.advanceRight = false;
3417  }
3418  else
3419  {
3420  state->u.scan.reset = true;
3421  state->u.scan.advanceNested = false;
3422 
3423  if (state->u.scan.nested)
3424  JsonTableJoinReset(state->u.scan.nested);
3425  }
3426 }
static void JsonTableJoinReset(JsonTableJoinState *state)

Referenced by JsonTableNextRow().

◆ JsonTableNextJoinRow()

static bool JsonTableNextJoinRow ( JsonTableJoinState state)
static

Definition at line 3359 of file jsonpath_exec.c.

3360 {
3361  if (!state->is_join)
3362  return JsonTableNextRow(&state->u.scan);
3363 
3364  if (state->u.join.advanceRight)
3365  {
3366  /* fetch next inner row */
3367  if (JsonTableNextJoinRow(state->u.join.right))
3368  return true;
3369 
3370  /* inner rows are exhausted */
3371  if (state->u.join.cross)
3372  state->u.join.advanceRight = false; /* next outer row */
3373  else
3374  return false; /* end of scan */
3375  }
3376 
3377  while (!state->u.join.advanceRight)
3378  {
3379  /* fetch next outer row */
3380  bool left = JsonTableNextJoinRow(state->u.join.left);
3381 
3382  if (state->u.join.cross)
3383  {
3384  if (!left)
3385  return false; /* end of scan */
3386 
3387  JsonTableRescanRecursive(state->u.join.right);
3388 
3389  if (!JsonTableNextJoinRow(state->u.join.right))
3390  continue; /* next outer row */
3391 
3392  state->u.join.advanceRight = true; /* next inner row */
3393  }
3394  else if (!left)
3395  {
3396  if (!JsonTableNextJoinRow(state->u.join.right))
3397  return false; /* end of scan */
3398 
3399  state->u.join.advanceRight = true; /* next inner row */
3400  }
3401 
3402  break;
3403  }
3404 
3405  return true;
3406 }
static bool JsonTableNextJoinRow(JsonTableJoinState *state)
static void JsonTableRescanRecursive(JsonTableJoinState *state)

References JsonTableNextRow(), and JsonTableRescanRecursive().

Referenced by JsonTableNextRow().

◆ JsonTableNextRow()

static bool JsonTableNextRow ( JsonTableScanState scan)
static

Definition at line 3434 of file jsonpath_exec.c.

3435 {
3436  /* reset context item if requested */
3437  if (scan->reset)
3438  {
3439  Assert(!scan->parent->currentIsNull);
3441  scan->reset = false;
3442  }
3443 
3444  if (scan->advanceNested)
3445  {
3446  /* fetch next nested row */
3447  scan->advanceNested = JsonTableNextJoinRow(scan->nested);
3448 
3449  if (scan->advanceNested)
3450  return true;
3451  }
3452 
3453  for (;;)
3454  {
3455  /* fetch next row */
3456  JsonbValue *jbv = JsonValueListNext(&scan->found, &scan->iter);
3457  MemoryContext oldcxt;
3458 
3459  if (!jbv)
3460  {
3461  scan->current = PointerGetDatum(NULL);
3462  scan->currentIsNull = true;
3463  return false; /* end of scan */
3464  }
3465 
3466  /* set current row item */
3467  oldcxt = MemoryContextSwitchTo(scan->mcxt);
3469  scan->currentIsNull = false;
3470  MemoryContextSwitchTo(oldcxt);
3471 
3472  scan->ordinal++;
3473 
3474  if (!scan->nested)
3475  break;
3476 
3477  JsonTableJoinReset(scan->nested);
3478 
3479  scan->advanceNested = JsonTableNextJoinRow(scan->nested);
3480 
3481  if (scan->advanceNested || scan->outerJoin)
3482  break;
3483  }
3484 
3485  return true;
3486 }
static void JsonTableResetContextItem(JsonTableScanState *scan, Datum item)
JsonValueListIterator iter
JsonValueList found

References JsonTableScanState::advanceNested, Assert(), JsonTableScanState::current, JsonTableScanState::currentIsNull, JsonTableScanState::found, JsonTableScanState::iter, JsonbPGetDatum, JsonbValueToJsonb(), JsonTableJoinReset(), JsonTableNextJoinRow(), JsonTableResetContextItem(), JsonValueListNext(), JsonTableScanState::mcxt, MemoryContextSwitchTo(), JsonTableScanState::nested, JsonTableScanState::ordinal, JsonTableScanState::outerJoin, JsonTableScanState::parent, PointerGetDatum, and JsonTableScanState::reset.

Referenced by JsonTableFetchRow(), and JsonTableNextJoinRow().

◆ JsonTableRescan()

static void JsonTableRescan ( JsonTableScanState scan)
static

◆ JsonTableRescanRecursive()

static void JsonTableRescanRecursive ( JsonTableJoinState state)
static

Definition at line 3337 of file jsonpath_exec.c.

3338 {
3339  if (state->is_join)
3340  {
3341  JsonTableRescanRecursive(state->u.join.left);
3342  JsonTableRescanRecursive(state->u.join.right);
3343  state->u.join.advanceRight = false;
3344  }
3345  else
3346  {
3347  JsonTableRescan(&state->u.scan);
3348  if (state->u.scan.nested)
3349  JsonTableRescanRecursive(state->u.scan.nested);
3350  }
3351 }
static void JsonTableRescan(JsonTableScanState *scan)

References JsonTableRescan().

Referenced by JsonTableNextJoinRow().

◆ JsonTableResetContextItem()

static void JsonTableResetContextItem ( JsonTableScanState scan,
Datum  item 
)
static

Definition at line 3297 of file jsonpath_exec.c.

3298 {
3299  MemoryContext oldcxt;
3301  Jsonb *js = (Jsonb *) DatumGetJsonbP(item);
3302 
3303  JsonValueListClear(&scan->found);
3304 
3306 
3307  oldcxt = MemoryContextSwitchTo(scan->mcxt);
3308 
3309  res = executeJsonPath(scan->path, scan->args, EvalJsonPathVar, js,
3310  scan->errorOnError, &scan->found, false /* FIXME */ );
3311 
3312  MemoryContextSwitchTo(oldcxt);
3313 
3314  if (jperIsError(res))
3315  {
3316  Assert(!scan->errorOnError);
3317  JsonValueListClear(&scan->found); /* EMPTY ON ERROR case */
3318  }
3319 
3320  JsonTableRescan(scan);
3321 }
static void JsonValueListClear(JsonValueList *jvl)
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:162

References JsonTableScanState::args, Assert(), DatumGetJsonbP, JsonTableScanState::errorOnError, EvalJsonPathVar(), executeJsonPath(), JsonTableScanState::found, jperIsError, JsonTableRescan(), JsonValueListClear(), JsonTableScanState::mcxt, MemoryContextResetOnly(), MemoryContextSwitchTo(), JsonTableScanState::path, and res.

Referenced by JsonTableNextRow(), and JsonTableSetDocument().

◆ JsonTableSetDocument()

static void JsonTableSetDocument ( TableFuncScanState state,
Datum  value 
)
static

Definition at line 3328 of file jsonpath_exec.c.

3329 {
3330  JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableSetDocument");
3331 
3333 }

References GetJsonTableContext(), JsonTableResetContextItem(), JsonTableContext::root, and value.

◆ JsonValueListAppend()

static void JsonValueListAppend ( JsonValueList jvl,
JsonbValue jbv 
)
static

Definition at line 2533 of file jsonpath_exec.c.

2534 {
2535  if (jvl->singleton)
2536  {
2537  jvl->list = list_make2(jvl->singleton, jbv);
2538  jvl->singleton = NULL;
2539  }
2540  else if (!jvl->list)
2541  jvl->singleton = jbv;
2542  else
2543  jvl->list = lappend(jvl->list, jbv);
2544 }
#define list_make2(x1, x2)
Definition: pg_list.h:208
JsonbValue * singleton

References lappend(), JsonValueList::list, list_make2, and JsonValueList::singleton.

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

◆ JsonValueListClear()

static void JsonValueListClear ( JsonValueList jvl)
static

Definition at line 2526 of file jsonpath_exec.c.

2527 {
2528  jvl->singleton = NULL;
2529  jvl->list = NULL;
2530 }

References JsonValueList::list, and JsonValueList::singleton.

Referenced by JsonTableResetContextItem().

◆ JsonValueListGetList()

static List * JsonValueListGetList ( JsonValueList jvl)
static

Definition at line 2565 of file jsonpath_exec.c.

2566 {
2567  if (jvl->singleton)
2568  return list_make1(jvl->singleton);
2569 
2570  return jvl->list;
2571 }
#define list_make1(x1)
Definition: pg_list.h:206

References JsonValueList::list, list_make1, and JsonValueList::singleton.

Referenced by jsonb_path_query_internal().

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 2559 of file jsonpath_exec.c.

2560 {
2561  return jvl->singleton ? jvl->singleton : linitial(jvl->list);
2562 }
#define linitial(l)
Definition: pg_list.h:174

References linitial, JsonValueList::list, and JsonValueList::singleton.

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

◆ JsonValueListInitIterator()

static void JsonValueListInitIterator ( const JsonValueList jvl,
JsonValueListIterator it 
)
static

Definition at line 2574 of file jsonpath_exec.c.

2575 {
2576  if (jvl->singleton)
2577  {
2578  it->value = jvl->singleton;
2579  it->list = NIL;
2580  it->next = NULL;
2581  }
2582  else if (jvl->list != NIL)
2583  {
2584  it->value = (JsonbValue *) linitial(jvl->list);
2585  it->list = jvl->list;
2586  it->next = list_second_cell(jvl->list);
2587  }
2588  else
2589  {
2590  it->value = NULL;
2591  it->list = NIL;
2592  it->next = NULL;
2593  }
2594 }
static ListCell * list_second_cell(const List *l)
Definition: pg_list.h:139

References linitial, JsonValueList::list, JsonValueListIterator::list, list_second_cell(), JsonValueListIterator::next, NIL, JsonValueList::singleton, and JsonValueListIterator::value.

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

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( JsonValueList jvl)
static

Definition at line 2553 of file jsonpath_exec.c.

2554 {
2555  return !jvl->singleton && list_length(jvl->list) <= 0;
2556 }

References JsonValueList::list, list_length(), and JsonValueList::singleton.

Referenced by executeBoolItem(), and executeJsonPath().

◆ JsonValueListLength()

static int JsonValueListLength ( const JsonValueList jvl)
static

◆ JsonValueListNext()

static JsonbValue * JsonValueListNext ( const JsonValueList jvl,
JsonValueListIterator it 
)
static

Definition at line 2600 of file jsonpath_exec.c.

2601 {
2602  JsonbValue *result = it->value;
2603 
2604  if (it->next)
2605  {
2606  it->value = lfirst(it->next);
2607  it->next = lnext(it->list, it->next);
2608  }
2609  else
2610  {
2611  it->value = NULL;
2612  }
2613 
2614  return result;
2615 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322

References lfirst, JsonValueListIterator::list, lnext(), JsonValueListIterator::next, and JsonValueListIterator::value.

Referenced by executeItemOptUnwrapResult(), executePredicate(), executeUnaryArithmExpr(), JsonTableNextRow(), and wrapItemsInArray().

◆ setBaseObject()

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

Definition at line 2514 of file jsonpath_exec.c.

2515 {
2516  JsonBaseObjectInfo baseObject = cxt->baseObject;
2517 
2518  cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
2519  (JsonbContainer *) jbv->val.binary.data;
2520  cxt->baseObject.id = id;
2521 
2522  return baseObject;
2523 }

References JsonPathExecContext::baseObject, JsonBaseObjectInfo::id, JsonBaseObjectInfo::jbc, jbvBinary, JsonbValue::type, and JsonbValue::val.

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

◆ wrapItemsInArray()

static JsonbValue * wrapItemsInArray ( const JsonValueList items)
static

Definition at line 2669 of file jsonpath_exec.c.

2670 {
2671  JsonbParseState *ps = NULL;
2673  JsonbValue *jbv;
2674 
2675  pushJsonbValue(&ps, WJB_BEGIN_ARRAY, NULL);
2676 
2677  JsonValueListInitIterator(items, &it);
2678  while ((jbv = JsonValueListNext(items, &it)))
2679  pushJsonbValue(&ps, WJB_ELEM, jbv);
2680 
2681  return pushJsonbValue(&ps, WJB_END_ARRAY, NULL);
2682 }
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26

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

Referenced by jsonb_path_query_array_internal(), and JsonPathQuery().

Variable Documentation

◆ JsonbTableRoutine

const TableFuncRoutine JsonbTableRoutine
Initial value:
=
{
NULL,
NULL,
NULL,
}
static void JsonTableSetDocument(TableFuncScanState *state, Datum value)
static void JsonTableDestroyOpaque(TableFuncScanState *state)
static void JsonTableInitOpaque(TableFuncScanState *state, int natts)
static Datum JsonTableGetValue(TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
static bool JsonTableFetchRow(TableFuncScanState *state)

Definition at line 3553 of file jsonpath_exec.c.

Referenced by ExecInitTableFuncScan().