SQLite: Handle tables and fields with a dot in the name correctly
Fixes: QTBUG-91885 Pick-to: 6.1 6.0 5.15 Change-Id: Iba76bb50266dd4fb5f50e4ea1549d1d2bb6e3431 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
83eca9a087
commit
66acee69a1
@ -74,13 +74,18 @@ Q_DECLARE_METATYPE(sqlite3_stmt*)
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static QString _q_escapeIdentifier(const QString &identifier)
|
||||
static QString _q_escapeIdentifier(const QString &identifier, QSqlDriver::IdentifierType type)
|
||||
{
|
||||
QString res = identifier;
|
||||
// If it contains [ and ] then we assume it to be escaped properly already as this indicates
|
||||
// the syntax is exactly how it should be
|
||||
if (identifier.contains(QLatin1Char('[')) && identifier.contains(QLatin1Char(']')))
|
||||
return res;
|
||||
if (!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"'))) {
|
||||
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
|
||||
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
|
||||
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
|
||||
if (type == QSqlDriver::TableName)
|
||||
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -912,13 +917,24 @@ static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool only
|
||||
{
|
||||
QString schema;
|
||||
QString table(tableName);
|
||||
int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
|
||||
const int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
|
||||
if (indexOfSeparator > -1) {
|
||||
schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
|
||||
table = tableName.mid(indexOfSeparator + 1);
|
||||
const int indexOfCloseBracket = tableName.indexOf(QLatin1Char(']'));
|
||||
if (indexOfCloseBracket != tableName.size() - 1) {
|
||||
// Handles a case like databaseName.tableName
|
||||
schema = tableName.left(indexOfSeparator + 1);
|
||||
table = tableName.mid(indexOfSeparator + 1);
|
||||
} else {
|
||||
const int indexOfOpenBracket = tableName.lastIndexOf(QLatin1Char('['), indexOfCloseBracket);
|
||||
if (indexOfOpenBracket > 0) {
|
||||
// Handles a case like databaseName.[tableName]
|
||||
schema = tableName.left(indexOfOpenBracket);
|
||||
table = tableName.mid(indexOfOpenBracket);
|
||||
}
|
||||
}
|
||||
}
|
||||
q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1Char(')'));
|
||||
|
||||
q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") +
|
||||
_q_escapeIdentifier(table, QSqlDriver::TableName) + QLatin1Char(')'));
|
||||
QSqlIndex ind;
|
||||
while (q.next()) {
|
||||
bool isPk = q.value(5).toInt();
|
||||
@ -980,8 +996,7 @@ QVariant QSQLiteDriver::handle() const
|
||||
|
||||
QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
return _q_escapeIdentifier(identifier);
|
||||
return _q_escapeIdentifier(identifier, type);
|
||||
}
|
||||
|
||||
static void handle_sqlite_callback(void *qobj,int aoperation, char const *adbname, char const *atablename,
|
||||
|
@ -154,6 +154,9 @@ private slots:
|
||||
|
||||
void invalidFilterAndHeaderData_data() { generic_data(); }
|
||||
void invalidFilterAndHeaderData(); //QTBUG-23879
|
||||
|
||||
void sqlite_selectFromIdentifierWithDot_data() { generic_data("QSQLITE"); }
|
||||
void sqlite_selectFromIdentifierWithDot();
|
||||
private:
|
||||
void generic_data(const QString& engine=QString());
|
||||
void generic_data_with_strategies(const QString& engine=QString());
|
||||
@ -161,6 +164,7 @@ private:
|
||||
|
||||
tst_QSqlTableModel::tst_QSqlTableModel()
|
||||
{
|
||||
QVERIFY(dbs.open());
|
||||
}
|
||||
|
||||
tst_QSqlTableModel::~tst_QSqlTableModel()
|
||||
@ -2160,5 +2164,50 @@ void tst_QSqlTableModel::modelInAnotherThread()
|
||||
QVERIFY(t.isFinished());
|
||||
}
|
||||
|
||||
void tst_QSqlTableModel::sqlite_selectFromIdentifierWithDot()
|
||||
{
|
||||
QFETCH(QString, dbName);
|
||||
QSqlDatabase db = QSqlDatabase::database(dbName);
|
||||
CHECK_DATABASE(db);
|
||||
{
|
||||
const auto fieldDot = qTableName("fieldDot", __FILE__, db);
|
||||
tst_Databases::safeDropTable(db, fieldDot);
|
||||
QSqlQuery qry(db);
|
||||
QVERIFY_SQL(qry, exec("create table " + fieldDot + " (id int primary key, "
|
||||
"\"person.firstname\" varchar(20))"));
|
||||
QVERIFY_SQL(qry, exec("insert into " + fieldDot + " values(1, 'Andy')"));
|
||||
QSqlTableModel model(0, db);
|
||||
model.setTable(fieldDot);
|
||||
QVERIFY_SQL(model, select());
|
||||
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
|
||||
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Andy"));
|
||||
}
|
||||
const auto tableDot = QLatin1Char('[') + qTableName("table.dot", __FILE__, db) + QLatin1Char(']');
|
||||
{
|
||||
tst_Databases::safeDropTable(db, tableDot);
|
||||
QSqlQuery qry(db);
|
||||
QVERIFY_SQL(qry, exec("create table " + tableDot + " (id int primary key, "
|
||||
"\"person.firstname\" varchar(20))"));
|
||||
QVERIFY_SQL(qry, exec("insert into " + tableDot + " values(1, 'Andy')"));
|
||||
QSqlTableModel model(0, db);
|
||||
model.setTable(tableDot);
|
||||
QVERIFY_SQL(model, select());
|
||||
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
|
||||
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Andy"));
|
||||
}
|
||||
{
|
||||
QSqlDatabase attachedDb = QSqlDatabase::addDatabase("QSQLITE", "attachedDb");
|
||||
attachedDb.setDatabaseName(db.databaseName().replace("foo.db", "attached.db"));
|
||||
QVERIFY(attachedDb.open());
|
||||
QSqlQuery qry(attachedDb);
|
||||
QVERIFY_SQL(qry, exec(QString("attach '%1' AS 'attached'").arg(db.databaseName())));
|
||||
QSqlTableModel model(0, attachedDb);
|
||||
model.setTable(QString("attached.%1").arg(tableDot));
|
||||
QVERIFY_SQL(model, select());
|
||||
QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
|
||||
QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Andy"));
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QSqlTableModel)
|
||||
#include "tst_qsqltablemodel.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user