Initialize the QSqlQuery to be invalid when creating a sql model
When QSqlQueryModel or QSqlTableModel is created it will create a QSqlQuery which defaults to using the default QSqlDatabase connection. If this connection belongs to another thread then it will throw a warning as this is not safe to use. Since the QSqlQuery is always recreated when a query is set, the instance which is a member of the class can effectively be invalid until a new one is set. Task-number: QTBUG-69213 Change-Id: I68a5dd59fe62788f531d59a0680da11b118ee383 Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
fbb4befa33
commit
28702cb239
@ -75,7 +75,7 @@ public:
|
||||
void initColOffsets(int size);
|
||||
int columnInQuery(int modelColumn) const;
|
||||
|
||||
mutable QSqlQuery query;
|
||||
mutable QSqlQuery query = { QSqlQuery(0) };
|
||||
mutable QSqlError error;
|
||||
QModelIndex bottom;
|
||||
QSqlRecord rec;
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
QSqlTableModel::EditStrategy strategy;
|
||||
bool busyInsertingRows;
|
||||
|
||||
QSqlQuery editQuery;
|
||||
QSqlQuery editQuery = { QSqlQuery(0) };
|
||||
QSqlIndex primaryIndex;
|
||||
QString tableName;
|
||||
QString filter;
|
||||
|
@ -31,11 +31,29 @@
|
||||
#include "../../kernel/qsqldatabase/tst_databases.h"
|
||||
#include <QtSql>
|
||||
#include <QtSql/private/qsqltablemodel_p.h>
|
||||
#include <QThread>
|
||||
|
||||
const QString test(qTableName("test", __FILE__, QSqlDatabase())),
|
||||
test2(qTableName("test2", __FILE__, QSqlDatabase())),
|
||||
test3(qTableName("test3", __FILE__, QSqlDatabase()));
|
||||
|
||||
// In order to catch when the warning message occurs, indicating that the database belongs to another
|
||||
// thread, we have to install our own message handler. To ensure that the test reporting still happens
|
||||
// as before, we call the originating one.
|
||||
//
|
||||
// For now, this is only called inside the modelInAnotherThread() test
|
||||
QtMessageHandler oldHandler = nullptr;
|
||||
|
||||
void sqlTableModelMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
if (type == QtWarningMsg &&
|
||||
msg == "QSqlDatabasePrivate::database: requested database does not "
|
||||
"belong to the calling thread.") {
|
||||
QFAIL("Requested database does not belong to the calling thread.");
|
||||
}
|
||||
if (oldHandler)
|
||||
oldHandler(type, context, msg);
|
||||
}
|
||||
|
||||
class tst_QSqlTableModel : public QObject
|
||||
{
|
||||
@ -116,6 +134,7 @@ private slots:
|
||||
|
||||
void sqlite_bigTable_data() { generic_data("QSQLITE"); }
|
||||
void sqlite_bigTable();
|
||||
void modelInAnotherThread();
|
||||
|
||||
// bug specific tests
|
||||
void insertRecordBeforeSelect_data() { generic_data(); }
|
||||
@ -276,6 +295,10 @@ void tst_QSqlTableModel::init()
|
||||
void tst_QSqlTableModel::cleanup()
|
||||
{
|
||||
recreateTestTables();
|
||||
if (oldHandler) {
|
||||
qInstallMessageHandler(oldHandler);
|
||||
oldHandler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSqlTableModel::select()
|
||||
@ -2100,5 +2123,29 @@ void tst_QSqlTableModel::invalidFilterAndHeaderData()
|
||||
QVERIFY(!v.isValid());
|
||||
}
|
||||
|
||||
class SqlThread : public QThread
|
||||
{
|
||||
public:
|
||||
SqlThread() : QThread() {}
|
||||
void run()
|
||||
{
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "non-default-connection");
|
||||
QSqlTableModel stm(nullptr, db);
|
||||
isDone = true;
|
||||
}
|
||||
bool isDone = false;
|
||||
};
|
||||
|
||||
void tst_QSqlTableModel::modelInAnotherThread()
|
||||
{
|
||||
oldHandler = qInstallMessageHandler(sqlTableModelMessageHandler);
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
CHECK_DATABASE(db);
|
||||
SqlThread t;
|
||||
t.start();
|
||||
QTRY_VERIFY(t.isDone);
|
||||
QVERIFY(t.isFinished());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QSqlTableModel)
|
||||
#include "tst_qsqltablemodel.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user