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 <axel.spoerl@qt.io>
(cherry picked from commit 48753a03de7c9c394fbf4cf69e2c2f3d1048c85f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Christian Ehrlicher 2024-09-01 20:43:52 +02:00 committed by Qt Cherry-pick Bot
parent 2f4680d143
commit 05c0ce01fb
2 changed files with 44 additions and 6 deletions

View File

@ -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<QRelation>::create();
}
d->relations.at(column)->init(this, relation);
d->relations.at(column)->init(this, relation, column);
}
/*!

View File

@ -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()