Function returns wrong data after datatype change

From: Jeff Trout <threshar(at)torgo(dot)978(dot)org>
To: pgsql-bugs(at)postgresql(dot)org
Subject: Function returns wrong data after datatype change
Date: 2007-01-24 15:15:03
Message-ID: 2C1DB953-56FA-4147-B368-69D9F2A3571C@torgo.978.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

I just ran across this, and I do not think it is entirely a PG bug or
even something that the backend can detect and handle.
The problem stems from swapping a table definition from under a
function. I had a rather large table that had a number of double
precision (dp) fields, and in a battle to make it smaller, thus fit
more in ram, I changed it to float4 (real). I did not do it with
alter table .. type .. I made a new table, insert into newtbl select
* from oldtbl; then switched the names. When trying to induce this
error if I reloaded the function I use to induce it PG does complain
about a datatype mismatch.

However, one thing that happens is you can successfully pg_dump the
new db (with the altered table) and load it and that function will
not complain.

Here's a self contained example.

createdb broken1
psql broken1

create table brokendp
(
cik int,
trade_date timestamp,
open_price double precision,
high_price double precision,
low_price double precision,
close_price double precision,
volume bigint,
id int
);

insert into brokendp values (803016, '19940103', 0, 9.375, 9.375,
9.375, 200, 9644195);
insert into brokendp values (12345, '19950101', 1.12, 2.23, 3.34,
4.45, 1000, 1234567);

create or replace function getBrokenDP(int)
returns double precision
as $$
select close_price
from brokendp
where cik = $1
order by trade_date asc
limit 1
$$
language 'sql';

select '803', getbrokendp(803016);
select '123', getbrokendp(12345);

create table newbrokendp
(
cik int,
trade_date timestamp,
open_price real,
high_price real,
low_price real,
close_price real,
volume bigint,
id int
);

--
-- I do not htink there is anything we can do about
-- this from a PG perspective.
--
insert into newbrokendp select * from brokendp;
alter table brokendp rename to oldbrokendp;
alter table newbrokendp rename to brokendp;

select 'switch';

select '803', getbrokendp(803016);
select '123', getbrokendp(12345);

commit;
\q

pg_dump broken1 > broken1.sql
createdb broken2
psql -f broken1.sql broken2

You'll see the numbers go radically different
(ie 9.375 changing to 5.39500333695425e-315)

and when you restore the backup, the getBrokenDP function will not
make a datatype complaint, so this error will go on for a long time
before it creeps up somewhere.

--
Jeff Trout <jeff(at)jefftrout(dot)com>
http://www.dellsmartexitin.com/
http://www.stuarthamm.net/

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message James Becerra 2007-01-24 16:10:38 BUG #2929: Error opening 5432 port
Previous Message Jaume Catarineu 2007-01-24 12:34:14 BUG #2927: Trigger execution hides foreign key error