@@ -42,6 +42,9 @@ static inline JsonPathExecResult recursiveExecute(JsonPathExecContext *cxt,
4242 JsonPathItem * jsp , JsonbValue * jb ,
4343 JsonValueList * found );
4444
45+ static inline JsonPathExecResult recursiveExecuteBool (JsonPathExecContext * cxt ,
46+ JsonPathItem * jsp , JsonbValue * jb );
47+
4548static inline JsonPathExecResult recursiveExecuteUnwrap (JsonPathExecContext * cxt ,
4649 JsonPathItem * jsp , JsonbValue * jb , JsonValueList * found );
4750
@@ -1239,6 +1242,34 @@ tryToParseDatetime(const char *template, text *datetime,
12391242 return ok ;
12401243}
12411244
1245+ static inline JsonPathExecResult
1246+ appendBoolResult (JsonPathExecContext * cxt , JsonPathItem * jsp ,
1247+ JsonValueList * found , JsonPathExecResult res , bool needBool )
1248+ {
1249+ JsonPathItem next ;
1250+ JsonbValue jbv ;
1251+ bool hasNext = jspGetNext (jsp , & next );
1252+
1253+ if (needBool )
1254+ {
1255+ Assert (!hasNext );
1256+ return res ;
1257+ }
1258+
1259+ if (!found && !hasNext )
1260+ return jperOk ; /* found singleton boolean value */
1261+
1262+ if (jperIsError (res ))
1263+ jbv .type = jbvNull ;
1264+ else
1265+ {
1266+ jbv .type = jbvBool ;
1267+ jbv .val .boolean = res == jperOk ;
1268+ }
1269+
1270+ return recursiveExecuteNext (cxt , jsp , & next , & jbv , found , true);
1271+ }
1272+
12421273/*
12431274 * Main executor function: walks on jsonpath structure and tries to find
12441275 * correspoding parts of jsonb. Note, jsonb and jsonpath values should be
@@ -1251,7 +1282,7 @@ tryToParseDatetime(const char *template, text *datetime,
12511282 */
12521283static JsonPathExecResult
12531284recursiveExecuteNoUnwrap (JsonPathExecContext * cxt , JsonPathItem * jsp ,
1254- JsonbValue * jb , JsonValueList * found )
1285+ JsonbValue * jb , JsonValueList * found , bool needBool )
12551286{
12561287 JsonPathItem elem ;
12571288 JsonPathExecResult res = jperNotFound ;
@@ -1262,7 +1293,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12621293 switch (jsp -> type ) {
12631294 case jpiAnd :
12641295 jspGetLeftArg (jsp , & elem );
1265- res = recursiveExecute (cxt , & elem , jb , NULL );
1296+ res = recursiveExecuteBool (cxt , & elem , jb );
12661297 if (res != jperNotFound )
12671298 {
12681299 JsonPathExecResult res2 ;
@@ -1273,27 +1304,29 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12731304 */
12741305
12751306 jspGetRightArg (jsp , & elem );
1276- res2 = recursiveExecute (cxt , & elem , jb , NULL );
1307+ res2 = recursiveExecuteBool (cxt , & elem , jb );
12771308
12781309 res = (res2 == jperOk ) ? res : res2 ;
12791310 }
1311+ res = appendBoolResult (cxt , jsp , found , res , needBool );
12801312 break ;
12811313 case jpiOr :
12821314 jspGetLeftArg (jsp , & elem );
1283- res = recursiveExecute (cxt , & elem , jb , NULL );
1315+ res = recursiveExecuteBool (cxt , & elem , jb );
12841316 if (res != jperOk )
12851317 {
12861318 JsonPathExecResult res2 ;
12871319
12881320 jspGetRightArg (jsp , & elem );
1289- res2 = recursiveExecute (cxt , & elem , jb , NULL );
1321+ res2 = recursiveExecuteBool (cxt , & elem , jb );
12901322
12911323 res = (res2 == jperNotFound ) ? res : res2 ;
12921324 }
1325+ res = appendBoolResult (cxt , jsp , found , res , needBool );
12931326 break ;
12941327 case jpiNot :
12951328 jspGetArg (jsp , & elem );
1296- switch ((res = recursiveExecute (cxt , & elem , jb , NULL )))
1329+ switch ((res = recursiveExecuteBool (cxt , & elem , jb )))
12971330 {
12981331 case jperOk :
12991332 res = jperNotFound ;
@@ -1304,11 +1337,13 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13041337 default :
13051338 break ;
13061339 }
1340+ res = appendBoolResult (cxt , jsp , found , res , needBool );
13071341 break ;
13081342 case jpiIsUnknown :
13091343 jspGetArg (jsp , & elem );
1310- res = recursiveExecute (cxt , & elem , jb , NULL );
1344+ res = recursiveExecuteBool (cxt , & elem , jb );
13111345 res = jperIsError (res ) ? jperOk : jperNotFound ;
1346+ res = appendBoolResult (cxt , jsp , found , res , needBool );
13121347 break ;
13131348 case jpiKey :
13141349 if (JsonbType (jb ) == jbvObject )
@@ -1575,6 +1610,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15751610 case jpiLessOrEqual :
15761611 case jpiGreaterOrEqual :
15771612 res = executeExpr (cxt , jsp , jb );
1613+ res = appendBoolResult (cxt , jsp , found , res , needBool );
15781614 break ;
15791615 case jpiAdd :
15801616 case jpiSub :
@@ -1589,7 +1625,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15891625 break ;
15901626 case jpiFilter :
15911627 jspGetArg (jsp , & elem );
1592- res = recursiveExecute (cxt , & elem , jb , NULL );
1628+ res = recursiveExecuteBool (cxt , & elem , jb );
15931629 if (res != jperOk )
15941630 res = jperNotFound ;
15951631 else
@@ -1638,6 +1674,8 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16381674 if (!jperIsError (res ))
16391675 res = JsonValueListIsEmpty (& vals ) ? jperNotFound : jperOk ;
16401676 }
1677+
1678+ res = appendBoolResult (cxt , jsp , found , res , needBool );
16411679 break ;
16421680 case jpiNull :
16431681 case jpiBool :
@@ -1973,9 +2011,11 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
19732011 break ;
19742012 case jpiStartsWith :
19752013 res = executeStartsWithPredicate (cxt , jsp , jb );
2014+ res = appendBoolResult (cxt , jsp , found , res , needBool );
19762015 break ;
19772016 case jpiLikeRegex :
19782017 res = executeLikeRegexPredicate (cxt , jsp , jb );
2018+ res = appendBoolResult (cxt , jsp , found , res , needBool );
19792019 break ;
19802020 default :
19812021 elog (ERROR ,"2Wrong state: %d" , jsp -> type );
@@ -1997,7 +2037,7 @@ recursiveExecuteUnwrapArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
19972037
19982038 for (; elem < last ; elem ++ )
19992039 {
2000- res = recursiveExecuteNoUnwrap (cxt , jsp , elem , found );
2040+ res = recursiveExecuteNoUnwrap (cxt , jsp , elem , found , false );
20012041
20022042 if (jperIsError (res ))
20032043 break ;
@@ -2017,7 +2057,7 @@ recursiveExecuteUnwrapArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
20172057 {
20182058 if (tok == WJB_ELEM )
20192059 {
2020- res = recursiveExecuteNoUnwrap (cxt , jsp , & v , found );
2060+ res = recursiveExecuteNoUnwrap (cxt , jsp , & v , found , false );
20212061 if (jperIsError (res ))
20222062 break ;
20232063 if (res == jperOk && !found )
@@ -2036,7 +2076,7 @@ recursiveExecuteUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
20362076 if (cxt -> lax && JsonbType (jb ) == jbvArray )
20372077 return recursiveExecuteUnwrapArray (cxt , jsp , jb , found );
20382078
2039- return recursiveExecuteNoUnwrap (cxt , jsp , jb , found );
2079+ return recursiveExecuteNoUnwrap (cxt , jsp , jb , found , false );
20402080}
20412081
20422082static inline JsonbValue *
@@ -2090,7 +2130,39 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
20902130 }
20912131 }
20922132
2093- return recursiveExecuteNoUnwrap (cxt , jsp , jb , found );
2133+ return recursiveExecuteNoUnwrap (cxt , jsp , jb , found , false);
2134+ }
2135+
2136+ static inline JsonPathExecResult
2137+ recursiveExecuteBool (JsonPathExecContext * cxt , JsonPathItem * jsp ,
2138+ JsonbValue * jb )
2139+ {
2140+ if (jspHasNext (jsp ))
2141+ elog (ERROR , "boolean jsonpath item can not have next item" );
2142+
2143+ switch (jsp -> type )
2144+ {
2145+ case jpiAnd :
2146+ case jpiOr :
2147+ case jpiNot :
2148+ case jpiIsUnknown :
2149+ case jpiEqual :
2150+ case jpiNotEqual :
2151+ case jpiGreater :
2152+ case jpiGreaterOrEqual :
2153+ case jpiLess :
2154+ case jpiLessOrEqual :
2155+ case jpiExists :
2156+ case jpiStartsWith :
2157+ case jpiLikeRegex :
2158+ break ;
2159+
2160+ default :
2161+ elog (ERROR , "invalid boolean jsonpath item type: %d" , jsp -> type );
2162+ break ;
2163+ }
2164+
2165+ return recursiveExecuteNoUnwrap (cxt , jsp , jb , NULL , true);
20942166}
20952167
20962168/*
0 commit comments