| /*------------------------------------------------------------------------- |
| * |
| * jsonpath.h |
| * Definitions for jsonpath datatype |
| * |
| * Copyright (c) 2019-2021, PostgreSQL Global Development Group |
| * |
| * IDENTIFICATION |
| * src/include/utils/jsonpath.h |
| * |
| *------------------------------------------------------------------------- |
| */ |
| |
| #ifndef JSONPATH_H |
| #define JSONPATH_H |
| |
| #include "fmgr.h" |
| #include "nodes/pg_list.h" |
| #include "utils/jsonb.h" |
| |
| typedef struct |
| { |
| int32 vl_len_; /* varlena header (do not touch directly!) */ |
| uint32 header; /* version and flags (see below) */ |
| char data[FLEXIBLE_ARRAY_MEMBER]; |
| } JsonPath; |
| |
| #define JSONPATH_VERSION (0x01) |
| #define JSONPATH_LAX (0x80000000) |
| #define JSONPATH_HDRSZ (offsetof(JsonPath, data)) |
| |
| #define DatumGetJsonPathP(d) ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM(d))) |
| #define DatumGetJsonPathPCopy(d) ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM_COPY(d))) |
| #define PG_GETARG_JSONPATH_P(x) DatumGetJsonPathP(PG_GETARG_DATUM(x)) |
| #define PG_GETARG_JSONPATH_P_COPY(x) DatumGetJsonPathPCopy(PG_GETARG_DATUM(x)) |
| #define PG_RETURN_JSONPATH_P(p) PG_RETURN_POINTER(p) |
| |
| #define jspIsScalar(type) ((type) >= jpiNull && (type) <= jpiBool) |
| |
| /* |
| * All node's type of jsonpath expression |
| */ |
| typedef enum JsonPathItemType |
| { |
| jpiNull = jbvNull, /* NULL literal */ |
| jpiString = jbvString, /* string literal */ |
| jpiNumeric = jbvNumeric, /* numeric literal */ |
| jpiBool = jbvBool, /* boolean literal: TRUE or FALSE */ |
| jpiAnd, /* predicate && predicate */ |
| jpiOr, /* predicate || predicate */ |
| jpiNot, /* ! predicate */ |
| jpiIsUnknown, /* (predicate) IS UNKNOWN */ |
| jpiEqual, /* expr == expr */ |
| jpiNotEqual, /* expr != expr */ |
| jpiLess, /* expr < expr */ |
| jpiGreater, /* expr > expr */ |
| jpiLessOrEqual, /* expr <= expr */ |
| jpiGreaterOrEqual, /* expr >= expr */ |
| jpiAdd, /* expr + expr */ |
| jpiSub, /* expr - expr */ |
| jpiMul, /* expr * expr */ |
| jpiDiv, /* expr / expr */ |
| jpiMod, /* expr % expr */ |
| jpiPlus, /* + expr */ |
| jpiMinus, /* - expr */ |
| jpiAnyArray, /* [*] */ |
| jpiAnyKey, /* .* */ |
| jpiIndexArray, /* [subscript, ...] */ |
| jpiAny, /* .** */ |
| jpiKey, /* .key */ |
| jpiCurrent, /* @ */ |
| jpiRoot, /* $ */ |
| jpiVariable, /* $variable */ |
| jpiFilter, /* ? (predicate) */ |
| jpiExists, /* EXISTS (expr) predicate */ |
| jpiType, /* .type() item method */ |
| jpiSize, /* .size() item method */ |
| jpiAbs, /* .abs() item method */ |
| jpiFloor, /* .floor() item method */ |
| jpiCeiling, /* .ceiling() item method */ |
| jpiDouble, /* .double() item method */ |
| jpiDatetime, /* .datetime() item method */ |
| jpiKeyValue, /* .keyvalue() item method */ |
| jpiSubscript, /* array subscript: 'expr' or 'expr TO expr' */ |
| jpiLast, /* LAST array subscript */ |
| jpiStartsWith, /* STARTS WITH predicate */ |
| jpiLikeRegex, /* LIKE_REGEX predicate */ |
| } JsonPathItemType; |
| |
| /* XQuery regex mode flags for LIKE_REGEX predicate */ |
| #define JSP_REGEX_ICASE 0x01 /* i flag, case insensitive */ |
| #define JSP_REGEX_DOTALL 0x02 /* s flag, dot matches newline */ |
| #define JSP_REGEX_MLINE 0x04 /* m flag, ^/$ match at newlines */ |
| #define JSP_REGEX_WSPACE 0x08 /* x flag, ignore whitespace in pattern */ |
| #define JSP_REGEX_QUOTE 0x10 /* q flag, no special characters */ |
| |
| /* |
| * Support functions to parse/construct binary value. |
| * Unlike many other representation of expression the first/main |
| * node is not an operation but left operand of expression. That |
| * allows to implement cheap follow-path descending in jsonb |
| * structure and then execute operator with right operand |
| */ |
| |
| typedef struct JsonPathItem |
| { |
| JsonPathItemType type; |
| |
| /* position form base to next node */ |
| int32 nextPos; |
| |
| /* |
| * pointer into JsonPath value to current node, all positions of current |
| * are relative to this base |
| */ |
| char *base; |
| |
| union |
| { |
| /* classic operator with two operands: and, or etc */ |
| struct |
| { |
| int32 left; |
| int32 right; |
| } args; |
| |
| /* any unary operation */ |
| int32 arg; |
| |
| /* storage for jpiIndexArray: indexes of array */ |
| struct |
| { |
| int32 nelems; |
| struct |
| { |
| int32 from; |
| int32 to; |
| } *elems; |
| } array; |
| |
| /* jpiAny: levels */ |
| struct |
| { |
| uint32 first; |
| uint32 last; |
| } anybounds; |
| |
| struct |
| { |
| char *data; /* for bool, numeric and string/key */ |
| int32 datalen; /* filled only for string/key */ |
| } value; |
| |
| struct |
| { |
| int32 expr; |
| char *pattern; |
| int32 patternlen; |
| uint32 flags; |
| } like_regex; |
| } content; |
| } JsonPathItem; |
| |
| #define jspHasNext(jsp) ((jsp)->nextPos > 0) |
| |
| extern void jspInit(JsonPathItem *v, JsonPath *js); |
| extern void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos); |
| extern bool jspGetNext(JsonPathItem *v, JsonPathItem *a); |
| extern void jspGetArg(JsonPathItem *v, JsonPathItem *a); |
| extern void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a); |
| extern void jspGetRightArg(JsonPathItem *v, JsonPathItem *a); |
| extern Numeric jspGetNumeric(JsonPathItem *v); |
| extern bool jspGetBool(JsonPathItem *v); |
| extern char *jspGetString(JsonPathItem *v, int32 *len); |
| extern bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, |
| JsonPathItem *to, int i); |
| |
| extern const char *jspOperationName(JsonPathItemType type); |
| |
| /* |
| * Parsing support data structures. |
| */ |
| |
| typedef struct JsonPathParseItem JsonPathParseItem; |
| |
| struct JsonPathParseItem |
| { |
| JsonPathItemType type; |
| JsonPathParseItem *next; /* next in path */ |
| |
| union |
| { |
| |
| /* classic operator with two operands: and, or etc */ |
| struct |
| { |
| JsonPathParseItem *left; |
| JsonPathParseItem *right; |
| } args; |
| |
| /* any unary operation */ |
| JsonPathParseItem *arg; |
| |
| /* storage for jpiIndexArray: indexes of array */ |
| struct |
| { |
| int nelems; |
| struct |
| { |
| JsonPathParseItem *from; |
| JsonPathParseItem *to; |
| } *elems; |
| } array; |
| |
| /* jpiAny: levels */ |
| struct |
| { |
| uint32 first; |
| uint32 last; |
| } anybounds; |
| |
| struct |
| { |
| JsonPathParseItem *expr; |
| char *pattern; /* could not be not null-terminated */ |
| uint32 patternlen; |
| uint32 flags; |
| } like_regex; |
| |
| /* scalars */ |
| Numeric numeric; |
| bool boolean; |
| struct |
| { |
| uint32 len; |
| char *val; /* could not be not null-terminated */ |
| } string; |
| } value; |
| }; |
| |
| typedef struct JsonPathParseResult |
| { |
| JsonPathParseItem *expr; |
| bool lax; |
| } JsonPathParseResult; |
| |
| extern JsonPathParseResult *parsejsonpath(const char *str, int len); |
| |
| extern int jspConvertRegexFlags(uint32 xflags); |
| |
| #endif |