Extend the entire savepoint logic to allow multiple active savepoints

Allow multiple savepoints in DBBrowserDB, i.e. setRestorePoint() doesn't
simply return if the DB is already set to dirty but creates an
additional savepoint.

Track the names of all savepoints which have not been either saved or
reverted yet.

Finally, and that's the whole point of this commit, change the savepoint
logic of the EditTableDialog. We used to have a transaction started when
opening a database which was only committed when the file was closed
again. This way the EditFileDialog could savely create a savepoint when
being opened and just release it when OK was clicked or revert to it
when cancel was clicked. Getting rid of the transaction broke this
logic. The dialog still worked but as the savepoint was released when
the changes were applied all changes made via the dialog were
immediately committed to the database. So clicking the revert button had
no effect on those changes. This is at best an unexpected behaviour but
could also be a problem when some changes are reverted while others
aren't. So, having the option now of keeping multiple savepoints opened
this problem can be fixed by just creating a new savepoint every time
the dialog is opened, reverting to it when it is cancelled and _not_
releasing it when OK is clicked.

I hope this works!
This commit is contained in:
Martin Kleusberg
2013-05-23 17:41:16 +02:00
parent 4dfabe4a78
commit a1b72c5eef
5 changed files with 63 additions and 34 deletions

View File

@@ -91,13 +91,16 @@ bool DBBrowserDB::open ( const QString & db)
bool DBBrowserDB::setRestorePoint(const QString& pointname)
{
if (!isOpen()) return false;
if (dirty) return false;
if(!isOpen())
return false;
if(savepointList.contains(pointname))
return true;
if (_db){
if(_db)
{
QString query = QString("SAVEPOINT %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(),
NULL,NULL,NULL);
sqlite3_exec(_db, query.toUtf8(), NULL, NULL, NULL);
savepointList.append(pointname);
setDirty(true);
}
return true;
@@ -105,29 +108,52 @@ bool DBBrowserDB::setRestorePoint(const QString& pointname)
bool DBBrowserDB::save(const QString& pointname)
{
if (!isOpen()) return false;
if(!isOpen() || savepointList.contains(pointname) == false)
return false;
if (_db){
if(_db)
{
QString query = QString("RELEASE %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(),
NULL,NULL,NULL);
setDirty(false);
sqlite3_exec(_db, query.toUtf8(), NULL,NULL,NULL);
savepointList.removeAll(pointname);
setDirty(!savepointList.empty());
}
return true;
}
bool DBBrowserDB::revert(const QString& pointname)
{
if (!isOpen()) return false;
if(!isOpen() || savepointList.contains(pointname) == false)
return false;
if (_db){
if(_db)
{
QString query = QString("ROLLBACK TO SAVEPOINT %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(),
NULL,NULL,NULL);
sqlite3_exec(_db, query.toUtf8(), NULL, NULL, NULL);
query = QString("RELEASE %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(),
NULL,NULL,NULL);
setDirty(false);
sqlite3_exec(_db, query.toUtf8(), NULL, NULL, NULL);
savepointList.removeAll(pointname);
setDirty(!savepointList.empty());
}
return true;
}
bool DBBrowserDB::saveAll()
{
foreach(const QString& point, savepointList)
{
if(!save(point))
return false;
}
return true;
}
bool DBBrowserDB::revertAll()
{
foreach(const QString& point, savepointList)
{
if(!revert(point))
return false;
}
return true;
}
@@ -188,14 +214,15 @@ void DBBrowserDB::close (){
QObject::tr("Do you want to save the changes "
"made to the database file %1?").arg(curDBFilename),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
save();
saveAll();
else
revert(); //not really necessary, I think... but will not hurt.
revertAll(); //not really necessary, I think... but will not hurt.
}
sqlite3_close(_db);
}
_db = 0;
objMap.clear();
savepointList.clear();
}
bool DBBrowserDB::dump(const QString& filename)
@@ -491,13 +518,13 @@ bool DBBrowserDB::createTable(const QString& name, const QList<DBBrowserField>&
sql.append(");");
// Execute it
return executeSQL(sql, false);
return executeSQL(sql);
}
bool DBBrowserDB::addColumn(const QString& tablename, const sqlb::FieldPtr& field)
{
QString sql = QString("ALTER TABLE `%1` ADD COLUMN %2").arg(tablename).arg(field->toString());
return executeSQL(sql, false);
return executeSQL(sql);
}
bool DBBrowserDB::renameColumn(const QString& tablename, const QString& from, const QString& to, const QString& type)
@@ -686,7 +713,7 @@ bool DBBrowserDB::dropColumn(const QString& tablename, const QString& column)
bool DBBrowserDB::renameTable(const QString& from_table, const QString& to_table)
{
QString sql = QString("ALTER TABLE `%1` RENAME TO `%2`").arg(from_table, to_table);
if(!executeSQL(sql, false))
if(!executeSQL(sql))
{
QString error = QObject::tr("Error renaming table '%1' to '%2'."
"Message from database engine:\n%3").arg(from_table).arg(to_table).arg(lastErrorMessage);