@@ -179,6 +179,7 @@ typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
179
179
JsonbValue * larg ,
180
180
JsonbValue * rarg ,
181
181
void * param );
182
+ typedef Numeric (* BinaryArithmFunc ) (Numeric num1 , Numeric num2 , bool * error );
182
183
183
184
static JsonPathExecResult executeJsonPath (JsonPath * path , Jsonb * vars ,
184
185
Jsonb * json , bool throwErrors , JsonValueList * result );
@@ -212,8 +213,8 @@ static JsonPathBool executePredicate(JsonPathExecContext *cxt,
212
213
JsonbValue * jb , bool unwrapRightArg ,
213
214
JsonPathPredicateCallback exec , void * param );
214
215
static JsonPathExecResult executeBinaryArithmExpr (JsonPathExecContext * cxt ,
215
- JsonPathItem * jsp , JsonbValue * jb , PGFunction func ,
216
- JsonValueList * found );
216
+ JsonPathItem * jsp , JsonbValue * jb ,
217
+ BinaryArithmFunc func , JsonValueList * found );
217
218
static JsonPathExecResult executeUnaryArithmExpr (JsonPathExecContext * cxt ,
218
219
JsonPathItem * jsp , JsonbValue * jb , PGFunction func ,
219
220
JsonValueList * found );
@@ -830,23 +831,23 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
830
831
831
832
case jpiAdd :
832
833
return executeBinaryArithmExpr (cxt , jsp , jb ,
833
- numeric_add , found );
834
+ numeric_add_opt_error , found );
834
835
835
836
case jpiSub :
836
837
return executeBinaryArithmExpr (cxt , jsp , jb ,
837
- numeric_sub , found );
838
+ numeric_sub_opt_error , found );
838
839
839
840
case jpiMul :
840
841
return executeBinaryArithmExpr (cxt , jsp , jb ,
841
- numeric_mul , found );
842
+ numeric_mul_opt_error , found );
842
843
843
844
case jpiDiv :
844
845
return executeBinaryArithmExpr (cxt , jsp , jb ,
845
- numeric_div , found );
846
+ numeric_div_opt_error , found );
846
847
847
848
case jpiMod :
848
849
return executeBinaryArithmExpr (cxt , jsp , jb ,
849
- numeric_mod , found );
850
+ numeric_mod_opt_error , found );
850
851
851
852
case jpiPlus :
852
853
return executeUnaryArithmExpr (cxt , jsp , jb , NULL , found );
@@ -999,12 +1000,22 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
999
1000
{
1000
1001
char * tmp = DatumGetCString (DirectFunctionCall1 (numeric_out ,
1001
1002
NumericGetDatum (jb -> val .numeric )));
1003
+ bool have_error = false;
1002
1004
1003
- (void ) float8in_internal (tmp ,
1004
- NULL ,
1005
- "double precision" ,
1006
- tmp );
1005
+ (void ) float8in_internal_opt_error (tmp ,
1006
+ NULL ,
1007
+ "double precision" ,
1008
+ tmp ,
1009
+ & have_error );
1007
1010
1011
+ if (have_error )
1012
+ RETURN_ERROR (ereport (ERROR ,
1013
+ (errcode (ERRCODE_NON_NUMERIC_JSON_ITEM ),
1014
+ errmsg (ERRMSG_NON_NUMERIC_JSON_ITEM ),
1015
+ errdetail ("jsonpath item method .%s() "
1016
+ "can only be applied to "
1017
+ "a numeric value" ,
1018
+ jspOperationName (jsp -> type )))));
1008
1019
res = jperOk ;
1009
1020
}
1010
1021
else if (jb -> type == jbvString )
@@ -1013,13 +1024,15 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1013
1024
double val ;
1014
1025
char * tmp = pnstrdup (jb -> val .string .val ,
1015
1026
jb -> val .string .len );
1027
+ bool have_error = false;
1016
1028
1017
- val = float8in_internal (tmp ,
1018
- NULL ,
1019
- "double precision" ,
1020
- tmp );
1029
+ val = float8in_internal_opt_error (tmp ,
1030
+ NULL ,
1031
+ "double precision" ,
1032
+ tmp ,
1033
+ & have_error );
1021
1034
1022
- if (isinf (val ))
1035
+ if (have_error || isinf (val ))
1023
1036
RETURN_ERROR (ereport (ERROR ,
1024
1037
(errcode (ERRCODE_NON_NUMERIC_JSON_ITEM ),
1025
1038
errmsg (ERRMSG_NON_NUMERIC_JSON_ITEM ),
@@ -1497,7 +1510,7 @@ executePredicate(JsonPathExecContext *cxt, JsonPathItem *pred,
1497
1510
*/
1498
1511
static JsonPathExecResult
1499
1512
executeBinaryArithmExpr (JsonPathExecContext * cxt , JsonPathItem * jsp ,
1500
- JsonbValue * jb , PGFunction func ,
1513
+ JsonbValue * jb , BinaryArithmFunc func ,
1501
1514
JsonValueList * found )
1502
1515
{
1503
1516
JsonPathExecResult jper ;
@@ -1506,7 +1519,7 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
1506
1519
JsonValueList rseq = {0 };
1507
1520
JsonbValue * lval ;
1508
1521
JsonbValue * rval ;
1509
- Datum res ;
1522
+ Numeric res ;
1510
1523
1511
1524
jspGetLeftArg (jsp , & elem );
1512
1525
@@ -1542,16 +1555,26 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
1542
1555
"is not a singleton numeric value" ,
1543
1556
jspOperationName (jsp -> type )))));
1544
1557
1545
- res = DirectFunctionCall2 (func ,
1546
- NumericGetDatum (lval -> val .numeric ),
1547
- NumericGetDatum (rval -> val .numeric ));
1558
+ if (jspThrowErrors (cxt ))
1559
+ {
1560
+ res = func (lval -> val .numeric , rval -> val .numeric , NULL );
1561
+ }
1562
+ else
1563
+ {
1564
+ bool error = false;
1565
+
1566
+ res = func (lval -> val .numeric , rval -> val .numeric , & error );
1567
+
1568
+ if (error )
1569
+ return jperError ;
1570
+ }
1548
1571
1549
1572
if (!jspGetNext (jsp , & elem ) && !found )
1550
1573
return jperOk ;
1551
1574
1552
1575
lval = palloc (sizeof (* lval ));
1553
1576
lval -> type = jbvNumeric ;
1554
- lval -> val .numeric = DatumGetNumeric ( res ) ;
1577
+ lval -> val .numeric = res ;
1555
1578
1556
1579
return executeNextItem (cxt , jsp , & elem , lval , found , false);
1557
1580
}
@@ -2108,6 +2131,7 @@ getArrayIndex(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
2108
2131
JsonValueList found = {0 };
2109
2132
JsonPathExecResult res = executeItem (cxt , jsp , jb , & found );
2110
2133
Datum numeric_index ;
2134
+ bool have_error = false;
2111
2135
2112
2136
if (jperIsError (res ))
2113
2137
return res ;
@@ -2124,7 +2148,15 @@ getArrayIndex(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
2124
2148
NumericGetDatum (jbv -> val .numeric ),
2125
2149
Int32GetDatum (0 ));
2126
2150
2127
- * index = DatumGetInt32 (DirectFunctionCall1 (numeric_int4 , numeric_index ));
2151
+ * index = numeric_int4_opt_error (DatumGetNumeric (numeric_index ),
2152
+ & have_error );
2153
+
2154
+ if (have_error )
2155
+ RETURN_ERROR (ereport (ERROR ,
2156
+ (errcode (ERRCODE_INVALID_JSON_SUBSCRIPT ),
2157
+ errmsg (ERRMSG_INVALID_JSON_SUBSCRIPT ),
2158
+ errdetail ("jsonpath array subscript is "
2159
+ "out of integer range" ))));
2128
2160
2129
2161
return jperOk ;
2130
2162
}
0 commit comments