Fix error reporting in TDS SQL driver.

The error and message handlers used by the freetds library were getting
reset to back to the default every time a database was opened.  The
Qt TDS SQL driver was calling dbinit() from QTDSDriver::open().  This
had two problems:

1. dbinit() would reset the error handler previously set by a call to
   dberrhandle().  A db error would then cause the application to
   abort.
2. freetds expects dbinit() and dbexit() to be called symmetrically.
   Opening multiple database connections would result in freetds not
   cleaning up on application close.

Solved by moving the dbinit() call into the QTDSDriver constructor.

Change-Id: I59018d83238672c903b96a4d7f3f21b664c3ff4c
Reviewed-by: Andy Shaw <andy.shaw@digia.com>
Reviewed-by: Mark Brand <mabrand@mabrand.nl>
This commit is contained in:
Aaron McCarthy 2012-11-08 15:13:10 +10:00 committed by The Qt Project
parent 597a6024f4
commit 7456562e7f
2 changed files with 36 additions and 2 deletions

View File

@ -138,10 +138,11 @@ QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, int errNo =
class QTDSDriverPrivate
{
public:
QTDSDriverPrivate(): login(0) {}
QTDSDriverPrivate(): login(0), initialized(false) {}
LOGINREC* login; // login information
QString hostName;
QString db;
bool initialized;
};
@ -537,6 +538,7 @@ QVariant QTDSDriver::handle() const
void QTDSDriver::init()
{
d = new QTDSDriverPrivate();
d->initialized = (dbinit() == SUCCEED);
// the following two code-lines will fail compilation on some FreeTDS versions
// just comment them out if you have FreeTDS (you won't get any errors and warnings then)
dberrhandle((QERRHANDLE)qTdsErrHandler);
@ -578,7 +580,7 @@ bool QTDSDriver::open(const QString & db,
{
if (isOpen())
close();
if (!dbinit()) {
if (!d->initialized) {
setOpenError(true);
return false;
}

View File

@ -86,6 +86,8 @@ private slots:
void eventNotification_data() { generic_data(); }
void eventNotification();
void addDatabase();
void errorReporting_data();
void errorReporting();
//database specific tests
void recordMySQL_data() { generic_data("QMYSQL"); }
@ -442,6 +444,36 @@ void tst_QSqlDatabase::addDatabase()
QVERIFY(!QSqlDatabase::contains("INVALID_CONNECTION"));
}
void tst_QSqlDatabase::errorReporting_data()
{
QTest::addColumn<QString>("driver");
QTest::newRow("QTDS") << QString::fromLatin1("QTDS");
QTest::newRow("QTDS7") << QString::fromLatin1("QTDS7");
}
void tst_QSqlDatabase::errorReporting()
{
QFETCH(QString, driver);
if (!QSqlDatabase::drivers().contains(driver))
QSKIP(QString::fromLatin1("Database driver %1 not available").arg(driver).toLocal8Bit().constData());
const QString dbName = QLatin1String("errorReportingDb-") + driver;
QSqlDatabase db = QSqlDatabase::addDatabase(driver, dbName);
db.setHostName(QLatin1String("127.0.0.1"));
db.setDatabaseName(QLatin1String("NonExistantDatabase"));
db.setUserName(QLatin1String("InvalidUser"));
db.setPassword(QLatin1String("IncorrectPassword"));
QVERIFY(!db.open());
db = QSqlDatabase();
QSqlDatabase::removeDatabase(dbName);
}
void tst_QSqlDatabase::open()
{
QFETCH(QString, dbName);