summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <[email protected]>2025-01-13 14:17:29 +0100
committerGiuseppe D'Angelo <[email protected]>2025-02-03 20:54:56 +0100
commitf744cef06cf3a56591782f487c545b55b2a673fb (patch)
treef130190e8e35a5dc4cb7b715eca3bef7276bb2ee
parentc0e96e0c8b2e9b39920597261a45683136d8483e (diff)
QSqlQuery: complete the deprecation/removal of its copies
QSqlQuery has been made movable in Qt 6.2 (14f9f00fdb2dc428610c08e3d9d03e38e9602166). The pre-existing copy operations have been deprecated, but not removed, in order to preserve SC/BC. This left us with two issues: 1) Whether or not to keep the deprecated copies in Qt 7. The answer is no: the copy operations are impossible to implement in a way consistent with value semantics (the state of the DB driver can't be copied in general). Therefore, mark the related APIs as to-be-removed, and not just deprecated. 2) While we no longer copy QSqlQuery from Qt code directly, QMetaType still detects the presence of the copy constructor and extracts it, triggering the deprecation warning. Rather than unconditionally suppressing the warning (which will hide any similar issue we might have in the future), add a local workaround that raises a runtime warning if QSqlQuery is copied through QMetaType, while not raising the deprecation warning when building Qt itself. [ChangeLog][QtSql][QSqlQuery] Copying a QSqlQuery object via QMetaType now raises a runtime warning. Note that copy operations for QSqlQuery objects have already been deprecated since Qt 6.2, and are planned to be removed in Qt 7. Fixes: QTBUG-132752 Task-number: QTBUG-91766 Pick-to: 6.9 Change-Id: I48714ad53ec706a5e4e055c45a1c05f372382940 Reviewed-by: Marc Mutz <[email protected]>
-rw-r--r--src/corelib/kernel/qmetatype.cpp12
-rw-r--r--src/corelib/kernel/qmetatype.h25
-rw-r--r--src/sql/kernel/qsqlquery.cpp8
-rw-r--r--src/sql/kernel/qsqlquery.h6
-rw-r--r--src/sql/models/qsqlquerymodel.cpp6
-rw-r--r--src/sql/models/qsqlquerymodel.h2
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp18
7 files changed, 68 insertions, 9 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index de7aa212081..be8467c2927 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -38,6 +38,7 @@
# include "qjsonobject.h"
# include "qjsonvalue.h"
# include "qline.h"
+# include "qloggingcategory.h"
# include "qmetaobject.h"
# include "qobject.h"
# include "qpoint.h"
@@ -58,6 +59,10 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_BOOTSTRAPPED
+Q_STATIC_LOGGING_CATEGORY(lcMetatypeDeprecated, "qt.core.qmetatype.deprecated");
+#endif
+
#define NS(x) QT_PREPEND_NAMESPACE(x)
QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl)
@@ -3265,6 +3270,13 @@ QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
*/
namespace QtPrivate {
+#if !defined(QT_BOOTSTRAPPED)
+void QMetaTypeCopyTraits::warnAboutDeprecatedCopy(const char *name)
+{
+ qCWarning(lcMetatypeDeprecated, "QMetaType: copy construction of type '%s' is deprecated", name);
+}
+#endif
+
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
// Explicit instantiation definition
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 44dbae5342e..0ec95c3bb99 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -28,7 +28,7 @@
#include <map>
#include <functional>
#include <optional>
-#include <QtCore/q20type_traits.h>
+#include <QtCore/qxptype_traits.h>
#ifdef Bool
#error qmetatype.h must be included before any header file that defines Bool
@@ -2408,6 +2408,20 @@ struct QDataStreamOperatorForType <T, true>
# pragma GCC visibility push(hidden)
#endif
+// ### Qt 7: consider removing this infrastructure if nothing uses it
+// (see also getCopyCtr())
+namespace QMetaTypeCopyTraits
+{
+ // Hack to suppress deprecation warnings from types
+ // with deprecated copy operations, cf. QTBUG-132752
+ template <typename T>
+ using HasDeprecatedCopyConstructorTest = typename T::_q_hasDeprecatedCopyConstructor;
+
+#if !defined(QT_BOOTSTRAPPED)
+ Q_CORE_EXPORT void warnAboutDeprecatedCopy(const char *name);
+#endif
+} // namespace QMetaTypeCopyTraits
+
template<typename S>
class QMetaTypeForType
{
@@ -2465,7 +2479,14 @@ public:
{
if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
return [](const QMetaTypeInterface *, void *addr, const void *other) {
- new (addr) S(*reinterpret_cast<const S *>(other));
+ if constexpr (qxp::is_detected_v<QMetaTypeCopyTraits::HasDeprecatedCopyConstructorTest, S>) {
+#if !defined(QT_BOOTSTRAPPED)
+ QMetaTypeCopyTraits::warnAboutDeprecatedCopy(getName());
+#endif
+ QT_IGNORE_DEPRECATIONS(new (addr) S(*reinterpret_cast<const S *>(other));)
+ } else {
+ new (addr) S(*reinterpret_cast<const S *>(other));
+ }
};
} else {
return nullptr;
diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index b9ebfedb639..57268e33cf0 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -216,11 +216,12 @@ QSqlQuery::~QSqlQuery()
delete d;
}
-#if QT_DEPRECATED_SINCE(6, 2)
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
/*!
Constructs a copy of \a other.
- \deprecated QSqlQuery cannot be meaningfully copied. Prepared
+ \deprecated [6.2] QSqlQuery cannot be meaningfully copied, and
+ therefore will no longer be copiable in Qt 7. Prepared
statements, bound values and so on will not work correctly, depending
on your database driver (for instance, changing the copy will affect
the original). Treat QSqlQuery as a move-only type instead.
@@ -235,7 +236,8 @@ QSqlQuery::QSqlQuery(const QSqlQuery& other)
/*!
Assigns \a other to this object.
- \deprecated QSqlQuery cannot be meaningfully copied. Prepared
+ \deprecated [6.2] QSqlQuery cannot be meaningfully copied, and
+ therefore will no longer be copiable in Qt 7. Prepared
statements, bound values and so on will not work correctly, depending
on your database driver (for instance, changing the copy will affect
the original). Treat QSqlQuery as a move-only type instead.
diff --git a/src/sql/kernel/qsqlquery.h b/src/sql/kernel/qsqlquery.h
index 96ad9022127..ec5f06550e1 100644
--- a/src/sql/kernel/qsqlquery.h
+++ b/src/sql/kernel/qsqlquery.h
@@ -32,7 +32,7 @@ public:
explicit QSqlQuery(const QString& query = QString(), const QSqlDatabase &db = QSqlDatabase());
explicit QSqlQuery(const QSqlDatabase &db);
-#if QT_DEPRECATED_SINCE(6, 2)
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
QT_DEPRECATED_VERSION_X_6_2("QSqlQuery is not meant to be copied. Use move construction instead.")
QSqlQuery(const QSqlQuery &other);
QT_DEPRECATED_VERSION_X_6_2("QSqlQuery is not meant to be copied. Use move assignment instead.")
@@ -111,6 +111,10 @@ public:
void finish();
bool nextResult();
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
+ // Avoid raising warnings in QMetaType, cf. QTBUG-132752
+ using _q_hasDeprecatedCopyConstructor = void;
+#endif
private:
QSqlQueryPrivate* d;
};
diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp
index 99aa82428e4..6cd2f342a9c 100644
--- a/src/sql/models/qsqlquerymodel.cpp
+++ b/src/sql/models/qsqlquerymodel.cpp
@@ -379,9 +379,11 @@ void QSqlQueryModel::queryChange()
// do nothing
}
-#if QT_DEPRECATED_SINCE(6, 2)
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
/*!
\deprecated [6.2] Use the \c{setQuery(QSqlQuery &&query)} overload instead.
+ This overload will be removed in Qt 7.
+
\overload
*/
void QSqlQueryModel::setQuery(const QSqlQuery &query)
@@ -389,7 +391,7 @@ void QSqlQueryModel::setQuery(const QSqlQuery &query)
QT_IGNORE_DEPRECATIONS(QSqlQuery copy = query;)
setQuery(std::move(copy));
}
-#endif // QT_DEPRECATED_SINCE(6, 2)
+#endif // QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
/*!
Resets the model and sets the data provider to be the given \a
diff --git a/src/sql/models/qsqlquerymodel.h b/src/sql/models/qsqlquerymodel.h
index f168d0bda13..72b9b053f03 100644
--- a/src/sql/models/qsqlquerymodel.h
+++ b/src/sql/models/qsqlquerymodel.h
@@ -40,7 +40,7 @@ public:
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
-#if QT_DEPRECATED_SINCE(6, 2)
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
QT_DEPRECATED_VERSION_X_6_2("QSqlQuery is not meant to be copied. Pass it by move instead.")
void setQuery(const QSqlQuery &query);
#endif
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index be98b7c1909..edc3c67587b 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -274,6 +274,12 @@ private slots:
void uuid_data() { generic_data(); }
void uuid();
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
+ // cleanup() is data-driven
+ void qmetatypeDeprecatedCopy_data() { generic_data(); }
+ void qmetatypeDeprecatedCopy();
+#endif
+
private:
// returns all database connections
void generic_data(const QString &engine=QString());
@@ -5282,5 +5288,17 @@ void tst_QSqlQuery::uuid()
QCOMPARE(qry.value(1).metaType().id(), QMetaType::QUuid);
}
+#if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 2)
+void tst_QSqlQuery::qmetatypeDeprecatedCopy()
+{
+ QMetaType mt = QMetaType::fromType<QSqlQuery>();
+ QSqlQuery query;
+
+ QTest::ignoreMessage(QtWarningMsg, "QMetaType: copy construction of type 'QSqlQuery' is deprecated");
+ void *copy = mt.create(&query);
+ mt.destroy(copy);
+}
+#endif
+
QTEST_MAIN(tst_QSqlQuery)
#include "tst_qsqlquery.moc"