Check driver validity before using it

Even though it is stated in the documentation that the SQL driver must
remain valid during the life time of QSqlQuery, there are users who don't
follow the rule. It's common that the destructor of QSqlQuery is called
after the driver is already deleted. This fix checks the validity of
the SQLite driver before QSqliteResult uses it in destructor.

Task-number: QTBUG-16967
Change-Id: If0f52113f12e14102da1671cd6e12bdaa267114f
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
This commit is contained in:
Honglei Zhang 2011-12-08 15:38:25 +02:00 committed by Qt by Nokia
parent b9ebb65c77
commit 67be01ae50
3 changed files with 14 additions and 6 deletions

View File

@ -292,7 +292,9 @@ QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db)
QSQLiteResult::~QSQLiteResult()
{
qobject_cast<const QSQLiteDriver *>(driver())->d->results.removeOne(this);
const QSqlDriver *sqlDriver = driver();
if (sqlDriver)
qobject_cast<const QSQLiteDriver *>(sqlDriver)->d->results.removeOne(this);
d->cleanup();
delete d;
}

View File

@ -48,6 +48,7 @@
#include "qsqlresult.h"
#include "qvector.h"
#include "qsqldriver.h"
#include "qpointer.h"
#include <QDebug>
QT_BEGIN_NAMESPACE
@ -64,7 +65,7 @@ class QSqlResultPrivate
{
public:
QSqlResultPrivate(QSqlResult* d)
: q(d), sqldriver(0), idx(QSql::BeforeFirstRow), active(false),
: q(d), idx(QSql::BeforeFirstRow), active(false),
isSel(false), forwardOnly(false), precisionPolicy(QSql::LowPrecisionDouble), bindCount(0), binds(QSqlResult::PositionalBinding)
{}
@ -98,7 +99,7 @@ public:
public:
QSqlResult* q;
const QSqlDriver* sqldriver;
QPointer<QSqlDriver> sqldriver;
int idx;
QString sql;
bool active;
@ -250,7 +251,7 @@ QString QSqlResultPrivate::namedToPositionalBinding()
QSqlResult::QSqlResult(const QSqlDriver *db)
{
d = new QSqlResultPrivate(this);
d->sqldriver = db;
d->sqldriver = const_cast<QSqlDriver *>(db);
if(db) {
setNumericalPrecisionPolicy(db->numericalPrecisionPolicy());
}

View File

@ -3135,6 +3135,7 @@ void tst_QSqlQuery::QTBUG_21884()
*/
void tst_QSqlQuery::QTBUG_16967()
{
QSqlQuery q2;
QFETCH(QString, dbName);
{
QSqlDatabase db = QSqlDatabase::database(dbName);
@ -3146,6 +3147,7 @@ void tst_QSqlQuery::QTBUG_16967()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QSqlQuery q(db);
q2 = q;
q.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, str TEXT);");
db.close();
QCOMPARE(db.lastError().type(), QSqlError::NoError);
@ -3154,8 +3156,9 @@ void tst_QSqlQuery::QTBUG_16967()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QSqlQuery q(db);
q.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, str TEXT);");
q.exec();
q2 = q;
q2.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, str TEXT);");
q2.exec();
db.close();
QCOMPARE(db.lastError().type(), QSqlError::NoError);
}
@ -3163,6 +3166,7 @@ void tst_QSqlQuery::QTBUG_16967()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QSqlQuery q(db);
q2 = q;
q.exec("INSERT INTO t1 (id, str) VALUES(1, \"test1\");");
db.close();
QCOMPARE(db.lastError().type(), QSqlError::NoError);
@ -3171,6 +3175,7 @@ void tst_QSqlQuery::QTBUG_16967()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QSqlQuery q(db);
q2 = q;
q.exec("SELECT * FROM t1;");
db.close();
QCOMPARE(db.lastError().type(), QSqlError::NoError);