From 8ba9d2e0220777bc1a2322eeece7fa9a5c55a96d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 11 Jun 2020 10:49:50 +0200 Subject: Change boundValues() to return a QVariantList This enables the order of boundValues to be consistent as with a QMap it could have been reordered which can be a problem for positional bindings. [ChangeLog][QtSQL] Changed signature of QSqlQuery::boundValues() to return a QVariantList Fixes: QTBUG-51609 Change-Id: I1c80fa8522fa7352723420b6fc9ec466406315fb Reviewed-by: Volker Hilsheimer --- src/sql/doc/snippets/sqldatabase/sqldatabase.cpp | 18 +---- src/sql/doc/src/qt6-changes.qdoc | 66 ++++++++++++++++++ src/sql/kernel/qsqlquery.cpp | 25 +++---- src/sql/kernel/qsqlquery.h | 6 +- tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 84 ++++++++++++----------- 5 files changed, 126 insertions(+), 73 deletions(-) create mode 100644 src/sql/doc/src/qt6-changes.qdoc diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp index c28e750b16..001e2ba3b2 100644 --- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp @@ -50,7 +50,6 @@ #include #include -#include #include using namespace std; @@ -202,23 +201,12 @@ void QSqlQuery_snippets() QSqlQuery query; { - // examine with named binding + // examine with named or positional binding //! [14] - QMap sqlIterator(query.boundValues()); - for (auto i = sqlIterator.begin(); i != sqlIterator.end(); ++i) { - cout << i.key().toUtf8().data() << ": " - << i.value().toString().toUtf8().data() << "\n"; - } -//! [14] - } - - { - // examine with positional binding -//! [15] - QList list = query.boundValues().values(); + QVariantList list = query.boundValues(); for (int i = 0; i < list.size(); ++i) cout << i << ": " << list.at(i).toString().toUtf8().data() << "\n"; -//! [15] +//! [14] } } diff --git a/src/sql/doc/src/qt6-changes.qdoc b/src/sql/doc/src/qt6-changes.qdoc new file mode 100644 index 0000000000..4bde13e0ed --- /dev/null +++ b/src/sql/doc/src/qt6-changes.qdoc @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qtsql-changes-qt6.html + \title Porting to Qt 6 - Qt Sql + + Qt 6 is a result of the conscious effort to make the framework more + efficient and easy to use. + + We try to maintain binary and source compatibility for all the public + APIs in each release. But some changes were inevitable in an effort to + make Qt a better framework. + + In this topic we summarize those changes in Qt Sql, and provide guidance + to handle them. + + \section1 QSqlQuery + + \section2 boundValues() Signature + + The return type for boundValues() has been changed from QMap + to a QVariantList. The order can be relied upon so it will be in the order of the + binding in the prepared query. Change code like the following: + + \code + QMap values = boundValues(); + int id = values[":id"].value().toInt(); + \endcode + + \code + QList values = boundValues().values(); + int id = values.at(0).toInt(); + \endcode + + to: + + \code + QList values = boundValues().values(); + int id = values.at(0).toInt(); + \endcode +*/ diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 98e65b019c..1e848f4168 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -180,7 +180,7 @@ QSqlQueryPrivate::~QSqlQueryPrivate() them in the same query. You can retrieve the values of all the fields in a single variable - (a map) using boundValues(). + using boundValues(). \note Not all SQL operations support binding values. Refer to your database system's documentation to check their availability. @@ -1144,27 +1144,24 @@ QVariant QSqlQuery::boundValue(int pos) const } /*! - Returns a map of the bound values. + \since 6.0 - With named binding, the bound values can be examined in the - following ways: + Returns a list of bound values. - \snippet sqldatabase/sqldatabase.cpp 14 + The order of the list is in binding order, irrespective of whether + named or positional binding is used. - With positional binding, the code becomes: + The bound values can be examined in the following way: - \snippet sqldatabase/sqldatabase.cpp 15 + \snippet sqldatabase/sqldatabase.cpp 14 \sa boundValue(), bindValue(), addBindValue() */ -QMap QSqlQuery::boundValues() const -{ - QMap map; - const QVector values(d->sqlResult->boundValues()); - for (int i = 0; i < values.count(); ++i) - map[d->sqlResult->boundValueName(i)] = values.at(i); - return map; +QVariantList QSqlQuery::boundValues() const +{ + const QVariantList values(d->sqlResult->boundValues()); + return values; } /*! diff --git a/src/sql/kernel/qsqlquery.h b/src/sql/kernel/qsqlquery.h index 3be04c492c..b270441273 100644 --- a/src/sql/kernel/qsqlquery.h +++ b/src/sql/kernel/qsqlquery.h @@ -43,18 +43,18 @@ #include #include #include +#include QT_BEGIN_NAMESPACE -class QVariant; class QSqlDriver; class QSqlError; class QSqlResult; class QSqlRecord; -template class QMap; class QSqlQueryPrivate; + class Q_SQL_EXPORT QSqlQuery { public: @@ -107,7 +107,7 @@ public: void addBindValue(const QVariant& val, QSql::ParamType type = QSql::In); QVariant boundValue(const QString& placeholder) const; QVariant boundValue(int pos) const; - QMap boundValues() const; + QVariantList boundValues() const; QString executedQuery() const; QVariant lastInsertId() const; void finish(); diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index e60d33081b..67d160d6af 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -2100,10 +2100,10 @@ void tst_QSqlQuery::prepare_bind_exec() q.bindValue( ":name", values[i] ); q.bindValue( ":id", i ); QVERIFY_SQL( q, exec() ); - QMap m = q.boundValues(); + QVariantList m = q.boundValues(); QCOMPARE(( int ) m.count(), 2 ); - QCOMPARE( m[":name"].toString(), values[i] ); - QCOMPARE( m[":id"].toInt(), i ); + QCOMPARE(m.at(0).toInt(), i); + QCOMPARE(m.at(1).toString(), values[i]); } q.bindValue( ":id", 8 ); @@ -2168,88 +2168,88 @@ void tst_QSqlQuery::prepare_bind_exec() /*** Below we test QSqlQuery::boundValues() with position arguments. * Due to the fact that the name of a positional argument is not - * specified by the Qt docs, we only test that the QMap contains - * the correct values and that QSqlResult::boundValueName returns - * the key that corrosponds to the correct value. ***/ + * specified by the Qt docs, we test that the QVector contains + * the correct values in the same order as QSqlResult::boundValueName + * returns since it should be in insertion order (i.e. field order). ***/ QVERIFY( q.prepare( "insert into " + qtest_prepare + " (id, name) values (?, ?)" ) ); q.bindValue( 0, 0 ); q.bindValue( 1, values[ 0 ] ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 0); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[0]); + QCOMPARE(q.boundValues().at(0).toInt(), 0); + QCOMPARE(q.boundValues().at(1).toString(), values[0]); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 0); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[0]); + QCOMPARE(q.boundValues().at(0).toInt(), 0); + QCOMPARE(q.boundValues().at(1).toString(), values[0]); q.addBindValue( 1 ); q.addBindValue( values[ 1 ] ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 1); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[1]); + QCOMPARE(q.boundValues().at(0).toInt(), 1); + QCOMPARE(q.boundValues().at(1).toString(), values[1]); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 1); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[1]); + QCOMPARE(q.boundValues().at(0).toInt(), 1); + QCOMPARE(q.boundValues().at(1).toString(), values[1]); q.addBindValue( 2 ); q.addBindValue( values[ 2 ] ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 2); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[2]); + QCOMPARE(q.boundValues().at(0).toInt(), 2); + QCOMPARE(q.boundValues().at(1).toString(), values[2]); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 2); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[2]); + QCOMPARE(q.boundValues().at(0).toInt(), 2); + QCOMPARE(q.boundValues().at(1).toString(), values[2]); q.addBindValue( 3 ); q.addBindValue( values[ 3 ] ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 3); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[3]); + QCOMPARE(q.boundValues().at(0).toInt(), 3); + QCOMPARE(q.boundValues().at(1).toString(), values[3]); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 3); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[3]); + QCOMPARE(q.boundValues().at(0).toInt(), 3); + QCOMPARE(q.boundValues().at(1).toString(), values[3]); q.addBindValue( 4 ); q.addBindValue( values[ 4 ] ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 4); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[4]); + QCOMPARE(q.boundValues().at(0).toInt(), 4); + QCOMPARE(q.boundValues().at(1).toString(), values[4]); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 4); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[4]); + QCOMPARE(q.boundValues().at(0).toInt(), 4); + QCOMPARE(q.boundValues().at(1).toString(), values[4]); q.bindValue( 1, values[ 5 ] ); q.bindValue( 0, 5 ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 5); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[5]); + QCOMPARE(q.boundValues().at(0).toInt(), 5); + QCOMPARE(q.boundValues().at(1).toString(), values[5]); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 5); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), values[5]); + QCOMPARE(q.boundValues().at(0).toInt(), 5); + QCOMPARE(q.boundValues().at(1).toString(), values[5]); q.bindValue( 0, 6 ); q.bindValue( 1, QString() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 6); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), QString()); + QCOMPARE(q.boundValues().at(0).toInt(), 6); + QCOMPARE(q.boundValues().at(1).toString(), QString()); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValues().size(), 2 ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 6); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), QString()); + QCOMPARE(q.boundValues().at(0).toInt(), 6); + QCOMPARE(q.boundValues().at(1).toString(), QString()); if ( db.driver()->hasFeature( QSqlDriver::Unicode ) ) { q.bindValue( 0, 7 ); q.bindValue( 1, utf8str ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 7); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), utf8str); + QCOMPARE(q.boundValues().at(0).toInt(), 7); + QCOMPARE(q.boundValues().at(1).toString(), utf8str); QVERIFY_SQL( q, exec() ); - QCOMPARE(q.boundValues()[q.result()->boundValueName(0)].toInt(), 7); - QCOMPARE(q.boundValues()[q.result()->boundValueName(1)].toString(), utf8str); + QCOMPARE(q.boundValues().at(0).toInt(), 7); + QCOMPARE(q.boundValues().at(1).toString(), utf8str); } QVERIFY_SQL( q, exec( "SELECT * FROM " + qtest_prepare + " order by id" ) ); @@ -3569,7 +3569,8 @@ void tst_QSqlQuery::QTBUG_551() q.bindValue(":outp", outLst, QSql::Out); QVERIFY_SQL(q, execBatch(QSqlQuery::ValuesAsColumns) ); - res_outLst = qvariant_cast(q.boundValues()[":outp"]); + res_outLst = qvariant_cast(q.boundValues().at(1)); + QCOMPARE(res_outLst[0].toString(), QLatin1String("1. Value is 0")); QCOMPARE(res_outLst[1].toString(), QLatin1String("2. Value is 1")); QCOMPARE(res_outLst[2].toString(), QLatin1String("3. Value is 2")); @@ -3580,7 +3581,8 @@ void tst_QSqlQuery::QTBUG_12186() QFETCH( QString, dbName ); QSqlDatabase db = QSqlDatabase::database(dbName); - // make sure that query.boundValues() returns the values in the right order even for more than 16 placeholders + // make sure that query.boundValues() returns the values in the right order + // even for more than 16 placeholders QSqlQuery query(db); query.prepare("INSERT INTO person (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); @@ -3593,7 +3595,7 @@ void tst_QSqlQuery::QTBUG_12186() foreach (QVariant v, values) query.bindValue(v.toInt(), v); - QCOMPARE(query.boundValues().values(), values); + QCOMPARE(query.boundValues(), values); } void tst_QSqlQuery::QTBUG_14132() -- cgit v1.2.3