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

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

Reply via email to