Re: DBD::ODBC fails after "Execute immediate success with info"

"Martin J. Evans" <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.general
Message-ID <[email protected]>
On 06/11/13 10:57, Jan Holčapek wrote:> Hello there,
>
> I've been using DBD::ODBC to connect to Vertica 6.1 for some time now,
> yet updating (quite old 1.23) DBD::ODBC to a recent one (1.45) introduced
> an issue. Frankly, I'm not sure if it's really a bug or not.
>
> My environment:
>
> Arch: x86_64
> OS: Scientific Linux 6.4
> Perl: 5.10.1
> DBI: 1.630 (updated from 1.609)
> DBD::ODBC 1.45 (updated from 1.23)
> unixODBC: 2.3.2
>
> Simple script reproducing the issue is this:
>
> --cut--
> #!/usr/bin/perl
> use strict;
> use warnings;
> use DBI;
> my $dbh = DBI->connect(
>          'dbi:ODBC:driver=vertica;database=verticadb;server=localhost',
>          'vertica',
>          undef,
>          {
>                  PrintError => 0,
>                  RaiseError => 1,
>                  AutoCommit => 1,
>          } );
> $dbh->trace(5);
> $dbh->begin_work;
> $dbh->do("drop table if exists foo");
> $dbh->commit;
> --cut--
>
> It fails and produces the following trace:
>
> --cut--
>      DBI::db=HASH(0x270e1d0) trace level set to 0x0/5 (DBI @ 0x0/0) in
> DBI 1.630-ithread (pid 27687)
>      -> begin_work in DBD::_::db for DBD::ODBC::db
> (DBI::db=HASH(0x270e2a8)~0x270e1d0) thr#249b010
> 1   -> FETCH for DBD::ODBC::db (DBI::db=HASH(0x270e1d0)~INNER
> 'AutoCommit') thr#249b010
> 1   <- FETCH= 1 at /usr/local/lib64/perl5/DBI.pm line 1732 via  at
> ./odbctest.pl line 15
> 1   -> STORE for DBD::ODBC::db (DBI::db=HASH(0x270e1d0)~INNER
> 'AutoCommit' 0) thr#249b010
>      setting AutoCommit
> 1   <- STORE= 1 at /usr/local/lib64/perl5/DBI.pm line 1734 via  at
> ./odbctest.pl line 15
> 1   -> STORE for DBD::ODBC::db (DBI::db=HASH(0x270e1d0)~INNER
> 'BegunWork' 1) thr#249b010
>      !!DBD::ODBC unsupported attribute passed (BegunWork)
>      STORE DBI::db=HASH(0x270e1d0) 'BegunWork' => 1
> 1   <- STORE= 1 at /usr/local/lib64/perl5/DBI.pm line 1735 via  at
> ./odbctest.pl line 15
>      <- begin_work= 1 at ./odbctest.pl line 15
>      -> do for DBD::ODBC::db (DBI::db=HASH(0x270e2a8)~0x270e1d0 'drop
> table if exists foo') thr#249b010
> 1   -> STORE for DBD::ODBC::db (DBI::db=HASH(0x270e1d0)~INNER
> 'Statement' 'drop table if exists foo') thr#249b010
>      !!DBD::ODBC unsupported attribute passed (Statement)
>      STORE DBI::db=HASH(0x270e1d0) 'Statement' => 'drop table if exists foo'
> 1   <- STORE= 1 at /usr/local/lib64/perl5/DBD/ODBC.pm line 433 via  at
> ./odbctest.pl line 16
>      SQLExecDirect drop table if exists foo
>      SQLExecDirect = 1

This means the ODBC API SQLExecDirect was called and it returned 1 (SQL_SUCCESS_WITH_INFO). According to the ODBC spec, when a driver returns SQL_SUCCESS_WITH_INFO there should be a diagnostic available to tell us what the informational state is.

>      !!dbd_error2(err_rc=1, what=Execute immediate success with info,
> handles=(2727670,2727c60,28f6480)
>      ** No error found 1 **

but we called the ODBC API SQLError and DBD::ODBC thinks there was none.

>      !! ERROR: 1 '    Unable to fetch information about the error' (err#1)
>      <- do= -1 at ./odbctest.pl line 16

so it is telling you, SQLExecute returned SQL_SUCCESS_WITH_INFO and then there was no error - which is an error.


> DBD::ODBC::db do failed:     Unable to fetch information about the
> error at ./odbctest.pl line 16.
>      -> DESTROY for DBD::ODBC::db (DBI::db=HASH(0x270e1d0)~INNER) thr#249b010
> Issuing rollback() due to DESTROY without explicit disconnect() of
> DBD::ODBC::db handle
> driver=vertica;database=verticadb;server=localhost at ./odbctest.pl
> line 16.
>         ERROR: 1 '    Unable to fetch information about the error' (err#1)
>      <- DESTROY= undef at ./odbctest.pl line 16 via  at ./odbctest.pl line 16
> --cut--
>
> If I comment out begin_work and commit, there is no error:
>
> --cut--
>      DBI::db=HASH(0x24ef420) trace level set to 0x0/5 (DBI @ 0x0/0) in
> DBI 1.630-ithread (pid 29782)
>      -> do for DBD::ODBC::db (DBI::db=HASH(0x24ef4f8)~0x24ef420 'drop
> table if exists foo') thr#24bd010
> 1   -> STORE for DBD::ODBC::db (DBI::db=HASH(0x24ef420)~INNER
> 'Statement' 'drop table if exists foo') thr#24bd010
>      !!DBD::ODBC unsupported attribute passed (Statement)
>      STORE DBI::db=HASH(0x24ef420) 'Statement' => 'drop table if exists foo'
> 1   <- STORE= 1 at /usr/local/lib64/perl5/DBD/ODBC.pm line 433 via  at
> ./odbctest.pl line 16
>      SQLExecDirect drop table if exists foo
>      SQLExecDirect = 1
>      !!dbd_error2(err_rc=1, what=Execute immediate success with info,
> handles=(25e89d0,27492f0,2917f70)
>      !SQLError(25e89d0,27492f0,2917f70) = (01000, 4185, NOTICE 4185:
> Nothing was dropped
> )
>      !! info: '' 'NOTICE 4185:  Nothing was dropped

This is the difference between an ODBC API saying it succeeded but with an issue you should be made aware of (SQL_SUCCESS_WITH_INFO) and I'll tell you what it is and it succeeded but with an issue and I refuse to tell you what it is (a bug either in the driver or DBD::ODBC).

In the first case the driver said it succeeded but then against the ODBC API, would not tell us the informational part. DBD::ODBC posted an error saying this.

In the second case the same happened but the driver told us it succeeded but it did not really drop anything. Because DBD::ODBC got the informational message it happily posted it and by default informationals in DBI just not print or raise an error.

>   (SQL-01000)' (err#0)
>      <- do= -1 at ./odbctest.pl line 16
>      -> DESTROY for DBD::ODBC::db (DBI::db=HASH(0x24ef420)~INNER) thr#24bd010
>         info: '' 'NOTICE 4185:  Nothing was dropped
>   (SQL-01000)' (err#0)
>      <- DESTROY= undef
> --cut--
>
> Both worked with DBD::ODBC 1.23. Through binary searching DBD::ODBC releases,
> I was able to figure out that release 1.31 introduced this behavior,
> namely this change
> https://metacpan.org/pod/release/MJEVANS/DBD-ODBC-1.45/Changes#pod1.30_6-2011-06-04
>
> So my question is: is it me, ODBC manager, DBD::ODBC or Vertica doing
> something wrong?
>
> Any insight is more than welcome!
>
> Thanks
> Jan
>

To rule out DBD::ODBC being at fault in its ODBC calls I'd need to see a ODBC driver manager trace. You can do this by:

1. run odbcinst -j to find out where your odbcinst file is located

e.g.,

$ odbcinst -j
unixODBC 2.2.14
DRIVERS............: /etc/odbcinst.ini   <------------- this file
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/martin/.odbc.ini
SQLULEN Size.......: 4
SQLLEN Size........: 4
SQLSETPOSIROW Size.: 2

2. add to the top of the odbcinst.ini file:

[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log

3. now run your basic script and send me /tmp/unixodbc.log

As to whether DBD::ODBC should issue an error if the driver says there is a problem and then won't tell us what it is - that is another issue I prepared to debate.

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.