On Wed, Nov 13, 2013 at 11:22:03AM -0800, David E. Wheeler wrote: > DBIers, > > Given this script: > > use v5.18; > use warnings; > use utf8; > use DBI; > > my $dbh = DBI->connect('dbi:SQLite:', '', '', { > PrintError => 0, > RaiseError => 1, > AutoCommit => 1, > Callbacks => { > connected => sub { > say 'connected'; > $_[0]->do('SELECT 1 from foo'); > return; > }, > } > }); > > say 'go'; > $dbh->do('SELECT 1 from foo'); > > The output is: > > connected > go > DBD::SQLite::db do failed: no such table: foo at /Users/david/bin/try > line 22. > > That doesn't seem right to me. Shouldn't the connected callback throw an > exception? IOW, I would not expect "go" to be output.
This turned out to be Quite Interesting.... Firstly, the RaiseError/PrintError logic only applies to 'top level calls', i.e. calls made by the application. That's why code executed 'within' the DBI and drivers has to do it's own error checking. Another issue is that the callback is passed the 'inner' handle not the outer (tied) one. That's not documented but ought to be as it's bound to lead to surprises. So in this example the do() call isn't passing through the DBI's method dispatcher. It's calling the drivers own do() method directly. That's not a big deal in this case as the dispatcher wouldn't have applied the RaiseError logic anyway as the call was made from 'within' the DBI. However, the do() does record an error on the handle which should be noticed by the DBI dispatcher when the connect() method is returning. The problem here seems to be that the callback is on the connected() method and that's marked as 'keep err'. [...later...] It turns out that this is fixed by the changes I made in 1.630 to improve the handling of errors recorded in methods that are marked 'keep err'. That change was originally for STORE but also fixes this. So I'll take a guess that you're not using DBI 1.630. (And hope I'm right.) Tim.