For some performance reasons it would be nice, if TDatabaseManager provides a UpdateDatabase method that will not trigger ValidateDatabase before.
In some cases I'm validating my database by calling ValidateDatabase, so that the User can decide, if he want's to rebuild database at all.
If user chooses yes, I almost got the same instance of TDatabaseManager, so that SQLStatements are already filled. They just need to be executed at all.
I gave it a try, by executing them on my own (using TXDataset), but there seems to be some magic behind regarding duplicate Statements.
(In my case, a Table and corresponding foreign keys are removed. This leads to an exception, that for sure, the foreign keys does not exist, while they will be dropped the second time...)
There is no magic in the execution. ValidateDatabase generates the SQL statements, and all you need to do is to execute them. Actually the code for UpdateDatabase is just this, you can simply copy and paste, do some quick adaptations, remove the ValidateDatabase part and you're good:
procedure TDatabaseManager.UpdateDatabase;
var
Trans: IDBTransaction;
begin
Trans := DoBeginTransaction;
try
ValidateDatabase;
if SQLExecutionEnabled then
ExecuteSQLStatements(SQLStatements, false);
DoCommit(Trans);
except
DoRollback(Trans);
raise;
end;
end;
Meanwhile I recognized, that the same error occurs using TDatabaseManager.UpdateDatabase.
Removing a Table, that is linked to other tables using foreign keys, is leading to an error, that UniqueKey does not exist, because ValidateDatabase generates this statement two times.
First one while removing table, second one while removing dependent objects.
I created an Entity (A) as usual, that is referenced from Entity (B).
If I then remove the Association from B and Entity A, TDatabaseManager.UpdateDatabase fails, because the foreign key will be removed two times.
Indeed, there is such flag, but it's not fully tested in all the possible situations. It's there for a fallback in case it's really needed, but it doesn't use a complex solver to check the deleted database objects tree.
But we can try to investigate and see if this can be improved at least in your case. Do you mind adding a feature request for that and attaching a sample project reproducing the issue of this specific case so we can try to improve it?