Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * jsonpath.h
4 : : * Definitions for jsonpath datatype
5 : : *
6 : : * Copyright (c) 2019-2024, 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 "executor/tablefunc.h"
18 : : #include "fmgr.h"
19 : : #include "nodes/pg_list.h"
20 : : #include "nodes/primnodes.h"
21 : : #include "utils/jsonb.h"
22 : :
23 : : typedef struct
24 : : {
25 : : int32 vl_len_; /* varlena header (do not touch directly!) */
26 : : uint32 header; /* version and flags (see below) */
27 : : char data[FLEXIBLE_ARRAY_MEMBER];
28 : : } JsonPath;
29 : :
30 : : #define JSONPATH_VERSION (0x01)
31 : : #define JSONPATH_LAX (0x80000000)
32 : : #define JSONPATH_HDRSZ (offsetof(JsonPath, data))
33 : :
34 : : static inline JsonPath *
565 peter@eisentraut.org 35 :CBC 98422 : DatumGetJsonPathP(Datum d)
36 : : {
37 : 98422 : return (JsonPath *) PG_DETOAST_DATUM(d);
38 : : }
39 : :
40 : : static inline JsonPath *
41 : 1989 : DatumGetJsonPathPCopy(Datum d)
42 : : {
43 : 1989 : return (JsonPath *) PG_DETOAST_DATUM_COPY(d);
44 : : }
45 : :
46 : : #define PG_GETARG_JSONPATH_P(x) DatumGetJsonPathP(PG_GETARG_DATUM(x))
47 : : #define PG_GETARG_JSONPATH_P_COPY(x) DatumGetJsonPathPCopy(PG_GETARG_DATUM(x))
48 : : #define PG_RETURN_JSONPATH_P(p) PG_RETURN_POINTER(p)
49 : :
50 : : #define jspIsScalar(type) ((type) >= jpiNull && (type) <= jpiBool)
51 : :
52 : : /*
53 : : * All node's type of jsonpath expression
54 : : *
55 : : * These become part of the on-disk representation of the jsonpath type.
56 : : * Therefore, to preserve pg_upgradability, the order must not be changed, and
57 : : * new values must be added at the end.
58 : : *
59 : : * It is recommended that switch cases etc. in other parts of the code also
60 : : * use this order, to maintain some consistency.
61 : : */
62 : : typedef enum JsonPathItemType
63 : : {
64 : : jpiNull = jbvNull, /* NULL literal */
65 : : jpiString = jbvString, /* string literal */
66 : : jpiNumeric = jbvNumeric, /* numeric literal */
67 : : jpiBool = jbvBool, /* boolean literal: TRUE or FALSE */
68 : : jpiAnd, /* predicate && predicate */
69 : : jpiOr, /* predicate || predicate */
70 : : jpiNot, /* ! predicate */
71 : : jpiIsUnknown, /* (predicate) IS UNKNOWN */
72 : : jpiEqual, /* expr == expr */
73 : : jpiNotEqual, /* expr != expr */
74 : : jpiLess, /* expr < expr */
75 : : jpiGreater, /* expr > expr */
76 : : jpiLessOrEqual, /* expr <= expr */
77 : : jpiGreaterOrEqual, /* expr >= expr */
78 : : jpiAdd, /* expr + expr */
79 : : jpiSub, /* expr - expr */
80 : : jpiMul, /* expr * expr */
81 : : jpiDiv, /* expr / expr */
82 : : jpiMod, /* expr % expr */
83 : : jpiPlus, /* + expr */
84 : : jpiMinus, /* - expr */
85 : : jpiAnyArray, /* [*] */
86 : : jpiAnyKey, /* .* */
87 : : jpiIndexArray, /* [subscript, ...] */
88 : : jpiAny, /* .** */
89 : : jpiKey, /* .key */
90 : : jpiCurrent, /* @ */
91 : : jpiRoot, /* $ */
92 : : jpiVariable, /* $variable */
93 : : jpiFilter, /* ? (predicate) */
94 : : jpiExists, /* EXISTS (expr) predicate */
95 : : jpiType, /* .type() item method */
96 : : jpiSize, /* .size() item method */
97 : : jpiAbs, /* .abs() item method */
98 : : jpiFloor, /* .floor() item method */
99 : : jpiCeiling, /* .ceiling() item method */
100 : : jpiDouble, /* .double() item method */
101 : : jpiDatetime, /* .datetime() item method */
102 : : jpiKeyValue, /* .keyvalue() item method */
103 : : jpiSubscript, /* array subscript: 'expr' or 'expr TO expr' */
104 : : jpiLast, /* LAST array subscript */
105 : : jpiStartsWith, /* STARTS WITH predicate */
106 : : jpiLikeRegex, /* LIKE_REGEX predicate */
107 : : jpiBigint, /* .bigint() item method */
108 : : jpiBoolean, /* .boolean() item method */
109 : : jpiDate, /* .date() item method */
110 : : jpiDecimal, /* .decimal() item method */
111 : : jpiInteger, /* .integer() item method */
112 : : jpiNumber, /* .number() item method */
113 : : jpiStringFunc, /* .string() item method */
114 : : jpiTime, /* .time() item method */
115 : : jpiTimeTz, /* .time_tz() item method */
116 : : jpiTimestamp, /* .timestamp() item method */
117 : : jpiTimestampTz, /* .timestamp_tz() item method */
118 : : } JsonPathItemType;
119 : :
120 : : /* XQuery regex mode flags for LIKE_REGEX predicate */
121 : : #define JSP_REGEX_ICASE 0x01 /* i flag, case insensitive */
122 : : #define JSP_REGEX_DOTALL 0x02 /* s flag, dot matches newline */
123 : : #define JSP_REGEX_MLINE 0x04 /* m flag, ^/$ match at newlines */
124 : : #define JSP_REGEX_WSPACE 0x08 /* x flag, ignore whitespace in pattern */
125 : : #define JSP_REGEX_QUOTE 0x10 /* q flag, no special characters */
126 : :
127 : : /*
128 : : * Support functions to parse/construct binary value.
129 : : * Unlike many other representation of expression the first/main
130 : : * node is not an operation but left operand of expression. That
131 : : * allows to implement cheap follow-path descending in jsonb
132 : : * structure and then execute operator with right operand
133 : : */
134 : :
135 : : typedef struct JsonPathItem
136 : : {
137 : : JsonPathItemType type;
138 : :
139 : : /* position form base to next node */
140 : : int32 nextPos;
141 : :
142 : : /*
143 : : * pointer into JsonPath value to current node, all positions of current
144 : : * are relative to this base
145 : : */
146 : : char *base;
147 : :
148 : : union
149 : : {
150 : : /* classic operator with two operands: and, or etc */
151 : : struct
152 : : {
153 : : int32 left;
154 : : int32 right;
155 : : } args;
156 : :
157 : : /* any unary operation */
158 : : int32 arg;
159 : :
160 : : /* storage for jpiIndexArray: indexes of array */
161 : : struct
162 : : {
163 : : int32 nelems;
164 : : struct
165 : : {
166 : : int32 from;
167 : : int32 to;
168 : : } *elems;
169 : : } array;
170 : :
171 : : /* jpiAny: levels */
172 : : struct
173 : : {
174 : : uint32 first;
175 : : uint32 last;
176 : : } anybounds;
177 : :
178 : : struct
179 : : {
180 : : char *data; /* for bool, numeric and string/key */
181 : : int32 datalen; /* filled only for string/key */
182 : : } value;
183 : :
184 : : struct
185 : : {
186 : : int32 expr;
187 : : char *pattern;
188 : : int32 patternlen;
189 : : uint32 flags;
190 : : } like_regex;
191 : : } content;
192 : : } JsonPathItem;
193 : :
194 : : #define jspHasNext(jsp) ((jsp)->nextPos > 0)
195 : :
196 : : extern void jspInit(JsonPathItem *v, JsonPath *js);
197 : : extern void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos);
198 : : extern bool jspGetNext(JsonPathItem *v, JsonPathItem *a);
199 : : extern void jspGetArg(JsonPathItem *v, JsonPathItem *a);
200 : : extern void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a);
201 : : extern void jspGetRightArg(JsonPathItem *v, JsonPathItem *a);
202 : : extern Numeric jspGetNumeric(JsonPathItem *v);
203 : : extern bool jspGetBool(JsonPathItem *v);
204 : : extern char *jspGetString(JsonPathItem *v, int32 *len);
205 : : extern bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from,
206 : : JsonPathItem *to, int i);
207 : : extern bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs);
208 : :
209 : : extern const char *jspOperationName(JsonPathItemType type);
210 : :
211 : : /*
212 : : * Parsing support data structures.
213 : : */
214 : :
215 : : typedef struct JsonPathParseItem JsonPathParseItem;
216 : :
217 : : struct JsonPathParseItem
218 : : {
219 : : JsonPathItemType type;
220 : : JsonPathParseItem *next; /* next in path */
221 : :
222 : : union
223 : : {
224 : :
225 : : /* classic operator with two operands: and, or etc */
226 : : struct
227 : : {
228 : : JsonPathParseItem *left;
229 : : JsonPathParseItem *right;
230 : : } args;
231 : :
232 : : /* any unary operation */
233 : : JsonPathParseItem *arg;
234 : :
235 : : /* storage for jpiIndexArray: indexes of array */
236 : : struct
237 : : {
238 : : int nelems;
239 : : struct
240 : : {
241 : : JsonPathParseItem *from;
242 : : JsonPathParseItem *to;
243 : : } *elems;
244 : : } array;
245 : :
246 : : /* jpiAny: levels */
247 : : struct
248 : : {
249 : : uint32 first;
250 : : uint32 last;
251 : : } anybounds;
252 : :
253 : : struct
254 : : {
255 : : JsonPathParseItem *expr;
256 : : char *pattern; /* could not be not null-terminated */
257 : : uint32 patternlen;
258 : : uint32 flags;
259 : : } like_regex;
260 : :
261 : : /* scalars */
262 : : Numeric numeric;
263 : : bool boolean;
264 : : struct
265 : : {
266 : : uint32 len;
267 : : char *val; /* could not be not null-terminated */
268 : : } string;
269 : : } value;
270 : : };
271 : :
272 : : typedef struct JsonPathParseResult
273 : : {
274 : : JsonPathParseItem *expr;
275 : : bool lax;
276 : : } JsonPathParseResult;
277 : :
278 : : extern JsonPathParseResult *parsejsonpath(const char *str, int len,
279 : : struct Node *escontext);
280 : :
281 : : extern bool jspConvertRegexFlags(uint32 xflags, int *result,
282 : : struct Node *escontext);
283 : :
284 : :
285 : : /*
286 : : * Evaluation of jsonpath
287 : : */
288 : :
289 : : /* External variable passed into jsonpath. */
290 : : typedef struct JsonPathVariable
291 : : {
292 : : char *name;
293 : : Oid typid;
294 : : int32 typmod;
295 : : Datum value;
296 : : bool isnull;
297 : : } JsonPathVariable;
298 : :
299 : :
300 : : /* SQL/JSON item */
301 : : extern bool JsonPathExists(Datum jb, JsonPath *path, bool *error, List *vars);
302 : : extern Datum JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper,
303 : : bool *empty, bool *error, List *vars);
304 : : extern JsonbValue *JsonPathValue(Datum jb, JsonPath *jp, bool *empty,
305 : : bool *error, List *vars);
306 : :
307 : : extern PGDLLIMPORT const TableFuncRoutine JsonbTableRoutine;
308 : :
309 : : #endif
|