Skip Menu |

This queue is for tickets about the DBD-SQLite CPAN distribution.

Report information
The Basics
Id: 61135
Status: rejected
Priority: 0/
Queue: DBD-SQLite

People
Owner: Nobody in particular
Requestors: tvmaly [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 1.29
Fixed in: (no value)



Subject: multiple execute and fetch in nested loop producing wrong values
When attempting to loop over values returned from one statement to execute against a statement twice for two different values, the fetchrow_arrayref returns the same exact data and the memory address is the same for each reference. I have prepared a test code that produces the problem. I have found it to be broken on both a perl linux distribution and a strawberry perl distribution both 5.8.x . The test should be run first with the --create to generate the sqlite then with the --load to populate the data. Finally run it with the --test to generate the file report.csv. You will see the following results in the file 1 51 Mr. 51 51 Main Street 1 51 Mr. 51 51 Main Street 2 52 Mr. 52 52 Main Street 2 52 Mr. 52 52 Main Street But you should see the results as 1 1 Mr. 1 1 Main Street 1 51 Mr. 51 51 Main Street 2 2 Mr. 2 2 Main Street 2 52 Mr. 52 52 Main Street
Subject: sqlt.pl
#!/usr/bin/perl use DBI; use IO::File; use Getopt::Long; my $args = {}; my $ok = GetOptions ( 'create' => \$args->{CREATE}, 'load' => \$args->{LOAD}, 'test' => \$args->{TEST} ); my $dbh = connection(); if(defined($args->{CREATE})) { $dbh->do(qq{ CREATE TABLE IF NOT EXISTS applicants ( id INTEGER PRIMARY KEY NOT NULL, title VARCHAR(80), street1 VARCHAR(36) )}); $dbh->do(qq{ CREATE TABLE IF NOT EXISTS matches ( id INTEGER PRIMARY KEY NOT NULL, applicant_id1 INTEGER NOT NULL, applicant_id2 INTEGER NOT NULL, score NUMERIC(20,3) )}); $dbh->do(qq{CREATE INDEX IF NOT EXISTS ma_app1_idx ON matches(applicant_id1)}) or die($dbh->errstr); $dbh->do(qq{CREATE INDEX IF NOT EXISTS ma_app2_idx ON matches(applicant_id2)}) or die($dbh->errstr); } if(defined($args->{LOAD})) { my $ith = $dbh->prepare(qq{INSERT INTO applicants (title,street1) VALUES(?,?)}) or die($dbh->errstr); my $jth = $dbh->prepare(qq{INSERT INTO matches (applicant_id1,applicant_id2,score) VALUES(?,?,?)}) or die($dbh->errstr); my $title = 'Mr. '; my $street = ' Main Street'; my $ft = ""; my $fs = ""; foreach my $i (1..100) { $ft = $title . $i; $fs = $i . $street; $ith->execute($ft,$fs); } $ith->finish() if $ith; my $off = 50; foreach my $i (1..50) { $jth->execute($i,$off+$i,100); } $jth->finish() if $jth; } if(defined($args->{TEST})) { print "REPORTING\n"; my $fh = IO::File->new('report.csv',">") or die($!); my $mth = $dbh->prepare(qq{SELECT id,applicant_id1,applicant_id2 from matches where id < ? order by id}) or die($dbh->errstr); my $sth = $dbh->prepare(qq{SELECT id,title,street1 from applicants where id=?}) or die($dbh->errstr); my $ar = []; my $br = []; my $cr = []; $mth->execute(3); my ($a1,$a2); while($ar = $mth->fetchrow_arrayref) { $a1 = $ar->[1]; $a2 = $ar->[2]; $sth->execute($a1); $br = $sth->fetchrow_arrayref; $sth->execute($a2); $cr = $sth->fetchrow_arrayref; print {$fh} $ar->[0] . ','. join(',',@$br) . "\n"; print {$fh} $ar->[0] . ','. join(',',@$cr) . "\n"; } $mth->finish() if $mth; $sth->finish() if $sth; $fh->close() if $fh; print "DONE REPORTING\n"; } sub connection { my $dbh = DBI->connect("dbi:SQLite:dbname=test.sqlt","","") or die($!); $dbh->do(qq{PRAGMA synchronous=OFF;}) or die($dbh->errstr); $dbh->do(qq{PRAGMA temp_store=MEMORY;}) or die($dbh->errstr); return $dbh; }
Hi. This is not a bug, but a well-known caveat when you use "fetchrow_arrayref". See DBI documentation for details. http://search.cpan.org/dist/DBI/DBI.pm#fetchrow_arrayref (see the last note) If you want to do what you have done in your test script, you might want to use "fetchrow_array" instead (or do what you like with the fetched array reference before you fetch another row). Kenichi On Tue Sep 07 11:12:40 2010, tvmaly@gmail.com wrote: Show quoted text
> When attempting to loop over values returned from one statement to > execute against a statement twice for two different values, the > fetchrow_arrayref returns the same exact data and the memory address
is Show quoted text
> the same for each reference. I have prepared a test code that
produces Show quoted text
> the problem. I have found it to be broken on both a perl linux > distribution and a strawberry perl distribution both 5.8.x . The test > should be run first with the --create to generate the sqlite then with > the --load to populate the data. Finally run it with the --test to > generate the file report.csv. You will see the following results in
the Show quoted text
> file > > 1 51 Mr. 51 51 Main Street > 1 51 Mr. 51 51 Main Street > 2 52 Mr. 52 52 Main Street > 2 52 Mr. 52 52 Main Street > > But you should see the results as > > 1 1 Mr. 1 1 Main Street > 1 51 Mr. 51 51 Main Street > 2 2 Mr. 2 2 Main Street > 2 52 Mr. 52 52 Main Street