summaryrefslogtreecommitdiffstats
path: root/src/sql
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2018-01-16 09:54:01 +0100
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-01-23 20:07:09 +0000
commit461ef575bcf778ba24b0be6b775098d4b80ae5e1 (patch)
tree068c1896a908482ed8d0aa88712c82bcfb0e15b0 /src/sql
parent7c69f6171ddc76d22e4f6e433be69c5cf365db8f (diff)
Always escape the table names when creating the SQL statement
Since some databases are case sensitive if part of the query is quoted, then we should ensure that all instances of the table name are escaped unless the test is delibrately testing the non-escaped case. As a result, this commit also removes some expected failures pertaining to PostgreSQL and also adds an entry to the list of tables being dropped when a test is finished. [ChangeLog][Sql][PostgreSQL] QSqlDatabase is now stricter about table names when used with record() and primaryIndex(). If the tablename was not quoted when it was created, then the table name passed to record() and primaryIndex() needs to be in lower case so that PostgreSQL is able to find it. Fixes: QTBUG-65788 Change-Id: Id1f54cb66b761c39edf858501b730ede7eec1fd3 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/sql')
-rw-r--r--src/sql/doc/snippets/code/doc_src_sql-driver.qdoc13
-rw-r--r--src/sql/doc/src/sql-driver.qdoc17
-rw-r--r--src/sql/kernel/qsqldatabase.cpp10
-rw-r--r--src/sql/kernel/qsqldriver.cpp16
4 files changed, 48 insertions, 8 deletions
diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc b/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc
index d127bdf8a5..9709deeccb 100644
--- a/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc
+++ b/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc
@@ -237,3 +237,16 @@ Could not create database object
//! [38]
QPSQLDriver::getResult: Query results lost - probably discarded on executing another SQL query.
//! [38]
+
+//! [39]
+CREATE TABLE "testTable" ("id" INTEGER);
+//! [39]
+
+//! [40]
+QString tableString("testTable");
+QSqlQuery q;
+// Create table query is not quoted, therefore it is mapped to lower case
+q.exec(QString("CREATE TABLE %1 (id INTEGER)").arg(tableString));
+// Call toLower() on the string so that it can be matched
+QSqlRecord rec = database.record(tableString.toLower());
+//! [40]
diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc
index fd95e89812..cccce48bb3 100644
--- a/src/sql/doc/src/sql-driver.qdoc
+++ b/src/sql/doc/src/sql-driver.qdoc
@@ -381,6 +381,23 @@
multibyte enabled PostgreSQL server can be found in the PostgreSQL
Administrator Guide, Chapter 5.
+ \section3 QPSQL Case Sensitivity
+
+ PostgreSQL databases will only respect case sensitivity if the table or field
+ name is quoted when the table is created. So for example, a SQL query such
+ as:
+
+ \snippet code/doc_src_sql-driver.qdoc 39
+
+ will ensure that it can be accessed with the same case that was used. If the
+ table or field name is not quoted when created, the actual table name
+ or field name will be lower-case. When QSqlDatabase::record() or
+ QSqlDatabase::primaryIndex() access a table or field that was unquoted
+ when created, the name passed to the function must be lower-case to
+ ensure it is found. For example:
+
+ \snippet code/doc_src_sql-driver.qdoc 40
+
\section3 QPSQL BLOB Support
Binary Large Objects are supported through the \c BYTEA field type in
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index 12ab9671b5..d63a9e59a8 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -1088,6 +1088,11 @@ QStringList QSqlDatabase::tables(QSql::TableType type) const
Returns the primary index for table \a tablename. If no primary
index exists, an empty QSqlIndex is returned.
+ \note Some drivers, such as the \l {QPSQL Case Sensitivity}{QPSQL}
+ driver, may may require you to pass \a tablename in lower case if
+ the table was not quoted when created. See the
+ \l{sql-driver.html}{Qt SQL driver} documentation for more information.
+
\sa tables(), record()
*/
@@ -1102,6 +1107,11 @@ QSqlIndex QSqlDatabase::primaryIndex(const QString& tablename) const
the table (or view) called \a tablename. The order in which the
fields appear in the record is undefined. If no such table (or
view) exists, an empty record is returned.
+
+ \note Some drivers, such as the \l {QPSQL Case Sensitivity}{QPSQL}
+ driver, may may require you to pass \a tablename in lower case if
+ the table was not quoted when created. See the
+ \l{sql-driver.html}{Qt SQL driver} documentation for more information.
*/
QSqlRecord QSqlDatabase::record(const QString& tablename) const
diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp
index 8c6ae382f6..7f7b81b05b 100644
--- a/src/sql/kernel/qsqldriver.cpp
+++ b/src/sql/kernel/qsqldriver.cpp
@@ -488,6 +488,8 @@ QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType ty
QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
const QSqlRecord &rec, bool preparedStatement) const
{
+ const auto tableNameString = tableName.isEmpty() ? QString()
+ : prepareIdentifier(tableName, QSqlDriver::TableName, this);
int i;
QString s;
s.reserve(128);
@@ -500,13 +502,12 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
if (s.isEmpty())
return s;
s.chop(2);
- s.prepend(QLatin1String("SELECT ")).append(QLatin1String(" FROM ")).append(tableName);
+ s = QLatin1String("SELECT ") + s + QLatin1String(" FROM ") + tableNameString;
break;
case WhereStatement:
{
- const QString tableNamePrefix = tableName.isEmpty()
- ? QString()
- : prepareIdentifier(tableName, QSqlDriver::TableName, this) + QLatin1Char('.');
+ const QString tableNamePrefix = tableNameString.isEmpty()
+ ? QString() : tableNameString + QLatin1Char('.');
for (int i = 0; i < rec.count(); ++i) {
if (!rec.isGenerated(i))
continue;
@@ -523,8 +524,7 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
break;
}
case UpdateStatement:
- s.append(QLatin1String("UPDATE ")).append(tableName).append(
- QLatin1String(" SET "));
+ s = s + QLatin1String("UPDATE ") + tableNameString + QLatin1String(" SET ");
for (i = 0; i < rec.count(); ++i) {
if (!rec.isGenerated(i))
continue;
@@ -541,10 +541,10 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
s.clear();
break;
case DeleteStatement:
- s.append(QLatin1String("DELETE FROM ")).append(tableName);
+ s = s + QLatin1String("DELETE FROM ") + tableNameString;
break;
case InsertStatement: {
- s.append(QLatin1String("INSERT INTO ")).append(tableName).append(QLatin1String(" ("));
+ s = s + QLatin1String("INSERT INTO ") + tableNameString + QLatin1String(" (");
QString vals;
for (i = 0; i < rec.count(); ++i) {
if (!rec.isGenerated(i))