diff --git a/sources/dataBase/sqlreadonly.cpp b/sources/dataBase/sqlreadonly.cpp index 95996bde5..f61aabbea 100644 --- a/sources/dataBase/sqlreadonly.cpp +++ b/sources/dataBase/sqlreadonly.cpp @@ -86,9 +86,16 @@ QSqlQuery execReadOnly(const QSqlDatabase &db, const QString &query, QString *er QSqlQuery result(db); const bool ok = result.exec(query); + //Switching query_only off aborts a statement SQLite is still + //stepping through -- an unsorted UNION ALL then ends after its + //first row. So the checked run is finished first, and a statement + //that passed is run again for the caller: SQLite refuses a write + //at its first step, so passing that step proves it read-only. + result.finish(); QSqlQuery(db).exec(QStringLiteral("PRAGMA query_only = OFF")); if (ok) { + result.exec(query); return result; } diff --git a/tests/qttest/tst_sqlreadonly.cpp b/tests/qttest/tst_sqlreadonly.cpp index a96735fd9..7159e1c28 100644 --- a/tests/qttest/tst_sqlreadonly.cpp +++ b/tests/qttest/tst_sqlreadonly.cpp @@ -40,6 +40,7 @@ #include #include +#include #include class TstSqlReadOnly : public QObject @@ -63,6 +64,7 @@ class TstSqlReadOnly : public QObject void doesNotExecuteWhatItRefuses(); void refusedQueryCannotBeRunAgain(); void acceptedQueryRunAgainStillReads(); + void returnsEveryRowOfACompoundSelect(); void leavesTheConnectionWritable(); private: @@ -242,6 +244,21 @@ void TstSqlReadOnly::acceptedQueryRunAgainStillReads() QCOMPARE(n, 2); } +void TstSqlReadOnly::returnsEveryRowOfACompoundSelect() +{ + // Switching query_only off aborts a statement SQLite is still + // stepping through, and an unsorted UNION ALL is one: it came back + // with its first row only. + QSqlQuery q = QETSql::execReadOnly( + m_db, "SELECT uuid FROM element UNION ALL SELECT uuid FROM element"); + QStringList uuids; + while (q.next()) { + uuids << q.value(0).toString(); + } + QVERIFY(!q.lastError().isValid()); + QCOMPARE(uuids, QStringList({"a", "b", "a", "b"})); +} + void TstSqlReadOnly::leavesTheConnectionWritable() { // query_only must not outlive the call, whatever its outcome: the