[SOLVED] EdatabaseError "Database connect string (DatabaseName) not filled in!" lazarus / 16-Databases ---------------------------------------------------------------------- swierzbicki · 2013-07-23 13:32 Hello, This looks like a newbie issue but, believe me, I'm losing my sanity on this ! I'm setting up an database connection within a worker thread. This used to works and suddenly stopped !. I'm getting each time an EdatabaseError "Database connect string (DatabaseName) not filled in!" error (within TDBWorkerThread.OpenLocalDB(ASQL : String) method, you can have a look at my code) All my Database objects are in a workerthread. They are created during the thread creation and configured via the thread properties. You can have a look, it's really basic : Code: [Select]        TDBWorkerThread = class(TThread)   private     { Déclarations privées }         fLocalConnection : TServerConnection; // it's basically a Record         fRemoteConnection : TServerConnection;         fConnection_Distante: TIBConnection;         fConnection_Locale: TSQLite3Connection;         fQuery_Distant: TSQLQuery;         fTransaction_Distante: TSQLTransaction;         fQuery_Local: TSQLQuery;         fTransaction_Locale: TSQLTransaction;         procedure OpenRemoteDB(ASQL : String);         procedure CloseRemoteDB(KeepConnectionAlive : Boolean);         procedure OpenLocalDB(ASQL : String);         procedure CloseLocalDB(KeepConnectionAlive : Boolean);   protected      procedure Execute; override;   public      constructor Create;      destructor Destroy; override;      property LocalConnection : TServerConnection Read fLocalConnection write fLocalConnection;      property RemoteConnection : TServerConnection Read fRemoteConnection write fRemoteConnection;   end; constructor TDBWorkerThread.Create; begin   FreeOnTerminate := True;   Suspended:=true;   fConnection_Distante := TIBConnection.create(nil);   fTransaction_Distante := TSQLTransaction.Create(nil);   fQuery_Distant := TSQLQuery.Create(nil);   fConnection_Distante.Transaction := fTransaction_Distante;   fTransaction_Distante.DataBase := fConnection_Distante;   fQuery_Distant.Transaction := fTransaction_Distante;   fQuery_Distant.DataBase := fConnection_Distante;   fConnection_Locale := TSQLite3Connection.create(nil);   fTransaction_Locale := TSQLTransaction.Create(nil);   fQuery_Local:= TSQLQuery.create(nil);   fConnection_Locale.Transaction := fTransaction_Locale;   fTransaction_Locale.DataBase := fConnection_Locale;   fQuery_Local.Transaction := fTransaction_Distante;   fQuery_Local.DataBase := fConnection_Locale;   inherited Create(True); end; destructor TDBWorkerThread.Destroy; begin   fProcessQueue.free;   FSyncId.free;   //RTLeventdestroy(fEvent);   FreeAndNil(fConnection_Distante);   FreeAndNil(fConnection_Locale);   FreeAndNil(fTransaction_Distante);   FreeAndNil(fTransaction_Locale);   FreeAndNil(fQuery_Distant);   FreeAndNil(fQuery_Local);   inherited Destroy; end; procedure TDBWorkerThread.OpenRemoteDB(ASQL : String); begin   if not fConnection_Distante.Connected then   begin   fConnection_Distante.Close;   fConnection_Distante.DatabaseName:= fRemoteConnection.Database;   fConnection_Distante.HostName:= fRemoteConnection.Host;   fConnection_Distante.Password:= fRemoteConnection.Password;   fConnection_Distante.UserName:= fRemoteConnection.Username;   fConnection_Distante.open;   end;   fQuery_Distant.close;   fQuery_Distant.SQL.Text:=ASQL;   fQuery_Distant.Open;   fQuery_Distant.FieldByName('Id').Required:=false; end; procedure TDBWorkerThread.CloseRemoteDB(KeepConnectionAlive : Boolean); begin   fQuery_Distant.close;   if not KeepConnectionAlive then fConnection_Distante.Close; end; procedure TDBWorkerThread.OpenLocalDB(ASQL : String); begin   if not fConnection_Locale.Connected then   begin   fConnection_Locale.close;   fConnection_Locale.DatabaseName:= fLocalConnection.Database;   fConnection_Locale.open;   end;   fQuery_Local.close;   fQuery_Local.SQL.Text:=ASql;   fQuery_Local.open;    // [b]<=== CRASH HERE WITH EDATABASEERROR, DatabaseName property is always blank ![/b]   fQuery_Local.FieldByName('Id').Required:=false; end; procedure TDBWorkerThread.CloseLocalDB(KeepConnectionAlive : Boolean); begin  fQuery_Local.close;  if not KeepConnectionAlive then fConnection_Locale.Close; end; procedure TDBWorkerThread.Execute; begin       while (not Terminated)  do     begin      try            OpenLocalDB('Select * from inventaire where DateSynchro is null order by ID');            // do my styff            OpenRemodeDB('Select * from inventaire where 0=1);            // do my styff       Except          on e: exception do          begin          // do my styff          end;       end; end; The thread is called that way : Code: [Select]Var LocalCnct, RemoteCnct : TServerConnection; begin    RemoteCnct.Database := 'D:\Firebird\xxx.GDB';    RemoteCnct.Host := '192.xx.xx.xx;    RemoteCnct.Username := 'ETGRE';    RemoteCnct.Password := 'xZEFGfsdg';    LocalCnct.Database:='XXX.db3';    MonbThread := TDBWorkerThread.create;    MonbThread.RemoteConnection := RemoteCnct;    MonbThread.LocalConnection := LocalCnct;    MonbThread.Start; end;  As you can see, everything looks correct ! what kind of errors am I doing ? I've also tried to set the DatabaseName property but it still remains blank ! Thank you for your advices ---------------------------------------------------------------------- taazz · 2013-07-23 14:42 Code: [Select]LocalCnct.Database ='xxxx.db3'; this is wrong, define the complete path to the file the dll used does not know or cares where your application is at the moment of connection. This might work on laboratory conditions but it is doubtful that it will work in the world with out problems for long especially when you take in to account that (at least on windows) it uses the current directory to fill in the path for you which is a global variable can be changed by any other program between calls. ---------------------------------------------------------------------- swierzbicki · 2013-07-23 15:35 taaz : I've just removed the whole path for my example. After a few hours of head burning I found the issue (that's a bug of either the LCL or FPC). Switching the order of created objects solves my issue : From : Code: [Select]  fConnection_Distante := TIBConnection.create(nil);   fTransaction_Distante := TSQLTransaction.Create(nil);   fQuery_Distant := TSQLQuery.Create(nil);   fConnection_Distante.Transaction := fTransaction_Distante;   fTransaction_Distante.DataBase := fConnection_Distante;   fQuery_Distant.Transaction := fTransaction_Distante;   fQuery_Distant.DataBase := fConnection_Distante;   fConnection_Locale := TSQLite3Connection.create(nil);   fTransaction_Locale := TSQLTransaction.Create(nil);   fQuery_Local:= TSQLQuery.create(nil);   fConnection_Locale.Transaction := fTransaction_Locale;   fTransaction_Locale.DataBase := fConnection_Locale;   fQuery_Local.Transaction := fTransaction_Distante;   fQuery_Local.DataBase := fConnection_Locale; to Code: [Select]  fConnection_Locale := TSQLite3Connection.create(nil);   fTransaction_Locale := TSQLTransaction.Create(nil);   fQuery_Local:= TSQLQuery.create(nil);   fConnection_Locale.Transaction := fTransaction_Locale;   fTransaction_Locale.DataBase := fConnection_Locale;   fQuery_Local.Transaction := fTransaction_Distante;   fQuery_Local.DataBase := fConnection_Locale;   fConnection_Distante := TIBConnection.create(nil);   fTransaction_Distante := TSQLTransaction.Create(nil);   fQuery_Distant := TSQLQuery.Create(nil);   fConnection_Distante.Transaction := fTransaction_Distante;   fTransaction_Distante.DataBase := fConnection_Distante;   fQuery_Distant.Transaction := fTransaction_Distante;   fQuery_Distant.DataBase := fConnection_Distante; How could this be possible ? ---------------------------------------------------------------------- taazz · 2013-07-23 16:01 That's weird to say the least before starting to doubt the compiler I would 1st check those units and see if a global variable exists that gets changed from any of those created objects that affects their run time behavior. If nothing is found then a bug report is in order of course I would wait a bit for the team members to see your problem and decide if it is a bug or not. If changing the order of creation has such an effect and no run time behavior altering code can be spotted then I would expect some sort of buffer overrun or some other weird bug that affects the memory which it must be almost impossible in the stock libraries, non the less you should check. ---------------------------------------------------------------------- swierzbicki · 2013-07-23 18:07 I've double, triple checked but there is no globals variables affecting any of these created objects. I was able to reproduce this behavior on both win32 and wince OS. How can I check for these buffer overrun or other bugs ? ---------------------------------------------------------------------- LacaK · 2013-07-24 05:40 Is this line correct? Code: [Select]fQuery_Local.Transaction := fTransaction_Distante; ---------------------------------------------------------------------- swierzbicki · 2013-07-24 09:58 Lacak : well well well, I feel a little bit stupid !!!  ... You are right, this should be fTransaction_Local Thank you for pointing this out !