Return an invalid QSqlDatabase when accessing from another thread
QSqlDatabase objects can only be used in the thread that the connection was opened for. So if the driver was created already then we check if the thread is correct. If it is not then we output a warning and return an invalid QSqlDatabase. [ChangeLog][QtSql][QSqlDatabase] QSqlDatabase::database() will return an invalid QSqlDatabase if the calling thread does not own the requested QSqlDatabase. Task-number: QTBUG-216 Change-Id: Ib5a25aa62129e3925f9819109af05961e5178bc5 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
2b0eb3fac3
commit
9b361f0e90
@ -50,6 +50,7 @@
|
||||
#include "private/qsqlnulldriver_p.h"
|
||||
#include "qmutex.h"
|
||||
#include "qhash.h"
|
||||
#include "qthread.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -232,6 +233,11 @@ QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open)
|
||||
dict->lock.lockForRead();
|
||||
QSqlDatabase db = dict->value(name);
|
||||
dict->lock.unlock();
|
||||
if (db.driver() && db.driver()->thread() != QThread::currentThread()) {
|
||||
qWarning("QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
|
||||
return QSqlDatabase();
|
||||
}
|
||||
|
||||
if (db.isValid() && !db.isOpen() && open) {
|
||||
if (!db.open())
|
||||
qWarning() << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
|
||||
|
@ -126,6 +126,8 @@ private slots:
|
||||
void formatValueTrimStrings();
|
||||
void precisionPolicy_data() { generic_data(); }
|
||||
void precisionPolicy();
|
||||
void multipleThreads_data() { generic_data(); }
|
||||
void multipleThreads();
|
||||
|
||||
void db2_valueCacheUpdate_data() { generic_data("QDB2"); }
|
||||
void db2_valueCacheUpdate();
|
||||
@ -2317,5 +2319,38 @@ void tst_QSqlDatabase::cloneDatabase()
|
||||
}
|
||||
}
|
||||
|
||||
class DatabaseThreadObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DatabaseThreadObject(const QString &name, QObject *parent = nullptr) : QObject(parent), dbName(name)
|
||||
{}
|
||||
public slots:
|
||||
void ready()
|
||||
{
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
|
||||
QSqlDatabase db = QSqlDatabase::database(dbName);
|
||||
QVERIFY(!db.isValid());
|
||||
QThread::currentThread()->exit();
|
||||
}
|
||||
private:
|
||||
QString dbName;
|
||||
};
|
||||
|
||||
void tst_QSqlDatabase::multipleThreads()
|
||||
{
|
||||
QFETCH(QString, dbName);
|
||||
QSqlDatabase db = QSqlDatabase::database(dbName);
|
||||
CHECK_DATABASE(db);
|
||||
DatabaseThreadObject dto(dbName);
|
||||
QThread t;
|
||||
dto.moveToThread(&t);
|
||||
connect(&t, &QThread::started, &dto, &DatabaseThreadObject::ready);
|
||||
t.start();
|
||||
QTRY_VERIFY(t.isRunning());
|
||||
QTRY_VERIFY(t.isFinished());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QSqlDatabase)
|
||||
#include "tst_qsqldatabase.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user