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