Re: float bug? perl 5.8, DBI and oracle 10.2.0
- From: erwan@xxxxxxxxxxxx (Erwan Lemonnier)
- Date: Wed, 18 Jul 2007 11:04:05 +0200
Hi again! Thanks Tim for this thorough explanation :)
For the record, DBD::Oracle binds parameters and fetches values as strings.
Great, now we are getting closer to the heart :)
As I wrote in my first post, the problem can be triggered with the
following perl test:
-----------------<snip>---------------------------
use strict;
use warnings;
use Data::Dumper;
use Test::More tests => 1;
use Carp qw(confess);
use DBI;
# database credentials: EDIT HERE
my $ORASID = $ENV{ORACLE_SID};
my $ORAUSR = 'username';
my $ORAPWD = 'password';
my $DBC;
sub sql_execute {
my ($sql,@arg) = @_;
my $sth = $DBC->prepare($sql);
if(!$sth || $sth->err) {
confess "prepare failed for [$sql]\nbecause: [".$DBC->errstr."]";
}
$sth->execute(@arg) ||
confess "exec failed: [".$sth->errstr."]\nin query [$sql]";
return $sth;
}
# connect to oracle
($DBC = DBI->connect("dbi:Oracle:$ORASID",$ORAUSR,$ORAPWD,
{
PrintError=>0,
AutoCommit=>0,
}
)) ||
confess "failure connecting to $ORASID: ".$DBI::errstr;
# create one temporary table with one numeric column filled with test data
eval { sql_execute("DROP TABLE test_oracle_bug"); };
sql_execute("CREATE TABLE test_oracle_bug (DATA NUMBER)");
sql_execute("INSERT INTO test_oracle_bug (DATA) VALUES (1.73696)");
$DBC->commit;
# fetch numeric from table
my $ret = sql_execute("SELECT DATA FROM test_oracle_bug")->fetchrow_arrayref;
my ($val) = @$ret;
my $sum = 1.73696 - $val;
is($sum,0,"does sum $sum == 0?");
-----------------<snip>---------------------------
As you see, the numeric value is inserted in the database with:
"INSERT INTO test_oracle_bug (DATA) VALUES (1.73696)"
I therefore assume that we are passing a string forward to
DBD::Oracle, and that it is a string that gets inserted into the
column DATA of type NUMBER in oracle. If I understood Tim well, the
number 1.73696 is then stored as a decimal string in the oracle
database.
When we later retrieve this value ("my ($val) = @$ret;") from the
table, what we get in $val should then be the same string, as returned
by DBD::Oracle. A look at $val with Devel::Peek confirms this:
"Dump($val);" says:
SV = PV(0x97bf684) at 0x988aed8
REFCNT = 1
FLAGS = (PADBUSY,PADMY,POK,pPOK)
PV = 0x9aaff18 "1.73696"\0
CUR = 7
LEN = 8
No IV (integer value) or NV (native float) in this SV (scalar value),
just a PV (string).
From there on, it would seem reasonable to believe that we can excludea DBI/DBD::Oracle problem: what we are dealing with is a string
representation of 1.73696.
Now, we reach the next line of code: "my $sum = 1.73696 - $val;". This
line evals to $sum = 2.22044604925031e-16. That's the problem.
However! if I try getting the same effect from pure perl code:
-----------------<snip>---------------------------
use strict;
use warnings;
use Test::More tests => 1;
my $val = "1.73696";
my $sum = 1.73696 - $val;
is($sum,0,"sum is 0");
-----------------<snip>---------------------------
Then the test passes, $sum is 0.
In other words, "1.73696 - $val" evaluates to 0 when $val is the
string "1.736960" hardcoded in the source code, but does not when $val
is the *same* string but returned by fetchrow_arrayref. Notice here
that according to Devel::Peek, the SV of the hardcoded $val and that
of the retrieved $val are identical. But obviously, something between
them must differ, otherwise the same operation on both would yield the
same result 8(
Is there any reason why the string 1.73696 returned by
fetchrow_arrayref would differ from the string "1.73696" hardcoded in
source code?
I have a feeling that Tim's example holds the answer:
$a = 42.1; $a += 0.1 for (1..30); # add 3
$b = "$a"; # cross the client/server interface as text
print "a=$a b=$b\n";
($a == $b) ? print "Equal\n" : print "Not equal!\n";
Need to think more...
/Erwan
.
- Follow-Ups:
- Re: float bug? perl 5.8, DBI and oracle 10.2.0
- From: Erwan Lemonnier
- Re: float bug? perl 5.8, DBI and oracle 10.2.0
- From: Martin Evans
- Re: float bug? perl 5.8, DBI and oracle 10.2.0
- References:
- Re: Re: float bug? perl 5.8, DBI and oracle 10.2.0
- From: Erwan Lemonnier
- Re: float bug? perl 5.8, DBI and oracle 10.2.0
- From: Christopher Sarnowski
- Re: float bug? perl 5.8, DBI and oracle 10.2.0
- From: Tim Bunce
- Re: Re: float bug? perl 5.8, DBI and oracle 10.2.0
- Prev by Date: Re: DBD::ODBC multiple active statements (was Trouble Installing DBD::ODBC with postgresql)
- Next by Date: Re: Efficient scanning of SQL Server 2005 tables?
- Previous by thread: Re: float bug? perl 5.8, DBI and oracle 10.2.0
- Next by thread: Re: float bug? perl 5.8, DBI and oracle 10.2.0
- Index(es):
Relevant Pages
|