postgres.git / summary / log / commit / refs

commit    df646509f371069c65f84309eb5749642e8650b3
Author:   Alexander Korotkov <akorotkov@postgresql.org>
Date:     Sat Jul 11 00:21:00 2020 +0000
First released in: 14.0, 12.4, 13.0

    Forbid numeric NaN in jsonpath
    
    SQL standard doesn't define numeric Inf or NaN values.  It appears even more
    ridiculous to support then in jsonpath assuming JSON doesn't support these
    values as well.  This commit forbids returning NaN from .double(), which was
    previously allowed.  NaN can't be result of inner-jsonpath computation over
    non-NaNs.  So, we can not expect NaN in the jsonpath output.
    
    Reported-by: Tom Lane
    Discussion: https://postgr.es/m/203949.1591879542%40sss.pgh.pa.us
    Author: Alexander Korotkov
    Reviewed-by: Tom Lane
    Backpatch-through: 12


src/backend/utils/adt/jsonb_util.c | 8 -------- src/backend/utils/adt/jsonpath_exec.c | 15 ++++++++------- src/test/regress/expected/jsonb_jsonpath.out | 12 ++---------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c index 04b70c805b4..4eeffa14243 100644 --- a/src/backend/utils/adt/jsonb_util.c +++ b/src/backend/utils/adt/jsonb_util.c @@ -1773,14 +1773,6 @@ convertJsonbScalar(StringInfo buffer, JEntry *jentry, JsonbValue *scalarVal) break; case jbvNumeric: - /* replace numeric NaN with string "NaN" */ - if (numeric_is_nan(scalarVal->val.numeric)) - { - appendToBuffer(buffer, "NaN", 3); - *jentry = 3; - break; - } - numlen = VARSIZE_ANY(scalarVal->val.numeric); padlen = padBufferToInt(buffer); diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index 25ec3dcd802..f146767bfc3 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -1044,15 +1044,16 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, { char *tmp = DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(jb->val.numeric))); + double val; bool have_error = false; - (void) float8in_internal_opt_error(tmp, - NULL, - "double precision", - tmp, - &have_error); + val = float8in_internal_opt_error(tmp, + NULL, + "double precision", + tmp, + &have_error); - if (have_error) + if (have_error || isinf(val) || isnan(val)) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), errmsg("numeric argument of jsonpath item method .%s() is out of range for type double precision", @@ -1073,7 +1074,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, tmp, &have_error); - if (have_error || isinf(val)) + if (have_error || isinf(val) || isnan(val)) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), errmsg("string argument of jsonpath item method .%s() is not a valid representation of a double precision number", diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out index f8a5deb2b99..57332111b42 100644 --- a/src/test/regress/expected/jsonb_jsonpath.out +++ b/src/test/regress/expected/jsonb_jsonpath.out @@ -1500,17 +1500,9 @@ ERROR: string argument of jsonpath item method .double() is not a valid represe select jsonb_path_query('1e1000', '$.double()'); ERROR: numeric argument of jsonpath item method .double() is out of range for type double precision select jsonb_path_query('"nan"', '$.double()'); - jsonb_path_query ------------------- - "NaN" -(1 row) - +ERROR: string argument of jsonpath item method .double() is not a valid representation of a double precision number select jsonb_path_query('"NaN"', '$.double()'); - jsonb_path_query ------------------- - "NaN" -(1 row) - +ERROR: string argument of jsonpath item method .double() is not a valid representation of a double precision number select jsonb_path_query('"inf"', '$.double()'); ERROR: string argument of jsonpath item method .double() is not a valid representation of a double precision number select jsonb_path_query('"-inf"', '$.double()'); [parent: 065718116746]