fix parsing of bound SQL statements for PostgreSQL

PostgreSQL allows bound variables inside square braces.

Task-number: QTBUG-34541

Change-Id: I4f069b3f1078d4cdf172fbac9e0d7d23d20d167a
Reviewed-by: Mark Brand <mabrand@mabrand.nl>
This commit is contained in:
Israel Lins Albuquerque 2013-11-04 19:45:28 -02:00 committed by The Qt Project
parent b3b689edcb
commit 5193c14536
5 changed files with 32 additions and 7 deletions

View File

@ -62,6 +62,7 @@ class QVariant;
class Q_SQL_EXPORT QSqlDriver : public QObject
{
friend class QSqlDatabase;
friend class QSqlResultPrivate;
Q_OBJECT
Q_DECLARE_PRIVATE(QSqlDriver)

View File

@ -51,6 +51,7 @@
#include "qsqldriver.h"
#include "qpointer.h"
#include "qsqlresult_p.h"
#include "private/qsqldriver_p.h"
#include <QDebug>
QT_BEGIN_NAMESPACE
@ -89,6 +90,7 @@ QString QSqlResultPrivate::positionalToNamedBinding(const QString &query) const
result.reserve(n * 5 / 4);
QChar closingQuote;
int count = 0;
bool ignoreBraces = (sqldriver->d_func()->dbmsType == QSqlDriverPrivate::PostgreSQL);
for (int i = 0; i < n; ++i) {
QChar ch = query.at(i);
@ -110,7 +112,7 @@ QString QSqlResultPrivate::positionalToNamedBinding(const QString &query) const
} else {
if (ch == QLatin1Char('\'') || ch == QLatin1Char('"') || ch == QLatin1Char('`'))
closingQuote = ch;
else if (ch == QLatin1Char('['))
else if (!ignoreBraces && ch == QLatin1Char('['))
closingQuote = QLatin1Char(']');
result += ch;
}
@ -129,6 +131,7 @@ QString QSqlResultPrivate::namedToPositionalBinding(const QString &query)
QChar closingQuote;
int count = 0;
int i = 0;
bool ignoreBraces = (sqldriver->d_func()->dbmsType == QSqlDriverPrivate::PostgreSQL);
while (i < n) {
QChar ch = query.at(i);
@ -160,7 +163,7 @@ QString QSqlResultPrivate::namedToPositionalBinding(const QString &query)
} else {
if (ch == QLatin1Char('\'') || ch == QLatin1Char('"') || ch == QLatin1Char('`'))
closingQuote = ch;
else if (ch == QLatin1Char('['))
else if (!ignoreBraces && ch == QLatin1Char('['))
closingQuote = QLatin1Char(']');
result += ch;
++i;

View File

@ -1,7 +1,7 @@
TARGET = tst_qsqlresult
CONFIG += testcase
QT = core sql testlib
QT = core core-private sql sql-private testlib
SOURCES += tst_qsqlresult.cpp
HEADERS += testsqldriver.h

View File

@ -45,6 +45,7 @@
#include <QtSql/QSqlResult>
#include <QtSql/QSqlDriver>
#include <QtSql/QSqlRecord>
#include <private/qsqldriver_p.h>
class TestSqlDriverResult : public QSqlResult
{
@ -77,6 +78,8 @@ protected:
class TestSqlDriver : public QSqlDriver
{
Q_DECLARE_PRIVATE(QSqlDriver)
public:
TestSqlDriver() {}
~TestSqlDriver() {}
@ -96,6 +99,12 @@ public:
int /* port */, const QString & /* options */)
{ return false; }
void close() {}
QSqlDriverPrivate::DBMSType dbmsType() const
{
Q_D(const QSqlDriver);
return d->dbmsType;
}
QSqlResult *createResult() const { return new TestSqlDriverResult(this); }
};

View File

@ -79,18 +79,30 @@ void tst_QSqlResult::parseOfBoundValues()
QVERIFY(result.savePrepare("SELECT :1 AS ':2'"));
QCOMPARE(result.boundValues().count(), 1);
QVERIFY(result.savePrepare("SELECT :1 AS [:2]"));
QCOMPARE(result.boundValues().count(), 1);
if (testDriver.dbmsType() == QSqlDriverPrivate::PostgreSQL)
QCOMPARE(result.boundValues().count(), 2);
else
QCOMPARE(result.boundValues().count(), 1);
QVERIFY(result.savePrepare("SELECT :1 AS [:2]]]"));
QCOMPARE(result.boundValues().count(), 1);
if (testDriver.dbmsType() == QSqlDriverPrivate::PostgreSQL)
QCOMPARE(result.boundValues().count(), 2);
else
QCOMPARE(result.boundValues().count(), 1);
QVERIFY(result.savePrepare("SELECT :1 AS [:2]]]]]"));
QCOMPARE(result.boundValues().count(), 1);
if (testDriver.dbmsType() == QSqlDriverPrivate::PostgreSQL)
QCOMPARE(result.boundValues().count(), 2);
else
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);
if (testDriver.dbmsType() == QSqlDriverPrivate::PostgreSQL)
QCOMPARE(result.boundValues().count(), 2);
else
QCOMPARE(result.boundValues().count(), 1);
QVERIFY(result.savePrepare("SELECT ? AS \"'?\""));
QCOMPARE(result.boundValues().count(), 1);