int8 bug on Alpha

Started by Adriaan Joubertalmost 25 years ago9 messages
#1Adriaan Joubert
a.joubert@albourne.com

Hi,

int8 is not handled correctly on Alpha. Inserting 2^63-1, 2^63-2 and
2^61
into

create table lint (i int8);

gives

test=# select * from lint;
i
----
-1
-2
0
(3 rows)

On linux it gives the correct values:

test=# select * from lint;
i
---------------------
9223372036854775807
9223372036854775806
2305843009213693952
(3 rows)

This is postgres 7.1b4, compiled with native cc on Tru64 4.0G. I seem to
recall running the regression tests, so perhaps this is not checked?
(just looked at int8.sql, and it is not checked.)

I'm swamped, so cannot look at it right now. If nobody else can look at
it, I will get back to it in about a fortnight.

Adriaan

#2Thomas Lockhart
lockhart@alumni.caltech.edu
In reply to: Adriaan Joubert (#1)
Re: int8 bug on Alpha

int8 is not handled correctly on Alpha. Inserting 2^63-1, 2^63-2 and
2^61...

How are you doing the inserts? If you aren't coercing the "2" to be an
int8, then (afaik) the math will be done in int4, then upconverted. So,
can you confirm that your inserts look like:

insert into lint values ('9223372036854775807');

or

insert into lint select (int8 '2') ^ 61;

- Thomas

#3Adriaan Joubert
a.joubert@albourne.com
In reply to: Adriaan Joubert (#1)
Re: int8 bug on Alpha

Thomas Lockhart wrote:

int8 is not handled correctly on Alpha. Inserting 2^63-1, 2^63-2 and
2^61...

How are you doing the inserts? If you aren't coercing the "2" to be an
int8, then (afaik) the math will be done in int4, then upconverted. So,
can you confirm that your inserts look like:

insert into lint values ('9223372036854775807');

OK, that was it. I inserted without quotes. If I insert the quotes it
works. So why does it work correctly on linux without quotes?

and

insert into lint values ('9223372036854775807'::int8);

works, but

insert into lint values (9223372036854775807::int8);

doesn't. I guess in the second case it converts it to an int4 and then
recasts to an int8?

Cheers,

Adriaan

#4Thomas Lockhart
lockhart@alumni.caltech.edu
In reply to: Adriaan Joubert (#1)
Re: int8 bug on Alpha

How are you doing the inserts? If you aren't coercing the "2" to be an
int8, then (afaik) the math will be done in int4, then upconverted. So,
can you confirm that your inserts look like:
insert into lint values ('9223372036854775807');

OK, that was it. I inserted without quotes. If I insert the quotes it
works. So why does it work correctly on linux without quotes?

For integers (optional sign and all digits), the code in
src/backend/parser/scan.l uses strtol() to read the string, then checks
for failure. If it fails, the number is interpreted as a double float on
the assumption that if it could hold more digits it would succeed!

Anyway, either strtol() thinks it *should* be able to read a 64 bit
integer, or your machine is silently overflowing. I used to have a bunch
of these boxes, and I recall spending quite a bit of time discovering
that Alphas have some explicit flags which can be set at compile time
which affect run-time detection of floating point and (perhaps) integer
overflow behavior.

Can you check these possibilities? I'd look at strtol() first, then the
overflow/underflow flags second...

- Thomas

#5Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Thomas Lockhart (#4)
Re: Re: int8 bug on Alpha

For integers (optional sign and all digits), the code in
src/backend/parser/scan.l uses strtol() to read the string, then checks
for failure. If it fails, the number is interpreted as a double float on
the assumption that if it could hold more digits it would succeed!

Anyway, either strtol() thinks it *should* be able to read a 64 bit
integer, or your machine is silently overflowing. I used to have a bunch
of these boxes, and I recall spending quite a bit of time discovering
that Alphas have some explicit flags which can be set at compile time
which affect run-time detection of floating point and (perhaps) integer
overflow behavior.

Can you check these possibilities? I'd look at strtol() first, then the
overflow/underflow flags second...

Intersting that the lack of strtol() failure on Alpha is causing the
problem.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
#6Adriaan Joubert
a.joubert@albourne.com
In reply to: Adriaan Joubert (#1)
Re: int8 bug on Alpha

Anyway, either strtol() thinks it *should* be able to read a 64 bit
integer, or your machine is silently overflowing. I used to have a bunch
of these boxes, and I recall spending quite a bit of time discovering
that Alphas have some explicit flags which can be set at compile time
which affect run-time detection of floating point and (perhaps) integer
overflow behavior.

Can you check these possibilities? I'd look at strtol() first, then the
overflow/underflow flags second...

Hmm, I wrote a trivial programme parsing long ints and get the following

#include <errno.h>

main (int argc, char *argv[]) {
long int a = strtol(argv[1], (char **) 0, 10);
printf("input='%s' ld=%ld (errno %d)\n",argv[1],a,errno);
}

emily:~/Tmp/C++$ a.out 9223372036854775807
input='9223372036854775807' ld=9223372036854775807 (errno 0)
emily:~/Tmp/C++$ a.out 9223372036854775808
input='9223372036854775808' ld=9223372036854775807 (errno 34)
emily:~/Tmp/C++$ a.out 9223372036854775806
input='9223372036854775806' ld=9223372036854775806 (errno 0)
emily:~/Tmp/C++$ a.out -9223372036854775808
input='-9223372036854775808' ld=-9223372036854775808 (errno 0)

so that seems to work correctly. And I compiled with the same compiler
flags with which postgres was compiled. Apparently long is defined as
'long long int' on alpha, and I tried it with that and it works as well.

I'll have to debug this properly, but first I need to get Friday out of
the way ;-)

Adriaan

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Lockhart (#4)
Re: Re: int8 bug on Alpha

Thomas Lockhart <lockhart@alumni.caltech.edu> writes:

For integers (optional sign and all digits), the code in
src/backend/parser/scan.l uses strtol() to read the string, then checks
for failure. If it fails, the number is interpreted as a double float on
the assumption that if it could hold more digits it would succeed!

Ohhhh....

This is an Alpha, remember? long *is* 64 bits on that machine,
therefore strtol is correct to accept the number. Unfortunately,
later in the parser we assign the datatype int4, not int8, to the
"integer" constant, and so it gets truncated. make_const is making
an unwarranted assumption that T_Integer is the same as int4 --- or,
if you prefer, make_const is OK and scan.l is erroneous to use
node type T_Integer for ints that exceed 32 bits.

This is a portability bug, no question. But I'd expect it to fail
like that on all Alpha-based platforms. Adriaan, when you say it
works on Linux, are you talking about Linux/Alpha or some other
hardware?

regards, tom lane

#8Adriaan Joubert
a.joubert@albourne.com
In reply to: Adriaan Joubert (#1)
Re: Re: int8 bug on Alpha

This is a portability bug, no question. But I'd expect it to fail
like that on all Alpha-based platforms. Adriaan, when you say it
works on Linux, are you talking about Linux/Alpha or some other
hardware?

No, PC Linux. I run a database on my laptop as well.

Adriaan

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Adriaan Joubert (#3)
Re: Re: int8 bug on Alpha

Adriaan Joubert <a.joubert@albourne.com> writes:

insert into lint values ('9223372036854775807'::int8);
works, but
insert into lint values (9223372036854775807::int8);
doesn't.

Fixed, and checked on Debian Alpha.

regards, tom lane