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).