Performance: Search libraries on system once per app instance and net type group. Cache these in TConnectionParameters.FLibraries. OLE DB providers take some time to collect.

This commit is contained in:
Ansgar Becker
2019-10-20 09:47:37 +02:00
parent f874c80626
commit 3f0db16f5b
2 changed files with 53 additions and 43 deletions

View File

@ -11,7 +11,7 @@ interface
uses uses
Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls,
VirtualTrees, Menus, Graphics, Generics.Collections, ActiveX, extra_controls, Messages, VirtualTrees, Menus, Graphics, Generics.Collections, ActiveX, extra_controls, Messages,
dbconnection, gnugettext, SynRegExpr, System.Types, System.IOUtils, Vcl.GraphUtil, ADODB; dbconnection, gnugettext, SynRegExpr, System.Types, Vcl.GraphUtil, ADODB;
type type
Tconnform = class(TExtForm) Tconnform = class(TExtForm)
@ -190,7 +190,6 @@ type
procedure WMNCLBUTTONDOWN(var Msg: TWMNCLButtonDown) ; message WM_NCLBUTTONDOWN; procedure WMNCLBUTTONDOWN(var Msg: TWMNCLButtonDown) ; message WM_NCLBUTTONDOWN;
procedure WMNCLBUTTONUP(var Msg: TWMNCLButtonUp) ; message WM_NCLBUTTONUP; procedure WMNCLBUTTONUP(var Msg: TWMNCLButtonUp) ; message WM_NCLBUTTONUP;
procedure RefreshBackgroundColors; procedure RefreshBackgroundColors;
procedure RefreshLibraries(Sess: TConnectionParameters);
public public
{ Public declarations } { Public declarations }
end; end;
@ -855,7 +854,7 @@ begin
RefreshBackgroundColors; RefreshBackgroundColors;
ColorBoxBackgroundColor.Selected := Sess.SessionColor; ColorBoxBackgroundColor.Selected := Sess.SessionColor;
editDatabases.Text := Sess.AllDatabasesStr; editDatabases.Text := Sess.AllDatabasesStr;
RefreshLibraries(Sess^); comboLibrary.Items := Sess.GetLibraries;
comboLibrary.ItemIndex := comboLibrary.Items.IndexOf(Sess.LibraryOrProvider); comboLibrary.ItemIndex := comboLibrary.Items.IndexOf(Sess.LibraryOrProvider);
if (comboLibrary.ItemIndex = -1) and (comboLibrary.Items.Count > 0) then begin if (comboLibrary.ItemIndex = -1) and (comboLibrary.Items.Count > 0) then begin
comboLibrary.ItemIndex := 0; comboLibrary.ItemIndex := 0;
@ -897,45 +896,6 @@ begin
end; end;
procedure Tconnform.RefreshLibraries(Sess: TConnectionParameters);
var
rx: TRegExpr;
Libs: TStringDynArray;
LibPath, LibFile: String;
Providers: TStringList;
Provider: String;
begin
// Detect existing dll files in app folder
comboLibrary.Clear;
rx := TRegExpr.Create;
rx.ModifierI := True;
case Sess.NetTypeGroup of
ngMySQL: rx.Expression := '^lib(mysql|mariadb).*\.dll$';
ngMSSQL: rx.Expression := '^(MSOLEDBSQL|SQLOLEDB)$';
ngPgSQL: rx.Expression := '^libpq.*\.dll$';
end;
if Sess.NetTypeGroup in [ngMySQL, ngPgSQL] then begin
Libs := TDirectory.GetFiles(ExtractFilePath(ParamStr(0)), '*.dll');
for LibPath in Libs do begin
LibFile := ExtractFileName(LibPath);
if rx.Exec(LibFile) then begin
comboLibrary.Items.Add(LibFile);
end;
end;
end else begin
Providers := TStringList.Create;
GetProviderNames(Providers);
for Provider in Providers do begin
if rx.Exec(Provider) then begin
comboLibrary.Items.Add(Provider);
end;
end;
end;
end;
procedure Tconnform.TimerStatisticsTimer(Sender: TObject); procedure Tconnform.TimerStatisticsTimer(Sender: TObject);
var var
LastConnect, Created, DummyDate: TDateTime; LastConnect, Created, DummyDate: TDateTime;

View File

@ -5,7 +5,7 @@ interface
uses uses
Classes, SysUtils, windows, dbstructures, SynRegExpr, Generics.Collections, Generics.Defaults, Classes, SysUtils, windows, dbstructures, SynRegExpr, Generics.Collections, Generics.Defaults,
DateUtils, Types, Math, Dialogs, ADODB, DB, DBCommon, ComObj, Graphics, ExtCtrls, StrUtils, DateUtils, Types, Math, Dialogs, ADODB, DB, DBCommon, ComObj, Graphics, ExtCtrls, StrUtils,
gnugettext, AnsiStrings, Controls, Forms; gnugettext, AnsiStrings, Controls, Forms, System.IOUtils;
type type
@ -202,6 +202,7 @@ type
ntMSSQL_NamedPipe, ntMSSQL_TCPIP, ntMSSQL_SPX, ntMSSQL_VINES, ntMSSQL_RPC, ntMSSQL_NamedPipe, ntMSSQL_TCPIP, ntMSSQL_SPX, ntMSSQL_VINES, ntMSSQL_RPC,
ntPgSQL_TCPIP, ntPgSQL_SSHtunnel); ntPgSQL_TCPIP, ntPgSQL_SSHtunnel);
TNetTypeGroup = (ngMySQL, ngMSSQL, ngPgSQL); TNetTypeGroup = (ngMySQL, ngMSSQL, ngPgSQL);
TNetGroupLibs = TDictionary<TNetTypeGroup, TStringList>;
TConnectionParameters = class(TObject) TConnectionParameters = class(TObject)
strict private strict private
@ -214,6 +215,7 @@ type
FWindowsAuth, FWantSSL, FIsFolder, FCleartextPluginEnabled: Boolean; FWindowsAuth, FWantSSL, FIsFolder, FCleartextPluginEnabled: Boolean;
FSessionColor: TColor; FSessionColor: TColor;
FLastConnect: TDateTime; FLastConnect: TDateTime;
class var FLibraries: TNetGroupLibs;
function GetImageIndex: Integer; function GetImageIndex: Integer;
function GetSessionName: String; function GetSessionName: String;
public public
@ -236,6 +238,7 @@ type
function IsAzure: Boolean; function IsAzure: Boolean;
function IsMemSQL: Boolean; function IsMemSQL: Boolean;
property ImageIndex: Integer read GetImageIndex; property ImageIndex: Integer read GetImageIndex;
function GetLibraries: TStringList;
function DefaultLibrary: String; function DefaultLibrary: String;
function DefaultPort: Integer; function DefaultPort: Integer;
function DefaultUsername: String; function DefaultUsername: String;
@ -1458,6 +1461,53 @@ begin
end; end;
function TConnectionParameters.GetLibraries: TStringList;
var
rx: TRegExpr;
Dlls: TStringDynArray;
DllPath, DllFile: String;
FoundLibs, Providers: TStringList;
Provider: String;
begin
if not Assigned(FLibraries) then begin
FLibraries := TNetGroupLibs.Create;
end;
if not FLibraries.ContainsKey(NetTypeGroup) then begin
FoundLibs := TStringList.Create;
rx := TRegExpr.Create;
rx.ModifierI := True;
case NetTypeGroup of
ngMySQL: rx.Expression := '^lib(mysql|mariadb).*\.dll$';
ngMSSQL: rx.Expression := '^(MSOLEDBSQL|SQLOLEDB)$';
ngPgSQL: rx.Expression := '^libpq.*\.dll$';
end;
if NetTypeGroup in [ngMySQL, ngPgSQL] then begin
Dlls := TDirectory.GetFiles(ExtractFilePath(ParamStr(0)), '*.dll');
for DllPath in Dlls do begin
DllFile := ExtractFileName(DllPath);
if rx.Exec(DllFile) then begin
FoundLibs.Add(DllFile);
end;
end;
SetLength(Dlls, 0);
end else begin
Providers := TStringList.Create;
GetProviderNames(Providers);
for Provider in Providers do begin
if rx.Exec(Provider) then begin
FoundLibs.Add(Provider);
end;
end;
Providers.Free;
end;
rx.Free;
FLibraries.Add(NetTypeGroup, FoundLibs);
end;
FLibraries.TryGetValue(NetTypeGroup, Result);
end;
function TConnectionParameters.GetSessionName: String; function TConnectionParameters.GetSessionName: String;
var var
LastBackSlash: Integer; LastBackSlash: Integer;