@@ -86,12 +86,16 @@ typedef struct JsonBaseObjectInfo
8686 int id ;
8787} JsonBaseObjectInfo ;
8888
89+ typedef int (* JsonPathVarCallback ) (void * vars , char * varName , int varNameLen ,
90+ JsonbValue * val , JsonbValue * baseObject );
91+
8992/*
9093 * Context of jsonpath execution.
9194 */
9295typedef struct JsonPathExecContext
9396{
94- Jsonb * vars ; /* variables to substitute into jsonpath */
97+ void * vars ; /* variables to substitute into jsonpath */
98+ JsonPathVarCallback getVar ;
9599 JsonbValue * root ; /* for $ evaluation */
96100 JsonbValue * current ; /* for @ evaluation */
97101 JsonBaseObjectInfo baseObject ; /* "base object" for .keyvalue()
@@ -173,7 +177,8 @@ typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
173177 void * param );
174178typedef Numeric (* BinaryArithmFunc ) (Numeric num1 , Numeric num2 , bool * error );
175179
176- static JsonPathExecResult executeJsonPath (JsonPath * path , Jsonb * vars ,
180+ static JsonPathExecResult executeJsonPath (JsonPath * path , void * vars ,
181+ JsonPathVarCallback getVar ,
177182 Jsonb * json , bool throwErrors ,
178183 JsonValueList * result , bool useTz );
179184static JsonPathExecResult executeItem (JsonPathExecContext * cxt ,
@@ -225,7 +230,10 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt,
225230static void getJsonPathItem (JsonPathExecContext * cxt , JsonPathItem * item ,
226231 JsonbValue * value );
227232static 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 );
229237static int JsonbArraySize (JsonbValue * jb );
230238static JsonPathBool executeComparison (JsonPathItem * cmp , JsonbValue * lv ,
231239 JsonbValue * rv , void * p );
@@ -283,7 +291,8 @@ jsonb_path_exists_internal(FunctionCallInfo fcinfo, bool tz)
283291 silent = PG_GETARG_BOOL (3 );
284292 }
285293
286- res = executeJsonPath (jp , vars , jb , !silent , NULL , tz );
294+ res = executeJsonPath (jp , vars , getJsonPathVariableFromJsonb ,
295+ jb , !silent , NULL , tz );
287296
288297 PG_FREE_IF_COPY (jb , 0 );
289298 PG_FREE_IF_COPY (jp , 1 );
@@ -338,7 +347,8 @@ jsonb_path_match_internal(FunctionCallInfo fcinfo, bool tz)
338347 silent = PG_GETARG_BOOL (3 );
339348 }
340349
341- (void ) executeJsonPath (jp , vars , jb , !silent , & found , tz );
350+ (void ) executeJsonPath (jp , vars , getJsonPathVariableFromJsonb ,
351+ jb , !silent , & found , tz );
342352
343353 PG_FREE_IF_COPY (jb , 0 );
344354 PG_FREE_IF_COPY (jp , 1 );
@@ -416,7 +426,8 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)
416426 vars = PG_GETARG_JSONB_P_COPY (2 );
417427 silent = PG_GETARG_BOOL (3 );
418428
419- (void ) executeJsonPath (jp , vars , jb , !silent , & found , tz );
429+ (void ) executeJsonPath (jp , vars , getJsonPathVariableFromJsonb ,
430+ jb , !silent , & found , tz );
420431
421432 funcctx -> user_fctx = JsonValueListGetList (& found );
422433
@@ -463,7 +474,8 @@ jsonb_path_query_array_internal(FunctionCallInfo fcinfo, bool tz)
463474 Jsonb * vars = PG_GETARG_JSONB_P (2 );
464475 bool silent = PG_GETARG_BOOL (3 );
465476
466- (void ) executeJsonPath (jp , vars , jb , !silent , & found , tz );
477+ (void ) executeJsonPath (jp , vars , getJsonPathVariableFromJsonb ,
478+ jb , !silent , & found , tz );
467479
468480 PG_RETURN_JSONB_P (JsonbValueToJsonb (wrapItemsInArray (& found )));
469481}
@@ -494,7 +506,8 @@ jsonb_path_query_first_internal(FunctionCallInfo fcinfo, bool tz)
494506 Jsonb * vars = PG_GETARG_JSONB_P (2 );
495507 bool silent = PG_GETARG_BOOL (3 );
496508
497- (void ) executeJsonPath (jp , vars , jb , !silent , & found , tz );
509+ (void ) executeJsonPath (jp , vars , getJsonPathVariableFromJsonb ,
510+ jb , !silent , & found , tz );
498511
499512 if (JsonValueListLength (& found ) >= 1 )
500513 PG_RETURN_JSONB_P (JsonbValueToJsonb (JsonValueListHead (& found )));
@@ -536,8 +549,9 @@ jsonb_path_query_first_tz(PG_FUNCTION_ARGS)
536549 * In other case it tries to find all the satisfied result items.
537550 */
538551static 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 )
541555{
542556 JsonPathExecContext cxt ;
543557 JsonPathExecResult res ;
@@ -549,22 +563,16 @@ executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors,
549563 if (!JsonbExtractScalar (& json -> root , & jbv ))
550564 JsonbInitBinary (& jbv , json );
551565
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-
560566 cxt .vars = vars ;
567+ cxt .getVar = getVar ;
561568 cxt .laxMode = (path -> header & JSONPATH_LAX ) != 0 ;
562569 cxt .ignoreStructuralErrors = cxt .laxMode ;
563570 cxt .root = & jbv ;
564571 cxt .current = & jbv ;
565572 cxt .baseObject .jbc = NULL ;
566573 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 );
568576 cxt .innermostArraySize = -1 ;
569577 cxt .throwErrors = throwErrors ;
570578 cxt .useTz = useTz ;
@@ -2092,7 +2100,7 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
20922100 & value -> val .string .len );
20932101 break ;
20942102 case jpiVariable :
2095- getJsonPathVariable (cxt , item , cxt -> vars , value );
2103+ getJsonPathVariable (cxt , item , value );
20962104 return ;
20972105 default :
20982106 elog (ERROR , "unexpected jsonpath item type" );
@@ -2104,42 +2112,63 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
21042112 */
21052113static void
21062114getJsonPathVariable (JsonPathExecContext * cxt , JsonPathItem * variable ,
2107- Jsonb * vars , JsonbValue * value )
2115+ JsonbValue * value )
21082116{
21092117 char * varName ;
21102118 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 ;
21112142 JsonbValue tmp ;
21122143 JsonbValue * v ;
21132144
2114- if (!vars )
2145+ if (!varName )
21152146 {
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 */
21182156 }
21192157
2120- Assert (variable -> type == jpiVariable );
2121- varName = jspGetString (variable , & varNameLength );
21222158 tmp .type = jbvString ;
21232159 tmp .val .string .val = varName ;
21242160 tmp .val .string .len = varNameLength ;
21252161
21262162 v = findJsonbValueFromContainer (& vars -> root , JB_FOBJECT , & tmp );
21272163
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 );
21402169
2141- JsonbInitBinary (& tmp , vars );
2142- setBaseObject ( cxt , & tmp , 1 ) ;
2170+ JsonbInitBinary (baseObject , vars );
2171+ return 1 ;
21432172}
21442173
21452174/**************** Support functions for JsonPath execution *****************/
0 commit comments