Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm writing a set of Apache::ASP scripts that comunicate with a MySQL database using DBI. I'm trying to make sure to catch all errors thrown by DBI (or my own code) and issue rollbacks but I find that it'm always learning better techniques. I ended up having three versions of error catching eval/if blocks so I decided I should look for a dynamic solution.

My latest version is the following:

my $dbh = $base::dbh; # get a database handle eval { # lots of inserts, updates, etc... }; if ($@) { my $err = $@; eval { $dbh->rollback }; # display formatted errors $base::showerrors( ($base::debug ? $err : "database related error"), ($@ ? " error performing rollback\n" : " rollback performed successfully\n") ); }

I have now come up with the following solution. I declare a couple of subs at the server startup (in global.asa)

sub dbtry (&@) { my ($dbtry, $dbcatch) = @_; local $dbh = $base::dbh; eval { local $_ = $dbh; &$dbtry }; if($@) { local $_ = "dbcaught:"; chomp $@; $_ .= ($base::debug) ? " $@" : " database related error"; eval { $dbh->rollback }; $_ .= ($@ ? " Error Performing Rollback\n" : " Rollback Performed Successfully\n"); &$dbcatch; } } sub dbcatch (&) { $_[0] }

Then I use the following (less cluttered) code to get a job done.

dbtry { # lots of inserts, updates, etc... } dbcatch { $base::showerrors("error: $_"); }

I'm also thinking about merging other error logging mechanisims I use in this code. I've never used this code in practice -- and I'm not entirely convinced that it's the best way to go. Can anyone see anything wrong with this code ? Does anyone know how to improve it ? Any experiences with similar techniques ?

Replies are listed 'Best First'.
Re: Catching what DBI throws
by diotalevi (Canon) on Oct 05, 2002 at 19:18 UTC

    I'm probably not the best person to respond to this but this appears to be crying out for some sort of exception handler. Our local PM group was going to discuss exceptions but didn't. The pre-dialog revealed that Alzabo is a heavy user of one of the exception styles. The net result is I'm still not the best person to answer but there are exception classes out there that handle this for you. I'd look at Exception and perhaps Exception::Class / Exception::Class::DBI. I'd almost suggest grabbing Alzabo to check out the exception style and go from there. Consider it a working code example. I know I will when I go check it out later.

    __SIG__
    printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B::svref_2object(sub{})->OUTSIDE

Re: Catching what DBI throws
by chromatic (Archbishop) on Oct 05, 2002 at 21:12 UTC

    It sounds like you're on the right track. What about taking it a step further and separating all database access code into a separate module? That way, you only have to catch the errors in a few places (select, update, delete), and your exception handling is much easier.

Re: Catching what DBI throws
by perrin (Chancellor) on Oct 06, 2002 at 03:15 UTC
    What you're doing is basically the same as the Error module, with the same dangers. It is easy to create closures by accident and leak tons of memory, and people may be confused by the fact that a "return" inside a dbtry only returns from the dbtry.

    I think what you had in the beginning was a better idea.