@@ -42,6 +42,9 @@ static inline JsonPathExecResult recursiveExecute(JsonPathExecContext *cxt,
42
42
JsonPathItem * jsp , JsonbValue * jb ,
43
43
JsonValueList * found );
44
44
45
+ static inline JsonPathExecResult recursiveExecuteBool (JsonPathExecContext * cxt ,
46
+ JsonPathItem * jsp , JsonbValue * jb );
47
+
45
48
static inline JsonPathExecResult recursiveExecuteUnwrap (JsonPathExecContext * cxt ,
46
49
JsonPathItem * jsp , JsonbValue * jb , JsonValueList * found );
47
50
@@ -1239,6 +1242,34 @@ tryToParseDatetime(const char *template, text *datetime,
1239
1242
return ok ;
1240
1243
}
1241
1244
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
+
1242
1273
/*
1243
1274
* Main executor function: walks on jsonpath structure and tries to find
1244
1275
* correspoding parts of jsonb. Note, jsonb and jsonpath values should be
@@ -1251,7 +1282,7 @@ tryToParseDatetime(const char *template, text *datetime,
1251
1282
*/
1252
1283
static JsonPathExecResult
1253
1284
recursiveExecuteNoUnwrap (JsonPathExecContext * cxt , JsonPathItem * jsp ,
1254
- JsonbValue * jb , JsonValueList * found )
1285
+ JsonbValue * jb , JsonValueList * found , bool needBool )
1255
1286
{
1256
1287
JsonPathItem elem ;
1257
1288
JsonPathExecResult res = jperNotFound ;
@@ -1262,7 +1293,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1262
1293
switch (jsp -> type ) {
1263
1294
case jpiAnd :
1264
1295
jspGetLeftArg (jsp , & elem );
1265
- res = recursiveExecute (cxt , & elem , jb , NULL );
1296
+ res = recursiveExecuteBool (cxt , & elem , jb );
1266
1297
if (res != jperNotFound )
1267
1298
{
1268
1299
JsonPathExecResult res2 ;
@@ -1273,27 +1304,29 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1273
1304
*/
1274
1305
1275
1306
jspGetRightArg (jsp , & elem );
1276
- res2 = recursiveExecute (cxt , & elem , jb , NULL );
1307
+ res2 = recursiveExecuteBool (cxt , & elem , jb );
1277
1308
1278
1309
res = (res2 == jperOk ) ? res : res2 ;
1279
1310
}
1311
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1280
1312
break ;
1281
1313
case jpiOr :
1282
1314
jspGetLeftArg (jsp , & elem );
1283
- res = recursiveExecute (cxt , & elem , jb , NULL );
1315
+ res = recursiveExecuteBool (cxt , & elem , jb );
1284
1316
if (res != jperOk )
1285
1317
{
1286
1318
JsonPathExecResult res2 ;
1287
1319
1288
1320
jspGetRightArg (jsp , & elem );
1289
- res2 = recursiveExecute (cxt , & elem , jb , NULL );
1321
+ res2 = recursiveExecuteBool (cxt , & elem , jb );
1290
1322
1291
1323
res = (res2 == jperNotFound ) ? res : res2 ;
1292
1324
}
1325
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1293
1326
break ;
1294
1327
case jpiNot :
1295
1328
jspGetArg (jsp , & elem );
1296
- switch ((res = recursiveExecute (cxt , & elem , jb , NULL )))
1329
+ switch ((res = recursiveExecuteBool (cxt , & elem , jb )))
1297
1330
{
1298
1331
case jperOk :
1299
1332
res = jperNotFound ;
@@ -1304,11 +1337,13 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1304
1337
default :
1305
1338
break ;
1306
1339
}
1340
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1307
1341
break ;
1308
1342
case jpiIsUnknown :
1309
1343
jspGetArg (jsp , & elem );
1310
- res = recursiveExecute (cxt , & elem , jb , NULL );
1344
+ res = recursiveExecuteBool (cxt , & elem , jb );
1311
1345
res = jperIsError (res ) ? jperOk : jperNotFound ;
1346
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1312
1347
break ;
1313
1348
case jpiKey :
1314
1349
if (JsonbType (jb ) == jbvObject )
@@ -1575,6 +1610,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1575
1610
case jpiLessOrEqual :
1576
1611
case jpiGreaterOrEqual :
1577
1612
res = executeExpr (cxt , jsp , jb );
1613
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1578
1614
break ;
1579
1615
case jpiAdd :
1580
1616
case jpiSub :
@@ -1589,7 +1625,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1589
1625
break ;
1590
1626
case jpiFilter :
1591
1627
jspGetArg (jsp , & elem );
1592
- res = recursiveExecute (cxt , & elem , jb , NULL );
1628
+ res = recursiveExecuteBool (cxt , & elem , jb );
1593
1629
if (res != jperOk )
1594
1630
res = jperNotFound ;
1595
1631
else
@@ -1638,6 +1674,8 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1638
1674
if (!jperIsError (res ))
1639
1675
res = JsonValueListIsEmpty (& vals ) ? jperNotFound : jperOk ;
1640
1676
}
1677
+
1678
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1641
1679
break ;
1642
1680
case jpiNull :
1643
1681
case jpiBool :
@@ -1973,9 +2011,11 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1973
2011
break ;
1974
2012
case jpiStartsWith :
1975
2013
res = executeStartsWithPredicate (cxt , jsp , jb );
2014
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1976
2015
break ;
1977
2016
case jpiLikeRegex :
1978
2017
res = executeLikeRegexPredicate (cxt , jsp , jb );
2018
+ res = appendBoolResult (cxt , jsp , found , res , needBool );
1979
2019
break ;
1980
2020
default :
1981
2021
elog (ERROR ,"2Wrong state: %d" , jsp -> type );
@@ -1997,7 +2037,7 @@ recursiveExecuteUnwrapArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
1997
2037
1998
2038
for (; elem < last ; elem ++ )
1999
2039
{
2000
- res = recursiveExecuteNoUnwrap (cxt , jsp , elem , found );
2040
+ res = recursiveExecuteNoUnwrap (cxt , jsp , elem , found , false );
2001
2041
2002
2042
if (jperIsError (res ))
2003
2043
break ;
@@ -2017,7 +2057,7 @@ recursiveExecuteUnwrapArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
2017
2057
{
2018
2058
if (tok == WJB_ELEM )
2019
2059
{
2020
- res = recursiveExecuteNoUnwrap (cxt , jsp , & v , found );
2060
+ res = recursiveExecuteNoUnwrap (cxt , jsp , & v , found , false );
2021
2061
if (jperIsError (res ))
2022
2062
break ;
2023
2063
if (res == jperOk && !found )
@@ -2036,7 +2076,7 @@ recursiveExecuteUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
2036
2076
if (cxt -> lax && JsonbType (jb ) == jbvArray )
2037
2077
return recursiveExecuteUnwrapArray (cxt , jsp , jb , found );
2038
2078
2039
- return recursiveExecuteNoUnwrap (cxt , jsp , jb , found );
2079
+ return recursiveExecuteNoUnwrap (cxt , jsp , jb , found , false );
2040
2080
}
2041
2081
2042
2082
static inline JsonbValue *
@@ -2090,7 +2130,39 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
2090
2130
}
2091
2131
}
2092
2132
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);
2094
2166
}
2095
2167
2096
2168
/*
0 commit comments