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

Commit 4d973f9

Browse files
author
Nikita Glukhov
committed
Remove PG_TRY/PG_CATCH in handling of numeric errors inside jsonpath
1 parent ba11aff commit 4d973f9

File tree

6 files changed

+296
-188
lines changed

6 files changed

+296
-188
lines changed

src/backend/utils/adt/float.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ float8in(PG_FUNCTION_ARGS)
420420
}
421421

422422
/*
423-
* float8in_internal - guts of float8in()
423+
* float8in_internal_safe - guts of float8in()
424424
*
425425
* This is exposed for use by functions that want a reasonably
426426
* platform-independent way of inputting doubles. The behavior is
@@ -438,8 +438,8 @@ float8in(PG_FUNCTION_ARGS)
438438
* unreasonable amount of extra casting both here and in callers, so we don't.
439439
*/
440440
double
441-
float8in_internal(char *num, char **endptr_p,
442-
const char *type_name, const char *orig_string)
441+
float8in_internal_safe(char *num, char **endptr_p, const char *type_name,
442+
const char *orig_string, ErrorData **edata)
443443
{
444444
double val;
445445
char *endptr;
@@ -453,10 +453,13 @@ float8in_internal(char *num, char **endptr_p,
453453
* strtod() on different platforms.
454454
*/
455455
if (*num == '\0')
456-
ereport(ERROR,
457-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
458-
errmsg("invalid input syntax for type %s: \"%s\"",
459-
type_name, orig_string)));
456+
{
457+
ereport_safe(edata, ERROR,
458+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
459+
errmsg("invalid input syntax for type %s: \"%s\"",
460+
type_name, orig_string)));
461+
return 0;
462+
}
460463

461464
errno = 0;
462465
val = strtod(num, &endptr);
@@ -529,17 +532,21 @@ float8in_internal(char *num, char **endptr_p,
529532
char *errnumber = pstrdup(num);
530533

531534
errnumber[endptr - num] = '\0';
532-
ereport(ERROR,
533-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
534-
errmsg("\"%s\" is out of range for type double precision",
535-
errnumber)));
535+
ereport_safe(edata, ERROR,
536+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
537+
errmsg("\"%s\" is out of range for type double precision",
538+
errnumber)));
539+
return 0;
536540
}
537541
}
538542
else
539-
ereport(ERROR,
540-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
541-
errmsg("invalid input syntax for type %s: \"%s\"",
542-
type_name, orig_string)));
543+
{
544+
ereport_safe(edata, ERROR,
545+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
546+
errmsg("invalid input syntax for type %s: \"%s\"",
547+
type_name, orig_string)));
548+
return 0;
549+
}
543550
}
544551
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
545552
else
@@ -562,10 +569,13 @@ float8in_internal(char *num, char **endptr_p,
562569
if (endptr_p)
563570
*endptr_p = endptr;
564571
else if (*endptr != '\0')
565-
ereport(ERROR,
566-
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
567-
errmsg("invalid input syntax for type %s: \"%s\"",
568-
type_name, orig_string)));
572+
{
573+
ereport_safe(edata, ERROR,
574+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
575+
errmsg("invalid input syntax for type %s: \"%s\"",
576+
type_name, orig_string)));
577+
return 0;
578+
}
569579

570580
return val;
571581
}

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 44 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,6 @@ static JsonPathExecResult
910910
executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
911911
JsonbValue *jb, JsonValueList *found)
912912
{
913-
MemoryContext mcxt = CurrentMemoryContext;
914913
JsonPathExecResult jper;
915914
JsonPathItem elem;
916915
JsonValueList lseq = { 0 };
@@ -919,11 +918,10 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
919918
JsonbValue *rval;
920919
JsonbValue lvalbuf;
921920
JsonbValue rvalbuf;
922-
PGFunction func;
923-
Datum ldatum;
924-
Datum rdatum;
925-
Datum res;
921+
Numeric (*func)(Numeric, Numeric, ErrorData **);
922+
Numeric res;
926923
bool hasNext;
924+
ErrorData *edata;
927925

928926
jspGetLeftArg(jsp, &elem);
929927

@@ -962,55 +960,38 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
962960
if (!found && !hasNext)
963961
return jperOk;
964962

965-
ldatum = NumericGetDatum(lval->val.numeric);
966-
rdatum = NumericGetDatum(rval->val.numeric);
967-
968963
switch (jsp->type)
969964
{
970965
case jpiAdd:
971-
func = numeric_add;
966+
func = numeric_add_internal;
972967
break;
973968
case jpiSub:
974-
func = numeric_sub;
969+
func = numeric_sub_internal;
975970
break;
976971
case jpiMul:
977-
func = numeric_mul;
972+
func = numeric_mul_internal;
978973
break;
979974
case jpiDiv:
980-
func = numeric_div;
975+
func = numeric_div_internal;
981976
break;
982977
case jpiMod:
983-
func = numeric_mod;
978+
func = numeric_mod_internal;
984979
break;
985980
default:
986981
elog(ERROR, "unknown jsonpath arithmetic operation %d", jsp->type);
987982
func = NULL;
988983
break;
989984
}
990985

991-
PG_TRY();
992-
{
993-
res = DirectFunctionCall2(func, ldatum, rdatum);
994-
}
995-
PG_CATCH();
996-
{
997-
int errcode = geterrcode();
998-
ErrorData *edata;
999-
1000-
if (ERRCODE_TO_CATEGORY(errcode) != ERRCODE_DATA_EXCEPTION)
1001-
PG_RE_THROW();
1002-
1003-
MemoryContextSwitchTo(mcxt);
1004-
edata = CopyErrorData();
1005-
FlushErrorState();
986+
edata = NULL;
987+
res = func(lval->val.numeric, rval->val.numeric, &edata);
1006988

989+
if (edata)
1007990
return jperMakeErrorData(edata);
1008-
}
1009-
PG_END_TRY();
1010991

1011992
lval = palloc(sizeof(*lval));
1012993
lval->type = jbvNumeric;
1013-
lval->val.numeric = DatumGetNumeric(res);
994+
lval->val.numeric = res;
1014995

1015996
return recursiveExecuteNext(cxt, jsp, &elem, lval, found, false);
1016997
}
@@ -1947,53 +1928,53 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
19471928
case jpiDouble:
19481929
{
19491930
JsonbValue jbv;
1950-
MemoryContext mcxt = CurrentMemoryContext;
1931+
ErrorData *edata = NULL;
19511932

19521933
if (JsonbType(jb) == jbvScalar)
19531934
jb = JsonbExtractScalar(jb->val.binary.data, &jbv);
19541935

1955-
PG_TRY();
1936+
if (jb->type == jbvNumeric)
19561937
{
1957-
if (jb->type == jbvNumeric)
1958-
{
1959-
/* only check success of numeric to double cast */
1960-
DirectFunctionCall1(numeric_float8,
1961-
NumericGetDatum(jb->val.numeric));
1962-
res = jperOk;
1963-
}
1964-
else if (jb->type == jbvString)
1965-
{
1966-
/* cast string as double */
1967-
char *str = pnstrdup(jb->val.string.val,
1968-
jb->val.string.len);
1969-
Datum val = DirectFunctionCall1(
1970-
float8in, CStringGetDatum(str));
1971-
pfree(str);
1938+
/* only check success of numeric to double cast */
1939+
(void) numeric_float8_internal(jb->val.numeric, &edata);
1940+
}
1941+
else if (jb->type == jbvString)
1942+
{
1943+
/* cast string as double */
1944+
char *str = pnstrdup(jb->val.string.val,
1945+
jb->val.string.len);
1946+
double val;
19721947

1948+
val = float8in_internal_safe(str, NULL, "double precision",
1949+
str, &edata);
1950+
pfree(str);
1951+
1952+
if (!edata)
1953+
{
19731954
jb = &jbv;
19741955
jb->type = jbvNumeric;
1975-
jb->val.numeric = DatumGetNumeric(DirectFunctionCall1(
1976-
float8_numeric, val));
1977-
res = jperOk;
1978-
1956+
jb->val.numeric = float8_numeric_internal(val, &edata);
19791957
}
1980-
else
1981-
res = jperMakeError(ERRCODE_NON_NUMERIC_JSON_ITEM);
19821958
}
1983-
PG_CATCH();
1959+
else
1960+
{
1961+
res = jperMakeError(ERRCODE_NON_NUMERIC_JSON_ITEM);
1962+
break;
1963+
}
1964+
1965+
if (edata)
19841966
{
1985-
if (ERRCODE_TO_CATEGORY(geterrcode()) !=
1986-
ERRCODE_DATA_EXCEPTION)
1987-
PG_RE_THROW();
1967+
if (ERRCODE_TO_CATEGORY(edata->sqlerrcode) !=
1968+
ERRCODE_DATA_EXCEPTION)
1969+
ThrowErrorData(edata);
19881970

1989-
FlushErrorState();
1990-
MemoryContextSwitchTo(mcxt);
1971+
FreeErrorData(edata);
19911972
res = jperMakeError(ERRCODE_NON_NUMERIC_JSON_ITEM);
19921973
}
1993-
PG_END_TRY();
1994-
1995-
if (res == jperOk)
1974+
else
1975+
{
19961976
res = recursiveExecuteNext(cxt, jsp, NULL, jb, found, true);
1977+
}
19971978
}
19981979
break;
19991980
case jpiDatetime:

0 commit comments

Comments
 (0)