1 /*------------------------------------------------------------------------- 2 * 3 * jsonpath.h 4 * Definitions for jsonpath datatype 5 * 6 * Copyright (c) 2019-2021, PostgreSQL Global Development Group 7 * 8 * IDENTIFICATION 9 * src/include/utils/jsonpath.h 10 * 11 *------------------------------------------------------------------------- 12 */ 13 14 #ifndef JSONPATH_H 15 #define JSONPATH_H 16 17 #include "fmgr.h" 18 #include "nodes/pg_list.h" 19 #include "utils/jsonb.h" 20 21 typedef struct 22 { 23 int32 vl_len_; /* varlena header (do not touch directly!) */ 24 uint32 header; /* version and flags (see below) */ 25 char data[FLEXIBLE_ARRAY_MEMBER]; 26 } JsonPath; 27 28 #define JSONPATH_VERSION (0x01) 29 #define JSONPATH_LAX (0x80000000) 30 #define JSONPATH_HDRSZ (offsetof(JsonPath, data)) 31 32 #define DatumGetJsonPathP(d) ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM(d))) 33 #define DatumGetJsonPathPCopy(d) ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM_COPY(d))) 34 #define PG_GETARG_JSONPATH_P(x) DatumGetJsonPathP(PG_GETARG_DATUM(x)) 35 #define PG_GETARG_JSONPATH_P_COPY(x) DatumGetJsonPathPCopy(PG_GETARG_DATUM(x)) 36 #define PG_RETURN_JSONPATH_P(p) PG_RETURN_POINTER(p) 37 38 #define jspIsScalar(type) ((type) >= jpiNull && (type) <= jpiBool) 39 40 /* 41 * All node's type of jsonpath expression 42 */ 43 typedef enum JsonPathItemType 44 { 45 jpiNull = jbvNull, /* NULL literal */ 46 jpiString = jbvString, /* string literal */ 47 jpiNumeric = jbvNumeric, /* numeric literal */ 48 jpiBool = jbvBool, /* boolean literal: TRUE or FALSE */ 49 jpiAnd, /* predicate && predicate */ 50 jpiOr, /* predicate || predicate */ 51 jpiNot, /* ! predicate */ 52 jpiIsUnknown, /* (predicate) IS UNKNOWN */ 53 jpiEqual, /* expr == expr */ 54 jpiNotEqual, /* expr != expr */ 55 jpiLess, /* expr < expr */ 56 jpiGreater, /* expr > expr */ 57 jpiLessOrEqual, /* expr <= expr */ 58 jpiGreaterOrEqual, /* expr >= expr */ 59 jpiAdd, /* expr + expr */ 60 jpiSub, /* expr - expr */ 61 jpiMul, /* expr * expr */ 62 jpiDiv, /* expr / expr */ 63 jpiMod, /* expr % expr */ 64 jpiPlus, /* + expr */ 65 jpiMinus, /* - expr */ 66 jpiAnyArray, /* [*] */ 67 jpiAnyKey, /* .* */ 68 jpiIndexArray, /* [subscript, ...] */ 69 jpiAny, /* .** */ 70 jpiKey, /* .key */ 71 jpiCurrent, /* @ */ 72 jpiRoot, /* $ */ 73 jpiVariable, /* $variable */ 74 jpiFilter, /* ? (predicate) */ 75 jpiExists, /* EXISTS (expr) predicate */ 76 jpiType, /* .type() item method */ 77 jpiSize, /* .size() item method */ 78 jpiAbs, /* .abs() item method */ 79 jpiFloor, /* .floor() item method */ 80 jpiCeiling, /* .ceiling() item method */ 81 jpiDouble, /* .double() item method */ 82 jpiDatetime, /* .datetime() item method */ 83 jpiKeyValue, /* .keyvalue() item method */ 84 jpiSubscript, /* array subscript: 'expr' or 'expr TO expr' */ 85 jpiLast, /* LAST array subscript */ 86 jpiStartsWith, /* STARTS WITH predicate */ 87 jpiLikeRegex, /* LIKE_REGEX predicate */ 88 } JsonPathItemType; 89 90 /* XQuery regex mode flags for LIKE_REGEX predicate */ 91 #define JSP_REGEX_ICASE 0x01 /* i flag, case insensitive */ 92 #define JSP_REGEX_DOTALL 0x02 /* s flag, dot matches newline */ 93 #define JSP_REGEX_MLINE 0x04 /* m flag, ^/$ match at newlines */ 94 #define JSP_REGEX_WSPACE 0x08 /* x flag, ignore whitespace in pattern */ 95 #define JSP_REGEX_QUOTE 0x10 /* q flag, no special characters */ 96 97 /* 98 * Support functions to parse/construct binary value. 99 * Unlike many other representation of expression the first/main 100 * node is not an operation but left operand of expression. That 101 * allows to implement cheap follow-path descending in jsonb 102 * structure and then execute operator with right operand 103 */ 104 105 typedef struct JsonPathItem 106 { 107 JsonPathItemType type; 108 109 /* position form base to next node */ 110 int32 nextPos; 111 112 /* 113 * pointer into JsonPath value to current node, all positions of current 114 * are relative to this base 115 */ 116 char *base; 117 118 union 119 { 120 /* classic operator with two operands: and, or etc */ 121 struct 122 { 123 int32 left; 124 int32 right; 125 } args; 126 127 /* any unary operation */ 128 int32 arg; 129 130 /* storage for jpiIndexArray: indexes of array */ 131 struct 132 { 133 int32 nelems; 134 struct 135 { 136 int32 from; 137 int32 to; 138 } *elems; 139 } array; 140 141 /* jpiAny: levels */ 142 struct 143 { 144 uint32 first; 145 uint32 last; 146 } anybounds; 147 148 struct 149 { 150 char *data; /* for bool, numeric and string/key */ 151 int32 datalen; /* filled only for string/key */ 152 } value; 153 154 struct 155 { 156 int32 expr; 157 char *pattern; 158 int32 patternlen; 159 uint32 flags; 160 } like_regex; 161 } content; 162 } JsonPathItem; 163 164 #define jspHasNext(jsp) ((jsp)->nextPos > 0) 165 166 extern void jspInit(JsonPathItem *v, JsonPath *js); 167 extern void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos); 168 extern bool jspGetNext(JsonPathItem *v, JsonPathItem *a); 169 extern void jspGetArg(JsonPathItem *v, JsonPathItem *a); 170 extern void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a); 171 extern void jspGetRightArg(JsonPathItem *v, JsonPathItem *a); 172 extern Numeric jspGetNumeric(JsonPathItem *v); 173 extern bool jspGetBool(JsonPathItem *v); 174 extern char *jspGetString(JsonPathItem *v, int32 *len); 175 extern bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, 176 JsonPathItem *to, int i); 177 178 extern const char *jspOperationName(JsonPathItemType type); 179 180 /* 181 * Parsing support data structures. 182 */ 183 184 typedef struct JsonPathParseItem JsonPathParseItem; 185 186 struct JsonPathParseItem 187 { 188 JsonPathItemType type; 189 JsonPathParseItem *next; /* next in path */ 190 191 union 192 { 193 194 /* classic operator with two operands: and, or etc */ 195 struct 196 { 197 JsonPathParseItem *left; 198 JsonPathParseItem *right; 199 } args; 200 201 /* any unary operation */ 202 JsonPathParseItem *arg; 203 204 /* storage for jpiIndexArray: indexes of array */ 205 struct 206 { 207 int nelems; 208 struct 209 { 210 JsonPathParseItem *from; 211 JsonPathParseItem *to; 212 } *elems; 213 } array; 214 215 /* jpiAny: levels */ 216 struct 217 { 218 uint32 first; 219 uint32 last; 220 } anybounds; 221 222 struct 223 { 224 JsonPathParseItem *expr; 225 char *pattern; /* could not be not null-terminated */ 226 uint32 patternlen; 227 uint32 flags; 228 } like_regex; 229 230 /* scalars */ 231 Numeric numeric; 232 bool boolean; 233 struct 234 { 235 uint32 len; 236 char *val; /* could not be not null-terminated */ 237 } string; 238 } value; 239 }; 240 241 typedef struct JsonPathParseResult 242 { 243 JsonPathParseItem *expr; 244 bool lax; 245 } JsonPathParseResult; 246 247 extern JsonPathParseResult *parsejsonpath(const char *str, int len); 248 249 extern int jspConvertRegexFlags(uint32 xflags); 250 251 #endif 252