On Mon, Nov 24, 2003 at 02:34:13PM -0700, Wiggins d Anconia wrote:
> 
> # localize the setting of dbh handle attributes
> {
>     local $dbh->{AutoCommit} = 0;
>     local $dbh->{RaiseError} = 1;
> 
>     # now perform our steps inside of an eval, allowing us to catch the 
>     # exceptions triggering a rollback
> 
>     my $sth;
>     eval {
>         my $st = "SELECT * ....";
>         my @bind = ( bind values );
> 
>         $sth = $dbh->prepare($st);
>         $sth->execute(@bind);
> 
>         $dbh->commit;
>     }
>     if ($@) {
>         $dbh->rollback;
>         # throw my normal exception stuffs here
>     }
> }
> 
> Questions:
> 1) Can/should I do the 'local' setting of the attributes within the eval
> block without causing any other issues?  I can't think of reasons not
> to, but maybe you can?

The current version of the DBI (and probably some previous ones) has a
bug whereby the automatic STORE that restores the previous attribute value
when the block scope ends, will clear $DBI::err and $DBI::errstr (and
$h->err, $h->errstr) so they won't hold the error details anymore.

When using RaiseError that's not a big problem as the error message is in $@

> 2) If the answer to number 1 is no, then presumably 'rollback' throws an
> exception itself so I would have to catch it too with an 'eval'?  Can
> rollback fail?

Yes, e.g., network connection failure / server down etc.

> If I can move the settings inside of the 'eval' then
> rollback failing should do "normal" error reporting correct, is that
> returning undef or true?

Yes.

> 3) Similar to #2, setting AutoCommit to 0 before setting the RaiseError
> would mean I need to check that it succeeds (which is just checking the
> boolean context of the attribute) moving it into the eval should mean I
> can put it after the RaiseError and let the eval catch its exception as
> well, correct?

Setting AutoCommit to 0 is defined by the DBI spec to be a fatal
error (regardless of RaiseError) if the driver/database can't handle
transactions at all.

[The mysql situation is a little blurred here but I'd expect setting
AutoCommit to 0 to not be an error for DBD::mysql, but (hopefully)
commit() could warn if there's no in-transaction-state to commit.
But I digress...]

Tim.

Reply via email to