diff options
-rw-r--r-- | src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp | 16 | ||||
-rw-r--r-- | tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 25 |
2 files changed, 40 insertions, 1 deletions
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index 67dd1a6ee5..444b18686a 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -446,7 +446,7 @@ static QString timespecToString(const QDateTime &dateTime) bool QSQLiteResult::exec() { Q_D(QSQLiteResult); - const QVector<QVariant> values = boundValues(); + QVector<QVariant> values = boundValues(); d->skippedStatus = false; d->skipRow = false; @@ -478,6 +478,20 @@ bool QSQLiteResult::exec() countIndexes); paramCountIsValid = bindParamCount == values.count(); + // When using named placeholders, it will reuse the index for duplicated + // placeholders. So we need to ensure the QVector has only one instance of + // each value as SQLite will do the rest for us. + QVector<QVariant> prunedValues; + QList<int> handledIndexes; + for (int i = 0, currentIndex = 0; i < values.size(); ++i) { + if (handledIndexes.contains(i)) + continue; + const auto placeHolder = QString::fromUtf8(sqlite3_bind_parameter_name(d->stmt, currentIndex + 1)); + handledIndexes << d->indexes[placeHolder]; + prunedValues << values.at(d->indexes[placeHolder].first()); + ++currentIndex; + } + values = prunedValues; } #endif diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 3ea13896d8..1a0340f153 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -2017,6 +2017,31 @@ void tst_QSqlQuery::prepare_bind_exec() QCOMPARE( q.value(1).toString(), QString("name") ); QCOMPARE( q.value(2).toString(), QString("name") ); + // Test that duplicated named placeholders before the next unique one works correctly - QTBUG-65150 + QVERIFY(q.prepare("insert into " + qtest_prepare + " (id, name, name2) values (:id, :id, :name)")); + for (i = 104; i < 106; ++i) { + q.bindValue(":id", i); + q.bindValue(":name", "name"); + QVERIFY(q.exec()); + } + QVERIFY(q.exec("select * from " + qtest_prepare + " where id > 103 order by id")); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 104); + QCOMPARE(q.value(1).toString(), QString("104")); + QCOMPARE(q.value(2).toString(), QString("name")); + + // Test that duplicated named placeholders in any order + QVERIFY(q.prepare("insert into " + qtest_prepare + " (id, name, name2) values (:id, :name, :id)")); + for (i = 107; i < 109; ++i) { + q.bindValue(":id", i); + q.bindValue(":name", "name"); + QVERIFY(q.exec()); + } + QVERIFY(q.exec("select * from " + qtest_prepare + " where id > 106 order by id")); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 107); + QCOMPARE(q.value(1).toString(), QString("name")); + QCOMPARE(q.value(2).toString(), QString("107")); } // end of SQLite scope } |