Subject: | unexpected rollback (or commit) when using a DBD::Mock::Session produces an uninformative error |
This is a somewhat odd situation, but it has a simple fix. The basic scenario is using a session to test code that uses the pattern
eval { ... }
if ($@) {$dbh->rollback }
If there is an unintentional error in the session sequence (or an genuinely unexpected error in the eval'd code), the rollback will be reached without being properly queued up in the session. Since ROLLBACK is not the next state of the DBD::Mock::Session object, the prepare of that statement (on line 338) will fail, causing the error
Can't call method "execute" on an undefined value at lib/perl5/site_perl/5.6.1/DBD/Mock.pm line 339.
The script below demonstrates the error; the attached patch simply makes commit and rollback return early (leaving error-reporting to the normal DBI mechanisms) if "prepare" fails.
#!/usr/local/bin/perl
use DBI;
my $dbh = DBI->connect("dbi:Mock:",undef,undef,{RaiseError=>1,PrintError=>0,AutoCommit=>0});
my $SQL = "select foo from bar where a = ? and b = ?";
# not that it matters *what* the SQL is...
my $s = DBD::Mock::Session->new("bugdemo",
{
statement=> $SQL,
bound_params=>[1,2],
results=>[['foo'],[1]]
},
{
statement=> $SQL,
bound_params=>[3,4],
results=>[['foo'],[1]],
},
);
$dbh->{mock_session} = $s;
my $sth=$dbh->prepare($SQL);
eval {
foreach my $bindlist ([3,4],[1,2]) { # intentional error for demonstration
$sth->execute(@$bindlist);
}
};
if ($@ ) { warn "Rolling back on error: $@\n";$dbh->rollback; }
print "OK";
Message body not shown because it is not plain text.