Subject: | DBD::Mock::Session error clobbered by subsequent method call on undef variable |
Hi,
I've noticed that when using a DBD::Mock::Session, if you exhaust the
states defined whilst using the mock database handle, you get an error
(as expected), but in certain cases at least, the real error is shadowed
by a subsequent error caused by DBD::Mock attempting to use an undef
statement handle variable.
This results in a misleading error message in the test results.
I attach a test case, and a patch for the specific case I came across
which makes the test pass. I've checked this against v1.39.
However, it looks like the same mistake also occurs elsewhere in
DBD/Mock.pm - the return value of a ->prepare call is used without
checking it is valid first. I'd attempt to fix them all but I'm pushed
for time, so for now I'm just demonstrating the problem. I would hope
the others are as simply fixed.
Thanks for writing/maintaining DBD::Mock
Nick
Subject: | Mock.pm.diff |
--- Mock.faulty.pm 2011-03-23 14:46:48.625442907 +0000
+++ Mock.fixed.pm 2011-03-23 14:45:02.520440818 +0000
@@ -322,7 +322,8 @@
if ($dbh->FETCH('AutoCommit')) {
$dbh->STORE('AutoCommit', 0);
$begin_work_commit = 1;
- my $sth = $dbh->prepare( 'BEGIN WORK' );
+ return
+ unless my $sth = $dbh->prepare( 'BEGIN WORK' );
my $rc = $sth->execute();
$sth->finish();
return $rc;
Subject: | bug_0002.t |
#!/usr/bin/perl
use Test::More tests => 7;
use strict;
use warnings;
use Test::Exception;
use DBI;
use DBD::Mock;
my @session = (
{
statement => 'BEGIN WORK',
results => [],
},
{
statement => 'SELECT count(*) as cnt FROM some_table',
results => [
['cnt'],
[1],
],
},
{
statement => 'COMMIT',
results => [],
},
);
my $dbh = DBI->connect('dbi:Mock:', '', '', { PrintError => 0, RaiseError => 1 });
# Add just part of the expected session, such that the next step would be a 'BEGIN WORK'
$dbh->{mock_session} = DBD::Mock::Session->new(@session);
# Now try and do the steps in @session, wrapping each in a transaction
my $ix = 1;
foreach my $step (@session) {
my $sth = $dbh->prepare($step->{statement});
ok $sth,
"step $ix, prepared statement";
ok $sth->execute($step->{bound_params}),
"step $ix, executed statement";
my $results = $sth->fetchall_arrayref;
++$ix;
}
# This should fail with a useful message, but the original message gets clobbered by
# "Can't call method "execute" on an undefined value£
throws_ok {
$dbh->begin_work;
} qr/\QSession states exhausted, only '3' in DBD::Mock::Session\E/;