19
19
#include "regex/regex.h"
20
20
#include "utils/builtins.h"
21
21
#include "utils/datum.h"
22
+ #include "utils/float.h"
22
23
#include "utils/formatting.h"
23
24
#include "utils/json.h"
24
25
#include "utils/jsonpath.h"
@@ -918,7 +919,6 @@ static JsonPathExecResult
918
919
executeBinaryArithmExpr (JsonPathExecContext * cxt , JsonPathItem * jsp ,
919
920
JsonbValue * jb , JsonValueList * found )
920
921
{
921
- MemoryContext mcxt = CurrentMemoryContext ;
922
922
JsonPathExecResult jper ;
923
923
JsonPathItem elem ;
924
924
JsonValueList lseq = { 0 };
@@ -927,11 +927,10 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
927
927
JsonbValue * rval ;
928
928
JsonbValue lvalbuf ;
929
929
JsonbValue rvalbuf ;
930
- PGFunction func ;
931
- Datum ldatum ;
932
- Datum rdatum ;
933
- Datum res ;
930
+ Numeric (* func )(Numeric , Numeric , ErrorData * * );
931
+ Numeric res ;
934
932
bool hasNext ;
933
+ ErrorData * edata ;
935
934
936
935
jspGetLeftArg (jsp , & elem );
937
936
@@ -970,55 +969,38 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
970
969
if (!found && !hasNext )
971
970
return jperOk ;
972
971
973
- ldatum = NumericGetDatum (lval -> val .numeric );
974
- rdatum = NumericGetDatum (rval -> val .numeric );
975
-
976
972
switch (jsp -> type )
977
973
{
978
974
case jpiAdd :
979
- func = numeric_add ;
975
+ func = numeric_add_internal ;
980
976
break ;
981
977
case jpiSub :
982
- func = numeric_sub ;
978
+ func = numeric_sub_internal ;
983
979
break ;
984
980
case jpiMul :
985
- func = numeric_mul ;
981
+ func = numeric_mul_internal ;
986
982
break ;
987
983
case jpiDiv :
988
- func = numeric_div ;
984
+ func = numeric_div_internal ;
989
985
break ;
990
986
case jpiMod :
991
- func = numeric_mod ;
987
+ func = numeric_mod_internal ;
992
988
break ;
993
989
default :
994
990
elog (ERROR , "unknown jsonpath arithmetic operation %d" , jsp -> type );
995
991
func = NULL ;
996
992
break ;
997
993
}
998
994
999
- PG_TRY ();
1000
- {
1001
- res = DirectFunctionCall2 (func , ldatum , rdatum );
1002
- }
1003
- PG_CATCH ();
1004
- {
1005
- int errcode = geterrcode ();
1006
- ErrorData * edata ;
1007
-
1008
- if (ERRCODE_TO_CATEGORY (errcode ) != ERRCODE_DATA_EXCEPTION )
1009
- PG_RE_THROW ();
1010
-
1011
- MemoryContextSwitchTo (mcxt );
1012
- edata = CopyErrorData ();
1013
- FlushErrorState ();
995
+ edata = NULL ;
996
+ res = func (lval -> val .numeric , rval -> val .numeric , & edata );
1014
997
998
+ if (edata )
1015
999
return jperMakeErrorData (edata );
1016
- }
1017
- PG_END_TRY ();
1018
1000
1019
1001
lval = palloc (sizeof (* lval ));
1020
1002
lval -> type = jbvNumeric ;
1021
- lval -> val .numeric = DatumGetNumeric ( res ) ;
1003
+ lval -> val .numeric = res ;
1022
1004
1023
1005
return recursiveExecuteNext (cxt , jsp , & elem , lval , found , false);
1024
1006
}
@@ -2032,53 +2014,53 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
2032
2014
case jpiDouble :
2033
2015
{
2034
2016
JsonbValue jbv ;
2035
- MemoryContext mcxt = CurrentMemoryContext ;
2017
+ ErrorData * edata = NULL ;
2036
2018
2037
2019
if (JsonbType (jb ) == jbvScalar )
2038
2020
jb = JsonbExtractScalar (jb -> val .binary .data , & jbv );
2039
2021
2040
- PG_TRY ();
2022
+ if ( jb -> type == jbvNumeric )
2041
2023
{
2042
- if (jb -> type == jbvNumeric )
2043
- {
2044
- /* only check success of numeric to double cast */
2045
- DirectFunctionCall1 (numeric_float8 ,
2046
- NumericGetDatum (jb -> val .numeric ));
2047
- res = jperOk ;
2048
- }
2049
- else if (jb -> type == jbvString )
2050
- {
2051
- /* cast string as double */
2052
- char * str = pnstrdup (jb -> val .string .val ,
2053
- jb -> val .string .len );
2054
- Datum val = DirectFunctionCall1 (
2055
- float8in , CStringGetDatum (str ));
2056
- pfree (str );
2024
+ /* only check success of numeric to double cast */
2025
+ (void ) numeric_float8_internal (jb -> val .numeric , & edata );
2026
+ }
2027
+ else if (jb -> type == jbvString )
2028
+ {
2029
+ /* cast string as double */
2030
+ char * str = pnstrdup (jb -> val .string .val ,
2031
+ jb -> val .string .len );
2032
+ double val ;
2057
2033
2034
+ val = float8in_internal_safe (str , NULL , "double precision" ,
2035
+ str , & edata );
2036
+ pfree (str );
2037
+
2038
+ if (!edata )
2039
+ {
2058
2040
jb = & jbv ;
2059
2041
jb -> type = jbvNumeric ;
2060
- jb -> val .numeric = DatumGetNumeric (DirectFunctionCall1 (
2061
- float8_numeric , val ));
2062
- res = jperOk ;
2063
-
2042
+ jb -> val .numeric = float8_numeric_internal (val , & edata );
2064
2043
}
2065
- else
2066
- res = jperMakeError (ERRCODE_NON_NUMERIC_JSON_ITEM );
2067
2044
}
2068
- PG_CATCH ();
2045
+ else
2046
+ {
2047
+ res = jperMakeError (ERRCODE_NON_NUMERIC_JSON_ITEM );
2048
+ break ;
2049
+ }
2050
+
2051
+ if (edata )
2069
2052
{
2070
- if (ERRCODE_TO_CATEGORY (geterrcode () ) !=
2071
- ERRCODE_DATA_EXCEPTION )
2072
- PG_RE_THROW ( );
2053
+ if (ERRCODE_TO_CATEGORY (edata -> sqlerrcode ) !=
2054
+ ERRCODE_DATA_EXCEPTION )
2055
+ ThrowErrorData ( edata );
2073
2056
2074
- FlushErrorState ();
2075
- MemoryContextSwitchTo (mcxt );
2057
+ FreeErrorData (edata );
2076
2058
res = jperMakeError (ERRCODE_NON_NUMERIC_JSON_ITEM );
2077
2059
}
2078
- PG_END_TRY ();
2079
-
2080
- if (res == jperOk )
2060
+ else
2061
+ {
2081
2062
res = recursiveExecuteNext (cxt , jsp , NULL , jb , found , true);
2063
+ }
2082
2064
}
2083
2065
break ;
2084
2066
case jpiDatetime :
0 commit comments