ADO Select Problem

ADO Select Problem

am 03.02.2007 00:29:35 von dmurray

Greetings,

For years, I've used the following construct for indexed, single-row
retrievals:

$sh = $dbh->prepare("select col from tbl where key = ?");
$sh->execute();
@ar = $sh->fetchrow_array();
if ($#ar > -1) {...

I got bit today by a problem either in ADO.pm (2.96) or ADO itself.
Very small sample program to reproduce problem:

#!/usr/bin/perl -w
use DBI;
use strict;
$|++;

my $wbh = DBI->connect("dbi:ADO:Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=db", 'user', 'pass', { RaiseError => 0, PrintError => 0 });
die "connect failed: " . DBI::errstr . "\n" if ! $wbh;

my $sh = $wbh->prepare("select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?");
$sh->trace(9);
print "\nexec 7861700\n\n";
my $r = $sh->execute('7861700','7'); # row does not exist
print "\n\nfetch 7861700\n\n";
my @ar = $sh->fetchrow_array();
print "\n\nexec 720021448\n\n";
$r = $sh->execute('720021448','8'); # row does not exist
# however 7200214,8 DOES exist
print "\n\nfetch 720021448\n\n";
my @br = $sh->fetchrow_array();
print "\nfailed\n\n" if ($br[1] && $br[1] ne '720021448');
print "\n\ndisco\n";
$wbh->disconnect();

My problem is, the second fetch returns the wrong row
(prod_num=7200214). In the program that does the meaningful work, I
have a check to see if the row doesn't exist (by looking at $#br), but
that succeeds, with the wrong data. A subsequent update statement (on
a different handle) then fails because the row is not in the table.

During testing, if I comment out the first fetch, the second fails
properly. My workaround is to change my coding style from

$sh->execute();
my @ar = $sh->fethcrow_array();

to

if ($sh->execute() != 0) {
my @ar = $sh->fetchrow_array();
}

But, I don't think the correct behavior is to return the wrong row.
It looks like (just a guess) that the size of bind_param 1 is getting
truncated during the failed first call, but the below trace doesn't
show that happening.

If I get any extra time (this took long enough to track down) I'll
play with { ado_size => 9 } as a bind_param.

Trace and more details follow.

TIA,
Dave

schema:

CREATE TABLE [dbo].[ProductXRef] (
[prod_num] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[whseloc] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[int_prod_num] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
CREATE UNIQUE CLUSTERED INDEX [pk_intxref] ON [dbo].[ProductXRef]([prod_num], [whseloc]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE UNIQUE INDEX [ix_productxref] ON [dbo].[ProductXRef]([whseloc], [int_prod_num]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO

Data: neither of the two requested rows exist in the table. The only
one that exists is the tuple ('7200214','8',NULL).

SQL Server Version 8.00.760 (SP3).
I don't know how to tell which version of ADO is installed on my
machines.
Duplicated on both XP-Pro SP3 and Windows 2003 SP1.
This is perl, v5.8.7 built for MSWin32-x86-multi-thread
(with 14 registered patches, see perl -V for more detail)

DBI::st=HASH(0x1b2e76c) trace level set to 0x0/9 (DBI @ 0x0/0) in DBI 1.53-ithread (pid 2928)

exec 7861700

-> execute for DBD::ADO::st (DBI::st=HASH(0x1b2e394)~0x1b2e76c '7861700' '7') thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1105 via at p1.pl line 12
1 <> FETCH= 'select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?' ('Statement' from cache) at C:/perl/site/lib/DBD/ADO.pm line 1105 via at p1.pl line 12
>> bind_param DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima1 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 12
1 -> bind_param for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 1 '7861700') thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1065
2 <> FETCH= 2 ('NUM_OF_PARAMS' from cache) at C:/perl/site/lib/DBD/ADO.pm line 1065
>> trace_msg DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @3 g0 ima5 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1091
2 -> trace_msg in DBD::_::common for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER ' -- Type : 200 7
' 5) thr#2247b4
-- Type : 200 7
2 <- trace_msg= 1 at C:/perl/site/lib/DBD/ADO.pm line 1091
1 <- bind_param= 1 at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 12
>> bind_param DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima1 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 12
1 -> bind_param for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 2 '7') thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1065
2 <> FETCH= 2 ('NUM_OF_PARAMS' from cache) at C:/perl/site/lib/DBD/ADO.pm line 1065
>> trace_msg DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @3 g0 ima5 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1091
2 -> trace_msg for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER ' -- Type : 200 1
' 5) thr#2247b4
-- Type : 200 1
2 <- trace_msg= 1 at C:/perl/site/lib/DBD/ADO.pm line 1091
1 <- bind_param= 1 at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 12
>> STORE DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima41c pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1186 via at p1.pl line 12
1 -> STORE for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'Statement' 'select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?') thr#2247b4
1 <- STORE= 'select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?' at C:/perl/site/lib/DBD/ADO.pm line 1186 via at p1.pl line 12
>> STORE DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima41c pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1187 via at p1.pl line 12
1 -> STORE for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'NUM_OF_FIELDS' 3) thr#2247b4
STORE DBI::st=HASH(0x1b2e76c) 'NUM_OF_FIELDS' => 3
1 <- STORE= 1 at C:/perl/site/lib/DBD/ADO.pm line 1187 via at p1.pl line 12
>> STORE DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima41c pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1188 via at p1.pl line 12
1 -> STORE for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'Active' 1) thr#2247b4
STORE DBI::st=HASH(0x1b2e76c) 'Active' => 1
1 <- STORE= 1 at C:/perl/site/lib/DBD/ADO.pm line 1188 via at p1.pl line 12
<- execute= '0E0' at p1.pl line 12


fetch 7861700

-> fetchrow_array in DBD::_::st for DBD::ADO::st (DBI::st=HASH(0x1b2e394)~0x1b2e76c) thr#2247b4
>> fetch DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/1 @1 g0 ima0 pid#2928) at p1.pl line 14
1 -> fetch for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER) thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1209 via at p1.pl line 14
2 -> FETCH for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'Active') thr#2247b4
.. FETCH DBI::st=HASH(0x1b2e76c) 'Active' = 1
2 <- FETCH= 1 at C:/perl/site/lib/DBD/ADO.pm line 1209 via at p1.pl line 14
>> finish DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @1 g0 ima1 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1216 via at p1.pl line 14
2 -> finish for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER) thr#2247b4
2 <- finish= 1 at C:/perl/site/lib/DBD/ADO.pm line 1216 via at p1.pl line 14
1 <- fetch= undef row-1 at p1.pl line 14
<- fetchrow_array= ( ) [0 items] row-1 at p1.pl line 14


exec 720021448

-> execute for DBD::ADO::st (DBI::st=HASH(0x1b2e394)~0x1b2e76c '720021448' '8') thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1105 via at p1.pl line 16
1 <> FETCH= 'select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?' ('Statement' from cache) at C:/perl/site/lib/DBD/ADO.pm line 1105 via at p1.pl line 16
>> bind_param DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima1 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 16
1 -> bind_param for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 1 '720021448') thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1065
2 <> FETCH= 2 ('NUM_OF_PARAMS' from cache) at C:/perl/site/lib/DBD/ADO.pm line 1065
>> trace_msg DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @3 g0 ima5 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1091
2 -> trace_msg for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER ' -- Type : 200 9
' 5) thr#2247b4
-- Type : 200 9
2 <- trace_msg= 1 at C:/perl/site/lib/DBD/ADO.pm line 1091
1 <- bind_param= 1 at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 16
>> bind_param DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima1 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 16
1 -> bind_param for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 2 '8') thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1065
2 <> FETCH= 2 ('NUM_OF_PARAMS' from cache) at C:/perl/site/lib/DBD/ADO.pm line 1065
>> trace_msg DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/3 @3 g0 ima5 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1091
2 -> trace_msg for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER ' -- Type : 200 1
' 5) thr#2247b4
-- Type : 200 1
2 <- trace_msg= 1 at C:/perl/site/lib/DBD/ADO.pm line 1091
1 <- bind_param= 1 at C:/perl/site/lib/DBD/ADO.pm line 1111 via at p1.pl line 16
>> STORE DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima41c pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1186 via at p1.pl line 16
1 -> STORE for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'Statement' 'select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?') thr#2247b4
1 <- STORE= 'select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?' at C:/perl/site/lib/DBD/ADO.pm line 1186 via at p1.pl line 16
>> STORE DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima41c pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1187 via at p1.pl line 16
1 -> STORE for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'NUM_OF_FIELDS' 3) thr#2247b4
1 <- STORE= 3 at C:/perl/site/lib/DBD/ADO.pm line 1187 via at p1.pl line 16
>> STORE DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @3 g0 ima41c pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1188 via at p1.pl line 16
1 -> STORE for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'Active' 1) thr#2247b4
STORE DBI::st=HASH(0x1b2e76c) 'Active' => 1
1 <- STORE= 1 at C:/perl/site/lib/DBD/ADO.pm line 1188 via at p1.pl line 16
<- execute= -1 at p1.pl line 16


fetch 720021448

-> fetchrow_array for DBD::ADO::st (DBI::st=HASH(0x1b2e394)~0x1b2e76c) thr#2247b4
>> fetch DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/1 @1 g0 ima0 pid#2928) at p1.pl line 18
1 -> fetch for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER) thr#2247b4
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1209 via at p1.pl line 18
2 -> FETCH for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'Active') thr#2247b4
.. FETCH DBI::st=HASH(0x1b2e76c) 'Active' = 1
2 <- FETCH= 1 at C:/perl/site/lib/DBD/ADO.pm line 1209 via at p1.pl line 18
>> FETCH DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @2 g0 ima404 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1251 via at p1.pl line 18
2 -> FETCH for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER 'ChopBlanks') thr#2247b4
.. FETCH DBI::st=HASH(0x1b2e76c) 'ChopBlanks' = ''
2 <- FETCH= '' at C:/perl/site/lib/DBD/ADO.pm line 1251 via at p1.pl line 18
>> _set_fbav DISPATCH (DBI::st=HASH(0x1b2e76c) rc1/2 @2 g0 ima0 pid#2928) at C:/perl/site/lib/DBD/ADO.pm line 1254 via at p1.pl line 18
2 -> _set_fbav in DBD::_::st for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER ARRAY(0x1b2d290)) thr#2247b4
dbih_setup_fbav for 3 fields => 0x1b2efdc
2 <- _set_fbav= [ undef '7200214' '8' ] at C:/perl/site/lib/DBD/ADO.pm line 1254 via at p1.pl line 18
1 <- fetch= [ undef '7200214' '8' ] row1 at p1.pl line 18
<- fetchrow_array= ( undef '7200214' '8' ) [3 items] row1 at p1.pl line 18

failed



disco
-> DESTROY for DBD::ADO::st (DBI::st=HASH(0x1b2e76c)~INNER) thr#2247b4
<- DESTROY= undef

Re: ADO Select Problem

am 03.02.2007 23:46:10 von ron

On Fri, 02 Feb 2007 18:29:35 -0500 (EST), David N Murray wrote:

Hi David

Good to see so much info supplied.

> my $r =3D $sh->execute('7861700','7'); # row does not exist print
> "\n\nfetch 7861700\n\n"; my @ar =3D $sh->fetchrow_array(); print
> "\n\nexec 720021448\n\n";
[snip]
> My problem is, the second fetch returns the wrong row
> (prod_num=3D7200214). In the program that does the meaningful work,

Could it be that 720021448 is simply being truncated?
--
Cheers
Ron Savage, ron@savage.net.au on 4/02/2007
http://savage.net.au/index.html
Let the record show: Microsoft is not an Australian company

Re: ADO Select Problem

am 07.02.2007 23:57:31 von opoulet

Le vendredi 02 février 2007 à 18:29 -0500, David N Murray a écrit :
> Greetings,
>
> For years, I've used the following construct for indexed, single-row
> retrievals:
>
> $sh = $dbh->prepare("select col from tbl where key = ?");
> $sh->execute();
> @ar = $sh->fetchrow_array();
> if ($#ar > -1) {...
>
> I got bit today by a problem either in ADO.pm (2.96) or ADO itself.
> Very small sample program to reproduce problem:
>
[SNIP]
> my $wbh = DBI->connect("dbi:ADO:Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=db", 'user', 'pass', { RaiseError => 0, PrintError => 0 });
> die "connect failed: " . DBI::errstr . "\n" if ! $wbh;
>
> my $sh = $wbh->prepare("select int_prod_num, prod_num, whseloc from ProductXRef where prod_num = ? and whseloc = ?");
> $sh->trace(9);
> print "\nexec 7861700\n\n";
> my $r = $sh->execute('7861700','7'); # row does not exist
> print "\n\nfetch 7861700\n\n";
> my @ar = $sh->fetchrow_array();
> print "\n\nexec 720021448\n\n";
> $r = $sh->execute('720021448','8'); # row does not exist
> # however 7200214,8 DOES exist
> print "\n\nfetch 720021448\n\n";
> my @br = $sh->fetchrow_array();
> print "\nfailed\n\n" if ($br[1] && $br[1] ne '720021448');
> print "\n\ndisco\n";
> $wbh->disconnect();
>
> My problem is, the second fetch returns the wrong row
> (prod_num=7200214). In the program that does the meaningful work, I
> have a check to see if the row doesn't exist (by looking at $#br), but
> that succeeds, with the wrong data. A subsequent update statement (on
> a different handle) then fails because the row is not in the table.
[SNIP]

David,

I have been bitten by this. It is, if I remember correctly, cause by
a bug somewhere within ADO. Searching in the list archives should give
you further info.

What is happening, when you use parametric queries, is that the "length"
of the parameters becomes "stuck" to the length of the first parameters
executed. This results in the subsequent parameters being truncated
during calls... and giving you "incorrect" results.

You have noticed this already.

What I do, is that I force a first execute using parameters with lengths
equal to the maximum size of the column, i.e from your example & schema:

$sh->execute( '0' x 50 , '0' x50 );


Note that this issue is hinted in the CAVEATS, ADO Providers part of
DBD::ADO

Cheers,
Olivier