PostgreSQL Source Code  git master
jsonpath_exec.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "regex/regex.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/formatting.h"
#include "utils/float.h"
#include "utils/guc.h"
#include "utils/json.h"
#include "utils/jsonpath.h"
#include "utils/date.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
 

Macros

#define jperIsError(jper)   ((jper) == jperError)
 
#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 struct JsonPathExecContext JsonPathExecContext
 
typedef struct JsonLikeRegexContext JsonLikeRegexContext
 
typedef enum JsonPathBool JsonPathBool
 
typedef enum JsonPathExecResult JsonPathExecResult
 
typedef struct JsonValueList JsonValueList
 
typedef struct JsonValueListIterator JsonValueListIterator
 
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, Jsonb *vars, Jsonb *json, bool throwErrors, JsonValueList *result)
 
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 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, Jsonb *vars, JsonbValue *value)
 
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)
 
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 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)
 
Datum jsonb_path_exists (PG_FUNCTION_ARGS)
 
Datum jsonb_path_exists_opr (PG_FUNCTION_ARGS)
 
Datum jsonb_path_match (PG_FUNCTION_ARGS)
 
Datum jsonb_path_match_opr (PG_FUNCTION_ARGS)
 
Datum jsonb_path_query (PG_FUNCTION_ARGS)
 
Datum jsonb_path_query_array (PG_FUNCTION_ARGS)
 
Datum jsonb_path_query_first (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)
 

Macro Definition Documentation

◆ jperIsError

◆ jspAutoUnwrap

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

◆ jspAutoWrap

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

Definition at line 156 of file jsonpath_exec.c.

Referenced by executeItemOptUnwrapTarget().

◆ jspIgnoreStructuralErrors

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

Definition at line 157 of file jsonpath_exec.c.

Referenced by executeItemOptUnwrapTarget().

◆ jspStrictAbsenseOfErrors

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

Definition at line 154 of file jsonpath_exec.c.

Referenced by executeBoolItem(), executeJsonPath(), and executePredicate().

◆ jspThrowErrors

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

Definition at line 158 of file jsonpath_exec.c.

Referenced by executeBinaryArithmExpr(), and executeItemOptUnwrapTarget().

◆ RETURN_ERROR

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

Definition at line 161 of file jsonpath_exec.c.

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

Typedef Documentation

◆ BinaryArithmFunc

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

Definition at line 173 of file jsonpath_exec.c.

◆ JsonBaseObjectInfo

◆ JsonLikeRegexContext

◆ JsonPathBool

◆ JsonPathExecContext

◆ JsonPathExecResult

◆ JsonPathPredicateCallback

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

Definition at line 169 of file jsonpath_exec.c.

◆ JsonValueList

◆ JsonValueListIterator

Enumeration Type Documentation

◆ JsonPathBool

Enumerator
jpbFalse 
jpbTrue 
jpbUnknown 

Definition at line 120 of file jsonpath_exec.c.

121 {
122  jpbFalse = 0,
123  jpbTrue = 1,
124  jpbUnknown = 2
125 } JsonPathBool;
JsonPathBool

◆ JsonPathExecResult

Enumerator
jperOk 
jperNotFound 
jperError 

Definition at line 128 of file jsonpath_exec.c.

129 {
130  jperOk = 0,
131  jperNotFound = 1,
132  jperError = 2
JsonPathExecResult

Function Documentation

◆ appendBoolResult()

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

Definition at line 1855 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

1857 {
1859  JsonbValue jbv;
1860 
1861  if (!jspGetNext(jsp, &next) && !found)
1862  return jperOk; /* found singleton boolean value */
1863 
1864  if (res == jpbUnknown)
1865  {
1866  jbv.type = jbvNull;
1867  }
1868  else
1869  {
1870  jbv.type = jbvBool;
1871  jbv.val.boolean = res == jpbTrue;
1872  }
1873 
1874  return executeNextItem(cxt, jsp, &next, &jbv, found, true);
1875 }
static int32 next
Definition: blutils.c:213
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
char * val
Definition: jsonb.h:264
Definition: jsonb.h:239
Definition: jsonb.h:236
enum jbvType type
Definition: jsonb.h:255
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)

◆ binaryCompareStrings()

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

Definition at line 1987 of file jsonpath_exec.c.

References cmp(), and Min.

Referenced by compareStrings().

1989 {
1990  int cmp;
1991 
1992  cmp = memcmp(s1, s2, Min(len1, len2));
1993 
1994  if (cmp != 0)
1995  return cmp;
1996 
1997  if (len1 == len2)
1998  return 0;
1999 
2000  return len1 < len2 ? -1 : 1;
2001 }
#define Min(x, y)
Definition: c.h:904
char * s1
char * s2
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742

◆ compareItems()

static JsonPathBool compareItems ( int32  op,
JsonbValue jb1,
JsonbValue jb2 
)
static

Definition at line 2075 of file jsonpath_exec.c.

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

Referenced by executeComparison().

2076 {
2077  int cmp;
2078  bool res;
2079 
2080  if (jb1->type != jb2->type)
2081  {
2082  if (jb1->type == jbvNull || jb2->type == jbvNull)
2083 
2084  /*
2085  * Equality and order comparison of nulls to non-nulls returns
2086  * always false, but inequality comparison returns true.
2087  */
2088  return op == jpiNotEqual ? jpbTrue : jpbFalse;
2089 
2090  /* Non-null items of different types are not comparable. */
2091  return jpbUnknown;
2092  }
2093 
2094  switch (jb1->type)
2095  {
2096  case jbvNull:
2097  cmp = 0;
2098  break;
2099  case jbvBool:
2100  cmp = jb1->val.boolean == jb2->val.boolean ? 0 :
2101  jb1->val.boolean ? 1 : -1;
2102  break;
2103  case jbvNumeric:
2104  cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
2105  break;
2106  case jbvString:
2107  if (op == jpiEqual)
2108  return jb1->val.string.len != jb2->val.string.len ||
2109  memcmp(jb1->val.string.val,
2110  jb2->val.string.val,
2111  jb1->val.string.len) ? jpbFalse : jpbTrue;
2112 
2113  cmp = compareStrings(jb1->val.string.val, jb1->val.string.len,
2114  jb2->val.string.val, jb2->val.string.len);
2115  break;
2116 
2117  case jbvBinary:
2118  case jbvArray:
2119  case jbvObject:
2120  return jpbUnknown; /* non-scalars are not comparable */
2121 
2122  default:
2123  elog(ERROR, "invalid jsonb value type %d", jb1->type);
2124  }
2125 
2126  switch (op)
2127  {
2128  case jpiEqual:
2129  res = (cmp == 0);
2130  break;
2131  case jpiNotEqual:
2132  res = (cmp != 0);
2133  break;
2134  case jpiLess:
2135  res = (cmp < 0);
2136  break;
2137  case jpiGreater:
2138  res = (cmp > 0);
2139  break;
2140  case jpiLessOrEqual:
2141  res = (cmp <= 0);
2142  break;
2143  case jpiGreaterOrEqual:
2144  res = (cmp >= 0);
2145  break;
2146  default:
2147  elog(ERROR, "unrecognized jsonpath operation: %d", op);
2148  return jpbUnknown;
2149  }
2150 
2151  return res ? jpbTrue : jpbFalse;
2152 }
char * val
Definition: jsonb.h:264
Definition: jsonb.h:239
Definition: jsonb.h:236
static int compareNumeric(Numeric a, Numeric b)
static int compareStrings(const char *mbstr1, int mblen1, const char *mbstr2, int mblen2)
#define ERROR
Definition: elog.h:43
enum jbvType type
Definition: jsonb.h:255
#define elog(elevel,...)
Definition: elog.h:226
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742

◆ compareNumeric()

static int compareNumeric ( Numeric  a,
Numeric  b 
)
static

Definition at line 2156 of file jsonpath_exec.c.

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

Referenced by compareItems().

2157 {
2159  NumericGetDatum(a),
2160  NumericGetDatum(b)));
2161 }
#define DatumGetInt32(X)
Definition: postgres.h:472
#define NumericGetDatum(X)
Definition: numeric.h:51
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2046
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:618

◆ compareStrings()

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

Definition at line 2008 of file jsonpath_exec.c.

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

Referenced by compareItems().

2010 {
2011  if (GetDatabaseEncoding() == PG_SQL_ASCII ||
2013  {
2014  /*
2015  * It's known property of UTF-8 strings that their per-byte comparison
2016  * result matches codepoints comparison result. ASCII can be
2017  * considered as special case of UTF-8.
2018  */
2019  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
2020  }
2021  else
2022  {
2023  char *utf8str1,
2024  *utf8str2;
2025  int cmp,
2026  utf8len1,
2027  utf8len2;
2028 
2029  /*
2030  * We have to convert other encodings to UTF-8 first, then compare.
2031  * Input strings may be not null-terminated and pg_server_to_any() may
2032  * return them "as is". So, use strlen() only if there is real
2033  * conversion.
2034  */
2035  utf8str1 = pg_server_to_any(mbstr1, mblen1, PG_UTF8);
2036  utf8str2 = pg_server_to_any(mbstr2, mblen2, PG_UTF8);
2037  utf8len1 = (mbstr1 == utf8str1) ? mblen1 : strlen(utf8str1);
2038  utf8len2 = (mbstr2 == utf8str2) ? mblen2 : strlen(utf8str2);
2039 
2040  cmp = binaryCompareStrings(utf8str1, utf8len1, utf8str2, utf8len2);
2041 
2042  /*
2043  * If pg_server_to_any() did no real conversion, then we actually
2044  * compared original strings. So, we already done.
2045  */
2046  if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
2047  return cmp;
2048 
2049  /* Free memory if needed */
2050  if (mbstr1 != utf8str1)
2051  pfree(utf8str1);
2052  if (mbstr2 != utf8str2)
2053  pfree(utf8str2);
2054 
2055  /*
2056  * When all Unicode codepoints are equal, return result of binary
2057  * comparison. In some edge cases, same characters may have different
2058  * representations in encoding. Then our behavior could diverge from
2059  * standard. However, that allow us to do simple binary comparison
2060  * for "==" operator, which is performance critical in typical cases.
2061  * In future to implement strict standard conformance, we can do
2062  * normalization of input JSON strings.
2063  */
2064  if (cmp == 0)
2065  return binaryCompareStrings(mbstr1, mblen1, mbstr2, mblen2);
2066  else
2067  return cmp;
2068  }
2069 }
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:626
void pfree(void *pointer)
Definition: mcxt.c:1031
int GetDatabaseEncoding(void)
Definition: mbutils.c:996
static int binaryCompareStrings(const char *s1, int len1, const char *s2, int len2)
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742

◆ copyJsonbValue()

static JsonbValue * copyJsonbValue ( JsonbValue src)
static

Definition at line 2164 of file jsonpath_exec.c.

References palloc().

Referenced by executeAnyItem(), and executeNextItem().

2165 {
2166  JsonbValue *dst = palloc(sizeof(*dst));
2167 
2168  *dst = *src;
2169 
2170  return dst;
2171 }
void * palloc(Size size)
Definition: mcxt.c:924

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

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

Referenced by executeItemOptUnwrapTarget(), and executeItemUnwrapTargetArray().

1308 {
1310  JsonbIterator *it;
1311  int32 r;
1312  JsonbValue v;
1313 
1315 
1316  if (level > last)
1317  return res;
1318 
1319  it = JsonbIteratorInit(jbc);
1320 
1321  /*
1322  * Recursively iterate over jsonb objects/arrays
1323  */
1324  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1325  {
1326  if (r == WJB_KEY)
1327  {
1328  r = JsonbIteratorNext(&it, &v, true);
1329  Assert(r == WJB_VALUE);
1330  }
1331 
1332  if (r == WJB_VALUE || r == WJB_ELEM)
1333  {
1334 
1335  if (level >= first ||
1336  (first == PG_UINT32_MAX && last == PG_UINT32_MAX &&
1337  v.type != jbvBinary)) /* leaves only requested */
1338  {
1339  /* check expression */
1340  if (jsp)
1341  {
1342  if (ignoreStructuralErrors)
1343  {
1344  bool savedIgnoreStructuralErrors;
1345 
1346  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
1347  cxt->ignoreStructuralErrors = true;
1348  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1349  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
1350  }
1351  else
1352  res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
1353 
1354  if (jperIsError(res))
1355  break;
1356 
1357  if (res == jperOk && !found)
1358  break;
1359  }
1360  else if (found)
1361  JsonValueListAppend(found, copyJsonbValue(&v));
1362  else
1363  return jperOk;
1364  }
1365 
1366  if (level < last && v.type == jbvBinary)
1367  {
1368  res = executeAnyItem
1369  (cxt, jsp, v.val.binary.data, found,
1370  level + 1, first, last,
1371  ignoreStructuralErrors, unwrapNext);
1372 
1373  if (jperIsError(res))
1374  break;
1375 
1376  if (res == jperOk && found == NULL)
1377  break;
1378  }
1379  }
1380  }
1381 
1382  return res;
1383 }
#define jperIsError(jper)
char * val
Definition: jsonb.h:264
Definition: jsonb.h:22
#define PG_UINT32_MAX
Definition: c.h:442
signed int int32
Definition: c.h:346
static JsonbValue * copyJsonbValue(JsonbValue *src)
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
JsonPathExecResult
void check_stack_depth(void)
Definition: postgres.c:3262
Definition: jsonb.h:23
static void JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv)
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
enum jbvType type
Definition: jsonb.h:255
static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ executeBinaryArithmExpr()

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

Definition at line 1476 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

1479 {
1480  JsonPathExecResult jper;
1481  JsonPathItem elem;
1482  JsonValueList lseq = {0};
1483  JsonValueList rseq = {0};
1484  JsonbValue *lval;
1485  JsonbValue *rval;
1486  Numeric res;
1487 
1488  jspGetLeftArg(jsp, &elem);
1489 
1490  /*
1491  * XXX: By standard only operands of multiplicative expressions are
1492  * unwrapped. We extend it to other binary arithmetic expressions too.
1493  */
1494  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &lseq);
1495  if (jperIsError(jper))
1496  return jper;
1497 
1498  jspGetRightArg(jsp, &elem);
1499 
1500  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &rseq);
1501  if (jperIsError(jper))
1502  return jper;
1503 
1504  if (JsonValueListLength(&lseq) != 1 ||
1505  !(lval = getScalar(JsonValueListHead(&lseq), jbvNumeric)))
1507  (errcode(ERRCODE_SINGLETON_JSON_ITEM_REQUIRED),
1508  errmsg("left operand of jsonpath operator %s is not a single numeric value",
1509  jspOperationName(jsp->type)))));
1510 
1511  if (JsonValueListLength(&rseq) != 1 ||
1512  !(rval = getScalar(JsonValueListHead(&rseq), jbvNumeric)))
1514  (errcode(ERRCODE_SINGLETON_JSON_ITEM_REQUIRED),
1515  errmsg("right operand of jsonpath operator %s is not a single numeric value",
1516  jspOperationName(jsp->type)))));
1517 
1518  if (jspThrowErrors(cxt))
1519  {
1520  res = func(lval->val.numeric, rval->val.numeric, NULL);
1521  }
1522  else
1523  {
1524  bool error = false;
1525 
1526  res = func(lval->val.numeric, rval->val.numeric, &error);
1527 
1528  if (error)
1529  return jperError;
1530  }
1531 
1532  if (!jspGetNext(jsp, &elem) && !found)
1533  return jperOk;
1534 
1535  lval = palloc(sizeof(*lval));
1536  lval->type = jbvNumeric;
1537  lval->val.numeric = res;
1538 
1539  return executeNextItem(cxt, jsp, &elem, lval, found, false);
1540 }
#define RETURN_ERROR(throw_error)
#define jperIsError(jper)
static void error(void)
Definition: sql-dyntest.c:147
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
char * val
Definition: jsonb.h:264
int errcode(int sqlerrcode)
Definition: elog.c:570
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
static int JsonValueListLength(const JsonValueList *jvl)
#define ERROR
Definition: elog.h:43
JsonPathExecResult
#define jspThrowErrors(cxt)
#define ereport(elevel, rest)
Definition: elog.h:141
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:707
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:997
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:976
JsonPathItemType type
Definition: jsonpath.h:106
enum jbvType type
Definition: jsonb.h:255
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
static JsonPathExecResult executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
static JsonbValue * JsonValueListHead(JsonValueList *jvl)

◆ executeBoolItem()

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

Definition at line 1151 of file jsonpath_exec.c.

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, and JsonPathItem::type.

Referenced by executeItemOptUnwrapTarget(), and executeNestedBoolItem().

1153 {
1154  JsonPathItem larg;
1155  JsonPathItem rarg;
1156  JsonPathBool res;
1157  JsonPathBool res2;
1158 
1159  if (!canHaveNext && jspHasNext(jsp))
1160  elog(ERROR, "boolean jsonpath item cannot have next item");
1161 
1162  switch (jsp->type)
1163  {
1164  case jpiAnd:
1165  jspGetLeftArg(jsp, &larg);
1166  res = executeBoolItem(cxt, &larg, jb, false);
1167 
1168  if (res == jpbFalse)
1169  return jpbFalse;
1170 
1171  /*
1172  * SQL/JSON says that we should check second arg in case of
1173  * jperError
1174  */
1175 
1176  jspGetRightArg(jsp, &rarg);
1177  res2 = executeBoolItem(cxt, &rarg, jb, false);
1178 
1179  return res2 == jpbTrue ? res : res2;
1180 
1181  case jpiOr:
1182  jspGetLeftArg(jsp, &larg);
1183  res = executeBoolItem(cxt, &larg, jb, false);
1184 
1185  if (res == jpbTrue)
1186  return jpbTrue;
1187 
1188  jspGetRightArg(jsp, &rarg);
1189  res2 = executeBoolItem(cxt, &rarg, jb, false);
1190 
1191  return res2 == jpbFalse ? res : res2;
1192 
1193  case jpiNot:
1194  jspGetArg(jsp, &larg);
1195 
1196  res = executeBoolItem(cxt, &larg, jb, false);
1197 
1198  if (res == jpbUnknown)
1199  return jpbUnknown;
1200 
1201  return res == jpbTrue ? jpbFalse : jpbTrue;
1202 
1203  case jpiIsUnknown:
1204  jspGetArg(jsp, &larg);
1205  res = executeBoolItem(cxt, &larg, jb, false);
1206  return res == jpbUnknown ? jpbTrue : jpbFalse;
1207 
1208  case jpiEqual:
1209  case jpiNotEqual:
1210  case jpiLess:
1211  case jpiGreater:
1212  case jpiLessOrEqual:
1213  case jpiGreaterOrEqual:
1214  jspGetLeftArg(jsp, &larg);
1215  jspGetRightArg(jsp, &rarg);
1216  return executePredicate(cxt, jsp, &larg, &rarg, jb, true,
1217  executeComparison, NULL);
1218 
1219  case jpiStartsWith: /* 'whole STARTS WITH initial' */
1220  jspGetLeftArg(jsp, &larg); /* 'whole' */
1221  jspGetRightArg(jsp, &rarg); /* 'initial' */
1222  return executePredicate(cxt, jsp, &larg, &rarg, jb, false,
1223  executeStartsWith, NULL);
1224 
1225  case jpiLikeRegex: /* 'expr LIKE_REGEX pattern FLAGS flags' */
1226  {
1227  /*
1228  * 'expr' is a sequence-returning expression. 'pattern' is a
1229  * regex string literal. SQL/JSON standard requires XQuery
1230  * regexes, but we use Postgres regexes here. 'flags' is a
1231  * string literal converted to integer flags at compile-time.
1232  */
1233  JsonLikeRegexContext lrcxt = {0};
1234 
1235  jspInitByBuffer(&larg, jsp->base,
1236  jsp->content.like_regex.expr);
1237 
1238  return executePredicate(cxt, jsp, &larg, NULL, jb, false,
1239  executeLikeRegex, &lrcxt);
1240  }
1241 
1242  case jpiExists:
1243  jspGetArg(jsp, &larg);
1244 
1245  if (jspStrictAbsenseOfErrors(cxt))
1246  {
1247  /*
1248  * In strict mode we must get a complete list of values to
1249  * check that there are no errors at all.
1250  */
1251  JsonValueList vals = {0};
1252  JsonPathExecResult res =
1253  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1254  false, &vals);
1255 
1256  if (jperIsError(res))
1257  return jpbUnknown;
1258 
1259  return JsonValueListIsEmpty(&vals) ? jpbFalse : jpbTrue;
1260  }
1261  else
1262  {
1263  JsonPathExecResult res =
1264  executeItemOptUnwrapResultNoThrow(cxt, &larg, jb,
1265  false, NULL);
1266 
1267  if (jperIsError(res))
1268  return jpbUnknown;
1269 
1270  return res == jperOk ? jpbTrue : jpbFalse;
1271  }
1272 
1273  default:
1274  elog(ERROR, "invalid boolean jsonpath item type: %d", jsp->type);
1275  return jpbUnknown;
1276  }
1277 }
#define jperIsError(jper)
static JsonPathBool executeBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool canHaveNext)
Definition: jsonpath.h:50
char * base
Definition: jsonpath.h:115
static bool JsonValueListIsEmpty(JsonValueList *jvl)
#define jspHasNext(jsp)
Definition: jsonpath.h:163
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition: jsonpath.c:830
JsonPathBool
static JsonPathBool executeStartsWith(JsonPathItem *jsp, JsonbValue *whole, JsonbValue *initial, void *param)
#define ERROR
Definition: elog.h:43
JsonPathExecResult
struct JsonPathItem::@129::@134 like_regex
static JsonPathBool executePredicate(JsonPathExecContext *cxt, JsonPathItem *pred, JsonPathItem *larg, JsonPathItem *rarg, JsonbValue *jb, bool unwrapRightArg, JsonPathPredicateCallback exec, void *param)
union JsonPathItem::@129 content
static JsonPathBool executeLikeRegex(JsonPathItem *jsp, JsonbValue *str, JsonbValue *rarg, void *param)
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:997
static JsonPathExecResult executeItemOptUnwrapResultNoThrow(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:976
JsonPathItemType type
Definition: jsonpath.h:106
#define elog(elevel,...)
Definition: elog.h:226
static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv, JsonbValue *rv, void *p)
#define jspStrictAbsenseOfErrors(cxt)
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:909

◆ executeComparison()

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

Definition at line 1978 of file jsonpath_exec.c.

References compareItems(), and JsonPathItem::type.

Referenced by executeBoolItem().

1979 {
1980  return compareItems(cmp->type, lv, rv);
1981 }
static JsonPathBool compareItems(int32 op, JsonbValue *jb1, JsonbValue *jb2)
JsonPathItemType type
Definition: jsonpath.h:106

◆ executeItem()

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

Definition at line 531 of file jsonpath_exec.c.

References executeItemOptUnwrapTarget(), and jspAutoUnwrap.

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

533 {
534  return executeItemOptUnwrapTarget(cxt, jsp, jb, found, jspAutoUnwrap(cxt));
535 }
static JsonPathExecResult executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrap)
#define jspAutoUnwrap(cxt)

◆ executeItemOptUnwrapResult()

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

Definition at line 1099 of file jsonpath_exec.c.

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

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

1102 {
1103  if (unwrap && jspAutoUnwrap(cxt))
1104  {
1105  JsonValueList seq = {0};
1107  JsonPathExecResult res = executeItem(cxt, jsp, jb, &seq);
1108  JsonbValue *item;
1109 
1110  if (jperIsError(res))
1111  return res;
1112 
1113  JsonValueListInitIterator(&seq, &it);
1114  while ((item = JsonValueListNext(&seq, &it)))
1115  {
1116  Assert(item->type != jbvArray);
1117 
1118  if (JsonbType(item) == jbvArray)
1119  executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
1120  else
1121  JsonValueListAppend(found, item);
1122  }
1123 
1124  return jperOk;
1125  }
1126 
1127  return executeItem(cxt, jsp, jb, found);
1128 }
static void JsonValueListInitIterator(const JsonValueList *jvl, JsonValueListIterator *it)
#define jperIsError(jper)
static int JsonbType(JsonbValue *jb)
static JsonbValue * JsonValueListNext(const JsonValueList *jvl, JsonValueListIterator *it)
JsonPathExecResult
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
static void JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv)
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:255
#define jspAutoUnwrap(cxt)

◆ executeItemOptUnwrapResultNoThrow()

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

Definition at line 1134 of file jsonpath_exec.c.

References executeItemOptUnwrapResult(), and JsonPathExecContext::throwErrors.

Referenced by executeBoolItem(), and executePredicate().

1138 {
1139  JsonPathExecResult res;
1140  bool throwErrors = cxt->throwErrors;
1141 
1142  cxt->throwErrors = false;
1143  res = executeItemOptUnwrapResult(cxt, jsp, jb, unwrap, found);
1144  cxt->throwErrors = throwErrors;
1145 
1146  return res;
1147 }
JsonPathExecResult
static JsonPathExecResult executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)

◆ executeItemOptUnwrapTarget()

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

Definition at line 543 of file jsonpath_exec.c.

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(), executeItemUnwrapTargetArray(), executeKeyValueMethod(), executeNestedBoolItem(), executeNextItem(), executeNumericItemMethod(), executeUnaryArithmExpr(), findJsonbValueFromContainer(), float8_numeric(), Float8GetDatum(), float8in_internal_opt_error(), getArrayIndex(), getIthJsonbValueFromContainer(), getJsonPathItem(), i, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, Int32GetDatum, int4_numeric(), isinf(), JB_FOBJECT, jbvArray, jbvBinary, jbvNumeric, jbvObject, jbvString, jpbTrue, jperError, jperIsError, jperNotFound, jperOk, jpiAbs, jpiAdd, jpiAnd, jpiAny, jpiAnyArray, jpiAnyKey, jpiBool, jpiCeiling, jpiCurrent, 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(), RETURN_ERROR, JsonPathExecContext::root, setBaseObject(), JsonPathItem::type, JsonbValue::type, JsonbValue::val, and val.

Referenced by executeAnyItem(), and executeItem().

545 {
546  JsonPathItem elem;
548  JsonBaseObjectInfo baseObject;
549 
552 
553  switch (jsp->type)
554  {
555  /* all boolean item types: */
556  case jpiAnd:
557  case jpiOr:
558  case jpiNot:
559  case jpiIsUnknown:
560  case jpiEqual:
561  case jpiNotEqual:
562  case jpiLess:
563  case jpiGreater:
564  case jpiLessOrEqual:
565  case jpiGreaterOrEqual:
566  case jpiExists:
567  case jpiStartsWith:
568  case jpiLikeRegex:
569  {
570  JsonPathBool st = executeBoolItem(cxt, jsp, jb, true);
571 
572  res = appendBoolResult(cxt, jsp, found, st);
573  break;
574  }
575 
576  case jpiKey:
577  if (JsonbType(jb) == jbvObject)
578  {
579  JsonbValue *v;
580  JsonbValue key;
581 
582  key.type = jbvString;
583  key.val.string.val = jspGetString(jsp, &key.val.string.len);
584 
585  v = findJsonbValueFromContainer(jb->val.binary.data,
586  JB_FOBJECT, &key);
587 
588  if (v != NULL)
589  {
590  res = executeNextItem(cxt, jsp, NULL,
591  v, found, false);
592 
593  /* free value if it was not added to found list */
594  if (jspHasNext(jsp) || !found)
595  pfree(v);
596  }
597  else if (!jspIgnoreStructuralErrors(cxt))
598  {
599  Assert(found);
600 
601  if (!jspThrowErrors(cxt))
602  return jperError;
603 
604  ereport(ERROR,
605  (errcode(ERRCODE_JSON_MEMBER_NOT_FOUND), \
606  errmsg("JSON object does not contain key \"%s\"",
607  pnstrdup(key.val.string.val,
608  key.val.string.len))));
609  }
610  }
611  else if (unwrap && JsonbType(jb) == jbvArray)
612  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
613  else if (!jspIgnoreStructuralErrors(cxt))
614  {
615  Assert(found);
617  (errcode(ERRCODE_JSON_MEMBER_NOT_FOUND),
618  errmsg("jsonpath member accessor can only be applied to an object"))));
619  }
620  break;
621 
622  case jpiRoot:
623  jb = cxt->root;
624  baseObject = setBaseObject(cxt, jb, 0);
625  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
626  cxt->baseObject = baseObject;
627  break;
628 
629  case jpiCurrent:
630  res = executeNextItem(cxt, jsp, NULL, cxt->current,
631  found, true);
632  break;
633 
634  case jpiAnyArray:
635  if (JsonbType(jb) == jbvArray)
636  {
637  bool hasNext = jspGetNext(jsp, &elem);
638 
639  res = executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL,
640  jb, found, jspAutoUnwrap(cxt));
641  }
642  else if (jspAutoWrap(cxt))
643  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
644  else if (!jspIgnoreStructuralErrors(cxt))
646  (errcode(ERRCODE_JSON_ARRAY_NOT_FOUND),
647  errmsg("jsonpath wildcard array accessor can only be applied to an array"))));
648  break;
649 
650  case jpiIndexArray:
651  if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
652  {
653  int innermostArraySize = cxt->innermostArraySize;
654  int i;
655  int size = JsonbArraySize(jb);
656  bool singleton = size < 0;
657  bool hasNext = jspGetNext(jsp, &elem);
658 
659  if (singleton)
660  size = 1;
661 
662  cxt->innermostArraySize = size; /* for LAST evaluation */
663 
664  for (i = 0; i < jsp->content.array.nelems; i++)
665  {
666  JsonPathItem from;
667  JsonPathItem to;
668  int32 index;
669  int32 index_from;
670  int32 index_to;
671  bool range = jspGetArraySubscript(jsp, &from,
672  &to, i);
673 
674  res = getArrayIndex(cxt, &from, jb, &index_from);
675 
676  if (jperIsError(res))
677  break;
678 
679  if (range)
680  {
681  res = getArrayIndex(cxt, &to, jb, &index_to);
682 
683  if (jperIsError(res))
684  break;
685  }
686  else
687  index_to = index_from;
688 
689  if (!jspIgnoreStructuralErrors(cxt) &&
690  (index_from < 0 ||
691  index_from > index_to ||
692  index_to >= size))
694  (errcode(ERRCODE_INVALID_JSON_SUBSCRIPT),
695  errmsg("jsonpath array subscript is out of bounds"))));
696 
697  if (index_from < 0)
698  index_from = 0;
699 
700  if (index_to >= size)
701  index_to = size - 1;
702 
703  res = jperNotFound;
704 
705  for (index = index_from; index <= index_to; index++)
706  {
707  JsonbValue *v;
708  bool copy;
709 
710  if (singleton)
711  {
712  v = jb;
713  copy = true;
714  }
715  else
716  {
717  v = getIthJsonbValueFromContainer(jb->val.binary.data,
718  (uint32) index);
719 
720  if (v == NULL)
721  continue;
722 
723  copy = false;
724  }
725 
726  if (!hasNext && !found)
727  return jperOk;
728 
729  res = executeNextItem(cxt, jsp, &elem, v, found,
730  copy);
731 
732  if (jperIsError(res))
733  break;
734 
735  if (res == jperOk && !found)
736  break;
737  }
738 
739  if (jperIsError(res))
740  break;
741 
742  if (res == jperOk && !found)
743  break;
744  }
745 
746  cxt->innermostArraySize = innermostArraySize;
747  }
748  else if (!jspIgnoreStructuralErrors(cxt))
749  {
751  (errcode(ERRCODE_JSON_ARRAY_NOT_FOUND),
752  errmsg("jsonpath array accessor can only be applied to an array"))));
753  }
754  break;
755 
756  case jpiLast:
757  {
758  JsonbValue tmpjbv;
759  JsonbValue *lastjbv;
760  int last;
761  bool hasNext = jspGetNext(jsp, &elem);
762 
763  if (cxt->innermostArraySize < 0)
764  elog(ERROR, "evaluating jsonpath LAST outside of array subscript");
765 
766  if (!hasNext && !found)
767  {
768  res = jperOk;
769  break;
770  }
771 
772  last = cxt->innermostArraySize - 1;
773 
774  lastjbv = hasNext ? &tmpjbv : palloc(sizeof(*lastjbv));
775 
776  lastjbv->type = jbvNumeric;
777  lastjbv->val.numeric =
779  Int32GetDatum(last)));
780 
781  res = executeNextItem(cxt, jsp, &elem,
782  lastjbv, found, hasNext);
783  }
784  break;
785 
786  case jpiAnyKey:
787  if (JsonbType(jb) == jbvObject)
788  {
789  bool hasNext = jspGetNext(jsp, &elem);
790 
791  if (jb->type != jbvBinary)
792  elog(ERROR, "invalid jsonb object type: %d", jb->type);
793 
794  return executeAnyItem
795  (cxt, hasNext ? &elem : NULL,
796  jb->val.binary.data, found, 1, 1, 1,
797  false, jspAutoUnwrap(cxt));
798  }
799  else if (unwrap && JsonbType(jb) == jbvArray)
800  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
801  else if (!jspIgnoreStructuralErrors(cxt))
802  {
803  Assert(found);
805  (errcode(ERRCODE_JSON_OBJECT_NOT_FOUND),
806  errmsg("jsonpath wildcard member accessor can only be applied to an object"))));
807  }
808  break;
809 
810  case jpiAdd:
811  return executeBinaryArithmExpr(cxt, jsp, jb,
812  numeric_add_opt_error, found);
813 
814  case jpiSub:
815  return executeBinaryArithmExpr(cxt, jsp, jb,
816  numeric_sub_opt_error, found);
817 
818  case jpiMul:
819  return executeBinaryArithmExpr(cxt, jsp, jb,
820  numeric_mul_opt_error, found);
821 
822  case jpiDiv:
823  return executeBinaryArithmExpr(cxt, jsp, jb,
824  numeric_div_opt_error, found);
825 
826  case jpiMod:
827  return executeBinaryArithmExpr(cxt, jsp, jb,
828  numeric_mod_opt_error, found);
829 
830  case jpiPlus:
831  return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
832 
833  case jpiMinus:
834  return executeUnaryArithmExpr(cxt, jsp, jb, numeric_uminus,
835  found);
836 
837  case jpiFilter:
838  {
839  JsonPathBool st;
840 
841  if (unwrap && JsonbType(jb) == jbvArray)
842  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
843  false);
844 
845  jspGetArg(jsp, &elem);
846  st = executeNestedBoolItem(cxt, &elem, jb);
847  if (st != jpbTrue)
848  res = jperNotFound;
849  else
850  res = executeNextItem(cxt, jsp, NULL,
851  jb, found, true);
852  break;
853  }
854 
855  case jpiAny:
856  {
857  bool hasNext = jspGetNext(jsp, &elem);
858 
859  /* first try without any intermediate steps */
860  if (jsp->content.anybounds.first == 0)
861  {
862  bool savedIgnoreStructuralErrors;
863 
864  savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
865  cxt->ignoreStructuralErrors = true;
866  res = executeNextItem(cxt, jsp, &elem,
867  jb, found, true);
868  cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
869 
870  if (res == jperOk && !found)
871  break;
872  }
873 
874  if (jb->type == jbvBinary)
875  res = executeAnyItem
876  (cxt, hasNext ? &elem : NULL,
877  jb->val.binary.data, found,
878  1,
879  jsp->content.anybounds.first,
880  jsp->content.anybounds.last,
881  true, jspAutoUnwrap(cxt));
882  break;
883  }
884 
885  case jpiNull:
886  case jpiBool:
887  case jpiNumeric:
888  case jpiString:
889  case jpiVariable:
890  {
891  JsonbValue vbuf;
892  JsonbValue *v;
893  bool hasNext = jspGetNext(jsp, &elem);
894 
895  if (!hasNext && !found)
896  {
897  res = jperOk; /* skip evaluation */
898  break;
899  }
900 
901  v = hasNext ? &vbuf : palloc(sizeof(*v));
902 
903  baseObject = cxt->baseObject;
904  getJsonPathItem(cxt, jsp, v);
905 
906  res = executeNextItem(cxt, jsp, &elem,
907  v, found, hasNext);
908  cxt->baseObject = baseObject;
909  }
910  break;
911 
912  case jpiType:
913  {
914  JsonbValue *jbv = palloc(sizeof(*jbv));
915 
916  jbv->type = jbvString;
917  jbv->val.string.val = pstrdup(JsonbTypeName(jb));
918  jbv->val.string.len = strlen(jbv->val.string.val);
919 
920  res = executeNextItem(cxt, jsp, NULL, jbv,
921  found, false);
922  }
923  break;
924 
925  case jpiSize:
926  {
927  int size = JsonbArraySize(jb);
928 
929  if (size < 0)
930  {
931  if (!jspAutoWrap(cxt))
932  {
933  if (!jspIgnoreStructuralErrors(cxt))
935  (errcode(ERRCODE_JSON_ARRAY_NOT_FOUND),
936  errmsg("jsonpath item method .%s() can only be applied to an array",
937  jspOperationName(jsp->type)))));
938  break;
939  }
940 
941  size = 1;
942  }
943 
944  jb = palloc(sizeof(*jb));
945 
946  jb->type = jbvNumeric;
947  jb->val.numeric =
949  Int32GetDatum(size)));
950 
951  res = executeNextItem(cxt, jsp, NULL, jb, found, false);
952  }
953  break;
954 
955  case jpiAbs:
956  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_abs,
957  found);
958 
959  case jpiFloor:
960  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_floor,
961  found);
962 
963  case jpiCeiling:
964  return executeNumericItemMethod(cxt, jsp, jb, unwrap, numeric_ceil,
965  found);
966 
967  case jpiDouble:
968  {
969  JsonbValue jbv;
970 
971  if (unwrap && JsonbType(jb) == jbvArray)
972  return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
973  false);
974 
975  if (jb->type == jbvNumeric)
976  {
978  NumericGetDatum(jb->val.numeric)));
979  bool have_error = false;
980 
981  (void) float8in_internal_opt_error(tmp,
982  NULL,
983  "double precision",
984  tmp,
985  &have_error);
986 
987  if (have_error)
989  (errcode(ERRCODE_NON_NUMERIC_JSON_ITEM),
990  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
991  jspOperationName(jsp->type)))));
992  res = jperOk;
993  }
994  else if (jb->type == jbvString)
995  {
996  /* cast string as double */
997  double val;
998  char *tmp = pnstrdup(jb->val.string.val,
999  jb->val.string.len);
1000  bool have_error = false;
1001 
1002  val = float8in_internal_opt_error(tmp,
1003  NULL,
1004  "double precision",
1005  tmp,
1006  &have_error);
1007 
1008  if (have_error || isinf(val))
1010  (errcode(ERRCODE_NON_NUMERIC_JSON_ITEM),
1011  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
1012  jspOperationName(jsp->type)))));
1013 
1014  jb = &jbv;
1015  jb->type = jbvNumeric;
1017  Float8GetDatum(val)));
1018  res = jperOk;
1019  }
1020 
1021  if (res == jperNotFound)
1023  (errcode(ERRCODE_NON_NUMERIC_JSON_ITEM),
1024  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
1025  jspOperationName(jsp->type)))));
1026 
1027  res = executeNextItem(cxt, jsp, NULL, jb, found, true);
1028  }
1029  break;
1030 
1031  case jpiKeyValue:
1032  if (unwrap && JsonbType(jb) == jbvArray)
1033  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1034 
1035  return executeKeyValueMethod(cxt, jsp, jb, found);
1036 
1037  default:
1038  elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
1039  }
1040 
1041  return res;
1042 }
#define RETURN_ERROR(throw_error)
#define jperIsError(jper)
#define jspIgnoreStructuralErrors(cxt)
static int JsonbType(JsonbValue *jb)
static JsonPathBool executeBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool canHaveNext)
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1172
static JsonPathExecResult executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, BinaryArithmFunc func, JsonValueList *found)
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
Definition: jsonpath.h:50
static JsonPathBool executeNestedBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb)
static JsonPathExecResult executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, PGFunction func, JsonValueList *found)
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2428
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2600
char * pstrdup(const char *in)
Definition: mcxt.c:1161
char * val
Definition: jsonb.h:264
#define NumericGetDatum(X)
Definition: numeric.h:51
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:655
#define jspHasNext(jsp)
Definition: jsonpath.h:163
int errcode(int sqlerrcode)
Definition: elog.c:570
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:616
JsonBaseObjectInfo baseObject
Definition: jsonpath_exec.c:97
Numeric numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2540
JsonPathBool
signed int int32
Definition: c.h:346
static JsonPathExecResult getArrayIndex(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, int32 *index)
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1723
Definition: type.h:89
static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *value)
static JsonPathExecResult executeNumericItemMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, PGFunction func, JsonValueList *found)
void pfree(void *pointer)
Definition: mcxt.c:1031
Datum numeric_uminus(PG_FUNCTION_ARGS)
Definition: numeric.c:1129
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition: numeric.c:1101
#define ERROR
Definition: elog.h:43
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
#define DatumGetCString(X)
Definition: postgres.h:566
JsonPathExecResult
int isinf(double x)
const char * JsonbTypeName(JsonbValue *jbv)
Definition: jsonb.c:191
void check_stack_depth(void)
Definition: postgres.c:3262
struct JsonPathItem::@129::@131 array
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
unsigned int uint32
Definition: c.h:358
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:416
#define jspThrowErrors(cxt)
struct JsonPathItem::@129::@132 anybounds
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbValue * root
Definition: jsonpath_exec.c:95
Datum numeric_floor(PG_FUNCTION_ARGS)
Definition: numeric.c:1354
union JsonPathItem::@129 content
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:707
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3193
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3383
Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2720
static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt, JsonbValue *jbv, int32 id)
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define DatumGetNumeric(X)
Definition: numeric.h:49
bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to, int i)
Definition: jsonpath.c:1046
#define Assert(condition)
Definition: c.h:732
#define JB_FOBJECT
Definition: jsonb.h:210
JsonPathItemType type
Definition: jsonpath.h:106
JsonbValue * current
Definition: jsonpath_exec.c:96
#define jspAutoWrap(cxt)
static JsonPathExecResult executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
enum jbvType type
Definition: jsonb.h:255
static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonValueList *found, JsonPathBool res)
#define Int32GetDatum(X)
Definition: postgres.h:479
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
Datum numeric_ceil(PG_FUNCTION_ARGS)
Definition: numeric.c:1329
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2484
#define elog(elevel,...)
Definition: elog.h:226
int i
#define jspAutoUnwrap(cxt)
double float8in_internal_opt_error(char *num, char **endptr_p, const char *type_name, const char *orig_string, bool *have_error)
Definition: float.c:372
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:327
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:909
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1034
long val
Definition: informix.c:684
static int JsonbArraySize(JsonbValue *jb)

◆ executeItemUnwrapTargetArray()

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

Definition at line 1048 of file jsonpath_exec.c.

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

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

1051 {
1052  if (jb->type != jbvBinary)
1053  {
1054  Assert(jb->type != jbvArray);
1055  elog(ERROR, "invalid jsonb array value type: %d", jb->type);
1056  }
1057 
1058  return executeAnyItem
1059  (cxt, jsp, jb->val.binary.data, found, 1, 1, 1,
1060  false, unwrapElements);
1061 }
char * val
Definition: jsonb.h:264
#define ERROR
Definition: elog.h:43
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found, uint32 level, uint32 first, uint32 last, bool ignoreStructuralErrors, bool unwrapNext)
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:255
#define elog(elevel,...)
Definition: elog.h:226

◆ executeJsonPath()

static JsonPathExecResult executeJsonPath ( JsonPath path,
Jsonb vars,
Jsonb json,
bool  throwErrors,
JsonValueList result 
)
static

Definition at line 472 of file jsonpath_exec.c.

References Assert, JsonPathExecContext::baseObject, JsonPathExecContext::current, ereport, errcode(), errdetail(), errmsg(), ERROR, executeItem(), JsonPath::header, JsonBaseObjectInfo::id, JsonPathExecContext::ignoreStructuralErrors, JsonPathExecContext::innermostArraySize, JsonBaseObjectInfo::jbc, jperIsError, jperNotFound, jperOk, JsonbExtractScalar(), JsonbInitBinary(), JsonContainerIsObject, JSONPATH_LAX, JsonValueListIsEmpty(), jspInit(), jspStrictAbsenseOfErrors, JsonPathExecContext::lastGeneratedObjectId, JsonPathExecContext::laxMode, JsonPathExecContext::root, Jsonb::root, JsonPathExecContext::throwErrors, and JsonPathExecContext::vars.

Referenced by jsonb_path_exists(), jsonb_path_match(), jsonb_path_query(), jsonb_path_query_array(), and jsonb_path_query_first().

474 {
476  JsonPathExecResult res;
477  JsonPathItem jsp;
478  JsonbValue jbv;
479 
480  jspInit(&jsp, path);
481 
482  if (!JsonbExtractScalar(&json->root, &jbv))
483  JsonbInitBinary(&jbv, json);
484 
485  if (vars && !JsonContainerIsObject(&vars->root))
486  {
487  ereport(ERROR,
488  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
489  errmsg("\"vars\" argument is not an object"),
490  errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object.")));
491  }
492 
493  cxt.vars = vars;
494  cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
496  cxt.root = &jbv;
497  cxt.current = &jbv;
498  cxt.baseObject.jbc = NULL;
499  cxt.baseObject.id = 0;
500  cxt.lastGeneratedObjectId = vars ? 2 : 1;
501  cxt.innermostArraySize = -1;
502  cxt.throwErrors = throwErrors;
503 
504  if (jspStrictAbsenseOfErrors(&cxt) && !result)
505  {
506  /*
507  * In strict mode we must get a complete list of values to check that
508  * there are no errors at all.
509  */
510  JsonValueList vals = {0};
511 
512  res = executeItem(&cxt, &jsp, &jbv, &vals);
513 
514  if (jperIsError(res))
515  return res;
516 
517  return JsonValueListIsEmpty(&vals) ? jperNotFound : jperOk;
518  }
519 
520  res = executeItem(&cxt, &jsp, &jbv, result);
521 
522  Assert(!throwErrors || !jperIsError(res));
523 
524  return res;
525 }
#define jperIsError(jper)
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1874
static bool JsonValueListIsEmpty(JsonValueList *jvl)
int errcode(int sqlerrcode)
Definition: elog.c:570
JsonBaseObjectInfo baseObject
Definition: jsonpath_exec.c:97
#define JSONPATH_LAX
Definition: jsonpath.h:29
#define ERROR
Definition: elog.h:43
JsonPathExecResult
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
int errdetail(const char *fmt,...)
Definition: elog.c:860
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbValue * root
Definition: jsonpath_exec.c:95
JsonbContainer root
Definition: jsonb.h:223
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
JsonbContainer * jbc
Definition: jsonpath_exec.c:85
static JsonbValue * JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
#define Assert(condition)
Definition: c.h:732
JsonbValue * current
Definition: jsonpath_exec.c:96
int errmsg(const char *fmt,...)
Definition: elog.c:784
void jspInit(JsonPathItem *v, JsonPath *js)
Definition: jsonpath.c:820
uint32 header
Definition: jsonpath.h:24
#define jspStrictAbsenseOfErrors(cxt)

◆ executeKeyValueMethod()

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

Definition at line 1744 of file jsonpath_exec.c.

References Assert, JsonPathExecContext::baseObject, DatumGetNumeric, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, executeNextItem(), JsonBaseObjectInfo::id, Int64GetDatum(), int8_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(), RETURN_ERROR, setBaseObject(), JsonPathItem::type, JsonbValue::type, JsonbValue::val, val, WJB_BEGIN_OBJECT, WJB_DONE, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by executeItemOptUnwrapTarget().

1746 {
1749  JsonbContainer *jbc;
1750  JsonbValue key;
1751  JsonbValue val;
1752  JsonbValue idval;
1753  JsonbValue keystr;
1754  JsonbValue valstr;
1755  JsonbValue idstr;
1756  JsonbIterator *it;
1757  JsonbIteratorToken tok;
1758  int64 id;
1759  bool hasNext;
1760 
1761  if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
1763  (errcode(ERRCODE_JSON_OBJECT_NOT_FOUND),
1764  errmsg("jsonpath item method .%s() can only be applied to an object",
1765  jspOperationName(jsp->type)))));
1766 
1767  jbc = jb->val.binary.data;
1768 
1769  if (!JsonContainerSize(jbc))
1770  return jperNotFound; /* no key-value pairs */
1771 
1772  hasNext = jspGetNext(jsp, &next);
1773 
1774  keystr.type = jbvString;
1775  keystr.val.string.val = "key";
1776  keystr.val.string.len = 3;
1777 
1778  valstr.type = jbvString;
1779  valstr.val.string.val = "value";
1780  valstr.val.string.len = 5;
1781 
1782  idstr.type = jbvString;
1783  idstr.val.string.val = "id";
1784  idstr.val.string.len = 2;
1785 
1786  /* construct object id from its base object and offset inside that */
1787  id = jb->type != jbvBinary ? 0 :
1788  (int64) ((char *) jbc - (char *) cxt->baseObject.jbc);
1789  id += (int64) cxt->baseObject.id * INT64CONST(10000000000);
1790 
1791  idval.type = jbvNumeric;
1793  Int64GetDatum(id)));
1794 
1795  it = JsonbIteratorInit(jbc);
1796 
1797  while ((tok = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
1798  {
1799  JsonBaseObjectInfo baseObject;
1800  JsonbValue obj;
1801  JsonbParseState *ps;
1802  JsonbValue *keyval;
1803  Jsonb *jsonb;
1804 
1805  if (tok != WJB_KEY)
1806  continue;
1807 
1808  res = jperOk;
1809 
1810  if (!hasNext && !found)
1811  break;
1812 
1813  tok = JsonbIteratorNext(&it, &val, true);
1814  Assert(tok == WJB_VALUE);
1815 
1816  ps = NULL;
1817  pushJsonbValue(&ps, WJB_BEGIN_OBJECT, NULL);
1818 
1819  pushJsonbValue(&ps, WJB_KEY, &keystr);
1820  pushJsonbValue(&ps, WJB_VALUE, &key);
1821 
1822  pushJsonbValue(&ps, WJB_KEY, &valstr);
1823  pushJsonbValue(&ps, WJB_VALUE, &val);
1824 
1825  pushJsonbValue(&ps, WJB_KEY, &idstr);
1826  pushJsonbValue(&ps, WJB_VALUE, &idval);
1827 
1828  keyval = pushJsonbValue(&ps, WJB_END_OBJECT, NULL);
1829 
1830  jsonb = JsonbValueToJsonb(keyval);
1831 
1832  JsonbInitBinary(&obj, jsonb);
1833 
1834  baseObject = setBaseObject(cxt, &obj, cxt->lastGeneratedObjectId++);
1835 
1836  res = executeNextItem(cxt, jsp, &next, &obj, found, true);
1837 
1838  cxt->baseObject = baseObject;
1839 
1840  if (jperIsError(res))
1841  return res;
1842 
1843  if (res == jperOk && !found)
1844  break;
1845  }
1846 
1847  return res;
1848 }
#define RETURN_ERROR(throw_error)
#define jperIsError(jper)
static int JsonbType(JsonbValue *jb)
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
static int32 next
Definition: blutils.c:213
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
char * val
Definition: jsonb.h:264
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:570
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:616
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3285
JsonBaseObjectInfo baseObject
Definition: jsonpath_exec.c:97
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
JsonPathExecResult
#define JsonContainerSize(jc)
Definition: jsonb.h:214
Definition: jsonb.h:23
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1699
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbIteratorToken
Definition: jsonb.h:20
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:707
JsonbContainer * jbc
Definition: jsonpath_exec.c:85
static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt, JsonbValue *jbv, int32 id)
static JsonbValue * JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
JsonPathItemType type
Definition: jsonpath.h:106
enum jbvType type
Definition: jsonb.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:784
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
long val
Definition: informix.c:684
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754

◆ executeLikeRegex()

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

Definition at line 1638 of file jsonpath_exec.c.

References JsonLikeRegexContext::cflags, JsonPathItem::content, cstring_to_text_with_len(), getScalar(), jbvString, jpbFalse, jpbTrue, jpbUnknown, JSP_REGEX_ICASE, JSP_REGEX_MLINE, JSP_REGEX_QUOTE, JSP_REGEX_SLINE, JSP_REGEX_WSPACE, JsonPathItem::like_regex, RE_compile_and_execute(), REG_ADVANCED, REG_EXPANDED, REG_ICASE, REG_NEWLINE, REG_QUOTE, JsonLikeRegexContext::regex, and JsonbValue::val.

Referenced by executeBoolItem().

1640 {
1641  JsonLikeRegexContext *cxt = param;
1642 
1643  if (!(str = getScalar(str, jbvString)))
1644  return jpbUnknown;
1645 
1646  /* Cache regex text and converted flags. */
1647  if (!cxt->regex)
1648  {
1649  uint32 flags = jsp->content.like_regex.flags;
1650 
1651  cxt->regex =
1653  jsp->content.like_regex.patternlen);
1654 
1655  /* Convert regex flags. */
1656  cxt->cflags = REG_ADVANCED;
1657 
1658  if (flags & JSP_REGEX_ICASE)
1659  cxt->cflags |= REG_ICASE;
1660  if (flags & JSP_REGEX_MLINE)
1661  cxt->cflags |= REG_NEWLINE;
1662  if (flags & JSP_REGEX_SLINE)
1663  cxt->cflags &= ~REG_NEWLINE;
1664  if (flags & JSP_REGEX_WSPACE)
1665  cxt->cflags |= REG_EXPANDED;
1666 
1667  /*
1668  * 'q' flag can work together only with 'i'. When other is specified,
1669  * then 'q' has no effect.
1670  */
1671  if ((flags & JSP_REGEX_QUOTE) &&
1672  !(flags & (JSP_REGEX_MLINE | JSP_REGEX_SLINE | JSP_REGEX_WSPACE)))
1673  {
1674  cxt->cflags &= ~REG_ADVANCED;
1675  cxt->cflags |= REG_QUOTE;
1676  }
1677  }
1678 
1679  if (RE_compile_and_execute(cxt->regex, str->val.string.val,
1680  str->val.string.len,
1681  cxt->cflags, DEFAULT_COLLATION_OID, 0, NULL))
1682  return jpbTrue;
1683 
1684  return jpbFalse;
1685 }
#define REG_QUOTE
Definition: regex.h:104
char * val
Definition: jsonb.h:264
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
#define JSP_REGEX_ICASE
Definition: jsonpath.h:90
#define REG_ICASE
Definition: regex.h:106
#define JSP_REGEX_MLINE
Definition: jsonpath.h:92
#define JSP_REGEX_WSPACE
Definition: jsonpath.h:93
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:343
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
#define JSP_REGEX_QUOTE
Definition: jsonpath.h:94
unsigned int uint32
Definition: c.h:358
#define REG_NEWLINE
Definition: regex.h:111
#define REG_ADVANCED
Definition: regex.h:103
struct JsonPathItem::@129::@134 like_regex
union JsonPathItem::@129 content
#define REG_EXPANDED
Definition: regex.h:108
#define JSP_REGEX_SLINE
Definition: jsonpath.h:91

◆ executeNestedBoolItem()

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

Definition at line 1284 of file jsonpath_exec.c.

References JsonPathExecContext::current, and executeBoolItem().

Referenced by executeItemOptUnwrapTarget().

1286 {
1287  JsonbValue *prev;
1288  JsonPathBool res;
1289 
1290  prev = cxt->current;
1291  cxt->current = jb;
1292  res = executeBoolItem(cxt, jsp, jb, false);
1293  cxt->current = prev;
1294 
1295  return res;
1296 }
static JsonPathBool executeBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool canHaveNext)
JsonPathBool
JsonbValue * current
Definition: jsonpath_exec.c:96

◆ executeNextItem()

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

Definition at line 1068 of file jsonpath_exec.c.

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

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

1071 {
1072  JsonPathItem elem;
1073  bool hasNext;
1074 
1075  if (!cur)
1076  hasNext = next != NULL;
1077  else if (next)
1078  hasNext = jspHasNext(cur);
1079  else
1080  {
1081  next = &elem;
1082  hasNext = jspGetNext(cur, next);
1083  }
1084 
1085  if (hasNext)
1086  return executeItem(cxt, next, v, found);
1087 
1088  if (found)
1089  JsonValueListAppend(found, copy ? copyJsonbValue(v) : v);
1090 
1091  return jperOk;
1092 }
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
#define jspHasNext(jsp)
Definition: jsonpath.h:163
static JsonbValue * copyJsonbValue(JsonbValue *src)
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
static void JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv)

◆ executeNumericItemMethod()

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

Definition at line 1692 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

1695 {
1697  Datum datum;
1698 
1699  if (unwrap && JsonbType(jb) == jbvArray)
1700  return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
1701 
1702  if (!(jb = getScalar(jb, jbvNumeric)))
1704  (errcode(ERRCODE_NON_NUMERIC_JSON_ITEM),
1705  errmsg("jsonpath item method .%s() can only be applied to a numeric value",
1706  jspOperationName(jsp->type)))));
1707 
1708  datum = DirectFunctionCall1(func, NumericGetDatum(jb->val.numeric));
1709 
1710  if (!jspGetNext(jsp, &next) && !found)
1711  return jperOk;
1712 
1713  jb = palloc(sizeof(*jb));
1714  jb->type = jbvNumeric;
1715  jb->val.numeric = DatumGetNumeric(datum);
1716 
1717  return executeNextItem(cxt, jsp, &next, jb, found, false);
1718 }
#define RETURN_ERROR(throw_error)
static int JsonbType(JsonbValue *jb)
static int32 next
Definition: blutils.c:213
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
char * val
Definition: jsonb.h:264
#define NumericGetDatum(X)
Definition: numeric.h:51
int errcode(int sqlerrcode)
Definition: elog.c:570
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:616
#define ERROR
Definition: elog.h:43
static JsonPathExecResult executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found, bool unwrapElements)
#define ereport(elevel, rest)
Definition: elog.h:141
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:707
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetNumeric(X)
Definition: numeric.h:49
JsonPathItemType type
Definition: jsonpath.h:106
enum jbvType type
Definition: jsonb.h:255
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)

◆ executePredicate()

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

Definition at line 1396 of file jsonpath_exec.c.

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

Referenced by executeBoolItem().

1400 {
1401  JsonPathExecResult res;
1402  JsonValueListIterator lseqit;
1403  JsonValueList lseq = {0};
1404  JsonValueList rseq = {0};
1405  JsonbValue *lval;
1406  bool error = false;
1407  bool found = false;
1408 
1409  /* Left argument is always auto-unwrapped. */
1410  res = executeItemOptUnwrapResultNoThrow(cxt, larg, jb, true, &lseq);
1411  if (jperIsError(res))
1412  return jpbUnknown;
1413 
1414  if (rarg)
1415  {
1416  /* Right argument is conditionally auto-unwrapped. */
1417  res = executeItemOptUnwrapResultNoThrow(cxt, rarg, jb,
1418  unwrapRightArg, &rseq);
1419  if (jperIsError(res))
1420  return jpbUnknown;
1421  }
1422 
1423  JsonValueListInitIterator(&lseq, &lseqit);
1424  while ((lval = JsonValueListNext(&lseq, &lseqit)))
1425  {
1426  JsonValueListIterator rseqit;
1427  JsonbValue *rval;
1428  bool first = true;
1429 
1430  JsonValueListInitIterator(&rseq, &rseqit);
1431  if (rarg)
1432  rval = JsonValueListNext(&rseq, &rseqit);
1433  else
1434  rval = NULL;
1435 
1436  /* Loop over right arg sequence or do single pass otherwise */
1437  while (rarg ? (rval != NULL) : first)
1438  {
1439  JsonPathBool res = exec(pred, lval, rval, param);
1440 
1441  if (res == jpbUnknown)
1442  {
1443  if (jspStrictAbsenseOfErrors(cxt))
1444  return jpbUnknown;
1445 
1446  error = true;
1447  }
1448  else if (res == jpbTrue)
1449  {
1450  if (!jspStrictAbsenseOfErrors(cxt))
1451  return jpbTrue;
1452 
1453  found = true;
1454  }
1455 
1456  first = false;
1457  if (rarg)
1458  rval = JsonValueListNext(&rseq, &rseqit);
1459  }
1460  }
1461 
1462  if (found) /* possible only in strict mode */
1463  return jpbTrue;
1464 
1465  if (error) /* possible only in lax mode */
1466  return jpbUnknown;
1467 
1468  return jpbFalse;
1469 }
static void JsonValueListInitIterator(const JsonValueList *jvl, JsonValueListIterator *it)
#define jperIsError(jper)
static void error(void)
Definition: sql-dyntest.c:147
static JsonbValue * JsonValueListNext(const JsonValueList *jvl, JsonValueListIterator *it)
JsonPathBool
JsonPathExecResult
static JsonPathExecResult executeItemOptUnwrapResultNoThrow(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
Definition: type.h:109
#define jspStrictAbsenseOfErrors(cxt)

◆ executeStartsWith()

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

Definition at line 1614 of file jsonpath_exec.c.

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

Referenced by executeBoolItem().

1616 {
1617  if (!(whole = getScalar(whole, jbvString)))
1618  return jpbUnknown; /* error */
1619 
1620  if (!(initial = getScalar(initial, jbvString)))
1621  return jpbUnknown; /* error */
1622 
1623  if (whole->val.string.len >= initial->val.string.len &&
1624  !memcmp(whole->val.string.val,
1625  initial->val.string.val,
1626  initial->val.string.len))
1627  return jpbTrue;
1628 
1629  return jpbFalse;
1630 }
char * val
Definition: jsonb.h:264
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)

◆ executeUnaryArithmExpr()

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

Definition at line 1547 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

1549 {
1550  JsonPathExecResult jper;
1551  JsonPathExecResult jper2;
1552  JsonPathItem elem;
1553  JsonValueList seq = {0};
1555  JsonbValue *val;
1556  bool hasNext;
1557 
1558  jspGetArg(jsp, &elem);
1559  jper = executeItemOptUnwrapResult(cxt, &elem, jb, true, &seq);
1560 
1561  if (jperIsError(jper))
1562  return jper;
1563 
1564  jper = jperNotFound;
1565 
1566  hasNext = jspGetNext(jsp, &elem);
1567 
1568  JsonValueListInitIterator(&seq, &it);
1569  while ((val = JsonValueListNext(&seq, &it)))
1570  {
1571  if ((val = getScalar(val, jbvNumeric)))
1572  {
1573  if (!found && !hasNext)
1574  return jperOk;
1575  }
1576  else
1577  {
1578  if (!found && !hasNext)
1579  continue; /* skip non-numerics processing */
1580 
1582  (errcode(ERRCODE_JSON_NUMBER_NOT_FOUND),
1583  errmsg("operand of unary jsonpath operator %s is not a numeric value",
1584  jspOperationName(jsp->type)))));
1585  }
1586 
1587  if (func)
1588  val->val.numeric =
1590  NumericGetDatum(val->val.numeric)));
1591 
1592  jper2 = executeNextItem(cxt, jsp, &elem, val, found, false);
1593 
1594  if (jperIsError(jper2))
1595  return jper2;
1596 
1597  if (jper2 == jperOk)
1598  {
1599  if (!found)
1600  return jperOk;
1601  jper = jperOk;
1602  }
1603  }
1604 
1605  return jper;
1606 }
static void JsonValueListInitIterator(const JsonValueList *jvl, JsonValueListIterator *it)
#define RETURN_ERROR(throw_error)
#define jperIsError(jper)
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:922
char * val
Definition: jsonb.h:264
#define NumericGetDatum(X)
Definition: numeric.h:51
int errcode(int sqlerrcode)
Definition: elog.c:570
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
static JsonbValue * JsonValueListNext(const JsonValueList *jvl, JsonValueListIterator *it)
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:616
#define ERROR
Definition: elog.h:43
JsonPathExecResult
#define ereport(elevel, rest)
Definition: elog.h:141
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:707
#define DatumGetNumeric(X)
Definition: numeric.h:49
JsonPathItemType type
Definition: jsonpath.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:784
static JsonPathExecResult executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, bool unwrap, JsonValueList *found)
static JsonPathExecResult executeNextItem(JsonPathExecContext *cxt, JsonPathItem *cur, JsonPathItem *next, JsonbValue *v, JsonValueList *found, bool copy)
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:909
long val
Definition: informix.c:684

◆ getArrayIndex()

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

Definition at line 2178 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

2180 {
2181  JsonbValue *jbv;
2182  JsonValueList found = {0};
2183  JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
2184  Datum numeric_index;
2185  bool have_error = false;
2186 
2187  if (jperIsError(res))
2188  return res;
2189 
2190  if (JsonValueListLength(&found) != 1 ||
2191  !(jbv = getScalar(JsonValueListHead(&found), jbvNumeric)))
2193  (errcode(ERRCODE_INVALID_JSON_SUBSCRIPT),
2194  errmsg("jsonpath array subscript is not a single numeric value"))));
2195 
2196  numeric_index = DirectFunctionCall2(numeric_trunc,
2197  NumericGetDatum(jbv->val.numeric),
2198  Int32GetDatum(0));
2199 
2200  *index = numeric_int4_opt_error(DatumGetNumeric(numeric_index),
2201  &have_error);
2202 
2203  if (have_error)
2205  (errcode(ERRCODE_INVALID_JSON_SUBSCRIPT),
2206  errmsg("jsonpath array subscript is out of integer range"))));
2207 
2208  return jperOk;
2209 }
#define RETURN_ERROR(throw_error)
#define jperIsError(jper)
Datum numeric_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:1282
char * val
Definition: jsonb.h:264
#define NumericGetDatum(X)
Definition: numeric.h:51
int errcode(int sqlerrcode)
Definition: elog.c:570
static JsonbValue * getScalar(JsonbValue *scalar, enum jbvType type)
static int JsonValueListLength(const JsonValueList *jvl)
Definition: type.h:89
#define ERROR
Definition: elog.h:43
JsonPathExecResult
static JsonPathExecResult executeItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb, JsonValueList *found)
#define ereport(elevel, rest)
Definition: elog.h:141
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:3211
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define Int32GetDatum(X)
Definition: postgres.h:479
int errmsg(const char *fmt,...)
Definition: elog.c:784
static JsonbValue * JsonValueListHead(JsonValueList *jvl)
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:618

◆ getJsonPathItem()

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

Definition at line 1883 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

1885 {
1886  switch (item->type)
1887  {
1888  case jpiNull:
1889  value->type = jbvNull;
1890  break;
1891  case jpiBool:
1892  value->type = jbvBool;
1893  value->val.boolean = jspGetBool(item);
1894  break;
1895  case jpiNumeric:
1896  value->type = jbvNumeric;
1897  value->val.numeric = jspGetNumeric(item);
1898  break;
1899  case jpiString:
1900  value->type = jbvString;
1901  value->val.string.val = jspGetString(item,
1902  &value->val.string.len);
1903  break;
1904  case jpiVariable:
1905  getJsonPathVariable(cxt, item, cxt->vars, value);
1906  return;
1907  default:
1908  elog(ERROR, "unexpected jsonpath item type");
1909  }
1910 }
char * val
Definition: jsonb.h:264
Definition: jsonb.h:239
Definition: jsonb.h:236
#define ERROR
Definition: elog.h:43
bool jspGetBool(JsonPathItem *v)
Definition: jsonpath.c:1018
JsonPathItemType type
Definition: jsonpath.h:106
enum jbvType type
Definition: jsonb.h:255
static void getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable, Jsonb *vars, JsonbValue *value)
#define elog(elevel,...)
Definition: elog.h:226
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1034
Numeric jspGetNumeric(JsonPathItem *v)
Definition: jsonpath.c:1026

◆ getJsonPathVariable()

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

Definition at line 1916 of file jsonpath_exec.c.

References Assert, ereport, errcode(), errmsg(), ERROR, findJsonbValueFromContainer(), JB_FOBJECT, jbvNull, jbvString, jpiVariable, JsonbInitBinary(), jspGetString(), pfree(), pnstrdup(), Jsonb::root, setBaseObject(), JsonPathItem::type, JsonbValue::type, and JsonbValue::val.

Referenced by getJsonPathItem().

1918 {
1919  char *varName;
1920  int varNameLength;
1921  JsonbValue tmp;
1922  JsonbValue *v;
1923 
1924  if (!vars)
1925  {
1926  value->type = jbvNull;
1927  return;
1928  }
1929 
1930  Assert(variable->type == jpiVariable);
1931  varName = jspGetString(variable, &varNameLength);
1932  tmp.type = jbvString;
1933  tmp.val.string.val = varName;
1934  tmp.val.string.len = varNameLength;
1935 
1936  v = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
1937 
1938  if (v)
1939  {
1940  *value = *v;
1941  pfree(v);
1942  }
1943  else
1944  {
1945  ereport(ERROR,
1946  (errcode(ERRCODE_UNDEFINED_OBJECT),
1947  errmsg("could not find jsonpath variable \"%s\"",
1948  pnstrdup(varName, varNameLength))));
1949  }
1950 
1951  JsonbInitBinary(&tmp, vars);
1952  setBaseObject(cxt, &tmp, 1);
1953 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1172
char * val
Definition: jsonb.h:264
int errcode(int sqlerrcode)
Definition: elog.c:570
Definition: jsonb.h:236
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbContainer root
Definition: jsonb.h:223
static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt, JsonbValue *jbv, int32 id)
static JsonbValue * JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
#define Assert(condition)
Definition: c.h:732
#define JB_FOBJECT
Definition: jsonb.h:210
JsonPathItemType type
Definition: jsonpath.h:106
enum jbvType type
Definition: jsonb.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:784
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:327
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1034

◆ getScalar()

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

Definition at line 2350 of file jsonpath_exec.c.

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

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

2351 {
2352  /* Scalars should be always extracted during jsonpath execution. */
2353  Assert(scalar->type != jbvBinary ||
2354  !JsonContainerIsScalar(scalar->val.binary.data));
2355 
2356  return scalar->type == type ? scalar : NULL;
2357 }
char * val
Definition: jsonb.h:264
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:255

◆ jsonb_path_exists()

Datum jsonb_path_exists ( PG_FUNCTION_ARGS  )

Definition at line 265 of file jsonpath_exec.c.

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

Referenced by jsonb_path_exists_opr().

266 {
267  Jsonb *jb = PG_GETARG_JSONB_P(0);
269  JsonPathExecResult res;
270  Jsonb *vars = NULL;
271  bool silent = true;
272 
273  if (PG_NARGS() == 4)
274  {
275  vars = PG_GETARG_JSONB_P(2);
276  silent = PG_GETARG_BOOL(3);
277  }
278 
279  res = executeJsonPath(jp, vars, jb, !silent, NULL);
280 
281  PG_FREE_IF_COPY(jb, 0);
282  PG_FREE_IF_COPY(jp, 1);
283 
284  if (jperIsError(res))
285  PG_RETURN_NULL();
286 
287  PG_RETURN_BOOL(res == jperOk);
288 }
#define jperIsError(jper)
Definition: jsonb.h:220
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors, JsonValueList *result)
JsonPathExecResult
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:34
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
#define PG_NARGS()
Definition: fmgr.h:198
Definition: regcomp.c:224
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_path_exists_opr()

Datum jsonb_path_exists_opr ( PG_FUNCTION_ARGS  )

Definition at line 296 of file jsonpath_exec.c.

References jsonb_path_exists().

297 {
298  /* just call the other one -- it can handle both cases */
299  return jsonb_path_exists(fcinfo);
300 }
Datum jsonb_path_exists(PG_FUNCTION_ARGS)

◆ jsonb_path_match()

Datum jsonb_path_match ( PG_FUNCTION_ARGS  )

Definition at line 308 of file jsonpath_exec.c.

References ereport, errcode(), errmsg(), ERROR, executeJsonPath(), 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_opr().

309 {
310  Jsonb *jb = PG_GETARG_JSONB_P(0);
312  JsonValueList found = {0};
313  Jsonb *vars = NULL;
314  bool silent = true;
315 
316  if (PG_NARGS() == 4)
317  {
318  vars = PG_GETARG_JSONB_P(2);
319  silent = PG_GETARG_BOOL(3);
320  }
321 
322  (void) executeJsonPath(jp, vars, jb, !silent, &found);
323 
324  PG_FREE_IF_COPY(jb, 0);
325  PG_FREE_IF_COPY(jp, 1);
326 
327  if (JsonValueListLength(&found) == 1)
328  {
329  JsonbValue *jbv = JsonValueListHead(&found);
330 
331  if (jbv->type == jbvBool)
332  PG_RETURN_BOOL(jbv->val.boolean);
333 
334  if (jbv->type == jbvNull)
335  PG_RETURN_NULL();
336  }
337 
338  if (!silent)
339  ereport(ERROR,
340  (errcode(ERRCODE_SINGLETON_JSON_ITEM_REQUIRED),
341  errmsg("single boolean result is expected")));
342 
343  PG_RETURN_NULL();
344 }
Definition: jsonb.h:220
char * val
Definition: jsonb.h:264
Definition: jsonb.h:239
int errcode(int sqlerrcode)
Definition: elog.c:570
Definition: jsonb.h:236
static int JsonValueListLength(const JsonValueList *jvl)
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors, JsonValueList *result)
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:34
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
#define PG_NARGS()
Definition: fmgr.h:198
enum jbvType type
Definition: jsonb.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: regcomp.c:224
static JsonbValue * JsonValueListHead(JsonValueList *jvl)
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_path_match_opr()

Datum jsonb_path_match_opr ( PG_FUNCTION_ARGS  )

Definition at line 352 of file jsonpath_exec.c.

References jsonb_path_match().

353 {
354  /* just call the other one -- it can handle both cases */
355  return jsonb_path_match(fcinfo);
356 }
Datum jsonb_path_match(PG_FUNCTION_ARGS)

◆ jsonb_path_query()

Datum jsonb_path_query ( PG_FUNCTION_ARGS  )

Definition at line 364 of file jsonpath_exec.c.

References executeJsonPath(), 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.

365 {
366  FuncCallContext *funcctx;
367  List *found;
368  JsonbValue *v;
369  ListCell *c;
370 
371  if (SRF_IS_FIRSTCALL())
372  {
373  JsonPath *jp;
374  Jsonb *jb;
375  MemoryContext oldcontext;
376  Jsonb *vars;
377  bool silent;
378  JsonValueList found = {0};
379 
380  funcctx = SRF_FIRSTCALL_INIT();
381  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
382 
383  jb = PG_GETARG_JSONB_P_COPY(0);
385  vars = PG_GETARG_JSONB_P_COPY(2);
386  silent = PG_GETARG_BOOL(3);
387 
388  (void) executeJsonPath(jp, vars, jb, !silent, &found);
389 
390  funcctx->user_fctx = JsonValueListGetList(&found);
391 
392  MemoryContextSwitchTo(oldcontext);
393  }
394 
395  funcctx = SRF_PERCALL_SETUP();
396  found = funcctx->user_fctx;
397 
398  c = list_head(found);
399 
400  if (c == NULL)
401  SRF_RETURN_DONE(funcctx);
402 
403  v = lfirst(c);
404  funcctx->user_fctx = list_delete_first(found);
405 
407 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
#define JsonbPGetDatum(p)
Definition: jsonb.h:73
#define PG_GETARG_JSONB_P_COPY(x)
Definition: jsonb.h:75
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors, JsonValueList *result)
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
static List * JsonValueListGetList(JsonValueList *jvl)
#define PG_GETARG_JSONPATH_P_COPY(x)
Definition: jsonpath.h:35
char * c
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
#define lfirst(lc)
Definition: pg_list.h:190
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
void * user_fctx
Definition: funcapi.h:83
Definition: regcomp.c:224
Definition: pg_list.h:50
List * list_delete_first(List *list)
Definition: list.c:857
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285

◆ jsonb_path_query_array()

Datum jsonb_path_query_array ( PG_FUNCTION_ARGS  )

Definition at line 415 of file jsonpath_exec.c.

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

416 {
417  Jsonb *jb = PG_GETARG_JSONB_P(0);
419  JsonValueList found = {0};
421  bool silent = PG_GETARG_BOOL(3);
422 
423  (void) executeJsonPath(jp, vars, jb, !silent, &found);
424 
426 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors, JsonValueList *result)
static JsonbValue * wrapItemsInArray(const JsonValueList *items)
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:34
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
Definition: regcomp.c:224
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_path_query_first()

Datum jsonb_path_query_first ( PG_FUNCTION_ARGS  )

Definition at line 434 of file jsonpath_exec.c.

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

435 {
436  Jsonb *jb = PG_GETARG_JSONB_P(0);
438  JsonValueList found = {0};
440  bool silent = PG_GETARG_BOOL(3);
441 
442  (void) executeJsonPath(jp, vars, jb, !silent, &found);
443 
444  if (JsonValueListLength(&found) >= 1)
446  else
447  PG_RETURN_NULL();
448 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
static int JsonValueListLength(const JsonValueList *jvl)
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors, JsonValueList *result)
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:34
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
Definition: regcomp.c:224
static JsonbValue * JsonValueListHead(JsonValueList *jvl)
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ JsonbArraySize()

static int JsonbArraySize ( JsonbValue jb)
static

Definition at line 1961 of file jsonpath_exec.c.

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

Referenced by executeItemOptUnwrapTarget().

1962 {
1963  Assert(jb->type != jbvArray);
1964 
1965  if (jb->type == jbvBinary)
1966  {
1967  JsonbContainer *jbc = jb->val.binary.data;
1968 
1969  if (JsonContainerIsArray(jbc) && !JsonContainerIsScalar(jbc))
1970  return JsonContainerSize(jbc);
1971  }
1972 
1973  return -1;
1974 }
char * val
Definition: jsonb.h:264
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
#define JsonContainerSize(jc)
Definition: jsonb.h:214
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:255

◆ JsonbInitBinary()

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

Definition at line 2313 of file jsonpath_exec.c.

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

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

2314 {
2315  jbv->type = jbvBinary;
2316  jbv->val.binary.data = &jb->root;
2317  jbv->val.binary.len = VARSIZE_ANY_EXHDR(jb);
2318 
2319  return jbv;
2320 }
char * val
Definition: jsonb.h:264
JsonbContainer root
Definition: jsonb.h:223
enum jbvType type
Definition: jsonb.h:255
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341

◆ JsonbType()

static int JsonbType ( JsonbValue jb)
static

Definition at line 2326 of file jsonpath_exec.c.

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

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

2327 {
2328  int type = jb->type;
2329 
2330  if (jb->type == jbvBinary)
2331  {
2332  JsonbContainer *jbc = (void *) jb->val.binary.data;
2333 
2334  /* Scalars should be always extracted during jsonpath execution. */
2336 
2337  if (JsonContainerIsObject(jbc))
2338  type = jbvObject;
2339  else if (JsonContainerIsArray(jbc))
2340  type = jbvArray;
2341  else
2342  elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
2343  }
2344 
2345  return type;
2346 }
char * val
Definition: jsonb.h:264
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
#define ERROR
Definition: elog.h:43
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
uint32 header
Definition: jsonb.h:200
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:255
#define elog(elevel,...)
Definition: elog.h:226

◆ JsonValueListAppend()

static void JsonValueListAppend ( JsonValueList jvl,
JsonbValue jbv 
)
static

Definition at line 2225 of file jsonpath_exec.c.

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

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

2226 {
2227  if (jvl->singleton)
2228  {
2229  jvl->list = list_make2(jvl->singleton, jbv);
2230  jvl->singleton = NULL;
2231  }
2232  else if (!jvl->list)
2233  jvl->singleton = jbv;
2234  else
2235  jvl->list = lappend(jvl->list, jbv);
2236 }
#define list_make2(x1, x2)
Definition: pg_list.h:229
List * lappend(List *list, void *datum)
Definition: list.c:321
JsonbValue * singleton

◆ JsonValueListGetList()

static List * JsonValueListGetList ( JsonValueList jvl)
static

Definition at line 2257 of file jsonpath_exec.c.

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

Referenced by jsonb_path_query().

2258 {
2259  if (jvl->singleton)
2260  return list_make1(jvl->singleton);
2261 
2262  return jvl->list;
2263 }
#define list_make1(x1)
Definition: pg_list.h:227
JsonbValue * singleton

◆ JsonValueListHead()

static JsonbValue * JsonValueListHead ( JsonValueList jvl)
static

Definition at line 2251 of file jsonpath_exec.c.

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

Referenced by executeBinaryArithmExpr(), getArrayIndex(), jsonb_path_match(), and jsonb_path_query_first().

2252 {
2253  return jvl->singleton ? jvl->singleton : linitial(jvl->list);
2254 }
#define linitial(l)
Definition: pg_list.h:195
JsonbValue * singleton

◆ JsonValueListInitIterator()

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

Definition at line 2266 of file jsonpath_exec.c.

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

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

2267 {
2268  if (jvl->singleton)
2269  {
2270  it->value = jvl->singleton;
2271  it->list = NIL;
2272  it->next = NULL;
2273  }
2274  else if (jvl->list != NIL)
2275  {
2276  it->value = (JsonbValue *) linitial(jvl->list);
2277  it->list = jvl->list;
2278  it->next = list_second_cell(jvl->list);
2279  }
2280  else
2281  {
2282  it->value = NULL;
2283  it->list = NIL;
2284  it->next = NULL;
2285  }
2286 }
#define NIL
Definition: pg_list.h:65
#define linitial(l)
Definition: pg_list.h:195
static ListCell * list_second_cell(const List *l)
Definition: pg_list.h:139
JsonbValue * singleton

◆ JsonValueListIsEmpty()

static bool JsonValueListIsEmpty ( JsonValueList jvl)
static

Definition at line 2245 of file jsonpath_exec.c.

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

Referenced by executeBoolItem(), and executeJsonPath().

2246 {
2247  return !jvl->singleton && list_length(jvl->list) <= 0;
2248 }
JsonbValue * singleton
static int list_length(const List *l)
Definition: pg_list.h:169

◆ JsonValueListLength()

static int JsonValueListLength ( const JsonValueList jvl)
static

Definition at line 2239 of file jsonpath_exec.c.

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

Referenced by executeBinaryArithmExpr(), getArrayIndex(), jsonb_path_match(), and jsonb_path_query_first().

2240 {
2241  return jvl->singleton ? 1 : list_length(jvl->list);
2242 }
JsonbValue * singleton
static int list_length(const List *l)
Definition: pg_list.h:169

◆ JsonValueListNext()

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

Definition at line 2292 of file jsonpath_exec.c.

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

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

2293 {
2294  JsonbValue *result = it->value;
2295 
2296  if (it->next)
2297  {
2298  it->value = lfirst(it->next);
2299  it->next = lnext(it->list, it->next);
2300  }
2301  else
2302  {
2303  it->value = NULL;
2304  }
2305 
2306  return result;
2307 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
#define lfirst(lc)
Definition: pg_list.h:190

◆ setBaseObject()

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

Definition at line 2213 of file jsonpath_exec.c.

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

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

2214 {
2215  JsonBaseObjectInfo baseObject = cxt->baseObject;
2216 
2217  cxt->baseObject.jbc = jbv->type != jbvBinary ? NULL :
2218  (JsonbContainer *) jbv->val.binary.data;
2219  cxt->baseObject.id = id;
2220 
2221  return baseObject;
2222 }
char * val
Definition: jsonb.h:264
JsonBaseObjectInfo baseObject
Definition: jsonpath_exec.c:97
JsonbContainer * jbc
Definition: jsonpath_exec.c:85
enum jbvType type
Definition: jsonb.h:255

◆ wrapItemsInArray()

static JsonbValue * wrapItemsInArray ( const JsonValueList items)
static

Definition at line 2361 of file jsonpath_exec.c.

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

Referenced by jsonb_path_query_array().

2362 {
2363  JsonbParseState *ps = NULL;
2365  JsonbValue *jbv;
2366 
2367  pushJsonbValue(&ps, WJB_BEGIN_ARRAY, NULL);
2368 
2369  JsonValueListInitIterator(items, &it);
2370  while ((jbv = JsonValueListNext(items, &it)))
2371  pushJsonbValue(&ps, WJB_ELEM, jbv);
2372 
2373  return pushJsonbValue(&ps, WJB_END_ARRAY, NULL);
2374 }
static void JsonValueListInitIterator(const JsonValueList *jvl, JsonValueListIterator *it)
static JsonbValue * JsonValueListNext(const JsonValueList *jvl, JsonValueListIterator *it)
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
Definition: jsonb.h:25