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