From 74074fe633acf80176f145dedf4b8e675fc548db Mon Sep 17 00:00:00 2001 From: rosenfield Date: Mon, 8 Oct 2007 21:29:16 +0000 Subject: [PATCH] Bugfix: There is no thread safety mechanism in Zeos for the SQL log, so implement one in HeidiSQL. This should speed up async queries tremendously, as they no longer have to wait for the GUI to repaint before firing the actual query. Haven't bothered thinking about thread safety around the creation of the critical section protecting the TStringList, mainly because I'm infinitely annoyed by Delphi not providing a thread-safe list capable of holding lists OOTB.. --- source/childwin.pas | 37 +++++++++++++++++++++++++++++++++++-- source/communication.pas | 1 + source/main.pas | 6 ++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/source/childwin.pas b/source/childwin.pas index 575596f7..69dc133a 100644 --- a/source/childwin.pas +++ b/source/childwin.pas @@ -510,6 +510,7 @@ type Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: WideString); procedure popupFilterPopup(Sender: TObject); + procedure ProcessSqlLog; private strHostRunning : String; @@ -534,6 +535,8 @@ type TablePropertiesForm : Ttbl_properties_form; FileNameSessionLog : String; FileHandleSessionLog : Textfile; + SqlMessages : TStringList; + SqlMessagesLock : TRtlCriticalSection; function GetQueryRunning: Boolean; procedure SetQueryRunning(running: Boolean); @@ -764,6 +767,10 @@ begin UserQueryFiring := False; TemporaryDatabase := ''; CachedTableLists := TStringList.Create; + InitializeCriticalSection(SqlMessagesLock); + EnterCriticalSection(SqlMessagesLock); + SqlMessages := TStringList.Create; + LeaveCriticalSection(SqlMessagesLock); FConn := AConn^; FMysqlConn := AMysqlConn; // we're now responsible to free it @@ -1087,6 +1094,9 @@ begin SetWindowConnected( false ); SetWindowName( main.discname ); Application.Title := APPNAME; + EnterCriticalSection(SqlMessagesLock); + FreeAndNil(SqlMessages); + LeaveCriticalSection(SqlMessagesLock); // Closing connection and saving some vars into registry case ( WindowState ) of @@ -1173,7 +1183,30 @@ begin msg := '/* ' + msg + ' */'; end; - SynMemoSQLLog.Lines.Add( msg ); + EnterCriticalSection(SqlMessagesLock); + try + SqlMessages.Add(msg); + finally + LeaveCriticalSection(SqlMessagesLock); + end; + PostMessage(MainForm.Handle, WM_PROCESSLOG, 0, 0); +end; + +procedure TMDIChild.ProcessSqlLog; +var + msg: string; +begin + EnterCriticalSection(SqlMessagesLock); + try + if SqlMessages = nil then Exit; + if SqlMessages.Count < 1 then Exit; + msg := SqlMessages[0]; + SqlMessages.Delete(0); + finally + LeaveCriticalSection(SqlMessagesLock); + end; + + SynMemoSQLLog.Lines.Add( String(msg) ); SynMemoSQLLog.GotoLineAndCenter( SynMemoSQLLog.Lines.Count ); SynMemoSQLLog.Repaint(); @@ -1834,7 +1867,7 @@ end; procedure TMDIChild.WaitForQueryCompletion(WaitForm: TForm); begin debug( 'Waiting for query to complete.' ); - WaitForm.ShowModal(); + WaitForm.ShowModal(); debug( 'Query complete.' ); end; diff --git a/source/communication.pas b/source/communication.pas index d165f91b..073af50d 100644 --- a/source/communication.pas +++ b/source/communication.pas @@ -23,6 +23,7 @@ uses const // Our custom message types. WM_COMPLETED = WM_APP + 1; + WM_PROCESSLOG = WM_APP + 2; // Our message subtypes for WM_COPYDATA messages. CMD_EXECUTEQUERY_NORESULTS = 1; { Slightly faster - Fire-and-forget, no results } CMD_EXECUTEQUERY_RESULTS = 2; { Normal - Wait for completion, fetch results } diff --git a/source/main.pas b/source/main.pas index 6adbdac0..6f196244 100644 --- a/source/main.pas +++ b/source/main.pas @@ -195,6 +195,7 @@ type procedure ExecuteRemoteNonQuery(sender: THandle; query: string); procedure HandleWMComplete(var msg: TMessage); message WM_COMPLETED; procedure HandleWMCopyData(var msg: TWMCopyData); message WM_COPYDATA; + procedure HandleWMProcessLog(var msg: TMessage); message WM_PROCESSLOG; private function GetChildwin: TMDIChild; public @@ -276,6 +277,11 @@ begin HandleWMCopyDataMessage(msg); end; +procedure TMainForm.HandleWMProcessLog(var msg: TMessage); +begin + ChildWin.ProcessSqlLog; +end; + procedure TMainForm.EnsureConnected; begin if ActiveMDIChild = nil then raise Exception.Create('Not connected.');