ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/examples/DBAdmin/DataModule.pas
Revision: 291
Committed: Fri Apr 17 10:26:08 2020 UTC (4 years ago) by tony
Content type: text/x-pascal
File size: 50218 byte(s)
Log Message:
Changed for 2.3.4 merged into public release

File Contents

# User Rev Content
1 tony 158 (*
2     * DataModule.pas
3     * Copyright (C) 2018 Tony Whyman <tony@mwasoftware.co.uk>
4     *
5     * DBAdmin is free software: you can redistribute it and/or modify it
6     * under the terms of the GNU General Public License as published by the
7     * Free Software Foundation, either version 3 of the License, or
8     * (at your option) any later version.
9     *
10     * DBAdmin is distributed in the hope that it will be useful, but
11     * WITHOUT ANY WARRANTY; without even the implied warranty of
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13     * See the GNU General Public License for more details.
14     *
15     * You should have received a copy of the GNU General Public License along
16     * with this program. If not, see <http://www.gnu.org/licenses/>.
17     *)
18     unit DataModule;
19    
20     {$mode objfpc}{$H+}
21    
22     interface
23    
24     uses
25     Classes, SysUtils, FileUtil, db, memds, IBDatabase, IBSQL, IBQuery,
26 tony 209 IBCustomDataSet, IBUpdate, IBDatabaseInfo, IBXServices, IB,
27     Dialogs, Controls, Forms;
28 tony 158
29     type
30    
31 tony 272 { TDBDataModule }
32 tony 158
33 tony 272 TDBDataModule = class(TDataModule)
34 tony 158 AccessRightsCHILDCOUNT: TIBLargeIntField;
35     AccessRightsDisplayName: TStringField;
36     AccessRightsID: TIBStringField;
37     AccessRightsImageIndex: TLongintField;
38     AccessRightsPARENT: TIBStringField;
39     AccessRightsSUBJECT_NAME: TIBStringField;
40     AccessRightsSUBJECT_TYPE: TIBSmallintField;
41     ApplicationProperties1: TApplicationProperties;
42     AttachmentsMONATTACHMENT_ID: TIBLargeIntField;
43     AttachmentsMONATTACHMENT_NAME: TIBStringField;
44     AttachmentsMONAUTH_METHOD: TIBStringField;
45     AttachmentsMONCHARACTER_SET_ID: TIBSmallintField;
46     AttachmentsMONCLIENT_VERSION: TIBStringField;
47     AttachmentsMONGARBAGE_COLLECTION: TIBSmallintField;
48     AttachmentsMONREMOTE_ADDRESS: TIBStringField;
49     AttachmentsMONREMOTE_HOST: TIBStringField;
50     AttachmentsMONREMOTE_OS_USER: TIBStringField;
51     AttachmentsMONREMOTE_PID: TIBIntegerField;
52     AttachmentsMONREMOTE_PROCESS: TIBStringField;
53     AttachmentsMONREMOTE_PROTOCOL: TIBStringField;
54     AttachmentsMONREMOTE_VERSION: TIBStringField;
55     AttachmentsMONROLE: TIBStringField;
56     AttachmentsMONSERVER_PID: TIBIntegerField;
57     AttachmentsMONSTATE: TIBSmallintField;
58     AttachmentsMONSTAT_ID: TIBIntegerField;
59     AttachmentsMONSYSTEM_FLAG: TIBSmallintField;
60     AttachmentsMONTIMESTAMP: TDateTimeField;
61     AttachmentsMONUSER: TIBStringField;
62     AttachmentsRDBBYTES_PER_CHARACTER: TIBSmallintField;
63     AttachmentsRDBCHARACTER_SET_ID: TIBSmallintField;
64     AttachmentsRDBCHARACTER_SET_NAME: TIBStringField;
65     AttachmentsRDBDEFAULT_COLLATE_NAME: TIBStringField;
66     AttachmentsRDBDESCRIPTION: TIBMemoField;
67     AttachmentsRDBFORM_OF_USE: TIBStringField;
68     AttachmentsRDBFUNCTION_NAME: TIBStringField;
69     AttachmentsRDBNUMBER_OF_CHARACTERS: TIBIntegerField;
70     AttachmentsRDBOWNER_NAME: TIBStringField;
71     AttachmentsRDBSECURITY_CLASS: TIBStringField;
72     AttachmentsRDBSYSTEM_FLAG: TIBSmallintField;
73     CharSetLookup: TIBQuery;
74 tony 272 ConfigDataset: TMemDataset;
75 tony 158 CurrentTransaction: TIBTransaction;
76     DatabaseQuery: TIBQuery;
77     Attachments: TIBQuery;
78     DBTables: TIBQuery;
79     AuthMappings: TIBQuery;
80     AccessRights: TIBQuery;
81 tony 209 IBConfigService1: TIBXConfigService;
82     IBServerProperties1: TIBXServerProperties;
83     IBLogService1: TIBXLogService;
84     IBSecurityService1: TIBXSecurityService;
85     IBOnlineValidationService1: TIBXOnlineValidationService;
86    
87     IBLimboTrans: TIBXLimboTransactionResolutionService;
88     IBXServicesConnection1: TIBXServicesConnection;
89     IBStatisticalService1: TIBXStatisticalService;
90     IBValidationService1: TIBXValidationService;
91     InLimboList: TIBXServicesLimboTransactionsList;
92     LegacyUserList: TIBXServicesUserList;
93 tony 158 SubjectAccessRights: TIBQuery;
94     AttUpdate: TIBUpdate;
95     AdminUserQuery: TIBSQL;
96     DBTablesUpdate: TIBUpdate;
97     UserListGROUPID: TLongintField;
98 tony 209 UserListSECPASSWORD: TIBStringField;
99     UserListSECUSER_NAME: TIBStringField;
100 tony 158 UserListSource: TDataSource;
101     DBCharSet: TIBQuery;
102     DBSecFiles: TIBQuery;
103     ExecDDL: TIBSQL;
104     IBDatabase1: TIBDatabase;
105     IBDatabaseInfo: TIBDatabaseInfo;
106     AttmtQuery: TIBQuery;
107     RoleNameList: TIBQuery;
108     TableNameLookup: TIBQuery;
109     TagsUpdate: TIBUpdate;
110     UpdateCharSet: TIBUpdate;
111     SecGlobalAuth: TIBQuery;
112     ShadowFiles: TIBQuery;
113     ShadowFilesFileMode: TStringField;
114     ShadowFilesRDBFILE_FLAGS: TSmallintField;
115     ShadowFilesRDBFILE_LENGTH: TIntegerField;
116     ShadowFilesRDBFILE_NAME: TIBStringField;
117     ShadowFilesRDBFILE_SEQUENCE: TSmallintField;
118     ShadowFilesRDBFILE_START: TIntegerField;
119     ShadowFilesRDBSHADOW_NUMBER: TSmallintField;
120     UpdateUserRoles: TIBUpdate;
121     UpdateUsers: TIBUpdate;
122     UserList: TIBQuery;
123     UserListCURRENT_CONNECTION: TIBLargeIntField;
124     UserListDBCREATOR: TBooleanField;
125     UserListLOGGEDIN: TBooleanField;
126     UserListSECACTIVE: TBooleanField;
127     UserListSECADMIN: TBooleanField;
128     UserListSECFIRST_NAME: TIBStringField;
129     UserListSECLAST_NAME: TIBStringField;
130     UserListSECMIDDLE_NAME: TIBStringField;
131     UserListSECPLUGIN: TIBStringField;
132     UserListUSERID: TLongintField;
133     UserTags: TIBQuery;
134     procedure AccessRightsCalcFields(DataSet: TDataSet);
135     procedure ApplicationProperties1Exception(Sender: TObject; E: Exception);
136     procedure AttachmentsAfterDelete(DataSet: TDataSet);
137     procedure AttachmentsAfterOpen(DataSet: TDataSet);
138     procedure AttachmentsBeforeOpen(DataSet: TDataSet);
139 tony 272 procedure ConfigDatasetAfterClose(DataSet: TDataSet);
140 tony 158 procedure CurrentTransactionAfterTransactionEnd(Sender: TObject);
141     procedure DatabaseQueryAfterOpen(DataSet: TDataSet);
142     procedure DatabaseQueryBeforeClose(DataSet: TDataSet);
143     procedure DBCharSetAfterClose(DataSet: TDataSet);
144     procedure DBCharSetBeforeOpen(DataSet: TDataSet);
145     procedure IBDatabase1AfterConnect(Sender: TObject);
146     procedure IBDatabase1AfterDisconnect(Sender: TObject);
147     procedure IBDatabase1BeforeDisconnect(Sender: TObject);
148     procedure IBDatabase1Login(Database: TIBDatabase; LoginParams: TStrings);
149     procedure AttUpdateApplyUpdates(Sender: TObject; UpdateKind: TUpdateKind;
150     Params: ISQLParams);
151     procedure DBTablesUpdateApplyUpdates(Sender: TObject; UpdateKind: TUpdateKind;
152     Params: ISQLParams);
153 tony 209 procedure IBValidationService1GetNextLine(Sender: TObject; var Line: string
154     );
155 tony 272 procedure IBXServicesConnection1AfterConnect(Sender: TObject);
156 tony 209 procedure IBXServicesConnection1Login(Service: TIBXServicesConnection;
157     var aServerName: string; LoginParams: TStrings);
158 tony 158 procedure LegacyUserListAfterOpen(DataSet: TDataSet);
159 tony 210 procedure LegacyUserListAfterPost(DataSet: TDataSet);
160 tony 158 procedure LegacyUserListBeforeClose(DataSet: TDataSet);
161     procedure ShadowFilesCalcFields(DataSet: TDataSet);
162     procedure SubjectAccessRightsBeforeOpen(DataSet: TDataSet);
163     procedure TagsUpdateApplyUpdates(Sender: TObject; UpdateKind: TUpdateKind;
164     Params: ISQLParams);
165     procedure UpdateCharSetApplyUpdates(Sender: TObject;
166     UpdateKind: TUpdateKind; Params: ISQLParams);
167     procedure UpdateUserRolesApplyUpdates(Sender: TObject;
168     UpdateKind: TUpdateKind; Params: ISQLParams);
169     procedure UpdateUsersApplyUpdates(Sender: TObject; UpdateKind: TUpdateKind;
170     Params: ISQLParams);
171     procedure UserListAfterInsert(DataSet: TDataSet);
172     procedure UserListAfterOpen(DataSet: TDataSet);
173     procedure UserListAfterPost(DataSet: TDataSet);
174     procedure UserListAfterScroll(DataSet: TDataSet);
175     procedure UserListBeforeClose(DataSet: TDataSet);
176     procedure UserTagsAfterInsert(DataSet: TDataSet);
177     private
178     FAfterDataReload: TNotifyEvent;
179     FAfterDBConnect: TNotifyEvent;
180     FDBHeaderScanned: boolean;
181     FDisconnecting: boolean;
182     FISShadowDatabase: boolean;
183     FDBUserName: string;
184     FDBPassword: string;
185     FLocalConnect: boolean;
186     FSubjectAccessRightsID: string;
187     {Parsed results of connectstring;}
188     FServerName: string;
189     FPortNo: string;
190     FProtocol: TProtocolAll;
191     FDatabasePathName: string;
192 tony 272 FHasUserAdminPrivilege: boolean;
193 tony 158 function GetAuthMethod: string;
194     function GetAutoAdmin: boolean;
195     function GetDatabaseName: string;
196 tony 273 function GetDBDateCreated: string;
197 tony 158 procedure GetDBFlags;
198     function GetDBOwner: string;
199     function GetDBReadOnly: boolean;
200     function GetDBSQLDialect: integer;
201     function GetDBUserName: string;
202 tony 229 function GetDescription: string;
203 tony 158 function GetForcedWrites: boolean;
204     function GetLingerDelay: string;
205     function GetNoReserve: boolean;
206     function GetPageBuffers: integer;
207     function GetRoleName: string;
208     function GetSecurityDatabase: string;
209 tony 231 function GetServerName: string;
210 tony 158 function GetSweepInterval: integer;
211     function GetUserAdminPrivilege: boolean;
212     procedure SetAutoAdmin(AValue: boolean);
213     procedure SetDBReadOnly(AValue: boolean);
214     procedure SetDBSQLDialect(AValue: integer);
215 tony 229 procedure SetDescription(AValue: string);
216 tony 158 procedure SetForcedWrites(AValue: boolean);
217     procedure SetLingerDelay(AValue: string);
218     procedure SetNoReserve(AValue: boolean);
219     procedure SetPageBuffers(AValue: integer);
220     procedure SetSweepInterval(AValue: integer);
221     procedure ReloadData(Data: PtrInt=0);
222 tony 272 protected
223     FServiceUserName: string;
224     function GetEmbeddedMode: boolean; virtual;
225     procedure ConnectServicesAPI; virtual;
226     function CallLoginDlg(var aDatabaseName, aUserName, aPassword: string;
227     var aCreateIfNotExist: boolean): TModalResult; virtual;
228 tony 158 public
229     destructor Destroy; override;
230 tony 272 function Connect: boolean; virtual;
231     procedure Disconnect; virtual;
232 tony 158 procedure DropDatabase;
233     procedure BackupDatabase;
234     procedure RestoreDatabase;
235     procedure BringDatabaseOnline;
236 tony 209 procedure ShutDown(aShutDownmode: TDBShutdownMode; aDelay: integer);
237 tony 158 procedure DatabaseRepair(Options: TValidateOptions; ReportLines: TStrings);
238     procedure OnlineValidation(ReportLines: TStrings; SelectedTablesOnly: boolean);
239     procedure LimboResolution(ActionID: TTransactionGlobalAction; Report: TStrings);
240     function IsDatabaseOnline: boolean;
241     function IsShadowDatabase: boolean;
242     procedure ActivateShadow;
243     procedure AddSecondaryFile(aFileName: string; StartAt,FileLength: integer);
244     procedure AddShadowSet;
245     procedure RemoveShadowSet(ShadowSet: integer);
246     procedure LoadPerformanceStatistics(Lines: TStrings);
247     procedure LoadDatabaseStatistics(OptionID: integer; Lines: TStrings);
248 tony 272 function LoadConfigData(ConfigFileData: TConfigFileData): boolean;
249 tony 158 procedure LoadServerProperties(Lines: TStrings);
250     procedure LoadServerLog(Lines: TStrings);
251     procedure RevokeAll;
252     procedure SyncSubjectAccessRights(ID: string);
253     property AutoAdmin: boolean read GetAutoAdmin write SetAutoAdmin;
254 tony 229 property Description: string read GetDescription write SetDescription;
255 tony 158 property Disconnecting: boolean read FDisconnecting;
256     property ForcedWrites: boolean read GetForcedWrites write SetForcedWrites;
257     property LingerDelay: string read GetLingerDelay write SetLingerDelay;
258     property DBReadOnly: boolean read GetDBReadOnly write SetDBReadOnly;
259     property NoReserve: boolean read GetNoReserve write SetNoReserve;
260     property PageBuffers: integer read GetPageBuffers write SetPageBuffers;
261     property SweepInterval: integer read GetSweepInterval write SetSweepInterval;
262     property DatabaseName: string read GetDatabaseName;
263     property SecurityDatabase: string read GetSecurityDatabase;
264     property AuthMethod: string read GetAuthMethod;
265     property EmbeddedMode: boolean read GetEmbeddedMode;
266     property DBUserName: string read GetDBUserName;
267     property RoleName: string read GetRoleName;
268     property DBOwner: string read GetDBOwner;
269     property DBSQLDialect: integer read GetDBSQLDialect write SetDBSQLDialect;
270 tony 273 property DBDateCreated: string read GetDBDateCreated;
271 tony 231 property ServerName: string read GetServerName;
272 tony 272 property ServiceUserName: string read FServiceUserName;
273     property HasUserAdminPrivilege: boolean read FHasUserAdminPrivilege;
274 tony 158 property AfterDBConnect: TNotifyEvent read FAfterDBConnect write FAfterDBConnect;
275     property AfterDataReload: TNotifyEvent read FAfterDataReload write FAfterDataReload;
276     end;
277    
278     var
279 tony 272 DBDataModule: TDBDataModule;
280 tony 158
281     implementation
282    
283     {$R *.lfm}
284    
285 tony 291 uses DBLoginDlgUnit, IBUtils, IBMessages, ShutdownDatabaseDlgUnit,
286 tony 158 BackupDlgUnit, RestoreDlgUnit, AddShadowSetDlgUnit, IBErrorCodes;
287    
288     const
289     sAddSecondarySQL = 'Alter Database Add File ''%s'' Starting at %d';
290     sAddSecondarySQL2 = 'Alter Database Add File ''%s'' Starting at %d Length %d';
291     sRemoveShadow = 'Drop Shadow %d';
292     sRemoveShadow12 = 'Drop Shadow %d DELETE FILE';
293     sPreserveShadow = 'Drop Shadow %d PRESERVE FILE';
294    
295     resourcestring
296     sPreserveShadowFiles = 'Preserve Shadow Set Files after drop?';
297    
298 tony 272 { TDBDataModule }
299 tony 158
300 tony 272 procedure TDBDataModule.UpdateCharSetApplyUpdates(Sender: TObject;
301 tony 158 UpdateKind: TUpdateKind; Params: ISQLParams);
302     begin
303     if UpdateKind = ukModify then
304     begin
305     ExecDDL.SQL.Text := 'ALTER DATABASE SET DEFAULT CHARACTER SET ' +
306     Params.ByName('RDB$CHARACTER_SET_NAME').AsString;
307     ExecDDL.ExecQuery;
308     end;
309     end;
310    
311 tony 272 procedure TDBDataModule.UpdateUserRolesApplyUpdates(Sender: TObject;
312 tony 158 UpdateKind: TUpdateKind; Params: ISQLParams);
313    
314     procedure Grant(Params: ISQLParams);
315     begin
316 tony 209 ExecDDL.SQL.Text := 'Grant ' + trim(Params.ByName('RDB$ROLE_NAME').AsString) + ' to ' + Params.ByName('SEC$USER_NAME').AsString;
317 tony 158 ExecDDL.ExecQuery;
318     end;
319    
320     procedure Revoke(Params: ISQLParams);
321     begin
322 tony 209 ExecDDL.SQL.Text := 'Revoke ' + trim(Params.ByName('RDB$ROLE_NAME').AsString) + ' from ' + Params.ByName('SEC$USER_NAME').AsString;
323 tony 158 ExecDDL.ExecQuery;
324     end;
325    
326     begin
327     if UpdateKind = ukModify then
328     begin
329     if Params.ByName('GRANTED').AsInteger = 0 then
330     Revoke(Params)
331     else
332     Grant(Params);
333     end;
334     end;
335    
336 tony 272 procedure TDBDataModule.UpdateUsersApplyUpdates(Sender: TObject;
337 tony 158 UpdateKind: TUpdateKind; Params: ISQLParams);
338    
339 tony 209 var UserName: string;
340    
341 tony 158 function FormatStmtOptions: string;
342     var Param: ISQLParam;
343     begin
344 tony 209 Result := UserName;
345     Param := Params.ByName('SEC$PASSWORD');
346 tony 158 if (Param <> nil) and not Param.IsNull then
347     Result += ' PASSWORD ''' + SQLSafeString(Param.AsString) + '''';
348     Param := Params.ByName('SEC$FIRST_NAME');
349     if Param <> nil then
350     Result += ' FIRSTNAME ''' + SQLSafeString(Param.AsString) + '''';
351     Param := Params.ByName('SEC$MIDDLE_NAME');
352     if Param <> nil then
353     Result += ' MIDDLENAME ''' + SQLSafeString(Param.AsString) + '''';
354     Param := Params.ByName('SEC$LAST_NAME');
355     if Param <> nil then
356     Result += ' LASTNAME ''' + SQLSafeString(Param.AsString) + '''';
357     Param := Params.ByName('SEC$ACTIVE');
358     if Param <> nil then
359     begin
360     if Param.AsBoolean then
361     Result += ' ACTIVE'
362     else
363     Result += ' INACTIVE';
364     end;
365     Param := Params.ByName('SEC$PLUGIN');
366     if Param <> nil then
367     Result += ' USING PLUGIN ' + QuoteIdentifierIfNeeded((Sender as TIBUpdate).DataSet.Database.SQLDialect,Param.AsString);
368     end;
369    
370     function GetAlterPasswordStmt: string;
371     var Param: ISQLParam;
372     begin
373     Result := '';
374 tony 209 Param := Params.ByName('SEC$PASSWORD');
375 tony 158 if (UpdateKind = ukModify) and not Param.IsNull then
376     begin
377 tony 209 Result := 'ALTER USER ' + UserName +
378 tony 158 ' PASSWORD ''' + SQLSafeString(Param.AsString) + '''';
379     Param := Params.ByName('SEC$PLUGIN');
380     if Param <> nil then
381     Result += ' USING PLUGIN ' + QuoteIdentifierIfNeeded((Sender as TIBUpdate).DataSet.Database.SQLDialect,Param.AsString);
382     end;
383     end;
384    
385     begin
386 tony 209 UserName := Trim(Params.ByName('SEC$USER_NAME').AsString);
387     {non SYSDBA user not an RDB$ADMIN can only change their password}
388     if (DBUserName <> 'SYSDBA') and (RoleName <> 'RDB$ADMIN') then
389     begin
390     ExecDDL.SQL.Text := GetAlterPasswordStmt;
391     if ExecDDL.SQL.Text <> '' then
392     ExecDDL.ExecQuery;
393     Exit;
394     end;
395 tony 158
396 tony 209 case UpdateKind of
397     ukInsert:
398     ExecDDL.SQL.Text := 'CREATE USER ' + FormatStmtOptions;
399     ukModify:
400     ExecDDL.SQL.Text := 'ALTER USER ' + FormatStmtOptions;
401     ukDelete:
402     ExecDDL.SQL.Text := 'DROP USER ' + UserName;
403     end;
404     ExecDDL.ExecQuery;
405 tony 158
406     if UpdateKind = ukInsert then
407     begin
408     {if new user is also given the admin role then we need to add this}
409     if Params.ByName('SEC$ADMIN').AsBoolean then
410     begin
411 tony 209 ExecDDL.SQL.Text := 'ALTER USER ' + UserName + ' GRANT ADMIN ROLE';
412 tony 158 ExecDDL.ExecQuery;
413     end;
414     end
415     else
416     if UpdateKind = ukModify then
417     {Update Admin Role if allowed}
418     begin
419     if Params.ByName('SEC$ADMIN').AsBoolean and not Params.ByName('OLD_SEC$ADMIN').AsBoolean then
420     begin
421 tony 209 ExecDDL.SQL.Text := 'ALTER USER ' + UserName + ' GRANT ADMIN ROLE';
422 tony 158 ExecDDL.ExecQuery;
423     end
424     else
425     if not Params.ByName('SEC$ADMIN').AsBoolean and Params.ByName('OLD_SEC$ADMIN').AsBoolean then
426     begin
427 tony 209 ExecDDL.SQL.Text := 'ALTER USER ' + UserName + ' REVOKE ADMIN ROLE';
428 tony 158 ExecDDL.ExecQuery;
429     end
430     end;
431    
432     {Update DB Creator Role}
433     if Params.ByName('DBCreator').AsBoolean and not Params.ByName('OLD_DBCreator').AsBoolean then
434     begin
435 tony 209 ExecDDL.SQL.Text := 'GRANT CREATE DATABASE TO USER ' + UserName;
436 tony 158 ExecDDL.ExecQuery;
437     end
438     else
439     if not Params.ByName('DBCreator').AsBoolean and Params.ByName('OLD_DBCreator').AsBoolean then
440     begin
441 tony 209 ExecDDL.SQL.Text := 'REVOKE CREATE DATABASE FROM USER ' + UserName;
442 tony 158 ExecDDL.ExecQuery;
443     end
444     end;
445    
446 tony 272 procedure TDBDataModule.UserListAfterInsert(DataSet: TDataSet);
447 tony 158 begin
448     DataSet.FieldByName('SEC$ADMIN').AsBoolean := false;
449     DataSet.FieldByName('SEC$ACTIVE').AsBoolean := false;
450     DataSet.FieldByName('DBCreator').AsBoolean := false;
451     DataSet.FieldByName('SEC$PLUGIN').AsString := 'Srp';
452     DataSet.FieldByName('UserID').AsInteger := 0;
453     DataSet.FieldByName('GroupID').AsInteger := 0;
454 tony 209 DataSet.FieldByName('SEC$PASSWORD').Clear;
455 tony 158 RoleNameList.Active := false; {Prevent role assignments until saved}
456     UserTags.Active := false; {ditto}
457     end;
458    
459 tony 272 procedure TDBDataModule.UserListAfterOpen(DataSet: TDataSet);
460 tony 158 begin
461     UserListSource.DataSet := UserList;
462     RoleNameList.Active := true;
463     UserTags.Active := true;
464     end;
465    
466 tony 272 procedure TDBDataModule.UserListAfterPost(DataSet: TDataSet);
467 tony 158 begin
468     CurrentTransaction.Commit;
469     end;
470    
471 tony 272 procedure TDBDataModule.UserListAfterScroll(DataSet: TDataSet);
472 tony 158 begin
473     UserList.FieldByName('SEC$PLUGIN').ReadOnly := UserList.State <> dsInsert;
474     end;
475    
476 tony 272 procedure TDBDataModule.UserListBeforeClose(DataSet: TDataSet);
477 tony 158 begin
478     RoleNameList.Active := false;
479     UserTags.Active := false;
480     end;
481    
482 tony 272 procedure TDBDataModule.UserTagsAfterInsert(DataSet: TDataSet);
483 tony 158 begin
484 tony 209 DataSet.FieldByName('SEC$USER_NAME').AsString := DataSet.DataSource.DataSet.FieldByName('SEC$USER_NAME').AsString;
485 tony 158 end;
486    
487 tony 272 procedure TDBDataModule.ConnectServicesAPI;
488 tony 209 begin
489     if IBXServicesConnection1.Connected then Exit;
490     try
491     IBXServicesConnection1.ConnectUsing(IBDatabase1);
492     except on E: Exception do
493     begin
494     Application.ShowException(E);
495     IBDatabase1.Connected := false;
496     FDBPassword := '';
497     Exit;
498     end;
499     end;
500     end;
501    
502 tony 272 function TDBDataModule.CallLoginDlg(var aDatabaseName, aUserName,
503     aPassword: string; var aCreateIfNotExist: boolean): TModalResult;
504     begin
505     Result := DBLoginDlg.ShowModal(aDatabaseName, aUserName, aPassword, aCreateIfNotExist);
506     end;
507    
508     procedure TDBDataModule.GetDBFlags;
509 tony 209 var Lines: TStringList;
510     i: integer;
511     line: string;
512 tony 158 begin
513     if FDBHeaderScanned or not DatabaseQuery.Active or not AttmtQuery.Active then Exit;
514     FIsShadowDatabase := false;
515    
516     try
517     with IBStatisticalService1 do
518     begin
519     Options := [HeaderPages];
520 tony 209 Lines := TStringList.Create;
521     try
522     Execute(Lines);
523     for i := 0 to Lines.Count - 1 do
524     begin
525     line := Lines[i];
526     if (Pos('Attributes',Line) <> 0) and (Pos('shadow',Line) <> 0) then
527     begin
528     FIsShadowDatabase := true;
529     break;
530     end;
531     end;
532     finally
533     Lines.Free;
534     end;
535     FDBHeaderScanned := true;
536 tony 158 end;
537     except on E: Exception do
538     MessageDlg('Error getting DB Header Page: ' + E.Message,mtError,[mbOK],0);
539     end;
540     end;
541    
542 tony 272 function TDBDataModule.GetDBOwner: string;
543 tony 158 var DBOField: TField;
544     begin
545     DBOField := DatabaseQuery.FindField('MON$OWNER');
546     if DBOField <> nil then
547     Result := Trim(DBOField.AsString)
548     else
549     Result := 'n/a';
550     end;
551    
552 tony 272 function TDBDataModule.GetAutoAdmin: boolean;
553 tony 158 begin
554     Result := false;
555     if not CurrentTransaction.Active then Exit;
556     SecGlobalAuth.Active := true; {sets AutoAdmin}
557     try
558     Result := SecGlobalAuth.FieldByName('Mappings').AsInteger > 0;
559     finally
560     SecGlobalAuth.Active := false;
561     end;
562     end;
563    
564 tony 272 function TDBDataModule.GetDatabaseName: string;
565 tony 158 begin
566     if DatabaseQuery.Active and not DatabaseQuery.FieldByName('MON$DATABASE_NAME').IsNull then
567     Result := DatabaseQuery.FieldByName('MON$DATABASE_NAME').AsString
568     else
569     Result := FDatabasePathName;
570     end;
571    
572 tony 273 function TDBDataModule.GetDBDateCreated: string;
573     begin
574     with DefaultFormatSettings do
575     try
576     Result := FormatDateTime(LongDateFormat + ' ' + LongTimeFormat,DatabaseQuery.FieldByName('MON$CREATION_DATE').AsDateTime);
577     except
578     Result := 'unknown';
579     end;
580     end;
581    
582 tony 272 function TDBDataModule.GetDBReadOnly: boolean;
583 tony 158 begin
584     Result := DatabaseQuery.Active and (DatabaseQuery.FieldByName('MON$READ_ONLY').AsInteger <> 0);
585     end;
586    
587 tony 272 function TDBDataModule.GetDBSQLDialect: integer;
588 tony 158 begin
589     Result := IBDatabaseInfo.DBSQLDialect;
590     end;
591    
592 tony 272 function TDBDataModule.GetDBUserName: string;
593     var DPB: IDPB;
594     info: IDPBItem;
595 tony 158 begin
596 tony 272 Result := '';
597     if AttmtQuery.Active then
598     Result := Trim(AttmtQuery.FieldByName('MON$USER').AsString)
599     else
600     if IBDatabase1.Connected then
601     begin
602     DPB := IBDatabase1.Attachment.getDPB;
603     info := DPB.Find(isc_dpb_user_name);
604     if info <> nil then
605     Result := info.AsString;
606     end
607 tony 158 end;
608    
609 tony 272 function TDBDataModule.GetDescription: string;
610 tony 229 begin
611 tony 272 if DatabaseQuery.Active then
612     Result := DatabaseQuery.FieldByName('RDB$DESCRIPTION').AsString
613     else
614     Result := '';
615 tony 229 end;
616    
617 tony 272 function TDBDataModule.GetEmbeddedMode: boolean;
618 tony 158 begin
619 tony 272 Result := AttmtQuery.Active and AttmtQuery.FieldByName('MON$REMOTE_PROTOCOL').IsNull;
620 tony 158 end;
621    
622 tony 272 function TDBDataModule.GetForcedWrites: boolean;
623 tony 158 begin
624     Result := DatabaseQuery.Active and (DatabaseQuery.FieldByName('MON$FORCED_WRITES').AsInteger <> 0);
625     end;
626    
627 tony 272 procedure TDBDataModule.SetLingerDelay(AValue: string);
628 tony 158 begin
629     if (StrToInt(AValue) = DatabaseQuery.FieldByName('RDB$LINGER').AsInteger) then Exit;
630    
631     if (AValue = '') or (StrToInt(AValue) = 0) then
632     begin
633     if MessageDlg('Turn off Linger Permanently?',mtConfirmation,[mbYes,mbNo],0) = mrNo then
634     begin
635     IBConfigService1.SetNoLinger;
636     CurrentTransaction.Commit; {Refresh}
637     Exit;
638     end;
639     ExecDDL.SQL.Text := 'ALTER DATABASE DROP LINGER'
640     end
641     else
642     ExecDDL.SQL.Text := 'ALTER DATABASE SET LINGER TO ' + AValue;
643     with ExecDDL do
644     begin
645     Transaction.Active := true;
646     ExecQuery;
647     Transaction.Commit;
648     end;
649     end;
650    
651    
652 tony 272 function TDBDataModule.GetAuthMethod: string;
653 tony 158 var AuthMeth: TField;
654     begin
655     AuthMeth := AttmtQuery.FindField('MON$AUTH_METHOD');
656     if AuthMeth = nil then
657     Result := 'Legacy_auth'
658     else
659     Result := AuthMeth.AsString;
660     end;
661    
662 tony 272 procedure TDBDataModule.SetNoReserve(AValue: boolean);
663 tony 158 begin
664     IBConfigService1.SetReserveSpace(AValue);
665     end;
666    
667 tony 272 procedure TDBDataModule.SetPageBuffers(AValue: integer);
668 tony 158 begin
669     IBDatabase1.Connected := false;
670     try
671     IBConfigService1.SetPageBuffers(AValue);
672     finally
673     IBDatabase1.Connected := true;
674     end;
675     end;
676    
677 tony 272 procedure TDBDataModule.SetSweepInterval(AValue: integer);
678 tony 158 begin
679     IBDatabase1.Connected := false;
680     try
681     IBConfigService1.SetSweepInterval(AValue);
682     finally
683     IBDatabase1.Connected := true;
684     end;
685     end;
686    
687 tony 272 procedure TDBDataModule.ReloadData(Data: PtrInt);
688 tony 158 begin
689     if csDestroying in ComponentState then Exit;
690     CurrentTransaction.Active := true;
691     DataBaseQuery.Active := true;
692     AttmtQuery.Active := true;
693 tony 209 if LegacyUserList.Active then
694     RoleNameList.Active := true;
695 tony 158 if assigned(FAfterDataReload) then
696     AfterDataReload(self);
697     end;
698    
699 tony 272 destructor TDBDataModule.Destroy;
700 tony 158 begin
701     Application.RemoveAsyncCalls(self);
702     inherited Destroy;
703     end;
704    
705 tony 272 function TDBDataModule.Connect: boolean;
706 tony 158
707     procedure ReportException(E: Exception);
708     begin
709     MessageDlg(E.Message,mtError,[mbOK],0);
710     FDBPassword := '';
711     end;
712    
713     procedure KillShadows;
714     begin
715 tony 211 with IBXServicesConnection1 do
716 tony 158 begin
717 tony 211 ServerName := FServerName;
718     Protocol := FProtocol;
719     PortNo := FPortNo;
720     Connected := true;
721 tony 158 end;
722 tony 211 try
723     with IBValidationService1 do
724     begin
725     DatabaseName := FDatabasePathName;
726     Options := [IBXServices.KillShadows];
727     Execute(nil);
728     MessageDlg('All Unavailable Shadows killed',mtInformation,[mbOK],0);
729     end;
730     finally
731     IBXServicesConnection1.Connected := false;
732     end;
733 tony 158 end;
734    
735 tony 232 var KillDone: boolean;
736 tony 158 begin
737 tony 232 KillDone := false;
738 tony 272 Result := false;
739 tony 158 Disconnect;
740     repeat
741     try
742     IBDatabase1.Connected := true;
743     except
744     on E:EIBClientError do
745     begin
746     Exit
747     end;
748     On E: EIBInterBaseError do
749     begin
750 tony 232 FDBPassword := '';
751     if (E.IBErrorCode = isc_io_error) and not KillDone then
752 tony 158 begin
753     if MessageDlg('I/O Error reported on database file. If this is a shadow file, do you want '+
754     'to kill all unavailable shadow sets?. The original message is ' + E.Message,
755 tony 211 mtInformation,[mbYes,mbNo],0) = mrNo then
756 tony 212 continue;
757 tony 211 try KillShadows except end;
758 tony 232 KillDone := true;
759 tony 158 end
760     else
761     ReportException(E);
762     end;
763     On E:Exception do
764     ReportException(E);
765     end;
766     until IBDatabase1.Connected;
767    
768     if assigned(FAfterDBConnect) then
769     AfterDBConnect(self);
770 tony 272 Result := IBDatabase1.Connected;
771 tony 158 end;
772    
773 tony 272 procedure TDBDataModule.Disconnect;
774 tony 158 begin
775     FDBUserName := '';
776     FDBPassword := '';
777 tony 272 FServiceUserName := '';
778 tony 158 FLocalConnect := false;
779     IBDatabase1.Connected := false;
780 tony 209 IBXServicesConnection1.Connected := false;
781     FDBHeaderScanned := false;
782 tony 158 end;
783    
784 tony 272 procedure TDBDataModule.DropDatabase;
785 tony 158 begin
786     IBDatabase1.DropDatabase;
787     Disconnect;
788     end;
789    
790 tony 272 procedure TDBDataModule.BackupDatabase;
791 tony 158 begin
792 tony 209 BackupDlg.ShowModal;
793 tony 158 end;
794    
795 tony 272 procedure TDBDataModule.RestoreDatabase;
796 tony 158 var DefaultPageSize: integer;
797     DefaultNumBuffers: integer;
798     begin
799     DefaultPageSize := DatabaseQuery.FieldByName('MON$PAGE_SIZE').AsInteger;
800     DefaultNumBuffers := DatabaseQuery.FieldByName('MON$PAGE_BUFFERS').AsInteger;
801     IBDatabase1.Connected := false;
802     try
803     RestoreDlg.ShowModal(DefaultPageSize,DefaultNumBuffers);
804     finally
805     IBDatabase1.Connected := true;
806     end;
807     end;
808    
809 tony 272 procedure TDBDataModule.BringDatabaseOnline;
810 tony 158 begin
811     if IsDatabaseOnline then
812     MessageDlg('Database is already online!',mtInformation,[mbOK],0)
813     else
814     begin
815     IBDatabase1.Connected := false;
816     try
817     IBConfigService1.BringDatabaseOnline;
818     finally
819     IBDatabase1.Connected := true;
820     end;
821     if IsDatabaseOnline then
822     MessageDlg('Database is back online',mtInformation,[mbOK],0)
823     else
824     MessageDlg('Database is still shutdown!',mtError,[mbOK],0);
825     end;
826     end;
827    
828 tony 272 procedure TDBDataModule.ShutDown(aShutDownmode: TDBShutdownMode; aDelay: integer
829 tony 209 );
830 tony 158 begin
831     IBDatabase1.Connected := false;
832     try
833 tony 218 ShutdownDatabaseDlg.Shutdown(aShutDownmode, aDelay);
834 tony 158 finally
835     IBDatabase1.Connected := true;
836     end;
837     end;
838    
839 tony 272 procedure TDBDataModule.DatabaseRepair(Options: TValidateOptions; ReportLines: TStrings);
840 tony 158
841     procedure ReportOptions;
842     var Line: string;
843     begin
844     Line := 'With Options: [';
845     if (ValidateDB in Options) then Line += 'ValidateDB ';
846     if (SweepDB in Options) then Line += 'SweepDB ';
847     if (KillShadows in Options) then Line += 'KillShadows ';
848     if (ValidateFull in Options) then Line += 'ValidateFull ';
849     if (CheckDB in Options) then Line += 'CheckDB ';
850     if (IgnoreChecksum in Options) then Line +='IgnoreChecksum ';
851     if (MendDB in Options) then Line +='MendDB ';
852     Line +=']';
853     ReportLines.Add(Line);
854     end;
855    
856     begin
857     ReportLines.Add(Format('Validation of %s started',[IBValidationService1.DatabaseName]));
858     ReportOptions;
859     IBDatabase1.Connected := false;
860     with IBValidationService1 do
861     try
862 tony 209 Execute(ReportLines);
863 tony 158 ReportLines.Add('Operation Completed');
864     MessageDlg('Operation Completed',mtInformation,[mbOK],0);
865     finally
866     IBDatabase1.Connected := true;
867     end;
868     end;
869    
870 tony 272 procedure TDBDataModule.OnlineValidation(ReportLines: TStrings;
871 tony 158 SelectedTablesOnly: boolean);
872     var TableNames: string;
873     Separator: string;
874     begin
875     if IBDatabaseInfo.ODSMajorVersion < 12 then
876     raise Exception.Create('Online Validation is not supported');
877     with IBOnlineValidationService1 do
878     begin
879     if SelectedTablesOnly then
880     begin
881     TableNames := '';
882     with DBTables do
883     if Active then
884     begin
885     DisableControls;
886     try
887     Separator := '';
888     First;
889     while not EOF do
890     begin
891     if FieldByName('Selected').AsInteger <> 0 then
892     begin
893     TableNames += Separator + FieldByName('RDB$RELATION_NAME').AsString;
894     Separator := '|';
895     end;
896     Next;
897     end;
898     finally
899     EnableControls;
900     end;
901     end;
902     IncludeTables := TableNames;
903     end
904     else
905     IncludeTables := '';
906     ReportLines.Add(Format('Online Validation of %s started',[IBOnlineValidationService1.DatabaseName]));
907 tony 209 Execute(ReportLines);
908 tony 158 ReportLines.Add('Online Validation Completed');
909     MessageDlg('Online Validation Completed',mtInformation,[mbOK],0);
910     end;
911     end;
912    
913 tony 272 procedure TDBDataModule.LimboResolution(ActionID: TTransactionGlobalAction;
914 tony 158 Report: TStrings);
915     begin
916     if not InLimboList.Active then
917     raise Exception.Create('Limbo Transactions List not available');
918    
919     with InLimboList do
920     if State = dsEdit then Post;
921     Report.Clear;
922 tony 209 Report.Add('Starting Limbo transaction resolution');
923     InLimboList.FixErrors(ActionID,Report);
924     Report.Add('Limbo Transaction resolution complete');
925     CurrentTransaction.Commit;
926 tony 158 end;
927    
928 tony 272 function TDBDataModule.GetLingerDelay: string;
929 tony 158 var Linger: TField;
930     begin
931     Result := 'n/a';
932     if not DatabaseQuery.Active then exit;
933     Linger := DatabaseQuery.FindField('RDB$LINGER');
934     if Linger <> nil then
935     begin
936     if Linger.IsNull then
937     Result := '0'
938     else
939     Result := Linger.AsString;
940     end;
941     end;
942    
943 tony 272 function TDBDataModule.GetNoReserve: boolean;
944 tony 158 begin
945     Result := DatabaseQuery.Active and (DatabaseQuery.FieldByName('MON$RESERVE_SPACE').AsInteger <> 0);
946     end;
947    
948 tony 272 function TDBDataModule.GetPageBuffers: integer;
949 tony 158 begin
950     Result := IBDatabaseInfo.NumBuffers;
951     end;
952    
953 tony 272 function TDBDataModule.GetRoleName: string;
954 tony 158 begin
955     Result := Trim(AttmtQuery.FieldByName('MON$ROLE').AsString);
956     end;
957    
958 tony 272 function TDBDataModule.GetSecurityDatabase: string;
959 tony 158 var SecPlugin: TField;
960     begin
961     SecPlugin := DatabaseQuery.FindField('MON$SEC_DATABASE');
962     if SecPlugin = nil then
963     Result := 'Legacy'
964     else
965     Result := Trim(SecPlugin.AsString);
966     end;
967    
968 tony 272 function TDBDataModule.GetServerName: string;
969 tony 231 begin
970     Result := IBXServicesConnection1.ServerName;
971     end;
972    
973 tony 272 function TDBDataModule.GetSweepInterval: integer;
974 tony 158 begin
975     if DatabaseQuery.Active then
976     Result := DatabaseQuery.FieldByName('MON$SWEEP_INTERVAL').AsInteger
977     else
978     Result := 0;
979     end;
980    
981 tony 272 function TDBDataModule.GetUserAdminPrivilege: boolean;
982 tony 158 begin
983     Result := false;
984     {For ODS 12 use SEC$USERS table}
985 tony 272 if IBDatabase1.Connected and (IBDatabaseInfo.ODSMajorVersion >= 12) then
986 tony 158 with AdminUserQuery do
987     begin
988     ExecQuery;
989     try
990     Result := not EOF and FieldByName('SEC$ADMIN').AsBoolean;
991     finally
992     Close;
993     end;
994     end
995     {if need to know for ODS 11.2 then will have to use Service API}
996     else
997     begin
998     with IBSecurityService1 do
999     begin
1000 tony 272 DisplayUser(ServiceUserName);
1001 tony 158 Result := (UserInfoCount > 0) and UserInfo[0].AdminRole;
1002     end;
1003     end;
1004     end;
1005    
1006 tony 272 procedure TDBDataModule.SetAutoAdmin(AValue: boolean);
1007 tony 158 begin
1008 tony 209 IBSecurityService1.SetAutoAdmin(AValue);
1009 tony 158 CurrentTransaction.Commit;
1010     end;
1011    
1012 tony 272 procedure TDBDataModule.SetDBReadOnly(AValue: boolean);
1013 tony 158 begin
1014     IBDatabase1.Connected := false;
1015     try
1016     IBConfigService1.SetReadOnly(AValue);
1017     finally
1018     IBDatabase1.Connected := true;
1019     end;
1020     end;
1021    
1022 tony 272 procedure TDBDataModule.SetDBSQLDialect(AValue: integer);
1023 tony 158 begin
1024     IBDatabase1.Connected := false;
1025     try
1026     IBConfigService1.SetDBSqlDialect(AValue);
1027     finally
1028     IBDatabase1.Connected := true;
1029     end;
1030     end;
1031    
1032 tony 272 procedure TDBDataModule.SetDescription(AValue: string);
1033 tony 229 begin
1034     with TIBSQL.Create(IBDatabase1) do
1035     try
1036     SQL.Text := 'Comment on Database is ''' + SQLSafeString(AValue) + '''';
1037     Transaction.Active := true;
1038     ExecQuery;
1039     finally
1040     Free;
1041     end;
1042     CurrentTransaction.Commit;
1043     end;
1044    
1045 tony 272 procedure TDBDataModule.SetForcedWrites(AValue: boolean);
1046 tony 158 begin
1047     IBConfigService1.SetAsyncMode(not AValue);
1048     end;
1049    
1050 tony 272 function TDBDataModule.IsDatabaseOnline: boolean;
1051 tony 158 begin
1052     Result := DatabaseQuery.Active and (DatabaseQuery.FieldByName('MON$SHUTDOWN_MODE').AsInteger = 0);
1053     end;
1054    
1055 tony 272 function TDBDataModule.IsShadowDatabase: boolean;
1056 tony 158 begin
1057     GetDBFlags;
1058     Result := FIsShadowDatabase;
1059     end;
1060    
1061 tony 272 procedure TDBDataModule.ActivateShadow;
1062 tony 158 begin
1063     IBConfigService1.ActivateShadow;
1064     MessageDlg('Shadow Database activated. You should now rename the file or change the database alias name to point to the shadow',
1065     mtInformation,[mbOK],0);
1066     end;
1067    
1068 tony 272 procedure TDBDataModule.AddSecondaryFile(aFileName: string; StartAt,
1069 tony 158 FileLength: integer);
1070     var SQLText: string;
1071     begin
1072     if FileLength <> -1 then
1073     SQLText := Format(sAddSecondarySQL2,[aFileName,StartAt,FileLength])
1074     else
1075     SQLText := Format(sAddSecondarySQL,[aFileName,StartAt]);
1076     ExecDDL.SQL.Text := SQLText;
1077     ExecDDL.ExecQuery;
1078     CurrentTransaction.Commit;
1079     end;
1080    
1081 tony 272 procedure TDBDataModule.AddShadowSet;
1082 tony 158 var CurrentLocation: TBookmark;
1083     ShadowSet: integer;
1084     begin
1085     if ShadowFiles.RecordCount = 0 then
1086     ShadowSet := 1
1087     else
1088     with ShadowFiles do
1089     begin
1090     CurrentLocation := Bookmark;
1091     DisableControls;
1092     try
1093     Last;
1094     ShadowSet := FieldByName('RDB$Shadow_Number').AsInteger + 1;
1095     finally
1096     Bookmark := CurrentLocation;
1097     EnableControls
1098     end
1099     end;
1100     AddShadowSetDlg.ShowModal(ShadowSet);
1101     CurrentTransaction.Active := true;
1102     end;
1103    
1104 tony 272 procedure TDBDataModule.RemoveShadowSet(ShadowSet: integer);
1105 tony 158 begin
1106     if IBDatabaseInfo.ODSMajorVersion < 12 then
1107     begin
1108     if MessageDlg(Format(sRemoveShadow,[ShadowSet]),mtConfirmation,[mbYes,mbNo],0) = mrYes then
1109     ExecDDL.SQL.Text := Format(sRemoveShadow,[ShadowSet]);
1110     end
1111     else
1112     case MessageDlg(Format(sPreserveShadowFiles,[ShadowSet]),mtConfirmation,[mbYes,mbNo,mbCancel],0) of
1113     mrNo:
1114     ExecDDL.SQL.Text :=Format(sRemoveShadow12,[ShadowSet]);
1115     mrYes:
1116     ExecDDL.SQL.Text := Format(sPreserveShadow,[ShadowSet]);
1117     mrCancel:
1118     Exit;
1119     end;
1120     ExecDDL.ExecQuery;
1121     CurrentTransaction.Commit;
1122     end;
1123    
1124 tony 272 procedure TDBDataModule.LoadPerformanceStatistics(Lines: TStrings);
1125 tony 158
1126     procedure AddPerfStats(Heading: string; stats: TStrings);
1127     var i: integer;
1128     begin
1129     with Lines do
1130     begin
1131     if stats.count = 0 then exit;
1132     Add('');
1133     Add(Heading);
1134     for i := 0 to stats.Count - 1 do
1135     begin
1136     if TableNameLookup.Locate('RDB$RELATION_ID',stats.Names[i],[]) then
1137     Add(' ' + TableNameLookup.FieldByName('RDB$RELATION_NAME').AsString + ' = ' + stats.ValueFromIndex[i]);
1138     end;
1139     end;
1140     end;
1141    
1142     begin
1143     TableNameLookup.Active := true;
1144     with IBDatabaseInfo, Lines do
1145     begin
1146     Add(Format('Number of reads from the memory buffer cache = %d',[Fetches]));
1147     Add(Format('Number of writes to the memory buffer cache = %d',[Marks]));
1148     Add(Format('Number of page reads = %d',[Reads]));
1149     Add(Format('Number of page writes = %d',[Writes]));
1150     Add('');
1151     Add('Since Database last attached:');
1152     AddPerfStats('Number of removals of a version of a record',BackoutCount);
1153     AddPerfStats('Number of database deletes',DeleteCount);
1154     AddPerfStats('Number of removals of a committed record',ExpungeCount);
1155     AddPerfStats('Number of inserts',InsertCount);
1156     AddPerfStats('Number of removals of old versions of fully mature records',PurgeCount);
1157     AddPerfStats('Number of reads done via an index',ReadIdxCount);
1158     AddPerfStats('Number of sequential table scans',ReadSeqCount);
1159     AddPerfStats('Number of database updates',UpdateCount);
1160     end;
1161     end;
1162    
1163 tony 272 procedure TDBDataModule.LoadDatabaseStatistics(OptionID: integer; Lines: TStrings);
1164 tony 158 begin
1165     if OptionID = 1 then
1166     LoadPerformanceStatistics(Lines)
1167     else
1168     with IBStatisticalService1 do
1169     begin
1170     case OptionID of
1171     0: Options := [HeaderPages];
1172     2: options := [DataPages];
1173     3: Options := [IndexPages];
1174     4: Options := [SystemRelations]
1175     end;
1176 tony 209 Execute(Lines);
1177 tony 158 end;
1178     end;
1179    
1180 tony 272 function TDBDataModule.LoadConfigData(ConfigFileData: TConfigFileData): boolean;
1181 tony 158 var i: integer;
1182 tony 272 aValue: integer;
1183 tony 158 begin
1184 tony 272 ConfigDataset.Active := true;
1185     ConfigDataset.Clear(false);
1186     for i := 0 to Length(ConfigFileData.ConfigFileKey) - 1 do
1187     begin
1188     aValue := ConfigFileData.ConfigFileValue[i] ;
1189     with ConfigDataset do
1190     case ConfigFileData.ConfigFileKey[i] of
1191     ISCCFG_LOCKMEM_KEY:
1192     AppendRecord(['Lock mem', aValue]);
1193     ISCCFG_LOCKSEM_KEY:
1194     AppendRecord(['Lock Semaphores', aValue]);
1195     ISCCFG_LOCKSIG_KEY:
1196     AppendRecord(['Lock sig', aValue]);
1197     ISCCFG_EVNTMEM_KEY:
1198     AppendRecord(['Event mem', aValue]);
1199     ISCCFG_PRIORITY_KEY:
1200     AppendRecord(['Priority', aValue]);
1201     ISCCFG_MEMMIN_KEY:
1202     AppendRecord(['Min memory', aValue]);
1203     ISCCFG_MEMMAX_KEY:
1204     AppendRecord(['Max Memory', aValue]);
1205     ISCCFG_LOCKORDER_KEY:
1206     AppendRecord(['Lock order', aValue]);
1207     ISCCFG_ANYLOCKMEM_KEY:
1208     AppendRecord(['Any lock mem', aValue]);
1209     ISCCFG_ANYLOCKSEM_KEY:
1210     AppendRecord(['Any lock semaphore',aValue]);
1211     ISCCFG_ANYLOCKSIG_KEY:
1212     AppendRecord(['any lock sig', aValue]);
1213     ISCCFG_ANYEVNTMEM_KEY:
1214     AppendRecord(['any event mem', aValue]);
1215     ISCCFG_LOCKHASH_KEY:
1216     AppendRecord(['Lock hash', aValue]);
1217     ISCCFG_DEADLOCK_KEY:
1218     AppendRecord(['Deadlock', aValue]);
1219     ISCCFG_LOCKSPIN_KEY:
1220     AppendRecord(['Lock spin', aValue]);
1221     ISCCFG_CONN_TIMEOUT_KEY:
1222     AppendRecord(['Conn timeout', aValue]);
1223     ISCCFG_DUMMY_INTRVL_KEY:
1224     AppendRecord(['Dummy interval', aValue]);
1225     ISCCFG_IPCMAP_KEY:
1226     AppendRecord(['Map size', aValue]);
1227     ISCCFG_DBCACHE_KEY:
1228     AppendRecord(['Cache size', aValue]);
1229     end;
1230     end;
1231     Result := ConfigDataset.Active and (ConfigDataset.RecordCount > 0);
1232     end;
1233    
1234     procedure TDBDataModule.LoadServerProperties(Lines: TStrings);
1235     var i: integer;
1236     begin
1237 tony 158 Lines.Clear;
1238     with IBServerProperties1 do
1239     begin
1240     Lines.Add('Server Version = ' + VersionInfo.ServerVersion);
1241     Lines.Add('Server Implementation = ' + VersionInfo.ServerImplementation);
1242     Lines.Add('Service Version = ' + IntToStr(VersionInfo.ServiceVersion));
1243 tony 209 with ServicesConnection do
1244 tony 158 Lines.Add(Format('Firebird Release = %d.%d.%d (Build no. %d)',[ServerVersionNo[1],
1245     ServerVersionNo[2],
1246     ServerVersionNo[3],
1247     ServerVersionNo[4]]));
1248     Lines.Add('No. of attachments = ' + IntToStr(DatabaseInfo.NoOfAttachments));
1249     Lines.Add('No. of databases = ' + IntToStr(DatabaseInfo.NoOfDatabases));
1250 tony 272 for i := 0 to length(DatabaseInfo.DbName) - 1 do
1251 tony 158 Lines.Add(Format('DB Name (%d) = %s',[i+1, DatabaseInfo.DbName[i]]));
1252     Lines.Add('Base Location = ' + ConfigParams.BaseLocation);
1253     Lines.Add('Lock File Location = ' + ConfigParams.LockFileLocation);
1254     Lines.Add('Security Database Location = ' + ConfigParams.SecurityDatabaseLocation);
1255     Lines.Add('Message File Location = ' + ConfigParams.MessageFileLocation);
1256     end;
1257     end;
1258    
1259 tony 272 procedure TDBDataModule.LoadServerLog(Lines: TStrings);
1260 tony 158 begin
1261     Lines.Clear;
1262 tony 209 if IBLogService1.ServicesConnection.ServiceIntf.getProtocol = Local then
1263 tony 158 Lines.Add('Server Log not available with embedded server')
1264     else
1265 tony 209 IBLogService1.Execute(Lines);
1266 tony 158 end;
1267    
1268 tony 272 procedure TDBDataModule.RevokeAll;
1269 tony 158 begin
1270     with SubjectAccessRights do
1271     if Active then
1272     begin
1273     DisableControls;
1274     try
1275     First;
1276     while not EOF do
1277     begin
1278     if FieldByName('OBJECT_TYPE').AsInteger = 0 {relation} then
1279     ExecDDL.SQL.Text := Format('Revoke All on %s from %s',[
1280     Trim(FieldByName('OBJECT_NAME').AsString),
1281     Trim(FieldByName('SUBJECT_NAME').AsString)])
1282     else
1283     if FieldByName('OBJECT_TYPE').AsInteger = 13 {role} then
1284     ExecDDL.SQL.Text := Format('Revoke %s from %s',[
1285     Trim(FieldByName('OBJECT_NAME').AsString),
1286     Trim(FieldByName('SUBJECT_NAME').AsString)])
1287     else
1288     ExecDDL.SQL.Text := Format('Revoke All on %s %s from %s',[
1289     Trim(FieldByName('OBJECT_TYPE_NAME').AsString),
1290     Trim(FieldByName('OBJECT_NAME').AsString),
1291     Trim(FieldByName('SUBJECT_NAME').AsString)]);
1292     ExecDDL.ExecQuery;
1293     Next;
1294     end;
1295     finally
1296     EnableControls;
1297     end;
1298     CurrentTransaction.Commit;
1299     end;
1300     end;
1301    
1302 tony 272 procedure TDBDataModule.SyncSubjectAccessRights(ID: string);
1303 tony 158 begin
1304     if (FSubjectAccessRightsID = ID) and SubjectAccessRights.Active then Exit;
1305     SubjectAccessRights.Active := false;
1306     FSubjectAccessRightsID := ID;
1307     SubjectAccessRights.Active := true;
1308     end;
1309    
1310 tony 272 procedure TDBDataModule.IBDatabase1Login(Database: TIBDatabase;
1311 tony 158 LoginParams: TStrings);
1312     var aDatabaseName: string;
1313     aUserName: string;
1314     aPassword: string;
1315     aCreateIfNotExist: boolean;
1316     begin
1317     if FLocalConnect or (FDBPassword <> '') {reconnect} then
1318     begin
1319     LoginParams.Values['user_name'] := FDBUserName;
1320     LoginParams.Values['password'] := FDBPassword;
1321     exit;
1322     end;
1323    
1324     aDatabaseName := Database.DatabaseName;
1325     aUserName := LoginParams.Values['user_name'];
1326     aPassword := '';
1327     aCreateIfNotExist := false;
1328 tony 272 if CallLoginDlg(aDatabaseName, aUserName, aPassword, aCreateIfNotExist) = mrOK then
1329 tony 158 begin
1330     FDBPassword := aPassword; {remember for reconnect}
1331     Database.DatabaseName := aDatabaseName;
1332     LoginParams.Values['user_name'] := aUserName;
1333     LoginParams.Values['password'] := aPassword;
1334     FDBUserName := aUserName;
1335     FDBPassword := aPassword;
1336     Database.CreateIfNotExists := aCreateIfNotExist;
1337     ParseConnectString(aDatabaseName,FServerName,FDatabasePathName,FProtocol,FPortNo);
1338     end
1339     else
1340     IBError(ibxeOperationCancelled, [nil]);
1341     end;
1342    
1343 tony 272 procedure TDBDataModule.AttUpdateApplyUpdates(Sender: TObject;
1344 tony 158 UpdateKind: TUpdateKind; Params: ISQLParams);
1345     begin
1346     if UpdateKind = ukDelete then
1347     begin
1348     ExecDDL.SQL.Text := 'Delete from MON$ATTACHMENTS Where MON$ATTACHMENT_ID =' +
1349     Params.ByName('MON$ATTACHMENT_ID').Asstring;
1350     ExecDDL.ExecQuery;
1351     end;
1352     end;
1353    
1354 tony 272 procedure TDBDataModule.DBTablesUpdateApplyUpdates(Sender: TObject;
1355 tony 158 UpdateKind: TUpdateKind; Params: ISQLParams);
1356     begin
1357     // Do nothing
1358     end;
1359    
1360 tony 272 procedure TDBDataModule.IBValidationService1GetNextLine(Sender: TObject;
1361 tony 209 var Line: string);
1362 tony 158 begin
1363 tony 209 Application.ProcessMessages;
1364 tony 158 end;
1365    
1366 tony 272 procedure TDBDataModule.IBXServicesConnection1AfterConnect(Sender: TObject);
1367     var UN: ISPBItem;
1368     begin
1369     UN := IBXServicesConnection1.ServiceIntf.getSPB.Find(isc_spb_user_name);
1370     if UN <> nil then
1371     FServiceUserName := UN.AsString;
1372     end;
1373    
1374     procedure TDBDataModule.IBXServicesConnection1Login(
1375 tony 209 Service: TIBXServicesConnection; var aServerName: string; LoginParams: TStrings);
1376 tony 158 begin
1377 tony 209 LoginParams.Values['user_name'] := FDBUserName;
1378     LoginParams.Values['password'] := FDBPassword;
1379 tony 158 end;
1380    
1381 tony 272 procedure TDBDataModule.LegacyUserListAfterOpen(DataSet: TDataSet);
1382 tony 158 begin
1383     UserListSource.DataSet := LegacyUserList;
1384 tony 272 if IBDatabase1.Connected then
1385     begin
1386     CurrentTransaction.Active := true;
1387     RoleNameList.Active := true;
1388     end;
1389 tony 158 end;
1390    
1391 tony 272 procedure TDBDataModule.LegacyUserListAfterPost(DataSet: TDataSet);
1392 tony 210 begin
1393 tony 272 if IBDatabase1.Connected then
1394     RoleNameList.Active := true;
1395 tony 210 end;
1396    
1397 tony 272 procedure TDBDataModule.LegacyUserListBeforeClose(DataSet: TDataSet);
1398 tony 158 begin
1399     RoleNameList.Active := false;
1400     end;
1401    
1402 tony 272 procedure TDBDataModule.ShadowFilesCalcFields(DataSet: TDataSet);
1403 tony 158 var Flags: integer;
1404     begin
1405     Flags := DataSet.FieldByName('RDB$FILE_FLAGS').AsInteger;
1406     if Flags and $10 <> 0 then
1407     DataSet.FieldByName('FileMode').AsString := 'C'
1408     else
1409     if Flags and $04 <> 0 then
1410     DataSet.FieldByName('FileMode').AsString := 'M'
1411     else
1412     if Flags and $01 <> 0 then
1413     if DataSet.FieldByName('RDB$FILE_SEQUENCE').AsInteger = 0 then
1414     DataSet.FieldByName('FileMode').AsString := 'A'
1415     else
1416     DataSet.FieldByName('FileMode').AsString := '+'
1417     else
1418     DataSet.FieldByName('FileMode').AsString := ''
1419     end;
1420    
1421 tony 272 procedure TDBDataModule.SubjectAccessRightsBeforeOpen(DataSet: TDataSet);
1422 tony 158 begin
1423     SubjectAccessRights.ParamByName('ID').AsString := FSubjectAccessRightsID;
1424     end;
1425    
1426 tony 272 procedure TDBDataModule.TagsUpdateApplyUpdates(Sender: TObject;
1427 tony 158 UpdateKind: TUpdateKind; Params: ISQLParams);
1428     var sql: string;
1429     begin
1430     sql := '';
1431     case UpdateKind of
1432     ukInsert,
1433     ukModify:
1434     begin
1435     sql := 'ALTER USER ' + Trim(Params.ByName('SEC$USER_NAME').AsString)
1436     + ' TAGS (' + QuoteIdentifierIfNeeded(IBDatabase1.SQLDialect,Params.ByName('SEC$KEY').AsString)
1437     + '=''' + SQLSafeString(Params.ByName('SEC$VALUE').AsString) + '''';
1438     if Params.ByName('SEC$KEY').AsString <> Params.ByName('OLD_SEC$KEY').AsString then
1439     sql += ', DROP ' + QuoteIdentifierIfNeeded(IBDatabase1.SQLDialect,Params.ByName('OLD_SEC$KEY').AsString);
1440     sql +=')'
1441     end;
1442    
1443     ukDelete:
1444     sql := 'ALTER USER ' + Trim(Params.ByName('SEC$USER_NAME').AsString)
1445     + ' TAGS (DROP ' + QuoteIdentifierIfNeeded(IBDatabase1.SQLDialect,Params.ByName('SEC$KEY').AsString) + ')';
1446     end;
1447     ExecDDL.SQL.Text := sql;
1448     ExecDDL.ExecQuery;
1449     end;
1450    
1451 tony 272 procedure TDBDataModule.IBDatabase1AfterConnect(Sender: TObject);
1452 tony 158 begin
1453     {Virtual tables did not exist prior to Firebird 2.1 - so don't bother with old version}
1454     with IBDatabaseInfo do
1455     if (ODSMajorVersion < 11) or ((ODSMajorVersion = 11) and (ODSMinorVersion < 1)) then
1456     begin
1457     IBDatabase1.Connected := false;
1458     raise Exception.Create('This application requires Firebird 2.1 or later');
1459     end
1460     else
1461     if ODSMajorVersion < 12 then
1462     {Don't expect to be able to find these fields}
1463     begin
1464     AttachmentsMONCLIENT_VERSION.FieldKind := fkCalculated;
1465     AttachmentsMONREMOTE_VERSION.FieldKind := fkCalculated;
1466     AttachmentsMONREMOTE_HOST.FieldKind := fkCalculated;
1467     AttachmentsMONREMOTE_OS_USER.FieldKind := fkCalculated;
1468     AttachmentsMONAUTH_METHOD.FieldKind := fkCalculated;
1469     AttachmentsMONSYSTEM_FLAG.FieldKind := fkCalculated;
1470     AttachmentsRDBSECURITY_CLASS.FieldKind := fkCalculated;
1471     AttachmentsRDBOWNER_NAME.FieldKind := fkCalculated;
1472     end
1473     else
1474     begin
1475     AttachmentsMONCLIENT_VERSION.FieldKind := fkData;
1476     AttachmentsMONREMOTE_VERSION.FieldKind := fkData;
1477     AttachmentsMONREMOTE_HOST.FieldKind := fkData;
1478     AttachmentsMONREMOTE_OS_USER.FieldKind := fkData;
1479     AttachmentsMONAUTH_METHOD.FieldKind := fkData;
1480     AttachmentsMONSYSTEM_FLAG.FieldKind := fkData;
1481     AttachmentsRDBSECURITY_CLASS.FieldKind := fkData;
1482     AttachmentsRDBOWNER_NAME.FieldKind := fkData;
1483     end;
1484    
1485     FLocalConnect := FProtocol = Local;
1486 tony 209 ConnectServicesAPI;
1487 tony 272 CurrentTransaction.Active := true;
1488     FHasUserAdminPrivilege := GetUserAdminPrivilege;
1489 tony 158 ReloadData;
1490     end;
1491    
1492 tony 272 procedure TDBDataModule.IBDatabase1AfterDisconnect(Sender: TObject);
1493 tony 158 begin
1494     FDisconnecting := false;
1495     end;
1496    
1497 tony 272 procedure TDBDataModule.IBDatabase1BeforeDisconnect(Sender: TObject);
1498 tony 158 begin
1499     FDisconnecting := true;
1500     end;
1501    
1502 tony 272 procedure TDBDataModule.DatabaseQueryAfterOpen(DataSet: TDataSet);
1503 tony 158 begin
1504     DBCharSet.Active := true;
1505     end;
1506    
1507 tony 272 procedure TDBDataModule.CurrentTransactionAfterTransactionEnd(Sender: TObject);
1508 tony 158 begin
1509     if not Disconnecting and not (csDestroying in ComponentState) then
1510 tony 229 begin
1511     CurrentTransaction.Active := true;
1512 tony 158 Application.QueueAsyncCall(@ReloadData,0);
1513 tony 229 end;
1514 tony 158 end;
1515    
1516 tony 272 procedure TDBDataModule.ApplicationProperties1Exception(Sender: TObject;
1517 tony 158 E: Exception);
1518     begin
1519     if E is EIBInterBaseError then
1520     begin
1521     if RoleNameList.State in [dsInsert,dsEdit] then
1522     RoleNameList.Cancel;
1523     if UserList.State in [dsInsert,dsEdit] then
1524     UserList.Cancel;
1525     end;
1526     MessageDlg(E.Message,mtError,[mbOK],0);
1527     if CurrentTransaction.Active then
1528     CurrentTransaction.Rollback;
1529     end;
1530    
1531 tony 272 procedure TDBDataModule.AccessRightsCalcFields(DataSet: TDataSet);
1532 tony 158 begin
1533     AccessRightsDisplayName.AsString := AccessRightsSUBJECT_NAME.AsString;
1534     if AccessRightsSUBJECT_TYPE.AsInteger = 8 then
1535     begin
1536     if (AccessRightsSUBJECT_NAME.AsString <> 'PUBLIC') and UserListSource.DataSet.Active and
1537 tony 209 not UserListSource.DataSet.Locate('SEC$USER_NAME',AccessRightsSUBJECT_NAME.AsString,[]) then
1538 tony 158 begin
1539     AccessRightsImageIndex.AsInteger := 4;
1540     AccessRightsDisplayName.AsString := AccessRightsSUBJECT_NAME.AsString + ' (stale)';
1541     end
1542     else
1543     AccessRightsImageIndex.AsInteger := -1
1544     end
1545     else
1546     AccessRightsImageIndex.AsInteger := -1;
1547     end;
1548    
1549 tony 272 procedure TDBDataModule.AttachmentsAfterDelete(DataSet: TDataSet);
1550 tony 158 begin
1551     CurrentTransaction.Commit;
1552     end;
1553    
1554 tony 272 procedure TDBDataModule.AttachmentsAfterOpen(DataSet: TDataSet);
1555 tony 158 begin
1556     Attachments.Locate('MON$ATTACHMENT_ID',AttmtQuery.FieldByName('MON$ATTACHMENT_ID').AsInteger,[]);
1557     end;
1558    
1559 tony 272 procedure TDBDataModule.AttachmentsBeforeOpen(DataSet: TDataSet);
1560 tony 158 begin
1561     if IBDatabaseInfo.ODSMajorVersion >= 12 then
1562     (DataSet as TIBQuery).Parser.Add2WhereClause('r.MON$SYSTEM_FLAG = 0');
1563     end;
1564    
1565 tony 272 procedure TDBDataModule.ConfigDatasetAfterClose(DataSet: TDataSet);
1566 tony 158 begin
1567 tony 272 ConfigDataset.Clear(false);
1568     end;
1569    
1570     procedure TDBDataModule.DatabaseQueryBeforeClose(DataSet: TDataSet);
1571     begin
1572 tony 158 DBCharSet.Active := false;
1573     end;
1574    
1575 tony 272 procedure TDBDataModule.DBCharSetAfterClose(DataSet: TDataSet);
1576     begin
1577 tony 158 CharSetLookup.Active := false;
1578     end;
1579    
1580 tony 272 procedure TDBDataModule.DBCharSetBeforeOpen(DataSet: TDataSet);
1581 tony 158 begin
1582     CharSetLookup.Active := true;
1583     end;
1584    
1585     end.
1586