Romuald Kler
Romuald Kler

Reputation: 11

delphi firedac sqlite commit

When I made a commit, I naively believed that the physical file of the database would be updated (changing the modification date), but obviously it does not work like that. The physical file of the database is modified when the database is closed !!!

i wrote a little test application with (delphi 10.2.3) * FDConnection1: TFDConnection; (all default setting) (cachedupdate is false) * FDQuery1: TFDQuery; (all default setting)

My SQLite database has just one table CREATE TABLE t_stritems ( IdItels INTEGER, St01 VARCHAR (200), St02 VARCHAR (200), St03 VARCHAR (200), PRIMARY KEY(IdItels) )

My code is very simple

Connect the database :

  FDConnection1.Connected := false;
  FDConnection1.Params.Clear;
  FDConnection1.Params.Add('DriverID=SQLite');
  FDConnection1.Params.ADD('Database=' + Edit1.text);
  FDConnection1.Connected := true;

Insert rows into the database

FDQuery1.Connection := FDConnection1;
FDQuery1.close;
fdquery1.sql.clear;
fdquery1.sql.add('DELETE FROM t_stritems');

FDConnection1.StartTransaction;
fdquery1.ExecSQL;
FDConnection1.Commit;

fdquery1.sql.clear;
fdquery1.sql.add('SELECT * FROM t_stritems');
fdquery1.Open;
for i := 0 to 15 do
  begin
    for j:= 1 to 2000 do
      begin
        FDQuery1.append;
        FDQuery1.FieldByname('IdItels').asInteger := (i*2000) + j;
        FDQuery1.FieldByname('St01').asString := 'Text 01 Number : ' + FDQuery1.FieldByname('IdItels').asString;
        FDQuery1.FieldByname('St02').asString := 'Text 02 Number : ' + FDQuery1.FieldByname('IdItels').asString;
        FDQuery1.FieldByname('St03').asString := 'Text 03 Number : ' + FDQuery1.FieldByname('IdItels').asString;
        FDQuery1.post;
      end;
//    FDConnection1.Commit;
  end;
end;

Test Process : Connect the database : (the t_stritems file of my database contains 32000 records; the size of the database file is 2338 ko) After the delete sql, I have in the directory of my database file a journal file (xxxx.db-journal). the database file size is 2338 ko after the first commit, I have always in the directory of my database file the journal file (xxxx.db-journal). the database file size is 2338 ko (no physical update) The program then adds 32000 records The modification date of the file (.db) of the database will be modified only when I leave my application. !!! the journal file (.db-log) will be deleted at the end of my application

Questions : How to make the commit save data to the database ? Is this normal ? That the physical file of the database is modified only at the closing of the application (and at the same time of the connection) ?

Thank you in advance for your answer Best regards Romuald

Upvotes: 0

Views: 1875

Answers (1)

Thersippos
Thersippos

Reputation: 27

It seems that you are confused on how to use databases in Delphi.

1) First of all you need to add try/finally in your code in order to catch any exceptions and prevent memory leaks.

2) Use connection.StartTransaction - connection.Commit paired.

3) Commit must be used at the end of your loop. When you finsih with updating your data, then you call Commit to perform all the updates you made on your fields.

Here is how I would re-write your code in order to implement my suggestions above:

  FDConnection1.Connected := false;
  FDConnection1.Params.Clear;
  FDConnection1.Params.Add('DriverID=SQLite');
  FDConnection1.Params.Add('Database=' + 'Edit1.text');
  FDConnection1.Connected := true;
  FDQuery1.Connection := FDConnection1;
  // your first transaction
  // just use ExceSQL directly to run your SQL query
  FDQuery1.ExecSQL('DELETE FROM t_stritems');
  try
    // start your transaction and use query.Open()
    FDConnection1.StartTransaction;
    FDQuery1.Open('SELECT * FROM t_stritems');
    for i := 0 to 15 do
      begin
        for j := 1 to 2000 do
          begin
            FDQuery1.FieldByName('IdItels').asInteger := (i * 2000) + j;
            FDQuery1.FieldByName('St01').AsString := 'Text 01 Number : ' + FDQuery1.FieldByName('IdItels').AsString;
            FDQuery1.FieldByName('St02').AsString := 'Text 02 Number : ' + FDQuery1.FieldByName('IdItels').AsString;
            FDQuery1.FieldByName('St03').AsString := 'Text 03 Number : ' + FDQuery1.FieldByName('IdItels').AsString;
            FDQuery1.Post();
          end;
        // Dont use Commit inside loop. You should call Commit after you loop logic
        // FDConnection1.Commit;
      end;
    FDConnection1.Commit;
  finally
    FDConnection1.Close();
    FDQuery1.Free();
    FDConnection1.Free();
  end;

Upvotes: 0

Related Questions