[freetds] FreeTDS, C++, and Exceptions
Lenon Kitchens
lenonk at sanctuary.org
Sat Jun 17 03:55:37 EDT 2006
Hi folks,
I have a problem with FreeTDS that I was hoping someone could help me
solve. I'm a developer for a company that deals in network management
software. Since basically all of our applications need to have the
ability to talk to one or more of SQLServer, Oracle, SQLite, Sybase, I
have written a C++ library to provide a common interface to all of these
APIs.
It wasn't until recently that I noticed a problem with the FreeTDS part
of my implementation. I have installed error and message handlers using
dberrhandle() and dbmsghandle(). At the end of each of these functions,
I throw an exception like so:
throw DBLibException(EGENERAL_EXCEPTION, err.str());
The "err" string is obviously filled out during the function. The
problem is that for some reason, this exception goes completely uncaught
and results in terminate() being called.
Here's the output of a test program:
[lenon at atllnxdev01 libcentivia]$ ./test
checking tdsport
terminate called after throwing an instance of 'DBLibException'
Aborted
Here's the test program itself:
#include <stdio.h>
int main(void) {
DBConnection *SQLServerConn;
try {
SQLServerConn = DBConnection::buildConnection(SQLServer, "10.0.0.0",
"username", "password");
SQLServerConn->connect("database");
// Foo is obviously an invalid table name which will cause an
exception
// to be thrown.
SQLServerConn->execute("select * from foo");
}
catch (DBLibException &e) {
cout << "DBLib Exception: " << e.getErrInfo() << endl;
return -1;
}
}
If I throw this exact same exception immediately before the call to
dbsqlexec(), it works fine.
Here are the two installed handlers:
int
sybErrHandler(DBPROCESS *dbProc, int severity, int dbErr, int osErr,
char *dbErrStr, char *osErrStr) {
string err;
// It's OK to end up here in response to a dbconvert() that
// resulted in overflow, so don't exit in that case.
if (dbErr == SYBEICONVI)
return 0;
/*
* For server messages, cancel the query and rely on the
* message handler to spew the appropriate error messages out.
*/
if (dbErr == SYBESMSG)
return INT_CANCEL;
err = "\nDBLIB ERROR: [" + string(dbErrStr) + "]";
if (osErr != DBNOERR)
err += "\nOS ERROR: [" + string(osErrStr) + "]";
throw DBLibException(EGENERAL_EXCEPTION, err);
}
int
sybMsgHandler(DBPROCESS *dbProc, DBINT msgNo, int msgState,
int severity, char *msgText, char *srvName, char *procName, int
line) {
if (msgNo == 5701 || msgNo == 5703 || msgNo == 5704)
return (INT_CONTINUE);
stringstream err;
err << "\nDBLIB MESSAGE: [msgno: " << msgNo <<
", level: " << severity << ", State: " << msgState << "]";
if (*srvName)
err << "\nSERVER: [" << srvName << "]";
if (*procName)
err << "\nPROCEDURE: [" << procName << "]";
if (line > 0)
err << "\nLINE: [" << line << "]";
err << "\nMESSAGE: " << msgText;
throw DBLibException(EGENERAL_EXCEPTION, err.str());
}
Any help will be greatly appreciated.
Thanks!
Lenon Kitchens
More information about the FreeTDS
mailing list