Fix transaction detection in SQL import

Fix a couple of problems in the detection of transaction statements
during the SQL import. Before this the detection was case-dependent as
well as dependent on the number of spaces you use. Also it did not
detect 'END TRANSACTION', 'COMMIT TRANSACTION', or 'BEGIN <qualifier>
TRANSACTION' at all. Finally, it could modify your statements if you
embed string in them which look like transaction statements. All of this
is, hopefully, fixed in this commit.

See issue #1764.
This commit is contained in:
Martin Kleusberg
2019-02-25 19:30:49 +01:00
parent e436cb2516
commit 0f6946c19d

View File

@@ -951,32 +951,10 @@ bool DBBrowserDB::executeMultiSQL(QByteArray query, bool dirty, bool log)
return false;
}
// Check if this SQL containts any transaction statements. If so remove them and create a savepoint instead by overriding the dirty parameter.
// TODO This should check for 'END TRANSACTION' too. It should be case insensitive and it should work with any amounts of whitespace etc. "Good" news
// is that none of this was ever done correctly before.
if(query.contains("BEGIN TRANSACTION;"))
{
query.replace("BEGIN TRANSACTION;", " ");
dirty = true;
}
if(query.contains("COMMIT;"))
{
query.replace("COMMIT;", " ");
dirty = true;
}
// Log the statement if needed
if(log)
logSQL(query, kLogMsg_App);
// Set DB to dirty/create restore point if necessary
QString savepoint_name;
if(dirty)
{
savepoint_name = generateSavepointName("execmultisql");
setSavepoint(savepoint_name);
}
// Show progress dialog
QProgressDialog progress(tr("Executing SQL..."),
tr("Cancel"), 0, 100);
@@ -993,6 +971,7 @@ bool DBBrowserDB::executeMultiSQL(QByteArray query, bool dirty, bool log)
unsigned int line = 0;
bool structure_updated = false;
int last_progress_value = -1;
QString savepoint_name;
while(tail && *tail != 0 && (res == SQLITE_OK || res == SQLITE_DONE))
{
line++;
@@ -1031,6 +1010,25 @@ bool DBBrowserDB::executeMultiSQL(QByteArray query, bool dirty, bool log)
next_statement.compare(0, 4, "DROP") == 0 ||
next_statement.compare(0, 8, "ROLLBACK") == 0)
structure_updated = true;
// Check for transaction statements and skip until the next semicolon
if(next_statement.compare(0, 5, "COMMIT") == 0 ||
next_statement.compare(0, 4, "END ") == 0 ||
next_statement.compare(0, 6, "BEGIN ") == 0)
{
while(tail != tail_end)
{
if(*++tail == ';')
break;
}
// Set DB to dirty and create a restore point if we haven't done that yet
if(dirty && savepoint_name.isNull())
{
savepoint_name = generateSavepointName("execmultisql");
setSavepoint(savepoint_name);
}
}
}
// Execute next statement