On Tue, Aug 04, 2009 at 04:13:19PM +0100, Martin Evans wrote:
> Tim Bunce wrote:
> > On Tue, Aug 04, 2009 at 01:19:43PM +0100, Martin Evans wrote:
> >> This is my second attempt to try and get some insight into how to do
> >> this. The DBD::ODBC::ping method calls DBI::_new_sth to obtain a new
> >> statement handle but DBD::ODBC prevents creating a new statement handle
> >> when not connected (you cannot actually get one even if you wanted). The
> >> problem is once DBD::ODBC discovers we are not connected it does:
> >>
> >> DBIh_SET_ERR_CHAR(
> >>   h, imp_xxh, Nullch, 1,
> >>   "Cannot allocate statement when disconnected from the database",
> >>             "08003", Nullch);
> >>
> >> and because PrintError is on the error is output and because RaiseError
> >> is on the error handler is called. Most people are calling ping when not
> >> connected and do not want this error and I wanted to mask it by
> >> temporarily disabling PrintError and RaiseError but it does not seem to
> >> work for me.
> >>
> >> Initially I tried using local $dbh->{PrintError} = 0 but this did not
> >> work. Then I remembered I needed to call STORE from inside the driver so
> >> changed to $dbh->STORE('PrintError', 0); but that does not work either.
> > 
> > That should work. Try calling $dbh->dump_handle after (and after doing
> > the same for RaiseError) that to see what the state of the handle is.
> > 
> > Tim.
> > 
> > p.s. You could also try using the HandleError attribute, but the above 
> > should
> > work so let's find out what's happening there first.
> 
> Thanks for the help Tim.
> 
> Ignoring RaiseError for now as I'm imagining it will work (once it
> works) the same as PrintError. The ping sub is currently:
> 
> sub ping {
>     my $dbh = shift;
>     my $state = undef;
> 
>     my ($catalog, $schema, $table, $type);
> 
>     $catalog = q{};
>     $schema = q{};
>     $table = 'NOXXTABLE';
>     $type = q{};
> 
>     print "PrintError=", $dbh->FETCH('PrintError'), "\n";
>     my $pe = $dbh->FETCH('PrintError');
>     $dbh->STORE('PrintError', 0);
>     $dbh->dump_handle;
>     my $evalret = eval {
>        # create a "blank" statement handle
>         my $sth = DBI::_new_sth($dbh, { 'Statement' => "SQLTables_PING" })
>             or return 1;
> 
>         DBD::ODBC::st::_tables($dbh,$sth, $catalog, $schema, $table, $type)
>               or return 1;
>         $sth->finish;
>         return 0;
>     };
>     $dbh->STORE('PrintError', $pe);
>     if ($evalret == 0) {
>         return 1;
>     } else {
>         return 0;
>     }
> }
> 
> and the following perl and output are observed:
> 
>  perl -Iblib/lib -Iblib/arch -le 'use DBI;$h = DBI->connect();print
> "ping=",$h->ping(),"\n";$h->disconnect; print "ping=",$h->ping(), "\n";'
> PrintError=1
> 
>     DBI::dump_handle (dbh 0x82c382c, com 0x82c4560, imp DBD::ODBC::db):
>        FLAGS 0x100217: COMSET IMPSET Active Warn PrintWarn AutoCommit
>        ERR ''
>        ERRSTR '[unixODBC][Easysoft][SQL Server Driver][SQL
> Server]Changed language setting to us_english. (SQL-01000)
> [unixODBC][Easysoft][SQL Server Driver][SQL Server]Changed database
> context to 'master'. (SQL-01000)'
>        PARENT DBI::dr=HASH(0x82bc5e0)
>        KIDS 0 (0 Active)
>        Name 'baugi'
> ping=1
> 
> PrintError=1
> 
>     DBI::dump_handle (dbh 0x82c382c, com 0x82c4560, imp DBD::ODBC::db):
>        FLAGS 0x100213: COMSET IMPSET Warn PrintWarn AutoCommit
>        PARENT DBI::dr=HASH(0x82bc5e0)
>        KIDS 0 (0 Active)
>        Name 'baugi'
> DBD::ODBC::db ping failed: Cannot allocate statement when disconnected
> from the database at -e line 1.
> ping=0
> 
> I don't know if it is anything of a clue but if I fail to restore
> PrintError with STORE at the end of ping, the error is not seen in the
> second call to ping).

Ah! The DBI is reporting the error information that's stored in the
handle when the ping method *returns*.

You need to use $h->set_err(...) to clear the error state before
returning.

Tim.

Reply via email to