Files
HeidiSQL/source/types_helpers.pas

506 lines
18 KiB
ObjectPascal

unit types_helpers;
interface
uses
Vcl.Graphics;
type
// === Database ===
TNetType = (ntMySQL_TCPIP, ntMySQL_NamedPipe, ntMySQL_SSHtunnel,
ntMSSQL_NamedPipe, ntMSSQL_TCPIP, ntMSSQL_SPX, ntMSSQL_VINES, ntMSSQL_RPC,
ntPgSQL_TCPIP,
ntMariaDB_TCPIP, ntMariaDB_NamedPipe, ntMariaDB_SSHtunnel);
TNetTypeGroup = (ngMySQL, ngMSSQL, ngPgSQL, ngMariaDB);
// === Users and Privileges ===
TNodeObjectKind = (
okGlobal, okSchema, okGroupTables, okGroupViews, okGroupProcedures,
okGroupFunctions, okGroupTriggers, okGroupEvents, okTable, okView,
okProcedure, okFunction, {okTrigger, okEvent, }okColumn
);
TNodeObjectKinds = set of TNodeObjectKind;
TPrivilege = (prNone, prExecute, prProcess, prSelect, prShowDatabases,
prShowView, prAlter, prAlterRoutine, prCreate, prCreateRoutine,
prCreateTableSpace, prCreateTemporaryTables, prCreateView, prDelete, prDrop,
prEvent, prIndex, prInsert, prReferences, prTrigger, prUpdate, prCreateRole,
prCreateUser, prDropRole, prFile, prGrant, prLockTables, prReload,
prReplicationClient, prReplicationSlave, prShutdown, prSuper);
TPrivileges = set of TPrivilege;
TPrivilegeHelper = record helper for TPrivilege
public
function AvailableForObjectKind(const AObjectKind: TNodeObjectKind): Boolean;
function AvailableForServer(
const ANetTypeGroup: TNetTypeGroup;
const AVersion: Integer): Boolean;
function ColorBG: TColor;
function ColorFG: TColor;
function ToString: string;
function FromString(const AString: string): Boolean;
const
CL_VIOLET_FG = clPurple;
CL_GREEN_FG = clGreen;
CL_RED_FG = clMaroon;
CL_BLUE_FG = clNavy;
CL_VIOLET_BG = $00FFE1FF;
CL_GREEN_BG = $00E1FFE1;
CL_RED_BG = $00E1E1FF;
CL_BLUE_BG = $00FFE1E1;
end;
TPrivilegesHelper = record helper for TPrivileges
public
function ToString: string;
function FromGrant(const AGrant: string): Boolean;
function FromString(const AString: string): Boolean;
end;
TUserKind = (ukGroupUsers, ukGroupRoles, ukUser, ukRole, ukHost);
TUserChangedPart = (ucpCaption, ucpProperties, ucpPrivileges);
TUserChangedParts = set of TUserChangedPart;
TUserProblem = (upNone, upEmptyPassword, upInvalidPasswordLen, upSkipNameResolve, upUnknown);
implementation
uses
apphelpers, SynRegExpr, System.Classes, System.SysUtils;
const
S_REGEX_GRANTS = '^GRANT\s+(.+)\s+ON\s+((TABLE|FUNCTION|PROCEDURE)\s+)?(\*|[`"]([^`"]+)[`"])\.(\*|[`"]([^`"]+)[`"])\s+TO\s+\S+(\s+IDENTIFIED\s+BY\s+(PASSWORD)?\s+''?([^'']+)''?)?(\s+.+)?$';
{ TPrivilegeHelper }
function TPrivilegeHelper.AvailableForObjectKind(
const AObjectKind: TNodeObjectKind): Boolean;
begin
Result:= FALSE;
case Self of
prAlter:
Result := AObjectKind in [okGlobal, okSchema, okTable];
prAlterRoutine:
Result := AObjectKind in [okGlobal, okSchema, okProcedure, okFunction];
prCreate:
Result := AObjectKind in [okGlobal, okSchema, okTable];
prCreateRole:
Result := AObjectKind in [okGlobal];
prCreateRoutine:
Result := AObjectKind in [okGlobal, okSchema, okProcedure, okFunction];
prCreateTableSpace:
Result := AObjectKind in [okGlobal];
prCreateTemporaryTables:
Result := AObjectKind in [okGlobal, okSchema];
prCreateUser:
Result := AObjectKind in [okGlobal];
prCreateView:
Result := AObjectKind in [okGlobal, okSchema, okView];
prDelete:
Result := AObjectKind in [okGlobal, okSchema, okTable];
prDrop:
Result := AObjectKind in [okGlobal, okSchema, okTable, okView];
prDropRole:
Result := AObjectKind in [okGlobal];
prEvent:
Result := AObjectKind in [okGlobal, okSchema];
prExecute:
Result := AObjectKind in [okGlobal, okSchema, okProcedure, okFunction];
prFile:
Result := AObjectKind in [okGlobal];
prGrant:
Result := AObjectKind in [okGlobal, okSchema, okTable, okProcedure,
okFunction, okColumn];
prIndex:
Result := AObjectKind in [okGlobal, okSchema, okTable];
prInsert:
Result := AObjectKind in [okGlobal, okSchema, okTable, okColumn];
prLockTables:
Result := AObjectKind in [okGlobal, okSchema];
prProcess:
Result := AObjectKind in [okGlobal];
prReferences:
Result := AObjectKind in [okGlobal, okSchema, okTable];
prReload:
Result := AObjectKind in [okGlobal];
prReplicationClient:
Result := AObjectKind in [okGlobal];
prReplicationSlave:
Result := AObjectKind in [okGlobal];
prSelect:
Result := AObjectKind in [okGlobal, okSchema, okTable, okColumn];
prShowDatabases:
Result := AObjectKind in [okGlobal];
prShowView:
Result := AObjectKind in [okGlobal, okSchema, okView];
prShutdown:
Result := AObjectKind in [okGlobal];
prSuper:
Result := AObjectKind in [okGlobal];
prTrigger:
Result := AObjectKind in [okGlobal, okSchema];
prUpdate:
Result := AObjectKind in [okGlobal, okSchema, okTable, okColumn];
end;
end;
function TPrivilegeHelper.AvailableForServer(const ANetTypeGroup: TNetTypeGroup;
const AVersion: Integer): Boolean;
var
NTG: TNetTypeGroup;
V: Integer;
begin
Result:= FALSE;
NTG:= ANetTypeGroup;
V:= AVersion;
case Self of
// TODO: Add other supported servers and their min versions!
prAlter:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prAlterRoutine:
Result := ((NTG = ngMySQL) and (V >= 50003)) or
((NTG = ngMariaDB) and (V >= 50100));
prCreate:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prCreateRole:
Result := ((NTG = ngMySQL) and (V >= 80000)) or
((NTG = ngMariaDB) and (FALSE)); // Not supported in MariaDB! Here we have to have CREATE USER privilege.
prCreateRoutine:
Result := ((NTG = ngMySQL) and (V >= 50003)) or
((NTG = ngMariaDB) and (V >= 50100));
prCreateTableSpace:
Result := ((NTG = ngMySQL) and (V >= 50404)) or
((NTG = ngMariaDB) and (FALSE));
prCreateTemporaryTables:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prCreateUser:
Result := ((NTG = ngMySQL) and (V >= 50003)) or
((NTG = ngMariaDB) and (V >= 50100));
prCreateView:
Result := ((NTG = ngMySQL) and (V >= 50001)) or
((NTG = ngMariaDB) and (V >= 50100));
prDelete:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prDrop:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prDropRole:
Result := ((NTG = ngMySQL) and (V >= 80000)) or
((NTG = ngMariaDB) and (FALSE)); // Not supported in MariaDB! Here we have to have CREATE USER privilege.
prEvent:
Result := ((NTG = ngMySQL) and (V >= 50106)) or
((NTG = ngMariaDB) and (V >= 50106));
prExecute:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prFile:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prGrant:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prIndex:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prInsert:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prLockTables:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prProcess:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prReferences:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prReload:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prReplicationClient:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prReplicationSlave:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prSelect:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prShowDatabases:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prShowView:
Result := ((NTG = ngMySQL) and (V >= 50001)) or
((NTG = ngMariaDB) and (V >= 50100));
prShutdown:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
prSuper:
Result := ((NTG = ngMySQL) and (V >= 40002)) or
((NTG = ngMariaDB) and (V >= 50100));
prTrigger:
Result := ((NTG = ngMySQL) and (V >= 50106)) or
((NTG = ngMariaDB) and (V >= 50106));
prUpdate:
Result := ((NTG = ngMySQL) and (V >= 0)) or
((NTG = ngMariaDB) and (V >= 50100));
end;
end;
function TPrivilegeHelper.ColorBG: TColor;
begin
Result:= clNone;
case Self of
prExecute: Result:= CL_GREEN_BG;
prProcess: Result:= CL_GREEN_BG;
prSelect: Result:= CL_GREEN_BG;
prShowDatabases: Result:= CL_GREEN_BG;
prShowView: Result:= CL_GREEN_BG;
prAlter: Result:= CL_RED_BG;
prAlterRoutine: Result:= CL_RED_BG;
prCreate: Result:= CL_RED_BG;
prCreateRoutine: Result:= CL_RED_BG;
prCreateTableSpace: Result:= CL_RED_BG;
prCreateTemporaryTables: Result:= CL_RED_BG;
prCreateView: Result:= CL_RED_BG;
prDelete: Result:= CL_RED_BG;
prDrop: Result:= CL_RED_BG;
prEvent: Result:= CL_RED_BG;
prIndex: Result:= CL_RED_BG;
prInsert: Result:= CL_RED_BG;
prReferences: Result:= CL_RED_BG;
prTrigger: Result:= CL_RED_BG;
prUpdate: Result:= CL_RED_BG;
prCreateRole: Result:= CL_BLUE_BG;
prCreateUser: Result:= CL_BLUE_BG;
prDropRole: Result:= CL_BLUE_BG;
prFile: Result:= CL_BLUE_BG;
prGrant: Result:= CL_BLUE_BG;
prLockTables: Result:= CL_BLUE_BG;
prReload: Result:= CL_BLUE_BG;
prReplicationClient: Result:= CL_BLUE_BG;
prReplicationSlave: Result:= CL_BLUE_BG;
prShutdown: Result:= CL_BLUE_BG;
prSuper: Result:= CL_BLUE_BG;
end;
end;
function TPrivilegeHelper.ColorFG: TColor;
begin
Result:= clNone;
case Self of
prExecute: Result:= CL_GREEN_FG;
prProcess: Result:= CL_GREEN_FG;
prSelect: Result:= CL_GREEN_FG;
prShowDatabases: Result:= CL_GREEN_FG;
prShowView: Result:= CL_GREEN_FG;
prAlter: Result:= CL_RED_FG;
prAlterRoutine: Result:= CL_RED_FG;
prCreate: Result:= CL_RED_FG;
prCreateRoutine: Result:= CL_RED_FG;
prCreateTableSpace: Result:= CL_RED_FG;
prCreateTemporaryTables: Result:= CL_RED_FG;
prCreateView: Result:= CL_RED_FG;
prDelete: Result:= CL_RED_FG;
prDrop: Result:= CL_RED_FG;
prEvent: Result:= CL_RED_FG;
prIndex: Result:= CL_RED_FG;
prInsert: Result:= CL_RED_FG;
prReferences: Result:= CL_RED_FG;
prTrigger: Result:= CL_RED_FG;
prUpdate: Result:= CL_RED_FG;
prCreateRole: Result:= CL_BLUE_FG;
prCreateUser: Result:= CL_BLUE_FG;
prDropRole: Result:= CL_BLUE_FG;
prFile: Result:= CL_BLUE_FG;
prGrant: Result:= CL_BLUE_FG;
prLockTables: Result:= CL_BLUE_FG;
prReload: Result:= CL_BLUE_FG;
prReplicationClient: Result:= CL_BLUE_FG;
prReplicationSlave: Result:= CL_BLUE_FG;
prShutdown: Result:= CL_BLUE_FG;
prSuper: Result:= CL_BLUE_FG;
end;
end;
function TPrivilegeHelper.FromString(const AString: string): Boolean;
begin
Self:= prNone;
if CompareText(AString, 'ALTER') = 0 then
Self:= prAlter
else if CompareText(AString, 'ALTER ROUTINE') = 0 then
Self:= prAlterRoutine
else if CompareText(AString, 'CREATE') = 0 then
Self:= prCreate
else if CompareText(AString, 'CREATE ROLE') = 0 then
Self:= prCreateRole
else if CompareText(AString, 'CREATE ROUTINE') = 0 then
Self:= prCreateRoutine
else if CompareText(AString, 'CREATE TABLESPACE') = 0 then
Self:= prCreateTableSpace
else if CompareText(AString, 'CREATE TEMPORARY TABLES') = 0 then
Self:= prCreateTemporaryTables
else if CompareText(AString, 'CREATE USER') = 0 then
Self:= prCreateUser
else if CompareText(AString, 'CREATE VIEW') = 0 then
Self:= prCreateView
else if CompareText(AString, 'DELETE') = 0 then
Self:= prDelete
else if CompareText(AString, 'DROP') = 0 then
Self:= prDrop
else if CompareText(AString, 'DROP ROLE') = 0 then
Self:= prDropRole
else if CompareText(AString, 'EVENT') = 0 then
Self:= prEvent
else if CompareText(AString, 'EXECUTE') = 0 then
Self:= prExecute
else if CompareText(AString, 'FILE') = 0 then
Self:= prFile
else if CompareText(AString, 'GRANT') = 0 then
Self:= prGrant
else if CompareText(AString, 'INDEX') = 0 then
Self:= prIndex
else if CompareText(AString, 'INSERT') = 0 then
Self:= prInsert
else if CompareText(AString, 'LOCK TABLES') = 0 then
Self:= prLockTables
else if CompareText(AString, 'PROCESS') = 0 then
Self:= prProcess
else if CompareText(AString, 'REFERENCES') = 0 then
Self:= prReferences
else if CompareText(AString, 'RELOAD') = 0 then
Self:= prReload
else if CompareText(AString, 'REPLICATION CLIENT') = 0 then
Self:= prReplicationClient
else if CompareText(AString, 'REPLICATION SLAVE') = 0 then
Self:= prReplicationSlave
else if CompareText(AString, 'SELECT') = 0 then
Self:= prSelect
else if CompareText(AString, 'SHOW DATABASES') = 0 then
Self:= prShowDatabases
else if CompareText(AString, 'SHOW VIEW') = 0 then
Self:= prShowView
else if CompareText(AString, 'SHUTDOWN') = 0 then
Self:= prShutdown
else if CompareText(AString, 'SUPER') = 0 then
Self:= prSuper
else if CompareText(AString, 'TRIGGER') = 0 then
Self:= prTrigger
else if CompareText(AString, 'UPDATE') = 0 then
Self:= prUpdate;
Result:= (Self <> prNone);
end;
function TPrivilegeHelper.ToString: string;
begin
case Self of
prAlter: Result:= 'ALTER';
prAlterRoutine: Result:= 'ALTER ROUTINE';
prCreate: Result:= 'CREATE';
prCreateRole: Result:= 'CREATE ROLE';
prCreateRoutine: Result:= 'CREATE ROUTINE';
prCreateTableSpace: Result:= 'CREATE TABLE SPACE';
prCreateTemporaryTables: Result:= 'CREATE TEMPORARY TABLES';
prCreateUser: Result:= 'CREATE USER';
prCreateView: Result:= 'CREATE VIEW';
prDelete: Result:= 'DELETE';
prDrop: Result:= 'DROP';
prDropRole: Result:= 'DROP ROLE';
prEvent: Result:= 'EVENT';
prExecute: Result:= 'EXECUTE';
prFile: Result:= 'FILE';
prGrant: Result:= 'GRANT';
prIndex: Result:= 'INDEX';
prInsert: Result:= 'INSERT';
prLockTables: Result:= 'LOCK TABLES';
prProcess: Result:= 'PROCESS';
prReferences: Result:= 'REFERENCES';
prReload: Result:= 'RELOAD';
prReplicationClient: Result:= 'REPLICATION CLIENT';
prReplicationSlave: Result:= 'REPLICATION SLAVE';
prSelect: Result:= 'SELECT';
prShowDatabases: Result:= 'SHOW DATABASES';
prShowView: Result:= 'SHOW VIEW';
prShutdown: Result:= 'SHUTDOWN';
prSuper: Result:= 'SUPER';
prTrigger: Result:= 'TRIGGER';
prUpdate: Result:= 'UPDATE';
end;
end;
{ TPrivilegesHelper }
function TPrivilegesHelper.FromGrant(const AGrant: string): Boolean;
var
R: TRegExpr;
S: string;
begin
Result:= FALSE;
R := TRegExpr.Create;
try
R.ModifierI:= True;
R.Expression:= S_REGEX_GRANTS;
if R.Exec(AGrant) then begin
S:= R.Match[1];
if S.Length > 0 then begin
Result:= Self.FromString(S);
end;
end;
finally
FreeAndNil(R);
end;
end;
function TPrivilegesHelper.FromString(const AString: string): Boolean;
var
P: TPrivilege;
S: string;
SL: TStringList;
begin
Result:= FALSE;
if CompareText(AString.Trim, 'ALL PRIVILEGES') = 0 then begin
for P:= Low(TPrivilege) to High(TPrivilege) do begin
Self:= Self + [P] - [prNone];
end;
Result:= TRUE;
end else begin
SL:= Explode(',', AString);
try
for S in SL do begin
if P.FromString(S.Trim) then begin
Self:= Self + [P] - [prNone];
end;
end;
Result:= (SL.Count > 0);
finally
FreeAndNil(SL);
end;
end;
end;
function TPrivilegesHelper.ToString: string;
var
P: TPrivilege;
S: string;
begin
Result:= '';
S:= '';
for P in Self do begin
S:= S + ',' + P.ToString;
end;
Result:= Copy(S, 2, Length(S));
end;
end.