Forbid numeric NaN in jsonpath
authorAlexander Korotkov <[email protected]>
Sat, 11 Jul 2020 00:21:00 +0000 (03:21 +0300)
committerAlexander Korotkov <[email protected]>
Sat, 11 Jul 2020 00:21:57 +0000 (03:21 +0300)
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
src/backend/utils/adt/jsonpath_exec.c
src/test/regress/expected/jsonb_jsonpath.out

index 7969f6f58435ff836417f5bb438b1d3fb72008da..53a0bb48b9209f8ec2b07a7cf8884a127605da1c 100644 (file)
@@ -1728,14 +1728,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);
 
index d8f3632021efa0c03308633ced237e653231e677..a557ed1ce1ef12106974166d47ed168adf6ae18f 100644 (file)
@@ -975,15 +975,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",
@@ -1004,7 +1005,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",
index 0c084a6c6c52c718780aaa049b7d5f4d5c83f06a..fb0fed11ac7b9f24911ff74e1a58cba674b7bdad 100644 (file)
@@ -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()');