summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp16
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp25
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
}