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.