ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/examples/DBAdmin/DataModule.pas
Revision: 232
Committed: Mon Apr 16 08:49:32 2018 UTC (6 years ago) by tony
Content type: text/x-pascal
File size: 46288 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 var KillDone: boolean;
693 begin
694 KillDone := false;
695 Disconnect;
696 repeat
697 try
698 IBDatabase1.Connected := true;
699 except
700 on E:EIBClientError do
701 begin
702 Exit
703 end;
704 On E: EIBInterBaseError do
705 begin
706 FDBPassword := '';
707 if (E.IBErrorCode = isc_io_error) and not KillDone then
708 begin
709 if MessageDlg('I/O Error reported on database file. If this is a shadow file, do you want '+
710 'to kill all unavailable shadow sets?. The original message is ' + E.Message,
711 mtInformation,[mbYes,mbNo],0) = mrNo then
712 continue;
713 try KillShadows except end;
714 KillDone := true;
715 end
716 else
717 ReportException(E);
718 end;
719 On E:Exception do
720 ReportException(E);
721 end;
722 until IBDatabase1.Connected;
723
724 if assigned(FAfterDBConnect) then
725 AfterDBConnect(self);
726 end;
727
728 procedure TDatabaseData.Disconnect;
729 begin
730 FDBUserName := '';
731 FDBPassword := '';
732 FLocalConnect := false;
733 IBDatabase1.Connected := false;
734 IBXServicesConnection1.Connected := false;
735 FDBHeaderScanned := false;
736 end;
737
738 procedure TDatabaseData.DropDatabase;
739 begin
740 IBDatabase1.DropDatabase;
741 Disconnect;
742 end;
743
744 procedure TDatabaseData.BackupDatabase;
745 begin
746 BackupDlg.ShowModal;
747 end;
748
749 procedure TDatabaseData.RestoreDatabase;
750 var DefaultPageSize: integer;
751 DefaultNumBuffers: integer;
752 begin
753 DefaultPageSize := DatabaseQuery.FieldByName('MON$PAGE_SIZE').AsInteger;
754 DefaultNumBuffers := DatabaseQuery.FieldByName('MON$PAGE_BUFFERS').AsInteger;
755 IBDatabase1.Connected := false;
756 try
757 RestoreDlg.ShowModal(DefaultPageSize,DefaultNumBuffers);
758 finally
759 IBDatabase1.Connected := true;
760 end;
761 end;
762
763 procedure TDatabaseData.BringDatabaseOnline;
764 begin
765 if IsDatabaseOnline then
766 MessageDlg('Database is already online!',mtInformation,[mbOK],0)
767 else
768 begin
769 IBDatabase1.Connected := false;
770 try
771 IBConfigService1.BringDatabaseOnline;
772 finally
773 IBDatabase1.Connected := true;
774 end;
775 if IsDatabaseOnline then
776 MessageDlg('Database is back online',mtInformation,[mbOK],0)
777 else
778 MessageDlg('Database is still shutdown!',mtError,[mbOK],0);
779 end;
780 end;
781
782 procedure TDatabaseData.ShutDown(aShutDownmode: TDBShutdownMode; aDelay: integer
783 );
784 begin
785 IBDatabase1.Connected := false;
786 try
787 ShutdownDatabaseDlg.Shutdown(aShutDownmode, aDelay);
788 finally
789 IBDatabase1.Connected := true;
790 end;
791 end;
792
793 procedure TDatabaseData.DatabaseRepair(Options: TValidateOptions; ReportLines: TStrings);
794
795 procedure ReportOptions;
796 var Line: string;
797 begin
798 Line := 'With Options: [';
799 if (ValidateDB in Options) then Line += 'ValidateDB ';
800 if (SweepDB in Options) then Line += 'SweepDB ';
801 if (KillShadows in Options) then Line += 'KillShadows ';
802 if (ValidateFull in Options) then Line += 'ValidateFull ';
803 if (CheckDB in Options) then Line += 'CheckDB ';
804 if (IgnoreChecksum in Options) then Line +='IgnoreChecksum ';
805 if (MendDB in Options) then Line +='MendDB ';
806 Line +=']';
807 ReportLines.Add(Line);
808 end;
809
810 begin
811 ReportLines.Add(Format('Validation of %s started',[IBValidationService1.DatabaseName]));
812 ReportOptions;
813 IBDatabase1.Connected := false;
814 with IBValidationService1 do
815 try
816 Execute(ReportLines);
817 ReportLines.Add('Operation Completed');
818 MessageDlg('Operation Completed',mtInformation,[mbOK],0);
819 finally
820 IBDatabase1.Connected := true;
821 end;
822 end;
823
824 procedure TDatabaseData.OnlineValidation(ReportLines: TStrings;
825 SelectedTablesOnly: boolean);
826 var TableNames: string;
827 Separator: string;
828 begin
829 if IBDatabaseInfo.ODSMajorVersion < 12 then
830 raise Exception.Create('Online Validation is not supported');
831 with IBOnlineValidationService1 do
832 begin
833 if SelectedTablesOnly then
834 begin
835 TableNames := '';
836 with DBTables do
837 if Active then
838 begin
839 DisableControls;
840 try
841 Separator := '';
842 First;
843 while not EOF do
844 begin
845 if FieldByName('Selected').AsInteger <> 0 then
846 begin
847 TableNames += Separator + FieldByName('RDB$RELATION_NAME').AsString;
848 Separator := '|';
849 end;
850 Next;
851 end;
852 finally
853 EnableControls;
854 end;
855 end;
856 IncludeTables := TableNames;
857 end
858 else
859 IncludeTables := '';
860 ReportLines.Add(Format('Online Validation of %s started',[IBOnlineValidationService1.DatabaseName]));
861 Execute(ReportLines);
862 ReportLines.Add('Online Validation Completed');
863 MessageDlg('Online Validation Completed',mtInformation,[mbOK],0);
864 end;
865 end;
866
867 procedure TDatabaseData.LimboResolution(ActionID: TTransactionGlobalAction;
868 Report: TStrings);
869 begin
870 if not InLimboList.Active then
871 raise Exception.Create('Limbo Transactions List not available');
872
873 with InLimboList do
874 if State = dsEdit then Post;
875 Report.Clear;
876 Report.Add('Starting Limbo transaction resolution');
877 InLimboList.FixErrors(ActionID,Report);
878 Report.Add('Limbo Transaction resolution complete');
879 CurrentTransaction.Commit;
880 end;
881
882 function TDatabaseData.GetLingerDelay: string;
883 var Linger: TField;
884 begin
885 Result := 'n/a';
886 if not DatabaseQuery.Active then exit;
887 Linger := DatabaseQuery.FindField('RDB$LINGER');
888 if Linger <> nil then
889 begin
890 if Linger.IsNull then
891 Result := '0'
892 else
893 Result := Linger.AsString;
894 end;
895 end;
896
897 function TDatabaseData.GetNoReserve: boolean;
898 begin
899 Result := DatabaseQuery.Active and (DatabaseQuery.FieldByName('MON$RESERVE_SPACE').AsInteger <> 0);
900 end;
901
902 function TDatabaseData.GetPageBuffers: integer;
903 begin
904 Result := IBDatabaseInfo.NumBuffers;
905 end;
906
907 function TDatabaseData.GetRoleName: string;
908 begin
909 Result := Trim(AttmtQuery.FieldByName('MON$ROLE').AsString);
910 end;
911
912 function TDatabaseData.GetSecurityDatabase: string;
913 var SecPlugin: TField;
914 begin
915 SecPlugin := DatabaseQuery.FindField('MON$SEC_DATABASE');
916 if SecPlugin = nil then
917 Result := 'Legacy'
918 else
919 Result := Trim(SecPlugin.AsString);
920 end;
921
922 function TDatabaseData.GetServerName: string;
923 begin
924 Result := IBXServicesConnection1.ServerName;
925 end;
926
927 function TDatabaseData.GetSweepInterval: integer;
928 begin
929 if DatabaseQuery.Active then
930 Result := DatabaseQuery.FieldByName('MON$SWEEP_INTERVAL').AsInteger
931 else
932 Result := 0;
933 end;
934
935 function TDatabaseData.GetUserAdminPrivilege: boolean;
936 begin
937 Result := false;
938 {For ODS 12 use SEC$USERS table}
939 if IBDatabaseInfo.ODSMajorVersion >= 12 then
940 with AdminUserQuery do
941 begin
942 ExecQuery;
943 try
944 Result := not EOF and FieldByName('SEC$ADMIN').AsBoolean;
945 finally
946 Close;
947 end;
948 end
949 {if need to know for ODS 11.2 then will have to use Service API}
950 else
951 begin
952 with IBSecurityService1 do
953 begin
954 DisplayUser(DBUserName);
955 Result := (UserInfoCount > 0) and UserInfo[0].AdminRole;
956 end;
957 end;
958 end;
959
960 procedure TDatabaseData.SetAutoAdmin(AValue: boolean);
961 begin
962 IBSecurityService1.SetAutoAdmin(AValue);
963 CurrentTransaction.Commit;
964 end;
965
966 procedure TDatabaseData.SetDBReadOnly(AValue: boolean);
967 begin
968 IBDatabase1.Connected := false;
969 try
970 IBConfigService1.SetReadOnly(AValue);
971 finally
972 IBDatabase1.Connected := true;
973 end;
974 end;
975
976 procedure TDatabaseData.SetDBSQLDialect(AValue: integer);
977 begin
978 IBDatabase1.Connected := false;
979 try
980 IBConfigService1.SetDBSqlDialect(AValue);
981 finally
982 IBDatabase1.Connected := true;
983 end;
984 end;
985
986 procedure TDatabaseData.SetDescription(AValue: string);
987 begin
988 with TIBSQL.Create(IBDatabase1) do
989 try
990 SQL.Text := 'Comment on Database is ''' + SQLSafeString(AValue) + '''';
991 Transaction.Active := true;
992 ExecQuery;
993 finally
994 Free;
995 end;
996 CurrentTransaction.Commit;
997 end;
998
999 procedure TDatabaseData.SetForcedWrites(AValue: boolean);
1000 begin
1001 IBConfigService1.SetAsyncMode(not AValue);
1002 end;
1003
1004 function TDatabaseData.IsDatabaseOnline: boolean;
1005 begin
1006 Result := DatabaseQuery.Active and (DatabaseQuery.FieldByName('MON$SHUTDOWN_MODE').AsInteger = 0);
1007 end;
1008
1009 function TDatabaseData.IsShadowDatabase: boolean;
1010 begin
1011 GetDBFlags;
1012 Result := FIsShadowDatabase;
1013 end;
1014
1015 procedure TDatabaseData.ActivateShadow;
1016 begin
1017 IBConfigService1.ActivateShadow;
1018 MessageDlg('Shadow Database activated. You should now rename the file or change the database alias name to point to the shadow',
1019 mtInformation,[mbOK],0);
1020 end;
1021
1022 procedure TDatabaseData.AddSecondaryFile(aFileName: string; StartAt,
1023 FileLength: integer);
1024 var SQLText: string;
1025 begin
1026 if FileLength <> -1 then
1027 SQLText := Format(sAddSecondarySQL2,[aFileName,StartAt,FileLength])
1028 else
1029 SQLText := Format(sAddSecondarySQL,[aFileName,StartAt]);
1030 ExecDDL.SQL.Text := SQLText;
1031 ExecDDL.ExecQuery;
1032 CurrentTransaction.Commit;
1033 end;
1034
1035 procedure TDatabaseData.AddShadowSet;
1036 var CurrentLocation: TBookmark;
1037 ShadowSet: integer;
1038 begin
1039 if ShadowFiles.RecordCount = 0 then
1040 ShadowSet := 1
1041 else
1042 with ShadowFiles do
1043 begin
1044 CurrentLocation := Bookmark;
1045 DisableControls;
1046 try
1047 Last;
1048 ShadowSet := FieldByName('RDB$Shadow_Number').AsInteger + 1;
1049 finally
1050 Bookmark := CurrentLocation;
1051 EnableControls
1052 end
1053 end;
1054 AddShadowSetDlg.ShowModal(ShadowSet);
1055 CurrentTransaction.Active := true;
1056 end;
1057
1058 procedure TDatabaseData.RemoveShadowSet(ShadowSet: integer);
1059 begin
1060 if IBDatabaseInfo.ODSMajorVersion < 12 then
1061 begin
1062 if MessageDlg(Format(sRemoveShadow,[ShadowSet]),mtConfirmation,[mbYes,mbNo],0) = mrYes then
1063 ExecDDL.SQL.Text := Format(sRemoveShadow,[ShadowSet]);
1064 end
1065 else
1066 case MessageDlg(Format(sPreserveShadowFiles,[ShadowSet]),mtConfirmation,[mbYes,mbNo,mbCancel],0) of
1067 mrNo:
1068 ExecDDL.SQL.Text :=Format(sRemoveShadow12,[ShadowSet]);
1069 mrYes:
1070 ExecDDL.SQL.Text := Format(sPreserveShadow,[ShadowSet]);
1071 mrCancel:
1072 Exit;
1073 end;
1074 ExecDDL.ExecQuery;
1075 CurrentTransaction.Commit;
1076 end;
1077
1078 procedure TDatabaseData.LoadPerformanceStatistics(Lines: TStrings);
1079
1080 procedure AddPerfStats(Heading: string; stats: TStrings);
1081 var i: integer;
1082 begin
1083 with Lines do
1084 begin
1085 if stats.count = 0 then exit;
1086 Add('');
1087 Add(Heading);
1088 for i := 0 to stats.Count - 1 do
1089 begin
1090 if TableNameLookup.Locate('RDB$RELATION_ID',stats.Names[i],[]) then
1091 Add(' ' + TableNameLookup.FieldByName('RDB$RELATION_NAME').AsString + ' = ' + stats.ValueFromIndex[i]);
1092 end;
1093 end;
1094 end;
1095
1096 begin
1097 TableNameLookup.Active := true;
1098 with IBDatabaseInfo, Lines do
1099 begin
1100 Add(Format('Number of reads from the memory buffer cache = %d',[Fetches]));
1101 Add(Format('Number of writes to the memory buffer cache = %d',[Marks]));
1102 Add(Format('Number of page reads = %d',[Reads]));
1103 Add(Format('Number of page writes = %d',[Writes]));
1104 Add('');
1105 Add('Since Database last attached:');
1106 AddPerfStats('Number of removals of a version of a record',BackoutCount);
1107 AddPerfStats('Number of database deletes',DeleteCount);
1108 AddPerfStats('Number of removals of a committed record',ExpungeCount);
1109 AddPerfStats('Number of inserts',InsertCount);
1110 AddPerfStats('Number of removals of old versions of fully mature records',PurgeCount);
1111 AddPerfStats('Number of reads done via an index',ReadIdxCount);
1112 AddPerfStats('Number of sequential table scans',ReadSeqCount);
1113 AddPerfStats('Number of database updates',UpdateCount);
1114 end;
1115 end;
1116
1117 procedure TDatabaseData.LoadDatabaseStatistics(OptionID: integer; Lines: TStrings);
1118 begin
1119 if OptionID = 1 then
1120 LoadPerformanceStatistics(Lines)
1121 else
1122 with IBStatisticalService1 do
1123 begin
1124 case OptionID of
1125 0: Options := [HeaderPages];
1126 2: options := [DataPages];
1127 3: Options := [IndexPages];
1128 4: Options := [SystemRelations]
1129 end;
1130 Execute(Lines);
1131 end;
1132 end;
1133
1134 procedure TDatabaseData.LoadServerProperties(Lines: TStrings);
1135 var i: integer;
1136 begin
1137 Lines.Clear;
1138 with IBServerProperties1 do
1139 begin
1140 Lines.Add('Server Version = ' + VersionInfo.ServerVersion);
1141 Lines.Add('Server Implementation = ' + VersionInfo.ServerImplementation);
1142 Lines.Add('Service Version = ' + IntToStr(VersionInfo.ServiceVersion));
1143 with ServicesConnection do
1144 Lines.Add(Format('Firebird Release = %d.%d.%d (Build no. %d)',[ServerVersionNo[1],
1145 ServerVersionNo[2],
1146 ServerVersionNo[3],
1147 ServerVersionNo[4]]));
1148 Lines.Add('No. of attachments = ' + IntToStr(DatabaseInfo.NoOfAttachments));
1149 Lines.Add('No. of databases = ' + IntToStr(DatabaseInfo.NoOfDatabases));
1150 for i := 0 to DatabaseInfo.NoOfDatabases - 1 do
1151 Lines.Add(Format('DB Name (%d) = %s',[i+1, DatabaseInfo.DbName[i]]));
1152 Lines.Add('Base Location = ' + ConfigParams.BaseLocation);
1153 Lines.Add('Lock File Location = ' + ConfigParams.LockFileLocation);
1154 Lines.Add('Security Database Location = ' + ConfigParams.SecurityDatabaseLocation);
1155 Lines.Add('Message File Location = ' + ConfigParams.MessageFileLocation);
1156 end;
1157 end;
1158
1159 procedure TDatabaseData.LoadServerLog(Lines: TStrings);
1160 begin
1161 Lines.Clear;
1162 if IBLogService1.ServicesConnection.ServiceIntf.getProtocol = Local then
1163 Lines.Add('Server Log not available with embedded server')
1164 else
1165 IBLogService1.Execute(Lines);
1166 end;
1167
1168 procedure TDatabaseData.RevokeAll;
1169 begin
1170 with SubjectAccessRights do
1171 if Active then
1172 begin
1173 DisableControls;
1174 try
1175 First;
1176 while not EOF do
1177 begin
1178 if FieldByName('OBJECT_TYPE').AsInteger = 0 {relation} then
1179 ExecDDL.SQL.Text := Format('Revoke All on %s from %s',[
1180 Trim(FieldByName('OBJECT_NAME').AsString),
1181 Trim(FieldByName('SUBJECT_NAME').AsString)])
1182 else
1183 if FieldByName('OBJECT_TYPE').AsInteger = 13 {role} then
1184 ExecDDL.SQL.Text := Format('Revoke %s from %s',[
1185 Trim(FieldByName('OBJECT_NAME').AsString),
1186 Trim(FieldByName('SUBJECT_NAME').AsString)])
1187 else
1188 ExecDDL.SQL.Text := Format('Revoke All on %s %s from %s',[
1189 Trim(FieldByName('OBJECT_TYPE_NAME').AsString),
1190 Trim(FieldByName('OBJECT_NAME').AsString),
1191 Trim(FieldByName('SUBJECT_NAME').AsString)]);
1192 ExecDDL.ExecQuery;
1193 Next;
1194 end;
1195 finally
1196 EnableControls;
1197 end;
1198 CurrentTransaction.Commit;
1199 end;
1200 end;
1201
1202 procedure TDatabaseData.SyncSubjectAccessRights(ID: string);
1203 begin
1204 if (FSubjectAccessRightsID = ID) and SubjectAccessRights.Active then Exit;
1205 SubjectAccessRights.Active := false;
1206 FSubjectAccessRightsID := ID;
1207 SubjectAccessRights.Active := true;
1208 end;
1209
1210 procedure TDatabaseData.IBDatabase1Login(Database: TIBDatabase;
1211 LoginParams: TStrings);
1212 var aDatabaseName: string;
1213 aUserName: string;
1214 aPassword: string;
1215 aCreateIfNotExist: boolean;
1216 begin
1217 if FLocalConnect or (FDBPassword <> '') {reconnect} then
1218 begin
1219 LoginParams.Values['user_name'] := FDBUserName;
1220 LoginParams.Values['password'] := FDBPassword;
1221 exit;
1222 end;
1223
1224 aDatabaseName := Database.DatabaseName;
1225 aUserName := LoginParams.Values['user_name'];
1226 aPassword := '';
1227 aCreateIfNotExist := false;
1228 if DBLoginDlg.ShowModal(aDatabaseName, aUserName, aPassword, aCreateIfNotExist) = mrOK then
1229 begin
1230 FDBPassword := aPassword; {remember for reconnect}
1231 Database.DatabaseName := aDatabaseName;
1232 LoginParams.Values['user_name'] := aUserName;
1233 LoginParams.Values['password'] := aPassword;
1234 FDBUserName := aUserName;
1235 FDBPassword := aPassword;
1236 Database.CreateIfNotExists := aCreateIfNotExist;
1237 ParseConnectString(aDatabaseName,FServerName,FDatabasePathName,FProtocol,FPortNo);
1238 end
1239 else
1240 IBError(ibxeOperationCancelled, [nil]);
1241 end;
1242
1243 procedure TDatabaseData.AttUpdateApplyUpdates(Sender: TObject;
1244 UpdateKind: TUpdateKind; Params: ISQLParams);
1245 begin
1246 if UpdateKind = ukDelete then
1247 begin
1248 ExecDDL.SQL.Text := 'Delete from MON$ATTACHMENTS Where MON$ATTACHMENT_ID =' +
1249 Params.ByName('MON$ATTACHMENT_ID').Asstring;
1250 ExecDDL.ExecQuery;
1251 end;
1252 end;
1253
1254 procedure TDatabaseData.DBTablesUpdateApplyUpdates(Sender: TObject;
1255 UpdateKind: TUpdateKind; Params: ISQLParams);
1256 begin
1257 // Do nothing
1258 end;
1259
1260 procedure TDatabaseData.IBValidationService1GetNextLine(Sender: TObject;
1261 var Line: string);
1262 begin
1263 Application.ProcessMessages;
1264 end;
1265
1266 procedure TDatabaseData.IBXServicesConnection1Login(
1267 Service: TIBXServicesConnection; var aServerName: string; LoginParams: TStrings);
1268 begin
1269 LoginParams.Values['user_name'] := FDBUserName;
1270 LoginParams.Values['password'] := FDBPassword;
1271 end;
1272
1273 procedure TDatabaseData.LegacyUserListAfterOpen(DataSet: TDataSet);
1274 begin
1275 UserListSource.DataSet := LegacyUserList;
1276 CurrentTransaction.Active := true;
1277 RoleNameList.Active := true;
1278 end;
1279
1280 procedure TDatabaseData.LegacyUserListAfterPost(DataSet: TDataSet);
1281 begin
1282 RoleNameList.Active := true;
1283 end;
1284
1285 procedure TDatabaseData.LegacyUserListBeforeClose(DataSet: TDataSet);
1286 begin
1287 RoleNameList.Active := false;
1288 end;
1289
1290 procedure TDatabaseData.ShadowFilesCalcFields(DataSet: TDataSet);
1291 var Flags: integer;
1292 begin
1293 Flags := DataSet.FieldByName('RDB$FILE_FLAGS').AsInteger;
1294 if Flags and $10 <> 0 then
1295 DataSet.FieldByName('FileMode').AsString := 'C'
1296 else
1297 if Flags and $04 <> 0 then
1298 DataSet.FieldByName('FileMode').AsString := 'M'
1299 else
1300 if Flags and $01 <> 0 then
1301 if DataSet.FieldByName('RDB$FILE_SEQUENCE').AsInteger = 0 then
1302 DataSet.FieldByName('FileMode').AsString := 'A'
1303 else
1304 DataSet.FieldByName('FileMode').AsString := '+'
1305 else
1306 DataSet.FieldByName('FileMode').AsString := ''
1307 end;
1308
1309 procedure TDatabaseData.SubjectAccessRightsBeforeOpen(DataSet: TDataSet);
1310 begin
1311 SubjectAccessRights.ParamByName('ID').AsString := FSubjectAccessRightsID;
1312 end;
1313
1314 procedure TDatabaseData.TagsUpdateApplyUpdates(Sender: TObject;
1315 UpdateKind: TUpdateKind; Params: ISQLParams);
1316 var sql: string;
1317 begin
1318 sql := '';
1319 case UpdateKind of
1320 ukInsert,
1321 ukModify:
1322 begin
1323 sql := 'ALTER USER ' + Trim(Params.ByName('SEC$USER_NAME').AsString)
1324 + ' TAGS (' + QuoteIdentifierIfNeeded(IBDatabase1.SQLDialect,Params.ByName('SEC$KEY').AsString)
1325 + '=''' + SQLSafeString(Params.ByName('SEC$VALUE').AsString) + '''';
1326 if Params.ByName('SEC$KEY').AsString <> Params.ByName('OLD_SEC$KEY').AsString then
1327 sql += ', DROP ' + QuoteIdentifierIfNeeded(IBDatabase1.SQLDialect,Params.ByName('OLD_SEC$KEY').AsString);
1328 sql +=')'
1329 end;
1330
1331 ukDelete:
1332 sql := 'ALTER USER ' + Trim(Params.ByName('SEC$USER_NAME').AsString)
1333 + ' TAGS (DROP ' + QuoteIdentifierIfNeeded(IBDatabase1.SQLDialect,Params.ByName('SEC$KEY').AsString) + ')';
1334 end;
1335 ExecDDL.SQL.Text := sql;
1336 ExecDDL.ExecQuery;
1337 end;
1338
1339 procedure TDatabaseData.IBDatabase1AfterConnect(Sender: TObject);
1340 begin
1341 {Virtual tables did not exist prior to Firebird 2.1 - so don't bother with old version}
1342 with IBDatabaseInfo do
1343 if (ODSMajorVersion < 11) or ((ODSMajorVersion = 11) and (ODSMinorVersion < 1)) then
1344 begin
1345 IBDatabase1.Connected := false;
1346 raise Exception.Create('This application requires Firebird 2.1 or later');
1347 end
1348 else
1349 if ODSMajorVersion < 12 then
1350 {Don't expect to be able to find these fields}
1351 begin
1352 AttachmentsMONCLIENT_VERSION.FieldKind := fkCalculated;
1353 AttachmentsMONREMOTE_VERSION.FieldKind := fkCalculated;
1354 AttachmentsMONREMOTE_HOST.FieldKind := fkCalculated;
1355 AttachmentsMONREMOTE_OS_USER.FieldKind := fkCalculated;
1356 AttachmentsMONAUTH_METHOD.FieldKind := fkCalculated;
1357 AttachmentsMONSYSTEM_FLAG.FieldKind := fkCalculated;
1358 AttachmentsRDBSECURITY_CLASS.FieldKind := fkCalculated;
1359 AttachmentsRDBOWNER_NAME.FieldKind := fkCalculated;
1360 end
1361 else
1362 begin
1363 AttachmentsMONCLIENT_VERSION.FieldKind := fkData;
1364 AttachmentsMONREMOTE_VERSION.FieldKind := fkData;
1365 AttachmentsMONREMOTE_HOST.FieldKind := fkData;
1366 AttachmentsMONREMOTE_OS_USER.FieldKind := fkData;
1367 AttachmentsMONAUTH_METHOD.FieldKind := fkData;
1368 AttachmentsMONSYSTEM_FLAG.FieldKind := fkData;
1369 AttachmentsRDBSECURITY_CLASS.FieldKind := fkData;
1370 AttachmentsRDBOWNER_NAME.FieldKind := fkData;
1371 end;
1372
1373 FLocalConnect := FProtocol = Local;
1374 ConnectServicesAPI;
1375 ReloadData;
1376 end;
1377
1378 procedure TDatabaseData.IBDatabase1AfterDisconnect(Sender: TObject);
1379 begin
1380 FDisconnecting := false;
1381 end;
1382
1383 procedure TDatabaseData.IBDatabase1BeforeDisconnect(Sender: TObject);
1384 begin
1385 FDisconnecting := true;
1386 end;
1387
1388 procedure TDatabaseData.DatabaseQueryAfterOpen(DataSet: TDataSet);
1389 begin
1390 DBCharSet.Active := true;
1391 end;
1392
1393 procedure TDatabaseData.CurrentTransactionAfterTransactionEnd(Sender: TObject);
1394 begin
1395 if not Disconnecting and not (csDestroying in ComponentState) then
1396 begin
1397 CurrentTransaction.Active := true;
1398 Application.QueueAsyncCall(@ReloadData,0);
1399 end;
1400 end;
1401
1402 procedure TDatabaseData.ApplicationProperties1Exception(Sender: TObject;
1403 E: Exception);
1404 begin
1405 if E is EIBInterBaseError then
1406 begin
1407 if RoleNameList.State in [dsInsert,dsEdit] then
1408 RoleNameList.Cancel;
1409 if UserList.State in [dsInsert,dsEdit] then
1410 UserList.Cancel;
1411 end;
1412 MessageDlg(E.Message,mtError,[mbOK],0);
1413 if CurrentTransaction.Active then
1414 CurrentTransaction.Rollback;
1415 end;
1416
1417 procedure TDatabaseData.AccessRightsCalcFields(DataSet: TDataSet);
1418 begin
1419 AccessRightsDisplayName.AsString := AccessRightsSUBJECT_NAME.AsString;
1420 if AccessRightsSUBJECT_TYPE.AsInteger = 8 then
1421 begin
1422 if (AccessRightsSUBJECT_NAME.AsString <> 'PUBLIC') and UserListSource.DataSet.Active and
1423 not UserListSource.DataSet.Locate('SEC$USER_NAME',AccessRightsSUBJECT_NAME.AsString,[]) then
1424 begin
1425 AccessRightsImageIndex.AsInteger := 4;
1426 AccessRightsDisplayName.AsString := AccessRightsSUBJECT_NAME.AsString + ' (stale)';
1427 end
1428 else
1429 AccessRightsImageIndex.AsInteger := -1
1430 end
1431 else
1432 AccessRightsImageIndex.AsInteger := -1;
1433 end;
1434
1435 procedure TDatabaseData.AttachmentsAfterDelete(DataSet: TDataSet);
1436 begin
1437 CurrentTransaction.Commit;
1438 end;
1439
1440 procedure TDatabaseData.AttachmentsAfterOpen(DataSet: TDataSet);
1441 begin
1442 Attachments.Locate('MON$ATTACHMENT_ID',AttmtQuery.FieldByName('MON$ATTACHMENT_ID').AsInteger,[]);
1443 end;
1444
1445 procedure TDatabaseData.AttachmentsBeforeOpen(DataSet: TDataSet);
1446 begin
1447 if IBDatabaseInfo.ODSMajorVersion >= 12 then
1448 (DataSet as TIBQuery).Parser.Add2WhereClause('r.MON$SYSTEM_FLAG = 0');
1449 end;
1450
1451 procedure TDatabaseData.DatabaseQueryBeforeClose(DataSet: TDataSet);
1452 begin
1453 DBCharSet.Active := false;
1454 end;
1455
1456 procedure TDatabaseData.DBCharSetAfterClose(DataSet: TDataSet);
1457 begin
1458 CharSetLookup.Active := false;
1459 end;
1460
1461 procedure TDatabaseData.DBCharSetBeforeOpen(DataSet: TDataSet);
1462 begin
1463 CharSetLookup.Active := true;
1464 end;
1465
1466 end.
1467