66
66
#include "funcapi.h"
67
67
#include "lib/stringinfo.h"
68
68
#include "libpq/pqformat.h"
69
+ #include "nodes/miscnodes.h"
69
70
#include "miscadmin.h"
70
71
#include "utils/builtins.h"
71
72
#include "utils/json.h"
72
73
#include "utils/jsonpath.h"
73
74
74
75
75
- static Datum jsonPathFromCstring (char * in , int len );
76
+ static Datum jsonPathFromCstring (char * in , int len , struct Node * escontext );
76
77
static char * jsonPathToCstring (StringInfo out , JsonPath * in ,
77
78
int estimated_len );
78
- static int flattenJsonPathParseItem (StringInfo buf , JsonPathParseItem * item ,
79
+ static bool flattenJsonPathParseItem (StringInfo buf , int * result ,
80
+ struct Node * escontext ,
81
+ JsonPathParseItem * item ,
79
82
int nestingLevel , bool insideArraySubscript );
80
83
static void alignStringInfoInt (StringInfo buf );
81
84
static int32 reserveSpaceForItemPointer (StringInfo buf );
@@ -95,7 +98,7 @@ jsonpath_in(PG_FUNCTION_ARGS)
95
98
char * in = PG_GETARG_CSTRING (0 );
96
99
int len = strlen (in );
97
100
98
- return jsonPathFromCstring (in , len );
101
+ return jsonPathFromCstring (in , len , fcinfo -> context );
99
102
}
100
103
101
104
/*
@@ -119,7 +122,7 @@ jsonpath_recv(PG_FUNCTION_ARGS)
119
122
else
120
123
elog (ERROR , "unsupported jsonpath version number: %d" , version );
121
124
122
- return jsonPathFromCstring (str , nbytes );
125
+ return jsonPathFromCstring (str , nbytes , NULL );
123
126
}
124
127
125
128
/*
@@ -165,24 +168,29 @@ jsonpath_send(PG_FUNCTION_ARGS)
165
168
* representation of jsonpath.
166
169
*/
167
170
static Datum
168
- jsonPathFromCstring (char * in , int len )
171
+ jsonPathFromCstring (char * in , int len , struct Node * escontext )
169
172
{
170
- JsonPathParseResult * jsonpath = parsejsonpath (in , len );
173
+ JsonPathParseResult * jsonpath = parsejsonpath (in , len , escontext );
171
174
JsonPath * res ;
172
175
StringInfoData buf ;
173
176
174
- initStringInfo (& buf );
175
- enlargeStringInfo (& buf , 4 * len /* estimation */ );
176
-
177
- appendStringInfoSpaces (& buf , JSONPATH_HDRSZ );
177
+ if (SOFT_ERROR_OCCURRED (escontext ))
178
+ return (Datum ) 0 ;
178
179
179
180
if (!jsonpath )
180
- ereport ( ERROR ,
181
+ ereturn ( escontext , ( Datum ) 0 ,
181
182
(errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
182
183
errmsg ("invalid input syntax for type %s: \"%s\"" , "jsonpath" ,
183
184
in )));
184
185
185
- flattenJsonPathParseItem (& buf , jsonpath -> expr , 0 , false);
186
+ initStringInfo (& buf );
187
+ enlargeStringInfo (& buf , 4 * len /* estimation */ );
188
+
189
+ appendStringInfoSpaces (& buf , JSONPATH_HDRSZ );
190
+
191
+ if (!flattenJsonPathParseItem (& buf , NULL , escontext ,
192
+ jsonpath -> expr , 0 , false))
193
+ return (Datum ) 0 ;
186
194
187
195
res = (JsonPath * ) buf .data ;
188
196
SET_VARSIZE (res , buf .len );
@@ -225,9 +233,10 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
225
233
* Recursive function converting given jsonpath parse item and all its
226
234
* children into a binary representation.
227
235
*/
228
- static int
229
- flattenJsonPathParseItem (StringInfo buf , JsonPathParseItem * item ,
230
- int nestingLevel , bool insideArraySubscript )
236
+ static bool
237
+ flattenJsonPathParseItem (StringInfo buf , int * result , struct Node * escontext ,
238
+ JsonPathParseItem * item , int nestingLevel ,
239
+ bool insideArraySubscript )
231
240
{
232
241
/* position from beginning of jsonpath data */
233
242
int32 pos = buf -> len - JSONPATH_HDRSZ ;
@@ -295,16 +304,22 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
295
304
int32 left = reserveSpaceForItemPointer (buf );
296
305
int32 right = reserveSpaceForItemPointer (buf );
297
306
298
- chld = !item -> value .args .left ? pos :
299
- flattenJsonPathParseItem (buf , item -> value .args .left ,
300
- nestingLevel + argNestingLevel ,
301
- insideArraySubscript );
307
+ if (!item -> value .args .left )
308
+ chld = pos ;
309
+ else if (! flattenJsonPathParseItem (buf , & chld , escontext ,
310
+ item -> value .args .left ,
311
+ nestingLevel + argNestingLevel ,
312
+ insideArraySubscript ))
313
+ return false;
302
314
* (int32 * ) (buf -> data + left ) = chld - pos ;
303
315
304
- chld = !item -> value .args .right ? pos :
305
- flattenJsonPathParseItem (buf , item -> value .args .right ,
306
- nestingLevel + argNestingLevel ,
307
- insideArraySubscript );
316
+ if (!item -> value .args .right )
317
+ chld = pos ;
318
+ else if (! flattenJsonPathParseItem (buf , & chld , escontext ,
319
+ item -> value .args .right ,
320
+ nestingLevel + argNestingLevel ,
321
+ insideArraySubscript ))
322
+ return false;
308
323
* (int32 * ) (buf -> data + right ) = chld - pos ;
309
324
}
310
325
break ;
@@ -323,9 +338,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
323
338
item -> value .like_regex .patternlen );
324
339
appendStringInfoChar (buf , '\0' );
325
340
326
- chld = flattenJsonPathParseItem (buf , item -> value .like_regex .expr ,
327
- nestingLevel ,
328
- insideArraySubscript );
341
+ if (! flattenJsonPathParseItem (buf , & chld , escontext ,
342
+ item -> value .like_regex .expr ,
343
+ nestingLevel ,
344
+ insideArraySubscript ))
345
+ return false;
329
346
* (int32 * ) (buf -> data + offs ) = chld - pos ;
330
347
}
331
348
break ;
@@ -341,10 +358,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
341
358
{
342
359
int32 arg = reserveSpaceForItemPointer (buf );
343
360
344
- chld = !item -> value .arg ? pos :
345
- flattenJsonPathParseItem (buf , item -> value .arg ,
346
- nestingLevel + argNestingLevel ,
347
- insideArraySubscript );
361
+ if (!item -> value .arg )
362
+ chld = pos ;
363
+ else if (! flattenJsonPathParseItem (buf , & chld , escontext ,
364
+ item -> value .arg ,
365
+ nestingLevel + argNestingLevel ,
366
+ insideArraySubscript ))
367
+ return false;
348
368
* (int32 * ) (buf -> data + arg ) = chld - pos ;
349
369
}
350
370
break ;
@@ -357,13 +377,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
357
377
break ;
358
378
case jpiCurrent :
359
379
if (nestingLevel <= 0 )
360
- ereport ( ERROR ,
380
+ ereturn ( escontext , false ,
361
381
(errcode (ERRCODE_SYNTAX_ERROR ),
362
382
errmsg ("@ is not allowed in root expressions" )));
363
383
break ;
364
384
case jpiLast :
365
385
if (!insideArraySubscript )
366
- ereport ( ERROR ,
386
+ ereturn ( escontext , false ,
367
387
(errcode (ERRCODE_SYNTAX_ERROR ),
368
388
errmsg ("LAST is allowed only in array subscripts" )));
369
389
break ;
@@ -383,15 +403,22 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
383
403
{
384
404
int32 * ppos ;
385
405
int32 topos ;
386
- int32 frompos =
387
- flattenJsonPathParseItem (buf ,
388
- item -> value .array .elems [i ].from ,
389
- nestingLevel , true) - pos ;
406
+ int32 frompos ;
407
+
408
+ if (! flattenJsonPathParseItem (buf , & frompos , escontext ,
409
+ item -> value .array .elems [i ].from ,
410
+ nestingLevel , true))
411
+ return false;
412
+ frompos -= pos ;
390
413
391
414
if (item -> value .array .elems [i ].to )
392
- topos = flattenJsonPathParseItem (buf ,
393
- item -> value .array .elems [i ].to ,
394
- nestingLevel , true) - pos ;
415
+ {
416
+ if (! flattenJsonPathParseItem (buf , & topos , escontext ,
417
+ item -> value .array .elems [i ].to ,
418
+ nestingLevel , true))
419
+ return false;
420
+ topos -= pos ;
421
+ }
395
422
else
396
423
topos = 0 ;
397
424
@@ -424,12 +451,17 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
424
451
425
452
if (item -> next )
426
453
{
427
- chld = flattenJsonPathParseItem (buf , item -> next , nestingLevel ,
428
- insideArraySubscript ) - pos ;
454
+ if (! flattenJsonPathParseItem (buf , & chld , escontext ,
455
+ item -> next , nestingLevel ,
456
+ insideArraySubscript ))
457
+ return false;
458
+ chld -= pos ;
429
459
* (int32 * ) (buf -> data + next ) = chld ;
430
460
}
431
461
432
- return pos ;
462
+ if (result )
463
+ * result = pos ;
464
+ return true;
433
465
}
434
466
435
467
/*
0 commit comments