summaryrefslogtreecommitdiffstats
path: root/tests/auto/sql
diff options
context:
space:
mode:
authorMark Brand <mabrand@mabrand.nl>2012-09-25 23:50:01 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-05 03:16:12 +0200
commit5fe272f68a59724022f545ac15c2f7d758c5ea86 (patch)
tree8824c1a0c6afd0dd858473c13404c3b8f4c90d45 /tests/auto/sql
parentc86ed49a7989adb3e2e3c42794e44609f12ce493 (diff)
QSqlTableModel: fix segfault when overriding selectRow()
The STL-style iteration over the cache in submitAll() assumed the iterator would remain valid until reaching cache.end(). This failed to consider that virtual selectRow() might be overridden so that it removes rows from the cache. For example, it might call select() which would empty the cache. The new approach checks at each iteration whether the row is still in the cache. Using foreach here is justified by its fitness for purpose and readability. New test included. Change-Id: Idee8807ede239c3ba56ff1604574c49f47385ad2 Reviewed-by: David Faure (fixes for KDE) <faure@kde.org>
Diffstat (limited to 'tests/auto/sql')
-rw-r--r--tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
index cbc9cd51c3..a4e1fa1c0d 100644
--- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
+++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -77,6 +77,8 @@ private slots:
void select();
void selectRow_data() { generic_data(); }
void selectRow();
+ void selectRowOverride_data() { generic_data(); }
+ void selectRowOverride();
void insertColumns_data() { generic_data_with_strategies(); }
void insertColumns();
void submitAll_data() { generic_data(); }
@@ -356,6 +358,53 @@ void tst_QSqlTableModel::selectRow()
q.exec("DELETE FROM " + tbl);
}
+class SelectRowOverrideTestModel: public QSqlTableModel
+{
+ Q_OBJECT
+public:
+ SelectRowOverrideTestModel(QObject *parent, QSqlDatabase db):QSqlTableModel(parent, db) { }
+ bool selectRow(int row)
+ {
+ Q_UNUSED(row)
+ return select();
+ }
+};
+
+void tst_QSqlTableModel::selectRowOverride()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QString tbl = qTableName("pktest", __FILE__);
+ QSqlQuery q(db);
+ q.exec("DELETE FROM " + tbl);
+ q.exec("INSERT INTO " + tbl + " (id, a) VALUES (0, 'a')");
+ q.exec("INSERT INTO " + tbl + " (id, a) VALUES (1, 'b')");
+ q.exec("INSERT INTO " + tbl + " (id, a) VALUES (2, 'c')");
+
+ SelectRowOverrideTestModel model(0, db);
+ model.setEditStrategy(QSqlTableModel::OnFieldChange);
+ model.setTable(tbl);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.columnCount(), 2);
+
+ q.exec("UPDATE " + tbl + " SET a = 'Qt' WHERE id = 2");
+ QModelIndex idx = model.index(1, 1);
+ // overridden selectRow() should select() whole table and not crash
+ model.setData(idx, QString("Qt"));
+
+ // both rows should have changed
+ QCOMPARE(model.data(idx).toString(), QString("Qt"));
+ idx = model.index(2, 1);
+ QCOMPARE(model.data(idx).toString(), QString("Qt"));
+
+ q.exec("DELETE FROM " + tbl);
+}
+
void tst_QSqlTableModel::insertColumns()
{
// Just like the select test, with extra stuff