Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
QSqlRelationalTableModel won't save row edits when relation is set
I'm using QSqlRelationalTableModel with QSqlRelationalDelegate to populate a QTableView from an sqlite3 database.
It displays fine, but when I double-click a cell to edit, make a change, and then click to another row the contents of the cells in the edited row become empty and the row-number changes to "!". Same thing if I hit enter instead of clicking to another row.
If I comment out the call to "setRelation" then it works.
If I change the edit strategy to OnManualSubmit it doesn't blank the row... but it never saves the changes (because I don't have any code to submit the change).
I tried subclassing the model and delegate to override the basic methods but even then when I manually submit the changes they don't end up in the database. The method calls report success but... nothing happens.
My next step will be do push the changes down outside of the model and forcing a refresh. (Either through a separate QSqlTableModel or raw QSqlQuery.) But my use-case here seems to be what the QSqlRelationalXX classes were made for, so I'm wondering if I've got something set up fundamentally wrong?
Here is where I set up the model and delegate:
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(); model->setTable("practice_to_drill"); // model->setRelation(0, QSqlRelation("drill", "id", "title")); /// Uncommenting this breaks editing model->setEditStrategy(QSqlTableModel::OnFieldChange); model->setFilter(QString("practice_id=%1").arg(practiceId)); model->setHeaderData(0, Qt::Horizontal, "Title"); model->setHeaderData(1, Qt::Horizontal, "PracticeId"); model->setHeaderData(2, Qt::Horizontal, "Sequence"); model->setHeaderData(3, Qt::Horizontal, "Length"); model->setHeaderData(4, Qt::Horizontal, "Notes"); model->select(); ui->repTable->setModel(model); ui->repTable->setItemDelegate(new QSqlRelationalDelegate(ui->repTable));
JonB last edited by JonB
Although I admit I don't know the detail, the point of
QSqlRelationalDelegateis that every row has a corresponding foreign key row. If you update a row in the table, I imagine it is then treated as (potentially) "invalid" until such time as you cause a refresh or re-read so that it knows it has its foreign key rows right. Does that sound correct?
@JonB That sounds plausible but I don't know how to confirm it. It almost sounds like you're saying that QSqlRelationalTableModel/QSqlRelationalDelegate aren't appropriate for writing back through, but it seems like that's the entire reason for QSqlRelationalDelegate existing.
JonB last edited by JonB
When you make your edit, which column(s) are you changing. The one to do with the foreign key, or a completely unrelated one?
I have not looked at the code, but what about trying out the docs example https://code.qt.io/cgit/qt/qtbase.git/tree/examples/sql/relationaltablemodel?h=5.14 and seeing how that behaves compared to yours? (Hmm, the docs refer to this from
QSqlRelationalDelegate, but I don't think it actually uses one :( ) Maybe start from that very simplified code, and check how it behaves when you add in editing, to remove whatever is in your current code from being at issue?
Thanks for suggesting that I start from the example. I compiled it and it did work, and when looking more closely at things that differ between the example and my code I realized that my schema was different even though the code was nearly identical.
In particular, I think I was running afoul of this note in the documentation:
Note: The table's primary key may not contain a relation to another table.
My table had
PRIMARY KEY (drill_id, practice_id),and
drill_idis the column 0 relation I was setting. When I remove that primary key from the schema I can edit using the delegate.
JonB last edited by
Ah ha! I did think it would be a good idea to go back to some simple example Qt provides, because one can be unaware that a change one has made can affect things unexpectedly!
Sounds like you now have what you were supposed to have, well done!