Documentation / Error checking
Documentation / Error checking
am 18.11.2005 13:15:50 von calius
(A bit long)
(Bottom line: is it, or is it not, enough to always check DBI::err)
Hello
The documentation for how to check the success of various DBI calls, and in
particular do(), selectrow_foo() and selectall_foo() is unclear and not
precise, at least for me. Actually I am not sure, after scrutinizing, how
exactly to check for errors.
Specific problems:
Looking at the doc for "err", we see: "The DBI resets $h->err to undef
before most DBI method calls", note the "most". Since the documentation for
specific methods does not say which do *not* reset err, I have no way of
knowing which do and which don't.
Also: looking at (for example) the doc for selectall_hashref(), we can find:
"If any method except fetchrow_hashref fails, and "RaiseError" is not set,
selectall_hashref will return undef. If fetchrow_hashref fails and
"RaiseError" is not set, then it will return with whatever data it has
fetched thus far. $DBI::err should be checked to catch that".
selectall_arrayref() and selectcol_arrayref() have similar documentation.
To me this looks like the correct way to check selectall_hashref() is then:
my $hr = $dbh->selectall_hashref( ... ); (!defined $hr || defined $DBI::err)
&& die( ... );
Justification: error returns undef, so we need to see whether the result is
defined at all. Checking DBI::err is to test "that" -- only some rows were
returned. It does *not* say explicitly that err is reset before hand, so I
can't be sure that testing err alone is enough!
Looking at selectrow_hashref() says that error is indicated by undef. It
does *not* say err will be set. So I can only assume I need to:
my $hr = $dbh->selectrow_hashref( ... ); !defined $hr && die( "..." );
Again it does not say err is reset before, so I cannot assume I can trust
err for telling me about errors. The docs only explicitly mention the return
value.
To summarize:
My understand of the docs as written is that errors for selectall_ and
selectcol_ methods should be checked as:
(!defined $return_value || defined $DBI::err) && die( ... );
.... that errors for selectrow_ methods should be checked as:
(defined $return_value) || die( ... );
.... and that errors for do() should be checked as:
($return_value) || die( ... );
Is that correct? Is it really not possible to only check for (defined
DBI::err) always?
Can someone verify, or clarify the docs?
Much obligied,
Nitzan
Re: Documentation / Error checking
am 18.11.2005 14:42:42 von Tim.Bunce
On Fri, Nov 18, 2005 at 02:15:50PM +0200, Nitzan Shaked wrote:
> (A bit long)
> (Bottom line: is it, or is it not, enough to always check DBI::err)
>
> Hello
>
> The documentation for how to check the success of various DBI calls, and in
> particular do(), selectrow_foo() and selectall_foo() is unclear and not
> precise, at least for me. Actually I am not sure, after scrutinizing, how
> exactly to check for errors.
>
> Specific problems:
>
> Looking at the doc for "err", we see: "The DBI resets $h->err to undef
> before most DBI method calls", note the "most". Since the documentation for
> specific methods does not say which do *not* reset err, I have no way of
> knowing which do and which don't.
I'll clarify the docs. Basically all methods calls reset err except for
just a few special cases such as err and errstr, obviously, and FETCH
(eg $foo = $h->{SomeAttribute}).
For the record, here's the current list of methods that don't reset err:
DBI::common::CLEAR
DBI::common::DESTROY
DBI::common::EXISTS
DBI::common::FETCH
DBI::common::FIRSTKEY
DBI::common::NEXTKEY
DBI::common::STORE
DBI::common::debug
DBI::common::dump_handle
DBI::common::err
DBI::common::errstr
DBI::common::func
DBI::common::parse_trace_flag
DBI::common::parse_trace_flags
DBI::common::private_data
DBI::common::state
DBI::common::trace
DBI::common::trace_msg
DBI::db::ping
DBI::db::rows
DBI::st::rows
This is a fuzzy area of the DBI and I'm not guaranteeing that this list
won't change over time.
> Also: looking at (for example) the doc for selectall_hashref(), we can find:
> "If any method except fetchrow_hashref fails, and "RaiseError" is not set,
> selectall_hashref will return undef. If fetchrow_hashref fails and
> "RaiseError" is not set, then it will return with whatever data it has
> fetched thus far. $DBI::err should be checked to catch that".
> selectall_arrayref() and selectcol_arrayref() have similar documentation.
>
> To me this looks like the correct way to check selectall_hashref() is then:
> my $hr = $dbh->selectall_hashref( ... ); (!defined $hr || defined $DBI::err)
> && die( ... );
Well, if you're going to die() I'd just set RaiseError and forget about it.
If there's some good reason you don't want to use RaiseError then this
would do:
my $hr = $dbh->selectall_hashref( ... );
die(...) if $DBI::err;
> Looking at selectrow_hashref() says that error is indicated by undef. It
> does *not* say err will be set. So I can only assume I need to:
>
> my $hr = $dbh->selectrow_hashref( ... ); !defined $hr && die( "..." );
my $hr = $dbh->selectrow_hashref( ... ) or die(...);
Tim.
RE: Documentation / Error checking
am 18.11.2005 14:49:21 von calius
Thanks Tim.
> I'll clarify the docs. Basically all methods calls reset err except for
> just a few special cases such as err and errstr, obviously, and FETCH
> eg $foo = $h->{SomeAttribute}).
From the first part of your answer I understand that's it's always okay to
test for "defined DBI::err" (if I want to die on warnings) or "DBI::err" if
I am willing to live with warnings and would like to die on errors only. Is
that correct?
> Well, if you're going to die() I'd just set RaiseError and forget about
it.
> If there's some good reason you don't want to use RaiseError then this
would do:
Of course when I write "die" I don't really mean die, I have error handling
code which does quite a bit. It's just a shorthand for writing. Otherwise I
would use RaiseError as you suggest.
> my $hr = $dbh->selectrow_hashref( ... ) or die(...);
.... but from your first part of your answer I may also do:
my $hr = $dbh->selectrow_hashref( ... );
defined $DBI::err and do_special_error_handling_code();
.... correct?
Thanks again,
Nitzan
Re: Documentation / Error checking
am 18.11.2005 23:41:15 von Tim.Bunce
On Fri, Nov 18, 2005 at 03:49:21PM +0200, Nitzan Shaked wrote:
> Thanks Tim.
>
> > I'll clarify the docs. Basically all methods calls reset err except for
> > just a few special cases such as err and errstr, obviously, and FETCH
> > eg $foo = $h->{SomeAttribute}).
>
> From the first part of your answer I understand that's it's always okay to
> test for "defined DBI::err" (if I want to die on warnings) or "DBI::err" if
> I am willing to live with warnings and would like to die on errors only. Is
> that correct?
You've missed out the $ sigils, but other than that, yes.
As per the docs:
A driver may return C<0> from err() to indicate a warning condition
after a method call. Similarly, a driver may return an empty string
to indicate a 'success with information' condition. In both these
cases the value is false but not undef. The errstr() and state()
methods may be used to retrieve extra information in these cases.
> > Well, if you're going to die() I'd just set RaiseError and forget about it.
> > If there's some good reason you don't want to use RaiseError then this would do:
>
> Of course when I write "die" I don't really mean die, I have error handling
> code which does quite a bit. It's just a shorthand for writing. Otherwise I
> would use RaiseError as you suggest.
Okay. (Don't forget to check out the HandleError attribute.)
> > my $hr = $dbh->selectrow_hashref( ... ) or die(...);
>
> ... but from your first part of your answer I may also do:
> my $hr = $dbh->selectrow_hashref( ... );
> defined $DBI::err and do_special_error_handling_code();
Yes.
Tim.