Introduce caching of collation table and table engines list in connection layer. Remove that stuff from main unit and automatically clear cached stuff on disconnection.

This commit is contained in:
Ansgar Becker
2009-11-22 23:42:39 +00:00
parent 46c650eabd
commit 92bd620309
6 changed files with 140 additions and 163 deletions

View File

@ -15,7 +15,6 @@ object CreateDatabaseForm: TCreateDatabaseForm
Position = poOwnerFormCenter Position = poOwnerFormCenter
OnClose = FormClose OnClose = FormClose
OnCreate = FormCreate OnCreate = FormCreate
OnDestroy = FormDestroy
OnShow = FormShow OnShow = FormShow
DesignSize = ( DesignSize = (
317 317

View File

@ -18,7 +18,6 @@ type
comboCollation: TComboBox; comboCollation: TComboBox;
lblPreview: TLabel; lblPreview: TLabel;
SynMemoPreview: TSynMemo; SynMemoPreview: TSynMemo;
procedure FormDestroy(Sender: TObject);
procedure btnOKClick(Sender: TObject); procedure btnOKClick(Sender: TObject);
procedure comboCharsetChange(Sender: TObject); procedure comboCharsetChange(Sender: TObject);
procedure Modified(Sender: TObject); procedure Modified(Sender: TObject);
@ -29,7 +28,7 @@ type
function GetCreateStatement: WideString; function GetCreateStatement: WideString;
private private
{ Private declarations } { Private declarations }
dsCollations : TMySQLQuery; CollationTable: TMySQLQuery;
defaultCharset : String; defaultCharset : String;
currentCollation : String; currentCollation : String;
public public
@ -53,45 +52,11 @@ var
charset: String; charset: String;
begin begin
InheritFont(Font); InheritFont(Font);
try
dsCollations := Mainform.Connection.GetResults('SHOW COLLATION');
// Detect servers default charset
defaultCharset := Mainform.Connection.GetVar( 'SHOW VARIABLES LIKE '+esc('character_set_server'), 1 );
except
// Ignore it when the above statements don't work on pre 4.1 servers.
// If the list(s) are nil, disable the combobox(es), so we create the db without charset.
end;
// Create a list with charsets from collations dataset
comboCharset.Enabled := dsCollations <> nil;
lblCharset.Enabled := comboCharset.Enabled;
if comboCharset.Enabled then
begin
comboCharset.Items.BeginUpdate;
dsCollations.First;
while not dsCollations.Eof do begin
charset := dsCollations.Col('Charset');
if comboCharset.Items.IndexOf(charset) = -1 then
comboCharset.Items.Add(charset);
dsCollations.Next;
end;
comboCharset.Items.EndUpdate;
end;
comboCollation.Enabled := dsCollations <> nil;
lblCollation.Enabled := comboCollation.Enabled;
// Setup SynMemoPreview // Setup SynMemoPreview
SynMemoPreview.Highlighter := Mainform.SynSQLSyn1; SynMemoPreview.Highlighter := Mainform.SynSQLSyn1;
end; end;
procedure TCreateDatabaseForm.FormDestroy(Sender: TObject);
begin
FreeAndNil(dsCollations);
end;
{** {**
Form gets displayed: Set default values. Form gets displayed: Set default values.
} }
@ -100,8 +65,28 @@ var
selectCharset, selectCharset,
currentCharset, currentCharset,
sql_create : WideString; sql_create : WideString;
Charset: String;
colpos: Integer; colpos: Integer;
begin begin
CollationTable := Mainform.Connection.CollationTable;
// Detect servers default charset
defaultCharset := Mainform.Connection.GetVar( 'SHOW VARIABLES LIKE '+esc('character_set_server'), 1 );
comboCharset.Enabled := Assigned(CollationTable);
lblCharset.Enabled := comboCharset.Enabled;
comboCollation.Enabled := comboCharset.Enabled;
lblCollation.Enabled := comboCharset.Enabled;
if comboCharset.Enabled then begin
// Create a list with charsets from collations dataset
comboCharset.Items.BeginUpdate;
while not CollationTable.Eof do begin
Charset := CollationTable.Col('Charset');
if comboCharset.Items.IndexOf(Charset) = -1 then
comboCharset.Items.Add(Charset);
CollationTable.Next;
end;
comboCharset.Items.EndUpdate;
end;
if modifyDB = '' then if modifyDB = '' then
begin begin
Caption := 'Create database ...'; Caption := 'Create database ...';
@ -157,21 +142,21 @@ var
defaultCollation : String; defaultCollation : String;
begin begin
// Abort if collations were not fetched successfully // Abort if collations were not fetched successfully
if dsCollations = nil then if not Assigned(CollationTable) then
Exit; Exit;
// Fill pulldown with fitting collations // Fill pulldown with fitting collations
comboCollation.Items.BeginUpdate; comboCollation.Items.BeginUpdate;
comboCollation.Items.Clear; comboCollation.Items.Clear;
dsCollations.First; CollationTable.First;
while not dsCollations.Eof do begin while not CollationTable.Eof do begin
if dsCollations.Col('Charset') = comboCharset.Text then if CollationTable.Col('Charset') = comboCharset.Text then
begin begin
comboCollation.Items.Add( dsCollations.Col('Collation')); comboCollation.Items.Add(CollationTable.Col('Collation'));
if dsCollations.Col('Default') = 'Yes' then if CollationTable.Col('Default') = 'Yes' then
defaultCollation := dsCollations.Col('Collation'); defaultCollation := CollationTable.Col('Collation');
end; end;
dsCollations.Next; CollationTable.Next;
end; end;
// Preselect default or current collation // Preselect default or current collation

View File

@ -708,9 +708,6 @@ type
EditVariableForm : TfrmEditVariable; EditVariableForm : TfrmEditVariable;
FileNameSessionLog : String; FileNameSessionLog : String;
FileHandleSessionLog : Textfile; FileHandleSessionLog : Textfile;
dsShowEngines,
dsHaveEngines,
dsCollations,
FSelectedTableColumns, FSelectedTableColumns,
FSelectedTableKeys : TMySQLQuery; FSelectedTableKeys : TMySQLQuery;
FilterPanelManuallyOpened : Boolean; FilterPanelManuallyOpened : Boolean;
@ -824,7 +821,6 @@ type
procedure ActivateFileLogging; procedure ActivateFileLogging;
procedure DeactivateFileLogging; procedure DeactivateFileLogging;
procedure TrimSQLLog; procedure TrimSQLLog;
procedure TableEnginesCombo(var Combobox: TCombobox);
function GetTreeNodeType(Tree: TBaseVirtualTree; Node: PVirtualNode): TListNodeType; function GetTreeNodeType(Tree: TBaseVirtualTree; Node: PVirtualNode): TListNodeType;
function GetFocusedTreeNodeType: TListNodeType; function GetFocusedTreeNodeType: TListNodeType;
procedure RefreshTree(DoResetTableCache: Boolean; SelectDatabase: WideString = ''); procedure RefreshTree(DoResetTableCache: Boolean; SelectDatabase: WideString = '');
@ -850,7 +846,6 @@ type
function GetRegKeyTable: String; function GetRegKeyTable: String;
procedure SaveListSetup( List: TVirtualStringTree ); procedure SaveListSetup( List: TVirtualStringTree );
procedure RestoreListSetup( List: TVirtualStringTree ); procedure RestoreListSetup( List: TVirtualStringTree );
function GetCollations(Items: TWideStrings = nil): TMySQLQuery;
procedure SetEditorTabCaption(Editor: TFrame; ObjName: WideString); procedure SetEditorTabCaption(Editor: TFrame; ObjName: WideString);
procedure ResetSelectedTableStuff; procedure ResetSelectedTableStuff;
procedure SetWindowCaption; procedure SetWindowCaption;
@ -1662,18 +1657,11 @@ begin
ClearAllTableLists; ClearAllTableLists;
FreeAndNil(AllDatabases); FreeAndNil(AllDatabases);
FreeAndNil(InformationSchemaTables); FreeAndNil(InformationSchemaTables);
FreeAndNil(dsShowEngines);
FreeAndNil(dsHaveEngines);
FreeAndNil(dsCollations);
FreeAndNil(FDataGridSelect); FreeAndNil(FDataGridSelect);
ResetSelectedTableStuff; ResetSelectedTableStuff;
SynMemoFilter.Clear; SynMemoFilter.Clear;
SetLength(FDataGridSort, 0); SetLength(FDataGridSort, 0);
// Free forms which use session based datasets, fx dsShowEngines
FreeAndNil(TableEditor);
FreeAndNil(CreateDatabaseForm);
// Closing connection // Closing connection
if Assigned(Connection) then if Assigned(Connection) then
FreeAndNil(Connection); FreeAndNil(Connection);
@ -5783,81 +5771,6 @@ begin
end; end;
{**
Fetch table engines from server
Currently used in tbl_properties and createtable
}
procedure TMainForm.TableEnginesCombo(var Combobox: TCombobox);
var
engineName, defaultEngine, engineSupport : String;
HaveEngineList : TStrings;
begin
Combobox.Items.BeginUpdate;
Combobox.Items.Clear;
// Cache datasets
if dsShowEngines = nil then begin
FreeAndNil(dsShowEngines);
try
dsShowEngines := Connection.GetResults('SHOW ENGINES');
except
// Ignore errors on old servers
end;
end;
if dsHaveEngines = nil then begin
FreeAndNil(dsHaveEngines);
dsHaveEngines := Connection.GetResults('SHOW VARIABLES LIKE ''have%''');
end;
if Assigned(dsShowEngines) then begin
dsShowEngines.First;
while not dsShowEngines.Eof do begin
engineName := dsShowEngines.Col('Engine');
engineSupport := LowerCase(dsShowEngines.Col('Support'));
// Add to dropdown if supported
if engineSupport <> 'no' then
Combobox.Items.Add(engineName);
// Check if this is the default engine
if engineSupport = 'default' then
defaultEngine := engineName;
dsShowEngines.Next;
end;
end
else begin
// Manually fetch available engine types by analysing have_* options
// This is for servers below 4.1 or when the SHOW ENGINES statement has
// failed for some other reason
// Add default engines which will not show in a have_* variable:
Combobox.Items.CommaText := 'MyISAM,MRG_MyISAM,HEAP';
defaultEngine := 'MyISAM';
// Possible other engines:
HaveEngineList := TStringList.Create;
HaveEngineList.CommaText := 'ARCHIVE,BDB,BLACKHOLE,CSV,EXAMPLE,FEDERATED,INNODB,ISAM';
dsHaveEngines.First;
while not dsHaveEngines.Eof do begin
engineName := copy(dsHaveEngines.Col(0), 6, Length(dsHaveEngines.Col(0)) );
// Strip additional "_engine" suffix, fx from "have_blackhole_engine"
if Pos('_', engineName) > 0 then
engineName := copy(engineName, 0, Pos('_', engineName)-1);
engineName := UpperCase(engineName);
// Add engine to dropdown if it's a) in HaveEngineList and b) activated
if (HaveEngineList.IndexOf(engineName) > -1)
and (LowerCase(dsHaveEngines.Col(1)) = 'yes') then
Combobox.Items.Add(engineName);
dsHaveEngines.Next;
end;
end;
Combobox.Sorted := True;
// Select default
Combobox.ItemIndex := Combobox.Items.IndexOf(defaultEngine);
Combobox.Items.EndUpdate;
end;
{** {**
A row in the process list was selected. Fill SynMemoProcessView with A row in the process list was selected. Fill SynMemoProcessView with
the SQL of that row. the SQL of that row.
@ -8215,28 +8128,6 @@ begin
end; end;
function TMainform.GetCollations(Items: TWideStrings = nil): TMySQLQuery;
begin
// Return cached collation list, used in several places, e.g. table editor
if dsCollations = nil then try
dsCollations := Connection.GetResults('SHOW COLLATION');
except
// Ignore errors on old servers
end;
if Assigned(dsCollations) then begin
dsCollations.First;
if Assigned(Items) then begin
while not dsCollations.Eof do begin
Items.Add(dsCollations.Col('Collation'));
dsCollations.Next;
end;
dsCollations.First;
end;
end;
Result := dsCollations;
end;
procedure TMainForm.PlaceObjectEditor(Which: TListNodeType); procedure TMainForm.PlaceObjectEditor(Which: TListNodeType);
var var
frm: TFrame; frm: TFrame;

View File

@ -83,6 +83,10 @@ type
FServerVersionUntouched: String; FServerVersionUntouched: String;
FLastQueryStart, FLastQueryEnd: Cardinal; FLastQueryStart, FLastQueryEnd: Cardinal;
FIsUnicode: Boolean; FIsUnicode: Boolean;
FTableEngines: TStringList;
FTableEngineDefault: String;
FCollationTable: TMySQLQuery;
FCollationsUnavailable: Boolean;
function GetActive: Boolean; function GetActive: Boolean;
procedure SetActive(Value: Boolean); procedure SetActive(Value: Boolean);
procedure SetDatabase(Value: WideString); procedure SetDatabase(Value: WideString);
@ -93,8 +97,12 @@ type
function GetServerVersionStr: String; function GetServerVersionStr: String;
function GetServerVersionInt: Integer; function GetServerVersionInt: Integer;
function GetLastQueryDuration: Cardinal; function GetLastQueryDuration: Cardinal;
function GetTableEngines: TStringList;
function GetCollationTable: TMySQLQuery;
function GetCollationList: TStringList;
procedure Log(Category: TMySQLLogCategory; Msg: WideString); procedure Log(Category: TMySQLLogCategory; Msg: WideString);
procedure DetectCapabilities; procedure DetectCapabilities;
procedure ClearCache;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
@ -119,6 +127,10 @@ type
property RowsAffected: Int64 read FRowsAffected; property RowsAffected: Int64 read FRowsAffected;
property LastQueryDuration: Cardinal read GetLastQueryDuration; property LastQueryDuration: Cardinal read GetLastQueryDuration;
property IsUnicode: Boolean read FIsUnicode; property IsUnicode: Boolean read FIsUnicode;
property TableEngines: TStringList read GetTableEngines;
property TableEngineDefault: String read FTableEngineDefault;
property CollationTable: TMySQLQuery read GetCollationTable;
property CollationList: TStringList read GetCollationList;
published published
property Active: Boolean read GetActive write SetActive default False; property Active: Boolean read GetActive write SetActive default False;
property Hostname: String read FHostname write FHostname; property Hostname: String read FHostname write FHostname;
@ -196,6 +208,7 @@ end;
destructor TMySQLConnection.Destroy; destructor TMySQLConnection.Destroy;
begin begin
if Active then Active := False; if Active then Active := False;
ClearCache;
inherited Destroy; inherited Destroy;
end; end;
@ -290,8 +303,10 @@ end;
function TMySQLConnection.GetActive: Boolean; function TMySQLConnection.GetActive: Boolean;
begin begin
if FActive and (mysql_ping(FHandle) <> 0) then if FActive and (mysql_ping(FHandle) <> 0) then begin
Active := False; Active := False;
ClearCache;
end;
Result := FActive; Result := FActive;
end; end;
@ -616,6 +631,93 @@ begin
end; end;
function TMySQLConnection.GetTableEngines: TStringList;
var
ShowEngines, HaveEngines: TMySQLQuery;
engineName, engineSupport: String;
PossibleEngines: TStringList;
begin
if not Assigned(FTableEngines) then begin
FTableEngines := TStringList.Create;
try
ShowEngines := GetResults('SHOW ENGINES');
while not ShowEngines.Eof do begin
engineName := ShowEngines.Col('Engine');
engineSupport := LowerCase(ShowEngines.Col('Support'));
// Add to dropdown if supported
if engineSupport <> 'no' then
FTableEngines.Add(engineName);
// Check if this is the default engine
if engineSupport = 'default' then
FTableEngineDefault := engineName;
ShowEngines.Next;
end;
except
// Ignore errors on old servers and try a fallback:
// Manually fetch available engine types by analysing have_* options
// This is for servers below 4.1 or when the SHOW ENGINES statement has
// failed for some other reason
HaveEngines := GetResults('SHOW VARIABLES LIKE ''have%''');
// Add default engines which will not show in a have_* variable:
FTableEngines.CommaText := 'MyISAM,MRG_MyISAM,HEAP';
FTableEngineDefault := 'MyISAM';
// Possible other engines:
PossibleEngines := TStringList.Create;
PossibleEngines.CommaText := 'ARCHIVE,BDB,BLACKHOLE,CSV,EXAMPLE,FEDERATED,INNODB,ISAM';
while not HaveEngines.Eof do begin
engineName := copy(HaveEngines.Col(0), 6, Length(HaveEngines.Col(0)));
// Strip additional "_engine" suffix, fx from "have_blackhole_engine"
if Pos('_', engineName) > 0 then
engineName := copy(engineName, 0, Pos('_', engineName)-1);
engineName := UpperCase(engineName);
// Add engine to list if it's a) in HaveEngineList and b) activated
if (PossibleEngines.IndexOf(engineName) > -1)
and (LowerCase(HaveEngines.Col(1)) = 'yes') then
FTableEngines.Add(engineName);
HaveEngines.Next;
end;
end;
end;
Result := FTableEngines;
end;
function TMySQLConnection.GetCollationTable: TMySQLQuery;
begin
if (not Assigned(FCollationTable)) and (not FCollationsUnavailable) then try
FCollationTable := GetResults('SHOW COLLATION');
except
// Ignore errors on old servers
FCollationsUnavailable := True;
end;
if Assigned(FCollationTable) then
FCollationTable.First;
Result := FCollationTable;
end;
function TMySQLConnection.GetCollationList: TStringList;
var
c: TMySQLQuery;
begin
c := CollationTable;
Result := TStringList.Create;
if not FCollationsUnavailable then while not c.Eof do begin
Result.Add(c.Col('Collation'));
c.Next;
end;
end;
procedure TMySQLConnection.ClearCache;
begin
// Free cached lists and results. Called when the connection was closed and/or destroyed
FreeAndNil(FCollationTable);
FCollationsUnavailable := False;
FreeAndNil(FTableEngines);
FTableEngineDefault := '';
end;
{ TMySQLQuery } { TMySQLQuery }

View File

@ -343,7 +343,7 @@ object frmTableEditor: TfrmTableEditor
TabOrder = 0 TabOrder = 0
OnChange = editNumEditChange OnChange = editNumEditChange
end end
object comboCollation: TTntComboBox object comboCollation: TComboBox
Left = 354 Left = 354
Top = 3 Top = 3
Width = 119 Width = 119

View File

@ -36,7 +36,7 @@ type
memoUnionTables: TTntMemo; memoUnionTables: TTntMemo;
comboInsertMethod: TComboBox; comboInsertMethod: TComboBox;
lblCollation: TLabel; lblCollation: TLabel;
comboCollation: TTNTComboBox; comboCollation: TComboBox;
lblEngine: TLabel; lblEngine: TLabel;
comboEngine: TComboBox; comboEngine: TComboBox;
treeIndexes: TVirtualStringTree; treeIndexes: TVirtualStringTree;
@ -302,9 +302,9 @@ begin
// Start with "basic" tab activated when just called // Start with "basic" tab activated when just called
if FAlterTableName <> AlterTableName then if FAlterTableName <> AlterTableName then
PageControlMain.ActivePage := tabBasic; PageControlMain.ActivePage := tabBasic;
Mainform.TableEnginesCombo(comboEngine); comboEngine.Items := Mainform.Connection.TableEngines;
comboCollation.Items.Clear; comboEngine.ItemIndex := comboEngine.Items.IndexOf(Mainform.Connection.TableEngineDefault);
Mainform.GetCollations(comboCollation.Items); comboCollation.Items := Mainform.Connection.CollationList;
FAlterTableName := AlterTableName; FAlterTableName := AlterTableName;
listColumns.BeginUpdate; listColumns.BeginUpdate;
FColumns.Clear; FColumns.Clear;
@ -688,8 +688,8 @@ begin
if comboInsertMethod.Enabled and (comboInsertMethod.Tag = ModifiedFlag) and (comboInsertMethod.Text <> '') then if comboInsertMethod.Enabled and (comboInsertMethod.Tag = ModifiedFlag) and (comboInsertMethod.Text <> '') then
Specs.Add('INSERT_METHOD='+comboInsertMethod.Text); Specs.Add('INSERT_METHOD='+comboInsertMethod.Text);
if chkCharsetConvert.Checked then begin if chkCharsetConvert.Checked then begin
Results := Mainform.GetCollations; Results := Mainform.Connection.CollationTable;
while not Results.Eof do begin if Assigned(Results) then while not Results.Eof do begin
if Results.Col('Collation') = comboCollation.Text then begin if Results.Col('Collation') = comboCollation.Text then begin
Specs.Add('CONVERT TO CHARSET '+Results.Col('Charset')); Specs.Add('CONVERT TO CHARSET '+Results.Col('Charset'));
break; break;
@ -1409,7 +1409,7 @@ begin
8: begin // Collation pulldown 8: begin // Collation pulldown
EnumEditor := TEnumEditorLink.Create(VT); EnumEditor := TEnumEditorLink.Create(VT);
EnumEditor.ValueList := TWideStringList.Create; EnumEditor.ValueList := TWideStringList.Create;
Mainform.GetCollations(EnumEditor.ValueList); EnumEditor.ValueList.Text := Mainform.Connection.CollationList.Text;
EnumEditor.ValueList.Insert(0, ''); EnumEditor.ValueList.Insert(0, '');
EditLink := EnumEditor; EditLink := EnumEditor;
end; end;