ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/examples/DBAdmin/DataModule.pas
Revision: 272
Committed: Mon Feb 4 13:34:37 2019 UTC (5 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 51655 byte(s)
Log Message:
Fixes merged

File Contents

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