mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Prevent data loss when editing table with foreign keys enabled
Our procedure for editing tables may involve a drop of the old table definition. This will trigger the "ON DELETE CASCADE" clauses of the child tables, leading to unexpected and silent data loss. Following the procedure described in: https://www.sqlite.org/lang_altertable.html we can guarantee that no data is deleted, but at the cost of opening a new transaction specific for the table modification. The possible pending changes must be saved before. This is only done when the foreign_keys pragma is enabled. See issue #1481
This commit is contained in:
@@ -948,8 +948,40 @@ void MainWindow::editObject()
|
||||
|
||||
if(type == "table")
|
||||
{
|
||||
// For a safe and possibly complex table modification we must follow the steps documented in
|
||||
// https://www.sqlite.org/lang_altertable.html
|
||||
// Paragraph (first procedure): Making Other Kinds Of Table Schema Changes
|
||||
|
||||
QString foreign_keys = db.getPragma("foreign_keys");
|
||||
if (foreign_keys == "1") {
|
||||
if(db.getDirty() && QMessageBox::question(this,
|
||||
QApplication::applicationName(),
|
||||
tr("Editing the table requires to save all pending changes now.\nAre you sure you want to save the database?"),
|
||||
QMessageBox::Save | QMessageBox::Default,
|
||||
QMessageBox::Cancel | QMessageBox::Escape) != QMessageBox::Save)
|
||||
return;
|
||||
// Commit all changes so the foreign_keys can be effective.
|
||||
fileSave();
|
||||
db.setPragma("foreign_keys", "0");
|
||||
}
|
||||
|
||||
EditTableDialog dialog(db, name, false, this);
|
||||
if(dialog.exec()) {
|
||||
bool ok = dialog.exec();
|
||||
|
||||
// If foreign_keys were enabled, we must commit or rollback the transaction so the foreign_keys pragma can be restored.
|
||||
if (foreign_keys == "1") {
|
||||
if (!db.executeSQL(QString("PRAGMA %1.foreign_key_check").arg(sqlb::escapeIdentifier(name.schema())))) {
|
||||
QMessageBox::warning(this, QApplication::applicationName(),
|
||||
tr("Error checking foreign keys after table modification. The changes will be reverted.\n"
|
||||
"Message from database engine:\n%1").arg(db.lastError()));
|
||||
db.revertAll();
|
||||
} else {
|
||||
// Commit all changes so the foreign_keys can be effective.
|
||||
fileSave();
|
||||
}
|
||||
db.setPragma("foreign_keys", foreign_keys);
|
||||
}
|
||||
if(ok) {
|
||||
ui->dataTable->filterHeader()->clearFilters();
|
||||
populateTable();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user