On Mon, Dec 06, 2004 at 09:10:33AM -0800, Jonathan Leffler wrote:
> On Fri, 3 Dec 2004 21:04:11 +0000, Tim Bunce <[EMAIL PROTECTED]> wrote:
> > On Thu, Dec 02, 2004 at 04:07:13PM -0800, Jonathan Leffler wrote:
> > 
> >         unless ($dbh = $drh->$connect_meth($dsn, $user, $pass, $attr)) {
> >             $user = '' if !defined $user;
> >             $dsn = '' if !defined $dsn;
> >             # $drh->errstr isn't safe here because $dbh->DESTROY may not 
> > have
> >             # been called yet and so the dbh errstr would not have been 
> > copied
> >             # up to the drh errstr. Certainly true for connect_cached!
> >             my $errstr = $DBI::errstr;
> >             $errstr = '(no error string)' if !defined $errstr;
> >             my $msg = "$class connect('$dsn','$user',...) failed: $errstr";
> >             DBI->trace_msg("       $msg\n");
> >             # XXX HandleWarn
> >             unless ($attr->{HandleError} && $attr->{HandleError}->($msg, 
> > $drh, $dbh)) {
> >                 Carp::croak($msg) if $attr->{RaiseError};
> >                 Carp::carp ($msg) if $attr->{PrintError};
> >             }
> >             $! = 0; # for the daft people who do DBI->connect(...) || die 
> > "$!";
> >             return $dbh; # normally undef, but HandleError could change it
> >         }
> > 
> > The code used to use $drh->errstr but, as the comment says, that's not safe.
> 
> I guess the question then becomes - how does $DBI::errstr get set?  It
> isn't visible in the code here, so it must be in the infrastructure
> that ends up in $drh->$connect_meth().  Unless the drivers are
> supposed to set it directly themselves?

Drivers should call $h->set_err(...) or use the C-code equivs
DBIh_SET_ERR_SV(...) or DBIh_SET_ERR_CHAR(). Old code typically
just sets err and errstr on the handle directly. That's not a
problem here.

The tricky part is that $h will typically be the $dbh but that $dbh
may (or may not) have been DESTROYed by the time $connect_meth()
returns.

If it has been DESTROYed then its err/errstr/state should get copied
up to the parent $drh so $drh->errstr would work, and $DBI::lasth should
be set to $drh so $DBI::errstr would equate to $drh->errstr.

But if it's not been DESTROYed then $DBI::lasth should still point
to $dbh and thus $DBI::errstr would equate to $dbh->errstr.

> > then you'll need to do some digging around that code to find out what's 
> > going on.
> 
> OK - thanks for the information.  I'll do a bit of poking, but I'm not
> sure whether it'll be to any useful effect.

A trace(9) from the $connect_method call through to the trace_msg(...)
should contain enough info for me to help more.

Tim.

Reply via email to