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
Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls,
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
Tconnform = class(TExtForm)
@ -190,7 +190,6 @@ type
procedure WMNCLBUTTONDOWN(var Msg: TWMNCLButtonDown) ; message WM_NCLBUTTONDOWN;
procedure WMNCLBUTTONUP(var Msg: TWMNCLButtonUp) ; message WM_NCLBUTTONUP;
procedure RefreshBackgroundColors;
procedure RefreshLibraries(Sess: TConnectionParameters);
public
{ Public declarations }
end;
@ -855,7 +854,7 @@ begin
RefreshBackgroundColors;
ColorBoxBackgroundColor.Selected := Sess.SessionColor;
editDatabases.Text := Sess.AllDatabasesStr;
RefreshLibraries(Sess^);
comboLibrary.Items := Sess.GetLibraries;
comboLibrary.ItemIndex := comboLibrary.Items.IndexOf(Sess.LibraryOrProvider);
if (comboLibrary.ItemIndex = -1) and (comboLibrary.Items.Count > 0) then begin
comboLibrary.ItemIndex := 0;
@ -897,45 +896,6 @@ begin
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);
var
LastConnect, Created, DummyDate: TDateTime;

View File

@ -5,7 +5,7 @@ interface
uses
Classes, SysUtils, windows, dbstructures, SynRegExpr, Generics.Collections, Generics.Defaults,
DateUtils, Types, Math, Dialogs, ADODB, DB, DBCommon, ComObj, Graphics, ExtCtrls, StrUtils,
gnugettext, AnsiStrings, Controls, Forms;
gnugettext, AnsiStrings, Controls, Forms, System.IOUtils;
type
@ -202,6 +202,7 @@ type
ntMSSQL_NamedPipe, ntMSSQL_TCPIP, ntMSSQL_SPX, ntMSSQL_VINES, ntMSSQL_RPC,
ntPgSQL_TCPIP, ntPgSQL_SSHtunnel);
TNetTypeGroup = (ngMySQL, ngMSSQL, ngPgSQL);
TNetGroupLibs = TDictionary<TNetTypeGroup, TStringList>;
TConnectionParameters = class(TObject)
strict private
@ -214,6 +215,7 @@ type
FWindowsAuth, FWantSSL, FIsFolder, FCleartextPluginEnabled: Boolean;
FSessionColor: TColor;
FLastConnect: TDateTime;
class var FLibraries: TNetGroupLibs;
function GetImageIndex: Integer;
function GetSessionName: String;
public
@ -236,6 +238,7 @@ type
function IsAzure: Boolean;
function IsMemSQL: Boolean;
property ImageIndex: Integer read GetImageIndex;
function GetLibraries: TStringList;
function DefaultLibrary: String;
function DefaultPort: Integer;
function DefaultUsername: String;
@ -1458,6 +1461,53 @@ begin
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;
var
LastBackSlash: Integer;