Recent

Author Topic: SQLite multiple connections in existing code  (Read 2208 times)

lainz

  • Hero Member
  • *****
  • Posts: 4468
    • https://lainz.github.io/
SQLite multiple connections in existing code
« on: December 26, 2018, 11:25:44 pm »
Hi, in the application I'm working to stablish a connection with SQLite is done in several places like this example procedure:

Code: Pascal  [Select][+][-]
  1. procedure CrearConexion(var SQLite3Connection: TSQLite3Connection);
  2. var bHayUnError:boolean;
  3.     sErrMsg: string;
  4. begin
  5.   bHayUnError:=false;
  6.   SQLite3Connection:=TSQLite3Connection.create(nil);
  7.   // Previene el error: Database connect string (DatabaseName) not filled in!
  8.   if dmConnection.gsDatabaseName = '' then
  9.     exit;
  10.   SQLite3Connection.DatabaseName := dmConnection.gsDatabaseName;
  11.   SQLite3Connection.Password:= '*************';
  12.   //SQLite3Connection.Params.Add('read_only');
  13.   repeat
  14.       try
  15.          SQLite3Connection.close;
  16.          SQLite3Connection.Open;
  17.          ExecSQL3(SQLite3Connection,'PRAGMA temp_store = 2;');
  18.          ExecSQL3(SQLite3Connection,'PRAGMA journal_mode=WAL;');
  19.       except on e:exception do
  20.         begin
  21.              sErrMsg:=e.Message;
  22.              bHayUnError:=not (Pos('DATABASE IS LOCKED',UpperCase(sErrMsg))>=1);
  23.             sleep(50);
  24.         end;
  25.       end;
  26.   until (SQLite3Connection.Connected) or (bHayUnError);
  27.   if bHayUnError then
  28.   begin
  29.     DebugLog(LocalPOS.Usuario, 'CrearConexion', 'ERROR ' + sErrMsg);
  30.     raise exception.Create('Error al conectar BD: '+sErrMsg);
  31.   end;
  32. end;

As you can see, the Open method of the connection (or query in other cases) is surrounded in a repeat .. untill block. This is done because the application can use somewhere else the connection.

Another short example:

Code: Pascal  [Select][+][-]
  1.      result:=true;
  2.      sqlqry:= tsqlQuery.Create(nil);
  3.      try//finally
  4.         try
  5.           SQLThreadTransaction:= TSQLTransaction.Create(nil);
  6.           if not Assigned(SQLite3InitialConnection) then
  7.         begin
  8.           CrearConexion(SQLite3ThreadConnection);
  9.           SQLThreadTransaction.DataBase := SQLite3ThreadConnection;
  10.           sqlqry.DataBase := SQLite3ThreadConnection;
  11.           sqlqry.Transaction:=SQLThreadTransaction;
  12.         end
  13.         else
  14.         begin
  15.           SQLThreadTransaction.DataBase := SQLite3InitialConnection;
  16.           sqlqry.DataBase := SQLite3InitialConnection;
  17.           sqlqry.Transaction:=SQLInitialTransaction;
  18.         end;  
  19.  
  20.  with sqlqry do
  21.           begin
  22.                Close;
  23.                SQL.Text:='SELECT COUNT(1) FROM '+sTabla+' WHERE insertedon IS NULL OR updatedon IS NULL';
  24.                try
  25.                  bHayUnError:=false;bOk:=false;
  26.                  repeat
  27.                     try
  28.                        Open;
  29.                        bOk:=true;
  30.                     except on e:exception do
  31.                       begin
  32.                            sErrMsg:=e.Message;
  33.                            bHayUnError:=not (Pos('DATABASE IS LOCKED',UpperCase(sErrMsg))>=1);
  34.                            sqlqry.close;
  35.                            sleep(50);
  36.                       end;
  37.                     end;
  38.                 until (bOk) or (bHayUnError);
  39. ... more code ...

As you can see, again between repeat .. until.

The application is just object oriented in the UI, and most of it is based on standalone functions and procedures and prefixed with 'g' the globals as in the first example.

The thing is, the repeat.. until thing must be removed to don't block the application when for example we're reading or saving to the DB.

There's a better way to determine that:
- There is something running with SQLite DB
- Wait until it finishes
- If there's success opening the query continue doint the thing the query needs to do

In a way that's using procedures or functions, and globals are allowed as well. Not classes because it will imply to refactor the entire application.

 

TinyPortal © 2005-2018