From 05c0ce01fbef7edaf979b4e3d3e2b12aee7101b1 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 1 Sep 2024 20:43:52 +0200 Subject: [PATCH] QSqlRelationalTableModel: properly clear relational dictionary When the relationModel is updated (e.g. a new row is added or removed), the internal relation cache needs a refresh to reflect those changes. Fixes: QTBUG-128434 Change-Id: Ie388c01d545564ad7b1424d70267166ac1e4bfd6 Reviewed-by: Axel Spoerl (cherry picked from commit 48753a03de7c9c394fbf4cf69e2c2f3d1048c85f) Reviewed-by: Qt Cherry-pick Bot --- src/sql/models/qsqlrelationaltablemodel.cpp | 21 ++++++++++++-- .../tst_qsqlrelationaltablemodel.cpp | 29 +++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp index d892be070e7..57cb6921d0e 100644 --- a/src/sql/models/qsqlrelationaltablemodel.cpp +++ b/src/sql/models/qsqlrelationaltablemodel.cpp @@ -105,7 +105,7 @@ struct QRelation public: Q_DISABLE_COPY(QRelation) // QRelatedTableModel stores a pointer to this class QRelation() = default; - void init(QSqlRelationalTableModel *parent, const QSqlRelation &relation); + void init(QSqlRelationalTableModel *parent, const QSqlRelation &relation, int column); void populateModel(); @@ -122,6 +122,7 @@ struct QRelation private: QSqlRelationalTableModel *m_parent = nullptr; + int col = -1; bool m_dictInitialized = false; }; @@ -139,11 +140,12 @@ private: Note: population of the model and dictionary are kept separate from initialization, and are populated on an as needed basis. */ -void QRelation::init(QSqlRelationalTableModel *parent, const QSqlRelation &relation) +void QRelation::init(QSqlRelationalTableModel *parent, const QSqlRelation &relation, int column) { Q_ASSERT(parent != nullptr); m_parent = parent; rel = relation; + col = column; } void QRelation::populateModel() @@ -156,6 +158,19 @@ void QRelation::populateModel() model = new QRelatedTableModel(this, m_parent, m_parent->database()); model->setTable(rel.tableName()); model->select(); + QObject::connect(model, &QAbstractItemModel::dataChanged, model, [&](const QModelIndex &tl, const QModelIndex &br) + { + if (tl.column() >= col && br.column() <= col) + clearDictionary(); + }); + QObject::connect(model, &QAbstractItemModel::rowsRemoved, model, [&]() + { + clearDictionary(); + }); + QObject::connect(model, &QAbstractItemModel::rowsInserted, model, [&]() + { + clearDictionary(); + }); } } @@ -477,7 +492,7 @@ void QSqlRelationalTableModel::setRelation(int column, const QSqlRelation &relat for (auto i = oldSize; i < d->relations.size(); ++i) d->relations[i] = QSharedPointer::create(); } - d->relations.at(column)->init(this, relation); + d->relations.at(column)->init(this, relation, column); } /*! diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp index aaf55da6e18..4115bf82bb0 100644 --- a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp +++ b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp @@ -456,6 +456,29 @@ void tst_QSqlRelationalTableModel::insertRecord() model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, select()); + constexpr auto fkTitleKey = 4711; + constexpr auto fkTitleVal = "new title"; + { + auto relModel = model.relationModel(2); + // make sure populateDictionary() is called + relModel->select(); + + QSqlRecord rec; + QSqlField f1("id", QMetaType(QMetaType::Int)); + QSqlField f2("title", QMetaType(QMetaType::QString)); + + f1.setValue(fkTitleKey); + f2.setValue(fkTitleVal); + + f1.setGenerated(true); + f2.setGenerated(true); + + rec.append(f1); + rec.append(f2); + + QVERIFY(relModel->insertRecord(-1, rec)); + } + QSqlRecord rec; QSqlField f1("id", QMetaType(QMetaType::Int)); QSqlField f2("name", QMetaType(QMetaType::QString)); @@ -464,7 +487,7 @@ void tst_QSqlRelationalTableModel::insertRecord() f1.setValue(7); f2.setValue("test"); - f3.setValue(1); + f3.setValue(fkTitleKey); f4.setValue(2); f1.setGenerated(true); @@ -481,7 +504,7 @@ void tst_QSqlRelationalTableModel::insertRecord() QCOMPARE(model.data(model.index(4, 0)).toInt(), 7); QCOMPARE(model.data(model.index(4, 1)).toString(), QString("test")); - QCOMPARE(model.data(model.index(4, 2)).toString(), QString("herr")); + QCOMPARE(model.data(model.index(4, 2)).toString(), QString(fkTitleVal)); // In LeftJoin mode, two additional rows are fetched model.setJoinMode(QSqlRelationalTableModel::LeftJoin); @@ -489,7 +512,7 @@ void tst_QSqlRelationalTableModel::insertRecord() QCOMPARE(model.data(model.index(6, 0)).toInt(), 7); QCOMPARE(model.data(model.index(6, 1)).toString(), QString("test")); - QCOMPARE(model.data(model.index(6, 2)).toString(), QString("herr")); + QCOMPARE(model.data(model.index(6, 2)).toString(), QString(fkTitleVal)); } void tst_QSqlRelationalTableModel::setRecord()