diff options
-rw-r--r-- | src/sql/kernel/qsqlresult.cpp | 75 | ||||
-rw-r--r-- | tests/auto/sql/kernel/qsqlresult/testsqldriver.h | 5 | ||||
-rw-r--r-- | tests/auto/sql/kernel/qsqlresult/tst_qsqlresult.cpp | 34 |
3 files changed, 93 insertions, 21 deletions
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 2ebfba0788..ea972abf50 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -87,17 +87,33 @@ QString QSqlResultPrivate::positionalToNamedBinding(const QString &query, QStrin QString result; result.reserve(n * 5 / 4); - bool inQuote = false; + QChar closingQuote; int count = 0; for (int i = 0; i < n; ++i) { QChar ch = query.at(i); - if (ch == QLatin1Char('?') && !inQuote) { - result += fieldSerialFunc(count++); - } else { - if (ch == QLatin1Char('\'')) - inQuote = !inQuote; + if (!closingQuote.isNull()) { + if (ch == closingQuote) { + if (closingQuote == QLatin1Char(']') + && i + 1 < n && query.at(i + 1) == closingQuote) { + // consume the extra character. don't close. + ++i; + result += ch; + } else { + closingQuote = QChar(); + } + } result += ch; + } else { + if (ch == QLatin1Char('?')) { + result += fieldSerialFunc(count++); + } else { + if (ch == QLatin1Char('\'') || ch == QLatin1Char('"') || ch == QLatin1Char('`')) + closingQuote = ch; + else if (ch == QLatin1Char('[')) + closingQuote = QLatin1Char(']'); + result += ch; + } } } result.squeeze(); @@ -110,28 +126,45 @@ QString QSqlResultPrivate::namedToPositionalBinding(const QString &query) QString result; result.reserve(n); - bool inQuote = false; + QChar closingQuote; int count = 0; int i = 0; while (i < n) { QChar ch = query.at(i); - if (ch == QLatin1Char(':') && !inQuote - && (i == 0 || query.at(i - 1) != QLatin1Char(':')) - && (i + 1 < n && qIsAlnum(query.at(i + 1)))) { - int pos = i + 2; - while (pos < n && qIsAlnum(query.at(pos))) - ++pos; - QString holder(query.mid(i, pos - i)); - indexes[holder].append(count++); - holders.append(QHolder(holder, i)); - result += QLatin1Char('?'); - i = pos; - } else { - if (ch == QLatin1Char('\'')) - inQuote = !inQuote; + if (!closingQuote.isNull()) { + if (ch == closingQuote) { + if (closingQuote == QLatin1Char(']') + && i + 1 < n && query.at(i + 1) == closingQuote) { + // consume the extra character. don't close. + ++i; + result += ch; + } else { + closingQuote = QChar(); + } + } result += ch; ++i; + } else { + if (ch == QLatin1Char(':') + && (i == 0 || query.at(i - 1) != QLatin1Char(':')) + && (i + 1 < n && qIsAlnum(query.at(i + 1)))) { + int pos = i + 2; + while (pos < n && qIsAlnum(query.at(pos))) + ++pos; + QString holder(query.mid(i, pos - i)); + indexes[holder].append(count++); + holders.append(QHolder(holder, i)); + result += QLatin1Char('?'); + i = pos; + } else { + if (ch == QLatin1Char('\'') || ch == QLatin1Char('"') || ch == QLatin1Char('`')) + closingQuote = ch; + else if (ch == QLatin1Char('[')) + closingQuote = QLatin1Char(']'); + result += ch; + ++i; + } } } result.squeeze(); diff --git a/tests/auto/sql/kernel/qsqlresult/testsqldriver.h b/tests/auto/sql/kernel/qsqlresult/testsqldriver.h index 720b819839..7040ddf360 100644 --- a/tests/auto/sql/kernel/qsqlresult/testsqldriver.h +++ b/tests/auto/sql/kernel/qsqlresult/testsqldriver.h @@ -58,6 +58,11 @@ public: return QSqlResult::savePrepare(sqlquery); } + QVector<QVariant> boundValues() const + { + return QSqlResult::boundValues(); + } + protected: QVariant data(int /* index */) { return QVariant(); } bool isNull(int /* index */) { return false; } diff --git a/tests/auto/sql/kernel/qsqlresult/tst_qsqlresult.cpp b/tests/auto/sql/kernel/qsqlresult/tst_qsqlresult.cpp index 7e901d4b2c..ba6b4d1fbf 100644 --- a/tests/auto/sql/kernel/qsqlresult/tst_qsqlresult.cpp +++ b/tests/auto/sql/kernel/qsqlresult/tst_qsqlresult.cpp @@ -53,6 +53,7 @@ public: private slots: void positionalToNamedBinding(); + void parseOfBoundValues(); }; @@ -66,6 +67,39 @@ void tst_QSqlResult::positionalToNamedBinding() TestSqlDriverResult result(&testDriver); QString query("INSERT INTO MYTABLE (ID, NAME, BIRTH) VALUES(?, ?, ?)"); QVERIFY(result.savePrepare(query)); + QCOMPARE(result.boundValues().count(), 3); +} + +void tst_QSqlResult::parseOfBoundValues() +{ + TestSqlDriver testDriver; + TestSqlDriverResult result(&testDriver); + QVERIFY(result.savePrepare("SELECT :1 AS \":2\"")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT :1 AS ':2'")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT :1 AS [:2]")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT :1 AS [:2]]]")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT :1 AS [:2]]]]]")); + QCOMPARE(result.boundValues().count(), 1); + + QVERIFY(result.savePrepare("SELECT ? AS \"?\"")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT ? AS '?'")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT ? AS [?]")); + QCOMPARE(result.boundValues().count(), 1); + + QVERIFY(result.savePrepare("SELECT ? AS \"'?\"")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT ? AS '?\"'")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT ? AS '?''?'")); + QCOMPARE(result.boundValues().count(), 1); + QVERIFY(result.savePrepare("SELECT ? AS [\"?']")); + QCOMPARE(result.boundValues().count(), 1); } QTEST_MAIN( tst_QSqlResult ) |