Tim Bunce wrote:
> 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.
> 
> 

When I add $dbh->set_err(undef,'',''); it does clear the error. BTW, I
saw the following in Gofer.pm at the start of ping:

sub ping {
  my $dbh = shift;
  return $dbh->set_err(0, "can't ping while not connected") # warning
            unless $dbh->SUPER::FETCH('Active');

That did not work for me to generate a warning, even when I changed the
0 to "0" which is what I thought you did for a warning
(http://search.cpan.org/~timb/DBI-1.609/DBI.pm#set_err).

Martin
-- 
Martin J. Evans
Easysoft Limited
http://www.easysoft.com

Reply via email to