2000-01-04 17:19:34 +01:00
|
|
|
--
|
|
|
|
-- INT8
|
|
|
|
-- Test int8 64-bit integers.
|
|
|
|
--
|
|
|
|
CREATE TABLE INT8_TBL(q1 int8, q2 int8);
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL VALUES(' 123 ',' 456');
|
|
|
|
INSERT INTO INT8_TBL VALUES('123 ','4567890123456789');
|
2000-01-04 17:19:34 +01:00
|
|
|
INSERT INTO INT8_TBL VALUES('4567890123456789','123');
|
2008-10-05 16:26:30 +02:00
|
|
|
INSERT INTO INT8_TBL VALUES(+4567890123456789,'4567890123456789');
|
|
|
|
INSERT INTO INT8_TBL VALUES('+4567890123456789','-4567890123456789');
|
2004-03-11 03:11:14 +01:00
|
|
|
-- bad inputs
|
|
|
|
INSERT INTO INT8_TBL(q1) VALUES (' ');
|
2018-07-22 23:58:01 +02:00
|
|
|
ERROR: invalid input syntax for type bigint: " "
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' ');
|
|
|
|
^
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL(q1) VALUES ('xxx');
|
2018-07-22 23:58:01 +02:00
|
|
|
ERROR: invalid input syntax for type bigint: "xxx"
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('xxx');
|
|
|
|
^
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
|
2004-10-04 16:42:48 +02:00
|
|
|
ERROR: value "3908203590239580293850293850329485" is out of range for type bigint
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('39082035902395802938502938...
|
|
|
|
^
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
|
2004-10-04 16:42:48 +02:00
|
|
|
ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340...
|
|
|
|
^
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL(q1) VALUES ('- 123');
|
2018-07-22 23:58:01 +02:00
|
|
|
ERROR: invalid input syntax for type bigint: "- 123"
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('- 123');
|
|
|
|
^
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
|
2018-07-22 23:58:01 +02:00
|
|
|
ERROR: invalid input syntax for type bigint: " 345 5"
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
|
|
|
|
^
|
2004-03-11 03:11:14 +01:00
|
|
|
INSERT INTO INT8_TBL(q1) VALUES ('');
|
2018-07-22 23:58:01 +02:00
|
|
|
ERROR: invalid input syntax for type bigint: ""
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: INSERT INTO INT8_TBL(q1) VALUES ('');
|
|
|
|
^
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT * FROM INT8_TBL;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2008-10-05 16:26:30 +02:00
|
|
|
-- int8/int8 cmp
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 = 4567890123456789;
|
|
|
|
q1 | q2
|
|
|
|
------------------+------------------
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 <> 4567890123456789;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 < 4567890123456789;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 > 4567890123456789;
|
|
|
|
q1 | q2
|
|
|
|
----+----
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 <= 4567890123456789;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 >= 4567890123456789;
|
|
|
|
q1 | q2
|
|
|
|
------------------+------------------
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
-- int8/int4 cmp
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 = 456;
|
|
|
|
q1 | q2
|
|
|
|
-----+-----
|
|
|
|
123 | 456
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 <> 456;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(4 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 < 456;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 > 456;
|
|
|
|
q1 | q2
|
|
|
|
------------------+------------------
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 <= 456;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 >= 456;
|
|
|
|
q1 | q2
|
|
|
|
------------------+------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
-- int4/int8 cmp
|
|
|
|
SELECT * FROM INT8_TBL WHERE 123 = q1;
|
|
|
|
q1 | q2
|
|
|
|
-----+------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE 123 <> q1;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE 123 < q1;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE 123 > q1;
|
|
|
|
q1 | q2
|
|
|
|
----+----
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE 123 <= q1;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE 123 >= q1;
|
|
|
|
q1 | q2
|
|
|
|
-----+------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
-- int8/int2 cmp
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 = '456'::int2;
|
|
|
|
q1 | q2
|
|
|
|
-----+-----
|
|
|
|
123 | 456
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 <> '456'::int2;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(4 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 < '456'::int2;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 > '456'::int2;
|
|
|
|
q1 | q2
|
|
|
|
------------------+------------------
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 <= '456'::int2;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE q2 >= '456'::int2;
|
|
|
|
q1 | q2
|
|
|
|
------------------+------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
-- int2/int8 cmp
|
|
|
|
SELECT * FROM INT8_TBL WHERE '123'::int2 = q1;
|
|
|
|
q1 | q2
|
|
|
|
-----+------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE '123'::int2 <> q1;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE '123'::int2 < q1;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE '123'::int2 > q1;
|
|
|
|
q1 | q2
|
|
|
|
----+----
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE '123'::int2 <= q1;
|
|
|
|
q1 | q2
|
|
|
|
------------------+-------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
4567890123456789 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
4567890123456789 | -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT * FROM INT8_TBL WHERE '123'::int2 >= q1;
|
|
|
|
q1 | q2
|
|
|
|
-----+------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4567890123456789
|
|
|
|
(2 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, q1 AS plus, -q1 AS minus FROM INT8_TBL;
|
|
|
|
five | plus | minus
|
|
|
|
------+------------------+-------------------
|
|
|
|
| 123 | -123
|
|
|
|
| 123 | -123
|
|
|
|
| 4567890123456789 | -4567890123456789
|
|
|
|
| 4567890123456789 | -4567890123456789
|
|
|
|
| 4567890123456789 | -4567890123456789
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, q1, q2, q1 + q2 AS plus FROM INT8_TBL;
|
|
|
|
five | q1 | q2 | plus
|
|
|
|
------+------------------+-------------------+------------------
|
|
|
|
| 123 | 456 | 579
|
|
|
|
| 123 | 4567890123456789 | 4567890123456912
|
|
|
|
| 4567890123456789 | 123 | 4567890123456912
|
|
|
|
| 4567890123456789 | 4567890123456789 | 9135780246913578
|
|
|
|
| 4567890123456789 | -4567890123456789 | 0
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
|
|
|
|
five | q1 | q2 | minus
|
|
|
|
------+------------------+-------------------+-------------------
|
|
|
|
| 123 | 456 | -333
|
|
|
|
| 123 | 4567890123456789 | -4567890123456666
|
|
|
|
| 4567890123456789 | 123 | 4567890123456666
|
|
|
|
| 4567890123456789 | 4567890123456789 | 0
|
|
|
|
| 4567890123456789 | -4567890123456789 | 9135780246913578
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2004-10-04 16:42:48 +02:00
|
|
|
SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL;
|
|
|
|
ERROR: bigint out of range
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
|
1998-07-08 16:29:09 +02:00
|
|
|
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
|
2000-01-04 17:19:34 +01:00
|
|
|
three | q1 | q2 | multiply
|
|
|
|
-------+------------------+------------------+--------------------
|
|
|
|
| 123 | 456 | 56088
|
|
|
|
| 123 | 4567890123456789 | 561850485185185047
|
|
|
|
| 4567890123456789 | 123 | 561850485185185047
|
1998-07-08 16:29:09 +02:00
|
|
|
(3 rows)
|
|
|
|
|
2008-10-05 16:26:30 +02:00
|
|
|
SELECT '' AS five, q1, q2, q1 / q2 AS divide, q1 % q2 AS mod FROM INT8_TBL;
|
|
|
|
five | q1 | q2 | divide | mod
|
|
|
|
------+------------------+-------------------+----------------+-----
|
|
|
|
| 123 | 456 | 0 | 123
|
|
|
|
| 123 | 4567890123456789 | 0 | 123
|
|
|
|
| 4567890123456789 | 123 | 37137318076884 | 57
|
|
|
|
| 4567890123456789 | 4567890123456789 | 1 | 0
|
|
|
|
| 4567890123456789 | -4567890123456789 | -1 | 0
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, q1, float8(q1) FROM INT8_TBL;
|
Change floating-point output format for improved performance.
Previously, floating-point output was done by rounding to a specific
decimal precision; by default, to 6 or 15 decimal digits (losing
information) or as requested using extra_float_digits. Drivers that
wanted exact float values, and applications like pg_dump that must
preserve values exactly, set extra_float_digits=3 (or sometimes 2 for
historical reasons, though this isn't enough for float4).
Unfortunately, decimal rounded output is slow enough to become a
noticable bottleneck when dealing with large result sets or COPY of
large tables when many floating-point values are involved.
Floating-point output can be done much faster when the output is not
rounded to a specific decimal length, but rather is chosen as the
shortest decimal representation that is closer to the original float
value than to any other value representable in the same precision. The
recently published Ryu algorithm by Ulf Adams is both relatively
simple and remarkably fast.
Accordingly, change float4out/float8out to output shortest decimal
representations if extra_float_digits is greater than 0, and make that
the new default. Applications that need rounded output can set
extra_float_digits back to 0 or below, and take the resulting
performance hit.
We make one concession to portability for systems with buggy
floating-point input: we do not output decimal values that fall
exactly halfway between adjacent representable binary values (which
would rely on the reader doing round-to-nearest-even correctly). This
is known to be a problem at least for VS2013 on Windows.
Our version of the Ryu code originates from
https://github.com/ulfjack/ryu/ at commit c9c3fb1979, but with the
following (significant) modifications:
- Output format is changed to use fixed-point notation for small
exponents, as printf would, and also to use lowercase 'e', a
minimum of 2 exponent digits, and a mandatory sign on the exponent,
to keep the formatting as close as possible to previous output.
- The output of exact midpoint values is disabled as noted above.
- The integer fast-path code is changed somewhat (since we have
fixed-point output and the upstream did not).
- Our project style has been largely applied to the code with the
exception of C99 declaration-after-statement, which has been
retained as an exception to our present policy.
- Most of upstream's debugging and conditionals are removed, and we
use our own configure tests to determine things like uint128
availability.
Changing the float output format obviously affects a number of
regression tests. This patch uses an explicit setting of
extra_float_digits=0 for test output that is not expected to be
exactly reproducible (e.g. due to numerical instability or differing
algorithms for transcendental functions).
Conversions from floats to numeric are unchanged by this patch. These
may appear in index expressions and it is not yet clear whether any
change should be made, so that can be left for another day.
This patch assumes that the only supported floating point format is
now IEEE format, and the documentation is updated to reflect that.
Code by me, adapting the work of Ulf Adams and other contributors.
References:
https://dl.acm.org/citation.cfm?id=3192369
Reviewed-by: Tom Lane, Andres Freund, Donald Dong
Discussion: https://postgr.es/m/87r2el1bx6.fsf@news-spur.riddles.org.uk
2019-02-13 16:20:33 +01:00
|
|
|
five | q1 | float8
|
|
|
|
------+------------------+-----------------------
|
|
|
|
| 123 | 123
|
|
|
|
| 123 | 123
|
|
|
|
| 4567890123456789 | 4.567890123456789e+15
|
|
|
|
| 4567890123456789 | 4.567890123456789e+15
|
|
|
|
| 4567890123456789 | 4.567890123456789e+15
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, q2, float8(q2) FROM INT8_TBL;
|
Change floating-point output format for improved performance.
Previously, floating-point output was done by rounding to a specific
decimal precision; by default, to 6 or 15 decimal digits (losing
information) or as requested using extra_float_digits. Drivers that
wanted exact float values, and applications like pg_dump that must
preserve values exactly, set extra_float_digits=3 (or sometimes 2 for
historical reasons, though this isn't enough for float4).
Unfortunately, decimal rounded output is slow enough to become a
noticable bottleneck when dealing with large result sets or COPY of
large tables when many floating-point values are involved.
Floating-point output can be done much faster when the output is not
rounded to a specific decimal length, but rather is chosen as the
shortest decimal representation that is closer to the original float
value than to any other value representable in the same precision. The
recently published Ryu algorithm by Ulf Adams is both relatively
simple and remarkably fast.
Accordingly, change float4out/float8out to output shortest decimal
representations if extra_float_digits is greater than 0, and make that
the new default. Applications that need rounded output can set
extra_float_digits back to 0 or below, and take the resulting
performance hit.
We make one concession to portability for systems with buggy
floating-point input: we do not output decimal values that fall
exactly halfway between adjacent representable binary values (which
would rely on the reader doing round-to-nearest-even correctly). This
is known to be a problem at least for VS2013 on Windows.
Our version of the Ryu code originates from
https://github.com/ulfjack/ryu/ at commit c9c3fb1979, but with the
following (significant) modifications:
- Output format is changed to use fixed-point notation for small
exponents, as printf would, and also to use lowercase 'e', a
minimum of 2 exponent digits, and a mandatory sign on the exponent,
to keep the formatting as close as possible to previous output.
- The output of exact midpoint values is disabled as noted above.
- The integer fast-path code is changed somewhat (since we have
fixed-point output and the upstream did not).
- Our project style has been largely applied to the code with the
exception of C99 declaration-after-statement, which has been
retained as an exception to our present policy.
- Most of upstream's debugging and conditionals are removed, and we
use our own configure tests to determine things like uint128
availability.
Changing the float output format obviously affects a number of
regression tests. This patch uses an explicit setting of
extra_float_digits=0 for test output that is not expected to be
exactly reproducible (e.g. due to numerical instability or differing
algorithms for transcendental functions).
Conversions from floats to numeric are unchanged by this patch. These
may appear in index expressions and it is not yet clear whether any
change should be made, so that can be left for another day.
This patch assumes that the only supported floating point format is
now IEEE format, and the documentation is updated to reflect that.
Code by me, adapting the work of Ulf Adams and other contributors.
References:
https://dl.acm.org/citation.cfm?id=3192369
Reviewed-by: Tom Lane, Andres Freund, Donald Dong
Discussion: https://postgr.es/m/87r2el1bx6.fsf@news-spur.riddles.org.uk
2019-02-13 16:20:33 +01:00
|
|
|
five | q2 | float8
|
|
|
|
------+-------------------+------------------------
|
|
|
|
| 456 | 456
|
|
|
|
| 4567890123456789 | 4.567890123456789e+15
|
|
|
|
| 123 | 123
|
|
|
|
| 4567890123456789 | 4.567890123456789e+15
|
|
|
|
| -4567890123456789 | -4.567890123456789e+15
|
2008-10-05 16:26:30 +02:00
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT 37 + q1 AS plus4 FROM INT8_TBL;
|
|
|
|
plus4
|
|
|
|
------------------
|
|
|
|
160
|
|
|
|
160
|
|
|
|
4567890123456826
|
|
|
|
4567890123456826
|
|
|
|
4567890123456826
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT 37 - q1 AS minus4 FROM INT8_TBL;
|
|
|
|
minus4
|
|
|
|
-------------------
|
|
|
|
-86
|
|
|
|
-86
|
|
|
|
-4567890123456752
|
|
|
|
-4567890123456752
|
|
|
|
-4567890123456752
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL;
|
|
|
|
five | twice int4
|
|
|
|
------+------------------
|
|
|
|
| 246
|
|
|
|
| 246
|
|
|
|
| 9135780246913578
|
|
|
|
| 9135780246913578
|
|
|
|
| 9135780246913578
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2000-01-04 17:19:34 +01:00
|
|
|
SELECT '' AS five, q1 * 2 AS "twice int4" FROM INT8_TBL;
|
|
|
|
five | twice int4
|
|
|
|
------+------------------
|
|
|
|
| 246
|
|
|
|
| 246
|
|
|
|
| 9135780246913578
|
|
|
|
| 9135780246913578
|
|
|
|
| 9135780246913578
|
1998-07-08 16:29:09 +02:00
|
|
|
(5 rows)
|
|
|
|
|
2008-10-05 16:26:30 +02:00
|
|
|
-- int8 op int4
|
|
|
|
SELECT q1 + 42::int4 AS "8plus4", q1 - 42::int4 AS "8minus4", q1 * 42::int4 AS "8mul4", q1 / 42::int4 AS "8div4" FROM INT8_TBL;
|
|
|
|
8plus4 | 8minus4 | 8mul4 | 8div4
|
|
|
|
------------------+------------------+--------------------+-----------------
|
|
|
|
165 | 81 | 5166 | 2
|
|
|
|
165 | 81 | 5166 | 2
|
|
|
|
4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733
|
|
|
|
4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733
|
|
|
|
4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
-- int4 op int8
|
|
|
|
SELECT 246::int4 + q1 AS "4plus8", 246::int4 - q1 AS "4minus8", 246::int4 * q1 AS "4mul8", 246::int4 / q1 AS "4div8" FROM INT8_TBL;
|
|
|
|
4plus8 | 4minus8 | 4mul8 | 4div8
|
|
|
|
------------------+-------------------+---------------------+-------
|
|
|
|
369 | 123 | 30258 | 2
|
|
|
|
369 | 123 | 30258 | 2
|
|
|
|
4567890123457035 | -4567890123456543 | 1123700970370370094 | 0
|
|
|
|
4567890123457035 | -4567890123456543 | 1123700970370370094 | 0
|
|
|
|
4567890123457035 | -4567890123456543 | 1123700970370370094 | 0
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
-- int8 op int2
|
|
|
|
SELECT q1 + 42::int2 AS "8plus2", q1 - 42::int2 AS "8minus2", q1 * 42::int2 AS "8mul2", q1 / 42::int2 AS "8div2" FROM INT8_TBL;
|
|
|
|
8plus2 | 8minus2 | 8mul2 | 8div2
|
|
|
|
------------------+------------------+--------------------+-----------------
|
|
|
|
165 | 81 | 5166 | 2
|
|
|
|
165 | 81 | 5166 | 2
|
|
|
|
4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733
|
|
|
|
4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733
|
|
|
|
4567890123456831 | 4567890123456747 | 191851385185185138 | 108759288653733
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
-- int2 op int8
|
|
|
|
SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 AS "2mul8", 246::int2 / q1 AS "2div8" FROM INT8_TBL;
|
|
|
|
2plus8 | 2minus8 | 2mul8 | 2div8
|
|
|
|
------------------+-------------------+---------------------+-------
|
|
|
|
369 | 123 | 30258 | 2
|
|
|
|
369 | 123 | 30258 | 2
|
|
|
|
4567890123457035 | -4567890123456543 | 1123700970370370094 | 0
|
|
|
|
4567890123457035 | -4567890123456543 | 1123700970370370094 | 0
|
|
|
|
4567890123457035 | -4567890123456543 | 1123700970370370094 | 0
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT q2, abs(q2) FROM INT8_TBL;
|
|
|
|
q2 | abs
|
|
|
|
-------------------+------------------
|
|
|
|
456 | 456
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
123 | 123
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
-4567890123456789 | 4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT min(q1), min(q2) FROM INT8_TBL;
|
|
|
|
min | min
|
|
|
|
-----+-------------------
|
|
|
|
123 | -4567890123456789
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT max(q1), max(q2) FROM INT8_TBL;
|
|
|
|
max | max
|
|
|
|
------------------+------------------
|
|
|
|
4567890123456789 | 4567890123456789
|
|
|
|
(1 row)
|
|
|
|
|
2000-03-08 02:34:41 +01:00
|
|
|
-- TO_CHAR()
|
|
|
|
--
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_1, to_char(q1, '9G999G999G999G999G999'), to_char(q2, '9,999,999,999,999,999')
|
2000-03-08 02:34:41 +01:00
|
|
|
FROM INT8_TBL;
|
|
|
|
to_char_1 | to_char | to_char
|
|
|
|
-----------+------------------------+------------------------
|
|
|
|
| 123 | 456
|
|
|
|
| 123 | 4,567,890,123,456,789
|
|
|
|
| 4,567,890,123,456,789 | 123
|
|
|
|
| 4,567,890,123,456,789 | 4,567,890,123,456,789
|
|
|
|
| 4,567,890,123,456,789 | -4,567,890,123,456,789
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_2, to_char(q1, '9G999G999G999G999G999D999G999'), to_char(q2, '9,999,999,999,999,999.999,999')
|
|
|
|
FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_2 | to_char | to_char
|
|
|
|
-----------+--------------------------------+--------------------------------
|
|
|
|
| 123.000,000 | 456.000,000
|
|
|
|
| 123.000,000 | 4,567,890,123,456,789.000,000
|
|
|
|
| 4,567,890,123,456,789.000,000 | 123.000,000
|
|
|
|
| 4,567,890,123,456,789.000,000 | 4,567,890,123,456,789.000,000
|
|
|
|
| 4,567,890,123,456,789.000,000 | -4,567,890,123,456,789.000,000
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_3, to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2 * -1), '9999999999999999.999PR')
|
2000-03-08 02:34:41 +01:00
|
|
|
FROM INT8_TBL;
|
|
|
|
to_char_3 | to_char | to_char
|
|
|
|
-----------+--------------------+------------------------
|
|
|
|
| <123> | <456.000>
|
|
|
|
| <123> | <4567890123456789.000>
|
|
|
|
| <4567890123456789> | <123.000>
|
|
|
|
| <4567890123456789> | <4567890123456789.000>
|
2003-03-27 17:35:31 +01:00
|
|
|
| <4567890123456789> | 4567890123456789.000
|
2000-03-08 02:34:41 +01:00
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999')
|
2000-03-08 02:34:41 +01:00
|
|
|
FROM INT8_TBL;
|
|
|
|
to_char_4 | to_char | to_char
|
|
|
|
-----------+-------------------+-------------------
|
|
|
|
| 123- | -456
|
|
|
|
| 123- | -4567890123456789
|
|
|
|
| 4567890123456789- | -123
|
|
|
|
| 4567890123456789- | -4567890123456789
|
|
|
|
| 4567890123456789- | +4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL;
|
2003-03-27 17:35:31 +01:00
|
|
|
to_char_5 | to_char
|
|
|
|
-----------+-------------------
|
|
|
|
| 456
|
|
|
|
| 4567890123456789
|
|
|
|
| 123
|
|
|
|
| 4567890123456789
|
2000-03-08 02:34:41 +01:00
|
|
|
| -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT '' AS to_char_6, to_char(q2, 'FMS9999999999999999') FROM INT8_TBL;
|
|
|
|
to_char_6 | to_char
|
|
|
|
-----------+-------------------
|
|
|
|
| +456
|
|
|
|
| +4567890123456789
|
|
|
|
| +123
|
|
|
|
| +4567890123456789
|
|
|
|
| -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT '' AS to_char_7, to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL;
|
|
|
|
to_char_7 | to_char
|
|
|
|
-----------+--------------------
|
|
|
|
| 456TH
|
|
|
|
| 4567890123456789TH
|
|
|
|
| 123RD
|
|
|
|
| 4567890123456789TH
|
|
|
|
| <4567890123456789>
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_8, to_char(q2, 'SG9999999999999999th') FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_8 | to_char
|
|
|
|
-----------+---------------------
|
|
|
|
| + 456th
|
|
|
|
| +4567890123456789th
|
|
|
|
| + 123rd
|
|
|
|
| +4567890123456789th
|
|
|
|
| -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_9, to_char(q2, '0999999999999999') FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_9 | to_char
|
|
|
|
-----------+-------------------
|
|
|
|
| 0000000000000456
|
|
|
|
| 4567890123456789
|
|
|
|
| 0000000000000123
|
|
|
|
| 4567890123456789
|
|
|
|
| -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_10, to_char(q2, 'S0999999999999999') FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_10 | to_char
|
|
|
|
------------+-------------------
|
|
|
|
| +0000000000000456
|
|
|
|
| +4567890123456789
|
|
|
|
| +0000000000000123
|
|
|
|
| +4567890123456789
|
|
|
|
| -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_11, to_char(q2, 'FM0999999999999999') FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_11 | to_char
|
|
|
|
------------+-------------------
|
|
|
|
| 0000000000000456
|
|
|
|
| 4567890123456789
|
|
|
|
| 0000000000000123
|
|
|
|
| 4567890123456789
|
|
|
|
| -4567890123456789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT '' AS to_char_12, to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL;
|
|
|
|
to_char_12 | to_char
|
|
|
|
------------+-----------------------
|
|
|
|
| 456.000
|
|
|
|
| 4567890123456789.000
|
|
|
|
| 123.000
|
|
|
|
| 4567890123456789.000
|
|
|
|
| -4567890123456789.000
|
|
|
|
(5 rows)
|
|
|
|
|
2010-11-23 21:27:50 +01:00
|
|
|
SELECT '' AS to_char_13, to_char(q2, 'L9999999999999999.000') FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_13 | to_char
|
|
|
|
------------+------------------------
|
|
|
|
| 456.000
|
|
|
|
| 4567890123456789.000
|
|
|
|
| 123.000
|
|
|
|
| 4567890123456789.000
|
|
|
|
| -4567890123456789.000
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT '' AS to_char_14, to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL;
|
2002-09-20 18:44:55 +02:00
|
|
|
to_char_14 | to_char
|
|
|
|
------------+--------------------
|
|
|
|
| 456.
|
|
|
|
| 4567890123456789.
|
|
|
|
| 123.
|
|
|
|
| 4567890123456789.
|
|
|
|
| -4567890123456789.
|
2000-03-08 02:34:41 +01:00
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL;
|
|
|
|
to_char_15 | to_char
|
|
|
|
------------+-------------------------------------------
|
2003-03-27 17:35:31 +01:00
|
|
|
| +4 5 6 . 0 0 0
|
|
|
|
| +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
|
|
|
|
| +1 2 3 . 0 0 0
|
|
|
|
| +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
|
|
|
|
| -4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
|
2000-03-08 02:34:41 +01:00
|
|
|
(5 rows)
|
|
|
|
|
2005-06-26 05:04:37 +02:00
|
|
|
SELECT '' AS to_char_16, to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
|
2000-03-08 02:34:41 +01:00
|
|
|
to_char_16 | to_char
|
|
|
|
------------+-----------------------------------------------------------
|
|
|
|
| text 9999 "text between quote marks" 456
|
|
|
|
| 45678 text 9012 9999 345 "text between quote marks" 6789
|
|
|
|
| text 9999 "text between quote marks" 123
|
|
|
|
| 45678 text 9012 9999 345 "text between quote marks" 6789
|
|
|
|
| -45678 text 9012 9999 345 "text between quote marks" 6789
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT '' AS to_char_17, to_char(q2, '999999SG9999999999') FROM INT8_TBL;
|
|
|
|
to_char_17 | to_char
|
|
|
|
------------+-------------------
|
|
|
|
| + 456
|
|
|
|
| 456789+0123456789
|
|
|
|
| + 123
|
|
|
|
| 456789+0123456789
|
|
|
|
| 456789-0123456789
|
|
|
|
(5 rows)
|
|
|
|
|
2008-10-05 16:26:30 +02:00
|
|
|
-- check min/max values and overflow behavior
|
2005-12-05 05:13:38 +01:00
|
|
|
select '-9223372036854775808'::int8;
|
|
|
|
int8
|
|
|
|
----------------------
|
|
|
|
-9223372036854775808
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
select '-9223372036854775809'::int8;
|
|
|
|
ERROR: value "-9223372036854775809" is out of range for type bigint
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: select '-9223372036854775809'::int8;
|
|
|
|
^
|
2005-12-05 05:13:38 +01:00
|
|
|
select '9223372036854775807'::int8;
|
|
|
|
int8
|
|
|
|
---------------------
|
|
|
|
9223372036854775807
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
select '9223372036854775808'::int8;
|
|
|
|
ERROR: value "9223372036854775808" is out of range for type bigint
|
2008-09-01 22:42:46 +02:00
|
|
|
LINE 1: select '9223372036854775808'::int8;
|
|
|
|
^
|
2008-10-05 16:26:30 +02:00
|
|
|
select -('-9223372036854775807'::int8);
|
|
|
|
?column?
|
|
|
|
---------------------
|
|
|
|
9223372036854775807
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
select -('-9223372036854775808'::int8);
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 + '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-9223372036854775800'::int8 + '-9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 - '-9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-9223372036854775800'::int8 - '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 * '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 / '0'::int8;
|
|
|
|
ERROR: division by zero
|
|
|
|
select '9223372036854775800'::int8 % '0'::int8;
|
|
|
|
ERROR: division by zero
|
|
|
|
select abs('-9223372036854775808'::int8);
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 + '100'::int4;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-9223372036854775800'::int8 - '100'::int4;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 * '100'::int4;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '100'::int4 + '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-100'::int4 - '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '100'::int4 * '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 + '100'::int2;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-9223372036854775800'::int8 - '100'::int2;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '9223372036854775800'::int8 * '100'::int2;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-9223372036854775808'::int8 / '0'::int2;
|
|
|
|
ERROR: division by zero
|
|
|
|
select '100'::int2 + '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '-100'::int2 - '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '100'::int2 * '9223372036854775800'::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
select '100'::int2 / '0'::int8;
|
|
|
|
ERROR: division by zero
|
|
|
|
SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 = 456;
|
|
|
|
q1
|
|
|
|
-----
|
|
|
|
123
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT CAST(q1 AS int4) FROM int8_tbl WHERE q2 <> 456;
|
|
|
|
ERROR: integer out of range
|
|
|
|
SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 = 456;
|
|
|
|
q1
|
|
|
|
-----
|
|
|
|
123
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT CAST(q1 AS int2) FROM int8_tbl WHERE q2 <> 456;
|
|
|
|
ERROR: smallint out of range
|
|
|
|
SELECT CAST('42'::int2 AS int8), CAST('-37'::int2 AS int8);
|
|
|
|
int8 | int8
|
|
|
|
------+------
|
|
|
|
42 | -37
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT CAST(q1 AS float4), CAST(q2 AS float8) FROM INT8_TBL;
|
Change floating-point output format for improved performance.
Previously, floating-point output was done by rounding to a specific
decimal precision; by default, to 6 or 15 decimal digits (losing
information) or as requested using extra_float_digits. Drivers that
wanted exact float values, and applications like pg_dump that must
preserve values exactly, set extra_float_digits=3 (or sometimes 2 for
historical reasons, though this isn't enough for float4).
Unfortunately, decimal rounded output is slow enough to become a
noticable bottleneck when dealing with large result sets or COPY of
large tables when many floating-point values are involved.
Floating-point output can be done much faster when the output is not
rounded to a specific decimal length, but rather is chosen as the
shortest decimal representation that is closer to the original float
value than to any other value representable in the same precision. The
recently published Ryu algorithm by Ulf Adams is both relatively
simple and remarkably fast.
Accordingly, change float4out/float8out to output shortest decimal
representations if extra_float_digits is greater than 0, and make that
the new default. Applications that need rounded output can set
extra_float_digits back to 0 or below, and take the resulting
performance hit.
We make one concession to portability for systems with buggy
floating-point input: we do not output decimal values that fall
exactly halfway between adjacent representable binary values (which
would rely on the reader doing round-to-nearest-even correctly). This
is known to be a problem at least for VS2013 on Windows.
Our version of the Ryu code originates from
https://github.com/ulfjack/ryu/ at commit c9c3fb1979, but with the
following (significant) modifications:
- Output format is changed to use fixed-point notation for small
exponents, as printf would, and also to use lowercase 'e', a
minimum of 2 exponent digits, and a mandatory sign on the exponent,
to keep the formatting as close as possible to previous output.
- The output of exact midpoint values is disabled as noted above.
- The integer fast-path code is changed somewhat (since we have
fixed-point output and the upstream did not).
- Our project style has been largely applied to the code with the
exception of C99 declaration-after-statement, which has been
retained as an exception to our present policy.
- Most of upstream's debugging and conditionals are removed, and we
use our own configure tests to determine things like uint128
availability.
Changing the float output format obviously affects a number of
regression tests. This patch uses an explicit setting of
extra_float_digits=0 for test output that is not expected to be
exactly reproducible (e.g. due to numerical instability or differing
algorithms for transcendental functions).
Conversions from floats to numeric are unchanged by this patch. These
may appear in index expressions and it is not yet clear whether any
change should be made, so that can be left for another day.
This patch assumes that the only supported floating point format is
now IEEE format, and the documentation is updated to reflect that.
Code by me, adapting the work of Ulf Adams and other contributors.
References:
https://dl.acm.org/citation.cfm?id=3192369
Reviewed-by: Tom Lane, Andres Freund, Donald Dong
Discussion: https://postgr.es/m/87r2el1bx6.fsf@news-spur.riddles.org.uk
2019-02-13 16:20:33 +01:00
|
|
|
q1 | q2
|
|
|
|
-------------+------------------------
|
|
|
|
123 | 456
|
|
|
|
123 | 4.567890123456789e+15
|
|
|
|
4.56789e+15 | 123
|
|
|
|
4.56789e+15 | 4.567890123456789e+15
|
|
|
|
4.56789e+15 | -4.567890123456789e+15
|
2008-10-05 16:26:30 +02:00
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT CAST('36854775807.0'::float4 AS int8);
|
|
|
|
int8
|
|
|
|
-------------
|
|
|
|
36854775808
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT CAST('922337203685477580700.0'::float8 AS int8);
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT CAST(q1 AS oid) FROM INT8_TBL;
|
|
|
|
ERROR: OID out of range
|
|
|
|
SELECT oid::int8 FROM pg_class WHERE relname = 'pg_class';
|
|
|
|
oid
|
|
|
|
------
|
|
|
|
1259
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- bit operations
|
|
|
|
SELECT q1, q2, q1 & q2 AS "and", q1 | q2 AS "or", q1 # q2 AS "xor", ~q1 AS "not" FROM INT8_TBL;
|
|
|
|
q1 | q2 | and | or | xor | not
|
|
|
|
------------------+-------------------+------------------+------------------+------------------+-------------------
|
|
|
|
123 | 456 | 72 | 507 | 435 | -124
|
|
|
|
123 | 4567890123456789 | 17 | 4567890123456895 | 4567890123456878 | -124
|
|
|
|
4567890123456789 | 123 | 17 | 4567890123456895 | 4567890123456878 | -4567890123456790
|
|
|
|
4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 0 | -4567890123456790
|
|
|
|
4567890123456789 | -4567890123456789 | 1 | -1 | -2 | -4567890123456790
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
SELECT q1, q1 << 2 AS "shl", q1 >> 3 AS "shr" FROM INT8_TBL;
|
|
|
|
q1 | shl | shr
|
|
|
|
------------------+-------------------+-----------------
|
|
|
|
123 | 492 | 15
|
|
|
|
123 | 492 | 15
|
|
|
|
4567890123456789 | 18271560493827156 | 570986265432098
|
|
|
|
4567890123456789 | 18271560493827156 | 570986265432098
|
|
|
|
4567890123456789 | 18271560493827156 | 570986265432098
|
|
|
|
(5 rows)
|
|
|
|
|
|
|
|
-- generate_series
|
|
|
|
SELECT * FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8);
|
|
|
|
generate_series
|
|
|
|
------------------
|
|
|
|
4567890123456789
|
|
|
|
4567890123456790
|
|
|
|
4567890123456791
|
|
|
|
4567890123456792
|
|
|
|
4567890123456793
|
|
|
|
4567890123456794
|
|
|
|
4567890123456795
|
|
|
|
4567890123456796
|
|
|
|
4567890123456797
|
|
|
|
4567890123456798
|
|
|
|
4567890123456799
|
|
|
|
(11 rows)
|
|
|
|
|
|
|
|
SELECT * FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 0);
|
|
|
|
ERROR: step size cannot equal zero
|
|
|
|
SELECT * FROM generate_series('+4567890123456789'::int8, '+4567890123456799'::int8, 2);
|
|
|
|
generate_series
|
|
|
|
------------------
|
|
|
|
4567890123456789
|
|
|
|
4567890123456791
|
|
|
|
4567890123456793
|
|
|
|
4567890123456795
|
|
|
|
4567890123456797
|
|
|
|
4567890123456799
|
|
|
|
(6 rows)
|
|
|
|
|
2010-11-20 07:07:04 +01:00
|
|
|
-- corner case
|
|
|
|
SELECT (-1::int8<<63)::text;
|
|
|
|
text
|
|
|
|
----------------------
|
|
|
|
-9223372036854775808
|
2010-11-20 04:13:11 +01:00
|
|
|
(1 row)
|
|
|
|
|
2010-11-20 07:07:04 +01:00
|
|
|
SELECT ((-1::int8<<63)+1)::text;
|
|
|
|
text
|
|
|
|
----------------------
|
|
|
|
-9223372036854775807
|
2010-11-20 04:13:11 +01:00
|
|
|
(1 row)
|
|
|
|
|
2012-11-19 18:24:25 +01:00
|
|
|
-- check sane handling of INT64_MIN overflow cases
|
|
|
|
SELECT (-9223372036854775808)::int8 * (-1)::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT (-9223372036854775808)::int8 / (-1)::int8;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT (-9223372036854775808)::int8 % (-1)::int8;
|
|
|
|
?column?
|
|
|
|
----------
|
|
|
|
0
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT (-9223372036854775808)::int8 * (-1)::int4;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT (-9223372036854775808)::int8 / (-1)::int4;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT (-9223372036854775808)::int8 % (-1)::int4;
|
|
|
|
?column?
|
|
|
|
----------
|
|
|
|
0
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
SELECT (-9223372036854775808)::int8 * (-1)::int2;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT (-9223372036854775808)::int8 / (-1)::int2;
|
|
|
|
ERROR: bigint out of range
|
|
|
|
SELECT (-9223372036854775808)::int8 % (-1)::int2;
|
|
|
|
?column?
|
|
|
|
----------
|
|
|
|
0
|
|
|
|
(1 row)
|
|
|
|
|
2015-03-25 20:54:08 +01:00
|
|
|
-- check rounding when casting from float
|
|
|
|
SELECT x, x::int8 AS int8_value
|
|
|
|
FROM (VALUES (-2.5::float8),
|
|
|
|
(-1.5::float8),
|
|
|
|
(-0.5::float8),
|
|
|
|
(0.0::float8),
|
|
|
|
(0.5::float8),
|
|
|
|
(1.5::float8),
|
|
|
|
(2.5::float8)) t(x);
|
|
|
|
x | int8_value
|
|
|
|
------+------------
|
|
|
|
-2.5 | -2
|
|
|
|
-1.5 | -2
|
|
|
|
-0.5 | 0
|
|
|
|
0 | 0
|
|
|
|
0.5 | 0
|
|
|
|
1.5 | 2
|
|
|
|
2.5 | 2
|
|
|
|
(7 rows)
|
|
|
|
|
2015-07-03 23:04:39 +02:00
|
|
|
-- check rounding when casting from numeric
|
|
|
|
SELECT x, x::int8 AS int8_value
|
|
|
|
FROM (VALUES (-2.5::numeric),
|
|
|
|
(-1.5::numeric),
|
|
|
|
(-0.5::numeric),
|
|
|
|
(0.0::numeric),
|
|
|
|
(0.5::numeric),
|
|
|
|
(1.5::numeric),
|
|
|
|
(2.5::numeric)) t(x);
|
|
|
|
x | int8_value
|
|
|
|
------+------------
|
|
|
|
-2.5 | -3
|
|
|
|
-1.5 | -2
|
|
|
|
-0.5 | -1
|
|
|
|
0.0 | 0
|
|
|
|
0.5 | 1
|
|
|
|
1.5 | 2
|
|
|
|
2.5 | 3
|
|
|
|
(7 rows)
|
|
|
|
|