@@ -86,12 +86,16 @@ typedef struct JsonBaseObjectInfo
86
86
int id ;
87
87
}JsonBaseObjectInfo ;
88
88
89
+ typedef int (* JsonPathVarCallback ) (void * vars ,char * varName ,int varNameLen ,
90
+ JsonbValue * val ,JsonbValue * baseObject );
91
+
89
92
/*
90
93
* Context of jsonpath execution.
91
94
*/
92
95
typedef struct JsonPathExecContext
93
96
{
94
- Jsonb * vars ;/* variables to substitute into jsonpath */
97
+ void * vars ;/* variables to substitute into jsonpath */
98
+ JsonPathVarCallback getVar ;
95
99
JsonbValue * root ;/* for $ evaluation */
96
100
JsonbValue * current ;/* for @ evaluation */
97
101
JsonBaseObjectInfo baseObject ;/* "base object" for .keyvalue()
@@ -173,7 +177,8 @@ typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
173
177
void * param );
174
178
typedef Numeric (* BinaryArithmFunc ) (Numeric num1 ,Numeric num2 ,bool * error );
175
179
176
- static JsonPathExecResult executeJsonPath (JsonPath * path ,Jsonb * vars ,
180
+ static JsonPathExecResult executeJsonPath (JsonPath * path ,void * vars ,
181
+ JsonPathVarCallback getVar ,
177
182
Jsonb * json ,bool throwErrors ,
178
183
JsonValueList * result ,bool useTz );
179
184
static JsonPathExecResult executeItem (JsonPathExecContext * cxt ,
@@ -225,7 +230,10 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt,
225
230
static void getJsonPathItem (JsonPathExecContext * cxt ,JsonPathItem * item ,
226
231
JsonbValue * value );
227
232
static void getJsonPathVariable (JsonPathExecContext * cxt ,
228
- JsonPathItem * variable ,Jsonb * vars ,JsonbValue * value );
233
+ JsonPathItem * variable ,JsonbValue * value );
234
+ static int getJsonPathVariableFromJsonb (void * varsJsonb ,char * varName ,
235
+ int varNameLen ,JsonbValue * val ,
236
+ JsonbValue * baseObject );
229
237
static int JsonbArraySize (JsonbValue * jb );
230
238
static JsonPathBool executeComparison (JsonPathItem * cmp ,JsonbValue * lv ,
231
239
JsonbValue * rv ,void * p );
@@ -283,7 +291,8 @@ jsonb_path_exists_internal(FunctionCallInfo fcinfo, bool tz)
283
291
silent = PG_GETARG_BOOL (3 );
284
292
}
285
293
286
- res = executeJsonPath (jp ,vars ,jb , !silent ,NULL ,tz );
294
+ res = executeJsonPath (jp ,vars ,getJsonPathVariableFromJsonb ,
295
+ jb , !silent ,NULL ,tz );
287
296
288
297
PG_FREE_IF_COPY (jb ,0 );
289
298
PG_FREE_IF_COPY (jp ,1 );
@@ -338,7 +347,8 @@ jsonb_path_match_internal(FunctionCallInfo fcinfo, bool tz)
338
347
silent = PG_GETARG_BOOL (3 );
339
348
}
340
349
341
- (void )executeJsonPath (jp ,vars ,jb , !silent ,& found ,tz );
350
+ (void )executeJsonPath (jp ,vars ,getJsonPathVariableFromJsonb ,
351
+ jb , !silent ,& found ,tz );
342
352
343
353
PG_FREE_IF_COPY (jb ,0 );
344
354
PG_FREE_IF_COPY (jp ,1 );
@@ -416,7 +426,8 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)
416
426
vars = PG_GETARG_JSONB_P_COPY (2 );
417
427
silent = PG_GETARG_BOOL (3 );
418
428
419
- (void )executeJsonPath (jp ,vars ,jb , !silent ,& found ,tz );
429
+ (void )executeJsonPath (jp ,vars ,getJsonPathVariableFromJsonb ,
430
+ jb , !silent ,& found ,tz );
420
431
421
432
funcctx -> user_fctx = JsonValueListGetList (& found );
422
433
@@ -463,7 +474,8 @@ jsonb_path_query_array_internal(FunctionCallInfo fcinfo, bool tz)
463
474
Jsonb * vars = PG_GETARG_JSONB_P (2 );
464
475
bool silent = PG_GETARG_BOOL (3 );
465
476
466
- (void )executeJsonPath (jp ,vars ,jb , !silent ,& found ,tz );
477
+ (void )executeJsonPath (jp ,vars ,getJsonPathVariableFromJsonb ,
478
+ jb , !silent ,& found ,tz );
467
479
468
480
PG_RETURN_JSONB_P (JsonbValueToJsonb (wrapItemsInArray (& found )));
469
481
}
@@ -494,7 +506,8 @@ jsonb_path_query_first_internal(FunctionCallInfo fcinfo, bool tz)
494
506
Jsonb * vars = PG_GETARG_JSONB_P (2 );
495
507
bool silent = PG_GETARG_BOOL (3 );
496
508
497
- (void )executeJsonPath (jp ,vars ,jb , !silent ,& found ,tz );
509
+ (void )executeJsonPath (jp ,vars ,getJsonPathVariableFromJsonb ,
510
+ jb , !silent ,& found ,tz );
498
511
499
512
if (JsonValueListLength (& found ) >=1 )
500
513
PG_RETURN_JSONB_P (JsonbValueToJsonb (JsonValueListHead (& found )));
@@ -536,8 +549,9 @@ jsonb_path_query_first_tz(PG_FUNCTION_ARGS)
536
549
* In other case it tries to find all the satisfied result items.
537
550
*/
538
551
static JsonPathExecResult
539
- executeJsonPath (JsonPath * path ,Jsonb * vars ,Jsonb * json ,bool throwErrors ,
540
- JsonValueList * result ,bool useTz )
552
+ executeJsonPath (JsonPath * path ,void * vars ,JsonPathVarCallback getVar ,
553
+ Jsonb * json ,bool throwErrors ,JsonValueList * result ,
554
+ bool useTz )
541
555
{
542
556
JsonPathExecContext cxt ;
543
557
JsonPathExecResult res ;
@@ -549,22 +563,16 @@ executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors,
549
563
if (!JsonbExtractScalar (& json -> root ,& jbv ))
550
564
JsonbInitBinary (& jbv ,json );
551
565
552
- if (vars && !JsonContainerIsObject (& vars -> root ))
553
- {
554
- ereport (ERROR ,
555
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
556
- errmsg ("\"vars\" argument is not an object" ),
557
- errdetail ("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." )));
558
- }
559
-
560
566
cxt .vars = vars ;
567
+ cxt .getVar = getVar ;
561
568
cxt .laxMode = (path -> header & JSONPATH_LAX )!= 0 ;
562
569
cxt .ignoreStructuralErrors = cxt .laxMode ;
563
570
cxt .root = & jbv ;
564
571
cxt .current = & jbv ;
565
572
cxt .baseObject .jbc = NULL ;
566
573
cxt .baseObject .id = 0 ;
567
- cxt .lastGeneratedObjectId = vars ?2 :1 ;
574
+ /* 1 + number of base objects in vars */
575
+ cxt .lastGeneratedObjectId = 1 + getVar (vars ,NULL ,0 ,NULL ,NULL );
568
576
cxt .innermostArraySize = -1 ;
569
577
cxt .throwErrors = throwErrors ;
570
578
cxt .useTz = useTz ;
@@ -2092,7 +2100,7 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
2092
2100
& value -> val .string .len );
2093
2101
break ;
2094
2102
case jpiVariable :
2095
- getJsonPathVariable (cxt ,item ,cxt -> vars , value );
2103
+ getJsonPathVariable (cxt ,item ,value );
2096
2104
return ;
2097
2105
default :
2098
2106
elog (ERROR ,"unexpected jsonpath item type" );
@@ -2104,42 +2112,63 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
2104
2112
*/
2105
2113
static void
2106
2114
getJsonPathVariable (JsonPathExecContext * cxt ,JsonPathItem * variable ,
2107
- Jsonb * vars , JsonbValue * value )
2115
+ JsonbValue * value )
2108
2116
{
2109
2117
char * varName ;
2110
2118
int varNameLength ;
2119
+ JsonbValue baseObject ;
2120
+ int baseObjectId ;
2121
+
2122
+ Assert (variable -> type == jpiVariable );
2123
+ varName = jspGetString (variable ,& varNameLength );
2124
+
2125
+ if (!cxt -> vars ||
2126
+ (baseObjectId = cxt -> getVar (cxt -> vars ,varName ,varNameLength ,value ,
2127
+ & baseObject ))< 0 )
2128
+ ereport (ERROR ,
2129
+ (errcode (ERRCODE_UNDEFINED_OBJECT ),
2130
+ errmsg ("could not find jsonpath variable \"%s\"" ,
2131
+ pnstrdup (varName ,varNameLength ))));
2132
+
2133
+ if (baseObjectId > 0 )
2134
+ setBaseObject (cxt ,& baseObject ,baseObjectId );
2135
+ }
2136
+
2137
+ static int
2138
+ getJsonPathVariableFromJsonb (void * varsJsonb ,char * varName ,int varNameLength ,
2139
+ JsonbValue * value ,JsonbValue * baseObject )
2140
+ {
2141
+ Jsonb * vars = varsJsonb ;
2111
2142
JsonbValue tmp ;
2112
2143
JsonbValue * v ;
2113
2144
2114
- if (!vars )
2145
+ if (!varName )
2115
2146
{
2116
- value -> type = jbvNull ;
2117
- return ;
2147
+ if (vars && !JsonContainerIsObject (& vars -> root ))
2148
+ {
2149
+ ereport (ERROR ,
2150
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
2151
+ errmsg ("\"vars\" argument is not an object" ),
2152
+ errdetail ("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." )));
2153
+ }
2154
+
2155
+ return vars ?1 :0 ;/* count of base objects */
2118
2156
}
2119
2157
2120
- Assert (variable -> type == jpiVariable );
2121
- varName = jspGetString (variable ,& varNameLength );
2122
2158
tmp .type = jbvString ;
2123
2159
tmp .val .string .val = varName ;
2124
2160
tmp .val .string .len = varNameLength ;
2125
2161
2126
2162
v = findJsonbValueFromContainer (& vars -> root ,JB_FOBJECT ,& tmp );
2127
2163
2128
- if (v )
2129
- {
2130
- * value = * v ;
2131
- pfree (v );
2132
- }
2133
- else
2134
- {
2135
- ereport (ERROR ,
2136
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
2137
- errmsg ("could not find jsonpath variable \"%s\"" ,
2138
- pnstrdup (varName ,varNameLength ))));
2139
- }
2164
+ if (!v )
2165
+ return -1 ;
2166
+
2167
+ * value = * v ;
2168
+ pfree (v );
2140
2169
2141
- JsonbInitBinary (& tmp ,vars );
2142
- setBaseObject ( cxt , & tmp , 1 ) ;
2170
+ JsonbInitBinary (baseObject ,vars );
2171
+ return 1 ;
2143
2172
}
2144
2173
2145
2174
/**************** Support functions for JsonPath execution *****************/