Re: DBI FETCH called on non-referenced attribute

"Martin J. Evans" <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.sybase.devel
Organization Easysoft Limited
Message-ID <[email protected]>
On 07/10/10 10:22, Tim Bunce wrote:
> On Wed, Oct 06, 2010 at 07:15:03PM +0100, Martin J. Evans wrote:
>>  Hi,
>>
>> Hoping someone can help me identify what might be going on here but
>> it looks to me like something in DBI has changed.
>>
>> use strict;
>> use DBI;
>>
>> my $attrs = { RaiseError => 1, PrintError => 0, AutoCommit => 1 };
>> my $h = DBI->connect("dbi:ODBC:DSN=xxx","xx","xx",
>> {odbc_SQL_ROWSET_SIZE => 2});
>>
>> This code used to work fine but now it fails with:
>>
>> Option type out of range (SQL-HY092) at
>> /home/martin/perl5/lib/perl5/i486-linux-gnu-thread-multi/DBI.pm line
>> 720.
> 
>     while ( my ($a, $v) = each %$apply) {
>         eval { $dbh->{$a} = $v } or $@ && warn $@;
>     }
> 
> Doesn't look like a FETCH to me. Umm, then again, perhaps it is.
> Try this:
> 
> -       eval { $dbh->{$a} = $v } or $@ && warn $@;
> +       eval { $dbh->{$a} = $v; 1 } or $@ && warn $@;

Stops FETCH happening (thanks) but has side effects - see below.

>> It appears FETCH is being called on odbc_SQL_ROWSET_SIZE (just my
>> example, could just as easily have been 9 for the actual ODBC
>> SQL_ROWSET_SIZE attribute) and this ends up calling
>> SQLGetConnectOption which says you cannot fetch SQL_ROWSET_SIZE. It
>> is permissible to set SQL_ROWSET_SIZE with SQLSetConnectOption but
>> not to retrieve it back.
> 
>> Why does DBI do a FETCH on the attribute when it is never retrieved
>> in the script? I don't think it used to (perhaps a long time ago).
> 
> What does trace show?

Before the change above it shows:

    >> FETCH       DISPATCH (DBI::db=HASH(0x95d2998) rc2/1 @2 g0 ima404 pid#18278) at /home/martin/perl5/lib/perl5/i486-linux-gnu-thread-multi/DBI.pm line 720
    -> FETCH for DBD::ODBC::db (DBI::db=HASH(0x95d2998)~INNER 'odbc_SQL_ROWSET_SIZE') thr#9478008
    FETCH odbc_SQL_ROWSET_SIZE
    !!dbd_error2(err_rc=-1, what=db_FETCH/SQLGetConnectOption, handles=(958a3a0,95d51f0,0)
    !SQLError(958a3a0,95d51f0,0) = (HY092, 0, [unixODBC][Easysoft][SQL Server Driver][SQL Server]Option type out of range)
    !!SQLGetConnectOption=-1 in dbd_db_FETCH
    .. FETCH DBI::db=HASH(0x95d2998) 'odbc_SQL_ROWSET_SIZE' = undef
    !! ERROR: 1 '[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) [state was 01000 now HY092]
[unixODBC][Easysoft][SQL Server Driver][SQL Server]Option type out of range (SQL-HY092)' (err#1)
    <- FETCH= undef at /home/martin/perl5/lib/perl5/i486-linux-gnu-thread-multi/DBI.pm line 720

In fact, I've known about this for ages but forgot about it - from DBD::ODBC Changes file:

 Why does level 15 tracing of any DBD::ODBC script show alot of these:
   !!DBD::ODBC unsupported attribute passed (PrintError)
   !!DBD::ODBC unsupported attribute passed (Username)
   !!DBD::ODBC unsupported attribute passed (dbi_connect_closure)
   !!DBD::ODBC unsupported attribute passed (LongReadLen)

I know see the following with a simple connect:
    !!DBD::ODBC unsupported attribute passed (PrintError)
    !!DBD::ODBC unsupported attribute passed (Username)
    !!DBD::ODBC unsupported attribute passed (dbi_connect_closure)

With your amendment the trace output still contains the "unsupported" messages from DBD::ODBC but there are no FETCH calls at all - so result.

Except make test fails with:

t/40profile.t .............. 1/60 
#   Failed test at t/40profile.t line 180.
#     Structures begin differing at:
#          $got->{Data}{}[0] = '6'   # MJE I think this is count of samples in Data->{''}
#     $expected->{Data}{}[0] = '7'

#   Failed test 'should have 9 nodes'
#   at t/40profile.t line 250.
#          got: '8'
#     expected: '9'

#   Failed test at t/40profile.t line 253.
#     Structures begin differing at:
#          $got->[1][0][0] = '2'
#     $expected->[1][0][0] = '1'
t/40profile.t .............. 44/60 
#   Failed test at t/40profile.t line 354.
#     Structures begin differing at:
#          $got->{foo}{bar}{baz}[0] = '11'
#     $expected->{foo}{bar}{baz}[0] = '12'

#   Failed test at t/40profile.t line 357.
#     Structures begin differing at:
#          $got->{foo}{ping}{pong}[0] = '11'
#     $expected->{foo}{ping}{pong}[0] = '12'

#   Failed test '$_ should contain statement'
#   at t/40profile.t line 364.
#     Structures begin differing at:
#          $got->{}[0] = '6'
#     $expected->{}[0] = '7'

#   Failed test at t/40profile.t line 423.
#          got: 'foo > DESTROY > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > STORE > baz: 0.0s / 5 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > connected > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > execute > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > fetchrow_hashref > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > finish > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > prepare > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# '
#     expected: 'foo > DESTROY > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > FETCH > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > STORE > baz: 0.0s / 5 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > connected > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > execute > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > fetchrow_hashref > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > finish > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# foo > prepare > baz: 0.0s / 1 = 0.0s avg (first 0.0s, min 0.0s, max 0.0s)
# '
# Looks like you failed 7 tests of 60.
t/40profile.t .............. Dubious, test returned 7 (wstat 1792, 0x700)
Failed 7/60 subtests 

so there is a side effect. It appears there is 1 less count each time.

> Tim.

Martin
-- 
Martin J. Evans
Easysoft Limited
http://www.easysoft.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.