72
72
#include "utils/jsonpath.h"
73
73
74
74
75
+ /* Context for jsonpath encoding. */
76
+ typedef struct JsonPathEncodingContext
77
+ {
78
+ StringInfo buf ;/* output buffer */
79
+ bool ext ;/* PG extensions are enabled? */
80
+ }JsonPathEncodingContext ;
81
+
75
82
static Datum jsonPathFromCstring (char * in ,int len );
76
83
static char * jsonPathToCstring (StringInfo out ,JsonPath * in ,
77
84
int estimated_len );
78
- static int flattenJsonPathParseItem (StringInfo buf ,JsonPathParseItem * item ,
79
- int nestingLevel ,bool insideArraySubscript );
85
+ static int flattenJsonPathParseItem (JsonPathEncodingContext * cxt ,
86
+ JsonPathParseItem * item ,
87
+ int nestingLevel ,
88
+ bool insideArraySubscript );
80
89
static void alignStringInfoInt (StringInfo buf );
81
90
static int32 reserveSpaceForItemPointer (StringInfo buf );
82
91
static void printJsonPathItem (StringInfo buf ,JsonPathItem * v ,bool inKey ,
@@ -167,6 +176,7 @@ jsonpath_send(PG_FUNCTION_ARGS)
167
176
static Datum
168
177
jsonPathFromCstring (char * in ,int len )
169
178
{
179
+ JsonPathEncodingContext cxt ;
170
180
JsonPathParseResult * jsonpath = parsejsonpath (in ,len );
171
181
JsonPath * res ;
172
182
StringInfoData buf ;
@@ -182,13 +192,18 @@ jsonPathFromCstring(char *in, int len)
182
192
errmsg ("invalid input syntax for type %s: \"%s\"" ,"jsonpath" ,
183
193
in )));
184
194
185
- flattenJsonPathParseItem (& buf ,jsonpath -> expr ,0 , false);
195
+ cxt .buf = & buf ;
196
+ cxt .ext = jsonpath -> ext ;
197
+
198
+ flattenJsonPathParseItem (& cxt ,jsonpath -> expr ,0 , false);
186
199
187
200
res = (JsonPath * )buf .data ;
188
201
SET_VARSIZE (res ,buf .len );
189
202
res -> header = JSONPATH_VERSION ;
190
203
if (jsonpath -> lax )
191
204
res -> header |=JSONPATH_LAX ;
205
+ if (jsonpath -> ext )
206
+ res -> header |=JSONPATH_EXT ;
192
207
193
208
PG_RETURN_JSONPATH_P (res );
194
209
}
@@ -212,6 +227,8 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
212
227
}
213
228
enlargeStringInfo (out ,estimated_len );
214
229
230
+ if (in -> header & JSONPATH_EXT )
231
+ appendBinaryStringInfo (out ,"pg " ,3 );
215
232
if (!(in -> header & JSONPATH_LAX ))
216
233
appendBinaryStringInfo (out ,"strict " ,7 );
217
234
@@ -221,14 +238,27 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
221
238
return out -> data ;
222
239
}
223
240
241
+ static void
242
+ checkJsonPathExtensionsEnabled (JsonPathEncodingContext * cxt ,
243
+ JsonPathItemType type )
244
+ {
245
+ if (!cxt -> ext )
246
+ ereport (ERROR ,
247
+ (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
248
+ errmsg ("%s contains extended operators that were not enabled" ,"jsonpath" ),
249
+ errhint ("use \"%s\" modifier at the start of %s string to enable extensions" ,
250
+ "pg" ,"jsonpath" )));
251
+ }
252
+
224
253
/*
225
254
* Recursive function converting given jsonpath parse item and all its
226
255
* children into a binary representation.
227
256
*/
228
257
static int
229
- flattenJsonPathParseItem (StringInfo buf ,JsonPathParseItem * item ,
258
+ flattenJsonPathParseItem (JsonPathEncodingContext * cxt ,JsonPathParseItem * item ,
230
259
int nestingLevel ,bool insideArraySubscript )
231
260
{
261
+ StringInfo buf = cxt -> buf ;
232
262
/* position from beginning of jsonpath data */
233
263
int32 pos = buf -> len - JSONPATH_HDRSZ ;
234
264
int32 chld ;
@@ -296,13 +326,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
296
326
int32 right = reserveSpaceForItemPointer (buf );
297
327
298
328
chld = !item -> value .args .left ?pos :
299
- flattenJsonPathParseItem (buf ,item -> value .args .left ,
329
+ flattenJsonPathParseItem (cxt ,item -> value .args .left ,
300
330
nestingLevel + argNestingLevel ,
301
331
insideArraySubscript );
302
332
* (int32 * ) (buf -> data + left )= chld - pos ;
303
333
304
334
chld = !item -> value .args .right ?pos :
305
- flattenJsonPathParseItem (buf ,item -> value .args .right ,
335
+ flattenJsonPathParseItem (cxt ,item -> value .args .right ,
306
336
nestingLevel + argNestingLevel ,
307
337
insideArraySubscript );
308
338
* (int32 * ) (buf -> data + right )= chld - pos ;
@@ -323,7 +353,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
323
353
item -> value .like_regex .patternlen );
324
354
appendStringInfoChar (buf ,'\0' );
325
355
326
- chld = flattenJsonPathParseItem (buf ,item -> value .like_regex .expr ,
356
+ chld = flattenJsonPathParseItem (cxt ,item -> value .like_regex .expr ,
327
357
nestingLevel ,
328
358
insideArraySubscript );
329
359
* (int32 * ) (buf -> data + offs )= chld - pos ;
@@ -342,7 +372,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
342
372
int32 arg = reserveSpaceForItemPointer (buf );
343
373
344
374
chld = !item -> value .arg ?pos :
345
- flattenJsonPathParseItem (buf ,item -> value .arg ,
375
+ flattenJsonPathParseItem (cxt ,item -> value .arg ,
346
376
nestingLevel + argNestingLevel ,
347
377
insideArraySubscript );
348
378
* (int32 * ) (buf -> data + arg )= chld - pos ;
@@ -384,12 +414,12 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
384
414
int32 * ppos ;
385
415
int32 topos ;
386
416
int32 frompos =
387
- flattenJsonPathParseItem (buf ,
417
+ flattenJsonPathParseItem (cxt ,
388
418
item -> value .array .elems [i ].from ,
389
419
nestingLevel , true)- pos ;
390
420
391
421
if (item -> value .array .elems [i ].to )
392
- topos = flattenJsonPathParseItem (buf ,
422
+ topos = flattenJsonPathParseItem (cxt ,
393
423
item -> value .array .elems [i ].to ,
394
424
nestingLevel , true)- pos ;
395
425
else
@@ -424,7 +454,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
424
454
425
455
if (item -> next )
426
456
{
427
- chld = flattenJsonPathParseItem (buf ,item -> next ,nestingLevel ,
457
+ chld = flattenJsonPathParseItem (cxt ,item -> next ,nestingLevel ,
428
458
insideArraySubscript )- pos ;
429
459
* (int32 * ) (buf -> data + next )= chld ;
430
460
}
@@ -832,7 +862,7 @@ operationPriority(JsonPathItemType op)
832
862
void
833
863
jspInit (JsonPathItem * v ,JsonPath * js )
834
864
{
835
- Assert ((js -> header & ~ JSONPATH_LAX )== JSONPATH_VERSION );
865
+ Assert ((js -> header & JSONPATH_VERSION_MASK )== JSONPATH_VERSION );
836
866
jspInitByBuffer (v ,js -> data ,0 );
837
867
}
838
868