SQL: Make QSqlDatabase::DriverDict creation thread-safe
Make the QSqlDatabase::DriverDict thread-safe and make sure it's properly cleaned up on destruction. Pick-to: 6.5 6.2 5.15 Fixes: QTBUG-112961 Change-Id: I1ff70e477579231754ef829fdede944d6042894d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
68f35a571a
commit
048a68c1e9
@ -9,6 +9,7 @@
|
|||||||
#include "qsqldriver.h"
|
#include "qsqldriver.h"
|
||||||
#include "qsqldriverplugin.h"
|
#include "qsqldriverplugin.h"
|
||||||
#include "qsqlindex.h"
|
#include "qsqlindex.h"
|
||||||
|
#include "QtCore/qapplicationstatic.h"
|
||||||
#include "private/qfactoryloader_p.h"
|
#include "private/qfactoryloader_p.h"
|
||||||
#include "private/qsqlnulldriver_p.h"
|
#include "private/qsqlnulldriver_p.h"
|
||||||
#include "qhash.h"
|
#include "qhash.h"
|
||||||
@ -23,8 +24,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
|
|||||||
|
|
||||||
const char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";
|
const char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";
|
||||||
|
|
||||||
typedef QHash<QString, QSqlDriverCreatorBase*> DriverDict;
|
|
||||||
|
|
||||||
class QConnectionDict: public QHash<QString, QSqlDatabase>
|
class QConnectionDict: public QHash<QString, QSqlDatabase>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -48,6 +47,14 @@ public:
|
|||||||
};
|
};
|
||||||
Q_GLOBAL_STATIC(QConnectionDict, dbDict)
|
Q_GLOBAL_STATIC(QConnectionDict, dbDict)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct DriverDict : public QHash<QString, QSqlDriverCreatorBase*>
|
||||||
|
{
|
||||||
|
~DriverDict();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Q_APPLICATION_STATIC(DriverDict, qtDriverDict)
|
||||||
|
|
||||||
class QSqlDatabasePrivate
|
class QSqlDatabasePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -120,23 +127,15 @@ void QSqlDatabasePrivate::cleanConnections()
|
|||||||
dict->clear();
|
dict->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool qDriverDictInit = false;
|
DriverDict::~DriverDict()
|
||||||
static void cleanDriverDict()
|
|
||||||
{
|
{
|
||||||
qDeleteAll(QSqlDatabasePrivate::driverDict());
|
qDeleteAll(*this);
|
||||||
QSqlDatabasePrivate::driverDict().clear();
|
|
||||||
QSqlDatabasePrivate::cleanConnections();
|
QSqlDatabasePrivate::cleanConnections();
|
||||||
qDriverDictInit = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverDict &QSqlDatabasePrivate::driverDict()
|
DriverDict &QSqlDatabasePrivate::driverDict()
|
||||||
{
|
{
|
||||||
static DriverDict dict;
|
return *qtDriverDict();
|
||||||
if (!qDriverDictInit) {
|
|
||||||
qDriverDictInit = true;
|
|
||||||
qAddPostRoutine(cleanDriverDict);
|
|
||||||
}
|
|
||||||
return dict;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
|
QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
|
||||||
@ -504,7 +503,7 @@ QStringList QSqlDatabase::drivers()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QReadLocker locker(&dbDict()->lock);
|
QReadLocker locker(&dbDict()->lock);
|
||||||
const DriverDict dict = QSqlDatabasePrivate::driverDict();
|
const DriverDict &dict = QSqlDatabasePrivate::driverDict();
|
||||||
for (const auto &[k, _] : dict.asKeyValueRange()) {
|
for (const auto &[k, _] : dict.asKeyValueRange()) {
|
||||||
if (!list.contains(k))
|
if (!list.contains(k))
|
||||||
list << k;
|
list << k;
|
||||||
@ -645,7 +644,7 @@ void QSqlDatabasePrivate::init(const QString &type)
|
|||||||
|
|
||||||
if (!driver) {
|
if (!driver) {
|
||||||
QReadLocker locker(&dbDict()->lock);
|
QReadLocker locker(&dbDict()->lock);
|
||||||
DriverDict dict = QSqlDatabasePrivate::driverDict();
|
const DriverDict &dict = QSqlDatabasePrivate::driverDict();
|
||||||
for (DriverDict::const_iterator it = dict.constBegin();
|
for (DriverDict::const_iterator it = dict.constBegin();
|
||||||
it != dict.constEnd() && !driver; ++it) {
|
it != dict.constEnd() && !driver; ++it) {
|
||||||
if (type == it.key()) {
|
if (type == it.key()) {
|
||||||
|
@ -121,6 +121,10 @@ void tst_QSql::open()
|
|||||||
|
|
||||||
void tst_QSql::openInvalid()
|
void tst_QSql::openInvalid()
|
||||||
{
|
{
|
||||||
|
int argc = 1;
|
||||||
|
char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
|
||||||
|
QCoreApplication app(argc, argv, false);
|
||||||
|
|
||||||
QSqlDatabase db;
|
QSqlDatabase db;
|
||||||
QVERIFY(!db.open());
|
QVERIFY(!db.open());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user