Re: Infinities in type numeric - Mailing list pgsql-hackers

From Dean Rasheed
Subject Re: Infinities in type numeric
Date
Msg-id CAEZATCWeSoY+ET9o4j3hm3VXxGoM782_JnL=Y+u0QxzAcnxcvg@mail.gmail.com
Whole thread Raw
In response to Re: Infinities in type numeric  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Infinities in type numeric
List pgsql-hackers
On Tue, 16 Jun 2020 at 18:24, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> The attached v3 patch fixes these things and also takes care of an
> oversight in v2: I'd made numeric() apply typmod restrictions to Inf,
> but not numeric_in() or numeric_recv().  I believe the patch itself
> is in pretty good shape now, though there are still some issues
> elsewhere as noted in the first message in this thread.
>

I had a look at this, and I think it's mostly in good shape. It looks
like everything from the first message in this thread has been
resolved, except I don't know about the jsonpath stuff, because I
haven't been following that.

I tried to go over all the edge cases and I think they all make sense,
except for a couple of cases which I've listed below, along with a few
other minor comments:

1). I don't think that the way in_range() handles infinities is quite
right. For example:

SELECT in_range('inf'::numeric, 10::numeric, 'inf'::numeric, false, false);
 in_range
----------
 f
(1 row)

But I think that should return "val >= base + offset", which is "Inf
>= Inf", which should be true.

Similarly, I think this should return true:

SELECT in_range('-inf'::numeric, 10::numeric, 'inf'::numeric, true, true);
 in_range
----------
 f
(1 row)

I think this could use some test coverage.

2). I think numeric_pg_lsn() needs updating -- this should probably be an error:

SELECT pg_lsn('inf'::numeric);
 pg_lsn
--------
 0/0
(1 row)

3). In the bottom half of numeric.c, there's a section header comment
saying "Local functions follow ... In general, these do not support
NaNs ...". That should probably also mention infinities. There are
also now more functions to mention that are exceptions to that comment
about not handling NaN/Inf, but I think that some of the new
exceptions can be avoided.

4). The comment for set_var_from_str() mentions that it doesn't handle
"NaN", so on the face of it, it ought to also mention that it doesn't
handle "Infinity" either. However, this is only a few lines down from
that "Local functions follow ..." section header comment, which
already covers that, so it seems pointless mentioning NaNs and
infinities again for this function (none of the other local functions
in that section of the file do).

5). It seems a bit odd that numeric_to_double_no_overflow() handles
infinite inputs, but not NaN inputs, while its only caller
numeric_float8_no_overflow() handles NaNs, but not infinities. ISTM
that it would be neater to have all the special-handling in one place
(in the caller). That would also stop numeric_to_double_no_overflow()
being an exception to the preceding section header comment about local
functions not handling Nan/Inf. In fact, I wonder why keep
numeric_to_double_no_overflow() at all? It could just be rolled into
its caller, making it more like numeric_float8().

6). The next function, numericvar_to_double_no_overflow(), has a
comment that just says "As above, but work from a NumericVar", but it
isn't really "as above" anymore, since it doesn't handle infinite
inputs. Depending on what happens to numeric_to_double_no_overflow(),
this function's comment might need some tweaking.

7). The new function numeric_is_integral() feels out of place where it
is, amongst arithmetic functions operating on NumericVar's, because it
operates on a Numeric, and also because it handles NaNs, making it
another exception to the preceding comment about local functions that
don't handle NaNs. Perhaps it would fit in better after
numeric_is_nan() and numeric_is_inf(). Even though it's a local
function, it feels more akin to those functions.

Finally, not really in the scope of this patch, but something I
noticed anyway while looking at edge cases -- float and numeric handle
NaN/0 differently:

SELECT 'nan'::float8 / 0::float8;
ERROR:  division by zero

SELECT 'nan'::numeric / 0::numeric;
 ?column?
----------
      NaN

I'm not sure if this is worth worrying about, or which behaviour is
preferable though.

Regards,
Dean



pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: sys_siglist[] is causing us trouble again
Next
From: Tom Lane
Date:
Subject: Re: sys_siglist[] is causing us trouble again