On 06/11/13 12:36, Jan Holčapek wrote:
Hi Martin,
3. now run your basic script and send me /tmp/unixodbc.log
attached is the log file you've requested. Please let me know your
findings, thanks!
--Jan
Hi Jan,
Your log shows:
[ODBC][7270][1383740710.126962][SQLExecDirect.c][240]
Entry:
Statement = 0x2266860
SQL = [drop table if exists foo][length = 24 (SQL_NTS)]
[ODBC][7270][1383740710.130936][SQLExecDirect.c][503]
Exit:[SQL_SUCCESS_WITH_INFO]
Here SQL_SUCCESS_WITH_INFO was returned. ODBC specifies that this state should
only be returned if the driver succeeded in performing your action but perhaps
with some notable event like, I did what you asked but I had to change it
slightly, or in this case, I could not drop the table foo because it does not
exist but the net effect is the same - foo does not exist.
[ODBC][7270][1383740710.131029][SQLError.c][352]
Entry:
Statement = 0x2266860
SQLState = 0x7fff72663d80
Native = 0x7fff72663978
Message Text = 0x7fff72663980
Buffer Length = 1023
Text Len Ptr = 0x7fff7266397e
[ODBC][7270][1383740710.131053][SQLError.c][389]
Exit:[SQL_NO_DATA]
We tried to find out the additional information on the statement handle but it
returned nothing.
[ODBC][7270][1383740710.131079][SQLError.c][434]
Entry:
Connection = 0x2097c60
SQLState = 0x7fff72663d80
Native = 0x7fff72663978
Message Text = 0x7fff72663980
Buffer Length = 1023
Text Len Ptr = 0x7fff7266397e
[ODBC][7270][1383740710.131094][SQLError.c][471]
Exit:[SQL_NO_DATA]
We tried again on the connection handle - same result.
[ODBC][7270][1383740710.131122][SQLError.c][514]
Entry:
Environment = 0x2097670
SQLState = 0x7fff72663d80
Native = 0x7fff72663978
Message Text = 0x7fff72663980
Buffer Length = 1023
Text Len Ptr = 0x7fff7266397e
[ODBC][7270][1383740710.131140][SQLError.c][551]
Exit:[SQL_NO_DATA]
we tried again on the environment handle - same result.
As you can see DBD::ODBC tried very hard to find out what the informational msg
was.
At this point DBD::ODBC considered this an error and issued the error that
SQLExecDirect returned SQL_SUCCESS_WITH_INFO but no informational message could
be found.
I believe this is a bug in your ODBC driver.
However, I took the decision in DBD::ODBC to report this an error and some
might argue differently. In this case it is fairly innocuous as you tried to
drop a table which did not exist and afterwards it does not exist - although
what happens if it was an error in your application and the table should have
existed? In other cases it is more clear cut - what if you tried to set a
statement attribute like a cursor to type A and the driver said, I've set a
cursor, but not to type A, I've set it to type B - an app would likely want to
know this.
I can see it might be inconvenient for you the way it is now as your forced to
do something like:
$h->{RaiseError} = 1;
eval {
$h->do(q/drop table foo/);
};
if ($@ && $h->errstr =~ /Unable to fetch information about the error/) {
# assume the drop was ok and the table did not exist
# but that is not really a safe assumption to make
} elsif ($@) {
# it is a real error
}
What should have happened is that the driver returned SQL_SUCCESS_WITH_INFO and an
informational msg was retrieved. execute/do would return success. DBD::ODBC would
have posted an informational msg and if you'd examined $h->err it would contain ''
(the empty string) to indicate an informational msg was available in $h->errstr.
I could be swayed to change this to a warning (which would be less inconvenient
to you since you could disable warnings when you are dropping a table) but I'd
need to be persuaded. This is one of those occasions when I'm damned either
way. If I don't report it as an error I end up debugging peoples ODBC logs only
to tell them their driver is broken and if I do report an error people come
back to me saying why is this an error.
However, to reiterate, I think your driver is broken in the following ways:
1. although it is perfectly reasonable for a driver to behave differently in a
transaction to out of one, yours is inconsistent. In a txn, it reports
SQL_SUCCESS_WITH_INFO and no informational msg, and out it reports
SQL_SUCCESS_WITH_INFO and gives an informational message that your table does
not exist.
2. I'd expect:
drop table foo if not exists;
to be successful, even if foo does not exist - it isn't for you
whereas with
drop table foo;
it would be reasonable to return SQL_SUCCESS_WITH_INFO saying foo did not exist.
BTW, are you sure your db can actually rollback a drop table, and if it cannot,
then why bother doing it in a txn?
Martin