summaryrefslogtreecommitdiffstats
path: root/src/sql/kernel/qsqldatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sql/kernel/qsqldatabase.cpp')
-rw-r--r--src/sql/kernel/qsqldatabase.cpp81
1 files changed, 67 insertions, 14 deletions
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index 988eee25b3..c25fabf0a4 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -3,10 +3,11 @@
#include "qsqldatabase.h"
#include "qsqlquery.h"
-#include "qdebug.h"
+#include "qloggingcategory.h"
#include "qcoreapplication.h"
#include "qreadwritelock.h"
#include "qsqldriver.h"
+#include "qsqldriver_p.h"
#include "qsqldriverplugin.h"
#include "qsqlindex.h"
#include "QtCore/qapplicationstatic.h"
@@ -17,16 +18,18 @@
QT_BEGIN_NAMESPACE
+static Q_LOGGING_CATEGORY(lcSqlDb, "qt.sql.qsqldatabase")
+
using namespace Qt::StringLiterals;
#define CHECK_QCOREAPPLICATION \
if (Q_UNLIKELY(!QCoreApplication::instance())) { \
- qWarning("QSqlDatabase requires a QCoreApplication"); \
+ qCWarning(lcSqlDb, "QSqlDatabase requires a QCoreApplication"); \
return; \
}
#define CHECK_QCOREAPPLICATION_RETVAL \
if (Q_UNLIKELY(!QCoreApplication::instance())) { \
- qWarning("QSqlDatabase requires a QCoreApplication"); \
+ qCWarning(lcSqlDb, "QSqlDatabase requires a QCoreApplication"); \
return {}; \
}
@@ -120,7 +123,7 @@ QSqlDatabasePrivate::~QSqlDatabasePrivate()
QtSqlGlobals::~QtSqlGlobals()
{
qDeleteAll(registeredDrivers);
- for (const auto &[k, v] : connections.asKeyValueRange())
+ for (const auto &[k, v] : std::as_const(connections).asKeyValueRange())
QSqlDatabasePrivate::invalidateDb(v, k, false);
}
@@ -134,8 +137,8 @@ QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn)
{
if (db.d->ref.loadRelaxed() != 1 && doWarn) {
- qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, "
- "all queries will cease to work.", name.toLocal8Bit().constData());
+ qCWarning(lcSqlDb, "QSqlDatabasePrivate::removeDatabase: connection '%ls' is still in use, "
+ "all queries will cease to work.", qUtf16Printable(name));
db.d->disable();
db.d->connName.clear();
}
@@ -161,8 +164,8 @@ void QSqlDatabasePrivate::addDatabase(const QSqlDatabase &db, const QString &nam
if (sqlGlobals->connections.contains(name)) {
invalidateDb(sqlGlobals->connections.take(name), name);
- qWarning("QSqlDatabasePrivate::addDatabase: duplicate connection name '%s', old "
- "connection removed.", name.toLocal8Bit().data());
+ qCWarning(lcSqlDb, "QSqlDatabasePrivate::addDatabase: duplicate connection name '%ls', old "
+ "connection removed.", qUtf16Printable(name));
}
sqlGlobals->connections.insert(name, db);
db.d->connName = name;
@@ -177,13 +180,13 @@ QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open)
if (!db.isValid())
return db;
if (db.driver()->thread() != QThread::currentThread()) {
- qWarning("QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
+ qCWarning(lcSqlDb, "QSqlDatabasePrivate::database: requested database does not belong to the calling thread.");
return QSqlDatabase();
}
if (open && !db.isOpen()) {
if (!db.open())
- qWarning() << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
+ qCWarning(lcSqlDb) << "QSqlDatabasePrivate::database: unable to open database:" << db.lastError().text();
}
return db;
@@ -236,6 +239,8 @@ void QSqlDatabasePrivate::disable()
Destroys the SQL driver creator object.
*/
+QSqlDriverCreatorBase::~QSqlDriverCreatorBase()
+ = default;
/*!
\fn QSqlDriver *QSqlDriverCreatorBase::createObject() const
@@ -280,6 +285,10 @@ void QSqlDatabasePrivate::disable()
QSqlDriver. Alternatively, you can subclass your own database
driver from QSqlDriver. See \l{How to Write Your Own Database
Driver} for more information.
+ A QSqlDatabase instance must only be accessed by the thread it
+ was created in. Therefore you have to make sure to create them
+ in the correct context. Alternatively you can change the context
+ with QSqlDatabase::moveToThread().
Create a connection (i.e., an instance of QSqlDatabase) by calling
one of the static addDatabase() functions, where you specify
@@ -646,11 +655,11 @@ void QSqlDatabasePrivate::init(const QString &type)
driver = qLoadPlugin<QSqlDriver, QSqlDriverPlugin>(loader(), type);
if (!driver) {
- qWarning("QSqlDatabase: %s driver not loaded", type.toLatin1().data());
- qWarning("QSqlDatabase: available drivers: %s",
- QSqlDatabase::drivers().join(u' ').toLatin1().data());
+ qCWarning(lcSqlDb, "QSqlDatabase: %ls driver not loaded", qUtf16Printable(type));
+ qCWarning(lcSqlDb, "QSqlDatabase: available drivers: %ls",
+ qUtf16Printable(QSqlDatabase::drivers().join(u' ')));
if (QCoreApplication::instance() == nullptr)
- qWarning("QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins");
+ qCWarning(lcSqlDb, "QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins");
driver = shared_null()->driver;
}
}
@@ -1331,6 +1340,50 @@ QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const
return d->precisionPolicy;
}
+/*!
+ \since 6.8
+
+ Changes the thread affinity for QSqlDatabase and its associated driver.
+ This function returns \c true when the function succeeds. Event processing
+ will continue in the \a targetThread.
+
+ During this operation you have to make sure that there is no QSqlQuery
+ bound to this instance otherwise the QSqlDatabase will not be moved to
+ the given thread and the function returns \c false.
+
+ Since the associated driver is derived from QObject, all constraints for
+ moving a QObject to another thread also apply to this function.
+
+ \sa QObject::moveToThread(), {Threads and the SQL Module}
+*/
+bool QSqlDatabase::moveToThread(QThread *targetThread)
+{
+ if (auto drv = driver()) {
+ if (drv != QSqlDatabasePrivate::shared_null()->driver) {
+ // two instances are alive - the one here and the one in dbDict()
+ if (d->ref.loadRelaxed() > 2) {
+ qWarning("QSqlDatabasePrivate::moveToThread: connection '%ls' is still in use "
+ "in the current thread.", qUtf16Printable(d->connName));
+ return false;
+ }
+ return drv->moveToThread(targetThread);
+ }
+ }
+ return false;
+}
+
+/*!
+ \since 6.8
+
+ Returns a pointer to the associated QThread instance.
+*/
+QThread *QSqlDatabase::thread() const
+{
+ if (auto drv = driver())
+ return drv->thread();
+ return nullptr;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)