Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a8f59a6

Browse files
author
Nikita Glukhov
committed
Remove PG_TRY in jsonpath arithmetics
1 parent b2daedf commit a8f59a6

File tree

6 files changed

+305
-188
lines changed

6 files changed

+305
-188
lines changed

src/backend/utils/adt/float.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ float8in(PG_FUNCTION_ARGS)
287287
}
288288

289289
/*
290-
* float8in_internal - guts of float8in()
290+
* float8in_internal_safe - guts of float8in()
291291
*
292292
* This is exposed for use by functions that want a reasonably
293293
* platform-independent way of inputting doubles. The behavior is
@@ -305,8 +305,8 @@ float8in(PG_FUNCTION_ARGS)
305305
* unreasonable amount of extra casting both here and in callers, so we don't.
306306
*/
307307
double
308-
float8in_internal(char *num, char **endptr_p,
309-
const char *type_name, const char *orig_string)
308+
float8in_internal_safe(char *num, char **endptr_p, const char *type_name,
309+
const char *orig_string, ErrorData **edata)
310310
{
311311
double val;
312312
char *endptr;
@@ -320,10 +320,13 @@ float8in_internal(char *num, char **endptr_p,
320320
* strtod() on different platforms.
321321
*/
322322
if (*num == '\0')
323-
ereport(ERROR,
324-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
325-
errmsg("invalid input syntax for type %s: \"%s\"",
326-
type_name, orig_string)));
323+
{
324+
ereport_safe(edata, ERROR,
325+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
326+
errmsg("invalid input syntax for type %s: \"%s\"",
327+
type_name, orig_string)));
328+
return 0;
329+
}
327330

328331
errno = 0;
329332
val = strtod(num, &endptr);
@@ -396,17 +399,21 @@ float8in_internal(char *num, char **endptr_p,
396399
char *errnumber = pstrdup(num);
397400

398401
errnumber[endptr - num] = '\0';
399-
ereport(ERROR,
400-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
401-
errmsg("\"%s\" is out of range for type double precision",
402-
errnumber)));
402+
ereport_safe(edata, ERROR,
403+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
404+
errmsg("\"%s\" is out of range for type double precision",
405+
errnumber)));
406+
return 0;
403407
}
404408
}
405409
else
406-
ereport(ERROR,
407-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
408-
errmsg("invalid input syntax for type %s: \"%s\"",
409-
type_name, orig_string)));
410+
{
411+
ereport_safe(edata, ERROR,
412+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
413+
errmsg("invalid input syntax for type %s: \"%s\"",
414+
type_name, orig_string)));
415+
return 0;
416+
}
410417
}
411418
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
412419
else
@@ -429,10 +436,13 @@ float8in_internal(char *num, char **endptr_p,
429436
if (endptr_p)
430437
*endptr_p = endptr;
431438
else if (*endptr != '\0')
432-
ereport(ERROR,
433-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
434-
errmsg("invalid input syntax for type %s: \"%s\"",
435-
type_name, orig_string)));
439+
{
440+
ereport_safe(edata, ERROR,
441+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
442+
errmsg("invalid input syntax for type %s: \"%s\"",
443+
type_name, orig_string)));
444+
return 0;
445+
}
436446

437447
return val;
438448
}

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 45 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "regex/regex.h"
2020
#include "utils/builtins.h"
2121
#include "utils/datum.h"
22+
#include "utils/float.h"
2223
#include "utils/formatting.h"
2324
#include "utils/json.h"
2425
#include "utils/jsonpath.h"
@@ -918,7 +919,6 @@ static JsonPathExecResult
918919
executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
919920
JsonbValue *jb, JsonValueList *found)
920921
{
921-
MemoryContext mcxt = CurrentMemoryContext;
922922
JsonPathExecResult jper;
923923
JsonPathItem elem;
924924
JsonValueList lseq = { 0 };
@@ -927,11 +927,10 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
927927
JsonbValue *rval;
928928
JsonbValue lvalbuf;
929929
JsonbValue rvalbuf;
930-
PGFunction func;
931-
Datum ldatum;
932-
Datum rdatum;
933-
Datum res;
930+
Numeric (*func)(Numeric, Numeric, ErrorData **);
931+
Numeric res;
934932
bool hasNext;
933+
ErrorData *edata;
935934

936935
jspGetLeftArg(jsp, &elem);
937936

@@ -970,55 +969,38 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
970969
if (!found && !hasNext)
971970
return jperOk;
972971

973-
ldatum = NumericGetDatum(lval->val.numeric);
974-
rdatum = NumericGetDatum(rval->val.numeric);
975-
976972
switch (jsp->type)
977973
{
978974
case jpiAdd:
979-
func = numeric_add;
975+
func = numeric_add_internal;
980976
break;
981977
case jpiSub:
982-
func = numeric_sub;
978+
func = numeric_sub_internal;
983979
break;
984980
case jpiMul:
985-
func = numeric_mul;
981+
func = numeric_mul_internal;
986982
break;
987983
case jpiDiv:
988-
func = numeric_div;
984+
func = numeric_div_internal;
989985
break;
990986
case jpiMod:
991-
func = numeric_mod;
987+
func = numeric_mod_internal;
992988
break;
993989
default:
994990
elog(ERROR, "unknown jsonpath arithmetic operation %d", jsp->type);
995991
func = NULL;
996992
break;
997993
}
998994

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);
1014997

998+
if (edata)
1015999
return jperMakeErrorData(edata);
1016-
}
1017-
PG_END_TRY();
10181000

10191001
lval = palloc(sizeof(*lval));
10201002
lval->type = jbvNumeric;
1021-
lval->val.numeric = DatumGetNumeric(res);
1003+
lval->val.numeric = res;
10221004

10231005
return recursiveExecuteNext(cxt, jsp, &elem, lval, found, false);
10241006
}
@@ -2032,53 +2014,53 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
20322014
case jpiDouble:
20332015
{
20342016
JsonbValue jbv;
2035-
MemoryContext mcxt = CurrentMemoryContext;
2017+
ErrorData *edata = NULL;
20362018

20372019
if (JsonbType(jb) == jbvScalar)
20382020
jb = JsonbExtractScalar(jb->val.binary.data, &jbv);
20392021

2040-
PG_TRY();
2022+
if (jb->type == jbvNumeric)
20412023
{
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;
20572033

2034+
val = float8in_internal_safe(str, NULL, "double precision",
2035+
str, &edata);
2036+
pfree(str);
2037+
2038+
if (!edata)
2039+
{
20582040
jb = &jbv;
20592041
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);
20642043
}
2065-
else
2066-
res = jperMakeError(ERRCODE_NON_NUMERIC_JSON_ITEM);
20672044
}
2068-
PG_CATCH();
2045+
else
2046+
{
2047+
res = jperMakeError(ERRCODE_NON_NUMERIC_JSON_ITEM);
2048+
break;
2049+
}
2050+
2051+
if (edata)
20692052
{
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);
20732056

2074-
FlushErrorState();
2075-
MemoryContextSwitchTo(mcxt);
2057+
FreeErrorData(edata);
20762058
res = jperMakeError(ERRCODE_NON_NUMERIC_JSON_ITEM);
20772059
}
2078-
PG_END_TRY();
2079-
2080-
if (res == jperOk)
2060+
else
2061+
{
20812062
res = recursiveExecuteNext(cxt, jsp, NULL, jb, found, true);
2063+
}
20822064
}
20832065
break;
20842066
case jpiDatetime:

0 commit comments

Comments
 (0)