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
0 commit comments