From ea8574bc1a13d1f9b83472ea66a953d7ef8a0cda Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Sun, 4 Apr 2010 23:30:37 +0000 Subject: [PATCH] Fix some AVs around ListTables by reintroducing recently deleted connection event OnDBObjectsCleared. Required in cases where cache is cleared or refreshed (!) elsewhere and ListTables get repainted later. --- source/main.pas | 13 +++++++++- source/mysql_connection.pas | 50 ++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/source/main.pas b/source/main.pas index 8f0697cb..7982a512 100644 --- a/source/main.pas +++ b/source/main.pas @@ -802,6 +802,7 @@ type procedure SaveQueryMemo(Tab: TQueryTab; Filename: String; OnlySelection: Boolean); procedure UpdateFilterPanel(Sender: TObject); procedure DatabaseChanged(Database: String); + procedure DBObjectsCleared(Database: String); function GetBlobContent(Results: TMySQLQuery; Column: Integer): String; procedure DoSearchReplace; procedure UpdateLineCharPanel; @@ -2413,6 +2414,7 @@ begin ConnectionAttempt := TMySQLConnection.Create(Self); ConnectionAttempt.OnLog := LogSQL; ConnectionAttempt.OnDatabaseChanged := DatabaseChanged; + ConnectionAttempt.OnDBObjectsCleared := DBObjectsCleared; ConnectionAttempt.ObjectNamesInSelectedDB := SynSQLSyn1.TableNames; ConnectionAttempt.Parameters := Params; try @@ -5079,6 +5081,8 @@ var begin // Find currently selected database node in database tree, // or the parent if a table is currently selected. + if csDestroying in ComponentState then + Exit; s := DBtree.FocusedNode; if not Assigned(s) then Result := '' else case DBtree.GetNodeLevel(s) of @@ -6575,6 +6579,13 @@ begin end; +procedure TMainForm.DBObjectsCleared(Database: String); +begin + if (Database='') or (ActiveDatabase=Database) then + InvalidateVT(ListTables, VTREE_NOTLOADED, False); +end; + + procedure TMainForm.DBtreeDblClick(Sender: TObject); var Node: PVirtualNode; @@ -6621,7 +6632,7 @@ begin // ReInit tree population if DoResetTableCache then begin - Connection.ClearDbObjects; + Connection.ClearAllDbObjects; FreeAndNil(AllDatabases); end; DBtree.ResetNode(DBTree.GetFirst); diff --git a/source/mysql_connection.pas b/source/mysql_connection.pas index f8c471a7..0a34d4bd 100644 --- a/source/mysql_connection.pas +++ b/source/mysql_connection.pas @@ -102,6 +102,7 @@ type FLogPrefix: String; FOnLog: TMySQLLogEvent; FOnDatabaseChanged: TMySQLDatabaseEvent; + FOnDBObjectsCleared: TMySQLDatabaseEvent; FRowsFound: Int64; FRowsAffected: Int64; FServerVersionUntouched: String; @@ -153,7 +154,8 @@ type function GetDBObjects(db: String; Refresh: Boolean=False): TDBObjectList; function GetDBSize(db: String): Int64; function DbObjectsCached(db: String): Boolean; - procedure ClearDbObjects(db: String=''); + procedure ClearDbObjects(db: String); + procedure ClearAllDbObjects; property Parameters: TConnectionParameters read FParameters write FParameters; property ThreadId: Cardinal read GetThreadId; property ConnectionUptime: Integer read GetConnectionUptime; @@ -183,6 +185,7 @@ type // Events property OnLog: TMySQLLogEvent read FOnLog write FOnLog; property OnDatabaseChanged: TMySQLDatabaseEvent read FOnDatabaseChanged write FOnDatabaseChanged; + property OnDBObjectsCleared: TMySQLDatabaseEvent read FOnDBObjectsCleared write FOnDBObjectsCleared; end; @@ -268,6 +271,7 @@ begin FLastQueryNetworkDuration := 0; FLogPrefix := ''; FIsUnicode := False; + FDBObjectLists := TStringList.Create; FDBSizes := TStringList.Create; end; @@ -967,40 +971,42 @@ begin FreeAndNil(FCharsetTable); FreeAndNil(FTableEngines); FreeAndNil(FInformationSchemaObjects); - ClearDbObjects; + ClearAllDbObjects; FTableEngineDefault := ''; end; -procedure TMySQLConnection.ClearDbObjects(db: String=''); +procedure TMySQLConnection.ClearDbObjects(db: String); var i, idx: Integer; begin - // Free all cached database object lists, or, if db is passed, only that one - if not Assigned(FDBObjectLists) then + // Free cached database object list + i := FDBObjectLists.IndexOf(db); + if i = -1 then Exit; - if db <> '' then begin - i := FDBObjectLists.IndexOf(db); - if i = -1 then - Exit; - TDBObjectList(FDBObjectLists.Objects[i]).Free; - FDBObjectLists.Delete(i); - idx := FDBSizes.IndexOfName(db); - if idx > -1 then - FDBSizes.Delete(idx); - end else begin - for i:=0 to FDBObjectLists.Count-1 do - TDBObjectList(FDBObjectLists.Objects[i]).Free; - FreeAndNil(FDBObjectLists); - FDBSizes.Clear; - end; + TDBObjectList(FDBObjectLists.Objects[i]).Free; + FDBObjectLists.Delete(i); + idx := FDBSizes.IndexOfName(db); + if idx > -1 then + FDBSizes.Delete(idx); + if Assigned(FOnDBObjectsCleared) then + FOnDBObjectsCleared(db); +end; + + +procedure TMySQLConnection.ClearAllDbObjects; +var + i: Integer; +begin + for i:=FDBObjectLists.Count-1 downto 0 do + ClearDbObjects(FDBObjectLists[i]); end; function TMySQLConnection.DbObjectsCached(db: String): Boolean; begin // Check if a table list is stored in cache - Result := Assigned(FDBObjectLists) and (FDBObjectLists.IndexOf(db) > -1); + Result := FDBObjectLists.IndexOf(db) > -1; end; @@ -1210,8 +1216,6 @@ begin Result.Sort; // Add list of objects in this database to cached list of all databases - if not Assigned(FDBObjectLists) then - FDBObjectLists := TStringList.Create; FDBObjectLists.AddObject(db, Result); FDBSizes.Values[db] := IntToStr(DBSize);