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