Обсуждение: BUG #15071: Error in PostgreSQL-specific :: type cast

Поиск
Список
Период
Сортировка

BUG #15071: Error in PostgreSQL-specific :: type cast

От
PG Bug reporting form
Дата:
The following bug has been logged on the website:

Bug reference:      15071
Logged by:          Yuriy Beliy
Email address:      whiteman.kr@gmail.com
PostgreSQL version: 10.1
Operating system:   Windows 10
Description:

PostgreSQL-specific :: type casts for lowest values of integer types are
produce "Out of range" errors:

SELECT -32768::smallint
^ERROR:  smallint out of range

SELECT -2147483648::integer
^ERROR:  integer out of range

SELECT     -9223372036854775808::bigint
^ERROR:  bigint out of range

Standard-syntax type casts are workes correctly:

SELECT cast(-32768 as smallint)
^Ok

SELECT cast(-2147483648 as integer)
^Ok

SELECT     cast(-9223372036854775808 as bigint)
^Ok

For highest values (+32767, +2147483647, +9223372036854775807) - :: type
cast works correctly.




Re: BUG #15071: Error in PostgreSQL-specific :: type cast

От
Daniel Gustafsson
Дата:
> On 16 Feb 2018, at 12:57, PG Bug reporting form <noreply@postgresql.org> wrote:
>
> The following bug has been logged on the website:
>
> Bug reference:      15071
> Logged by:          Yuriy Beliy
> Email address:      whiteman.kr@gmail.com
> PostgreSQL version: 10.1
> Operating system:   Windows 10
> Description:
>
> PostgreSQL-specific :: type casts for lowest values of integer types are
> produce "Out of range" errors:
>
> SELECT -32768::smallint
> ^ERROR:  smallint out of range

The parser will represents this as the numeric portion, 32768, and a “-“ in an
expression of type AEXPR_OP.  When passed to i4toi2(), only the numeric part is
passed and the out of range is due to 32768 > SHRT_MAX (same type of issue for
the other types).  Casting from non-numeric, like text for example, to smallint
works since it isn’t parsed into an “-“ expr: '-32768'::smallint;

Applying the “-“ op before passing to the typecast function seems the easy
answer, or passing the “-“ separately (which seems kludgier) This is quite old
code though, so I don’t know how much else that would break?

cheers ./daniel

Re: BUG #15071: Error in PostgreSQL-specific :: type cast

От
Tom Lane
Дата:
Daniel Gustafsson <daniel@yesql.se> writes:
>> On 16 Feb 2018, at 12:57, PG Bug reporting form <noreply@postgresql.org> wrote:
>> PostgreSQL-specific :: type casts for lowest values of integer types are
>> produce "Out of range" errors:
>>
>> SELECT -32768::smallint
>> ^ERROR:  smallint out of range

> The parser will represents this as the numeric portion, 32768, and a “-“ in an
> expression of type AEXPR_OP.

Right.  The point is that :: binds more tightly than unary minus[1],
so this is read as "-(32768::smallint)", and the out-of-range failure
is entirely appropriate.  You can avoid the problem with
(-32768)::smallint, or as you mentioned with '-32768'::smallint.

While we hear complaints about this regularly, I do not think that
changing the precedence order would be a good idea.  It's at least
conceivable that the behavior of the unary-minus operator would be
different for different datatypes, so enforcing the datatype selection
before applying the operator seems like the right decision from an
abstract-data-type standpoint.  (This argument explains why :: has
such a high precedence to begin with.)  You can even construct cases,
admittedly lame, where changing the precedence would result in failures
where there had been none before.

            regards, tom lane

[1] https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-PRECEDENCE


Re: BUG #15071: Error in PostgreSQL-specific :: type cast

От
Francisco Olarte
Дата:
On Fri, Feb 16, 2018 at 12:57 PM, PG Bug reporting form
<noreply@postgresql.org> wrote:

...
> SELECT -32768::smallint
> ^ERROR:  smallint out of range

This is interpreted as -(32768::smallint)

...
> Standard-syntax type casts are workes correctly:
> SELECT cast(-32768 as smallint)

This is not.

When in doubt, put parenthesis

postgres=# select (-32768)::smallint;
  int2
--------
 -32768
(1 row)

postgres=# select -(32768::smallint);
ERROR:  smallint out of range
postgres=# select -32768::smallint;
ERROR:  smallint out of range

And IIRC, expression with implicit casts ( like when comparing
constnat to columns) work because they use the conversion from
text/unknown...

postgres=# select '-32768'::smallint;
  int2
--------
 -32768
(1 row)

Francisco Olarte.