fbadmin.pp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. unit FBAdmin;
  2. { Interbase/Firebird Administration using the service manager
  3. Copyright (C) 2012 Ludo Brands
  4. This library is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU Library General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or (at your
  7. option) any later version with the following modification:
  8. As a special exception, the copyright holders of this library give you
  9. permission to link this library with independent modules to produce an
  10. executable, regardless of the license terms of these independent modules,and
  11. to copy and distribute the resulting executable under terms of your choice,
  12. provided that you also meet, for each linked independent module, the terms
  13. and conditions of the license of that module. An independent module is a
  14. module which is not derived from or based on this library. If you modify
  15. this library, you may extend this exception to your version of the library,
  16. but you are not obligated to do so. If you do not wish to do so, delete this
  17. exception statement from your version.
  18. This program is distributed in the hope that it will be useful, but WITHOUT
  19. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  20. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  21. for more details.
  22. You should have received a copy of the GNU Library General Public License
  23. along with this library; if not, write to the Free Software Foundation,
  24. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25. }
  26. {$mode objfpc}{$H+}
  27. {$Define LinkDynamically}
  28. interface
  29. uses
  30. Classes, SysUtils,
  31. {$IfDef LinkDynamically}
  32. ibase60dyn,
  33. {$Else}
  34. ibase60,
  35. {$EndIf}
  36. IBConnection;
  37. type
  38. TIBBackupOption=(IBBkpVerbose,IBBkpIgnoreChecksums,IBBkpIgnoreLimbo,IBBkpMetadataOnly,
  39. IBBkpNoGarbageCollect,IBBkpOldDescriptions,IBBkpNonTransportable,IBBkpConvert);
  40. TIBBackupOptions= set of TIBBackupOption;
  41. TIBRestoreOption=(IBResVerbose,IBResDeactivateIdx,IBResNoShadow,IBResNoValidity,
  42. IBResOneAtaTime,IBResReplace,IBResCreate,IBResUseAllSpace,IBResAMReadOnly,IBResAMReadWrite,
  43. IBFixFssData, IBFixFssMeta);
  44. TIBRestoreOptions= set of TIBRestoreOption;
  45. TServiceProtocol=(IBSPLOCAL,IBSPTCPIP,IBSPNETBEUI,IBSPNAMEDPIPE);
  46. TIBOnOutput= procedure(Sender: TObject; msg: string; IBAdminAction: string) of object;
  47. TIBStatOption = (IBDataPages, IBDbLog, IBHeaderPages, IBIndexPages, IBSystemRelations,
  48. IBRecordVersions, IBStatTables);
  49. TIBStatOptions = set of TIBStatOption;
  50. { TFBAdmin }
  51. TFBAdmin=class(TComponent)
  52. private
  53. FErrorCode: longint;
  54. FErrorMsg: string;
  55. FFixFssDataCharSet: String;
  56. FHost: string;
  57. FOnOutput: TIBOnOutput;
  58. FOutput: TStringList;
  59. FPassword: string;
  60. FPort: word;
  61. FProtocol: TServiceProtocol;
  62. FServerImplementation: string;
  63. FServerLockDir: string;
  64. FServerMsgDir: string;
  65. FServerRootDir: string;
  66. FServerSecDBDir: string;
  67. FServerVersion: string;
  68. FStatus: array [0..19] of ISC_STATUS;
  69. FSvcHandle: isc_svc_handle;
  70. FUseExceptions: boolean;
  71. FUser: string;
  72. function CheckConnected(ProcName: string):boolean;
  73. procedure CheckError(ProcName : string; Status : PISC_STATUS);
  74. function GetDBInfo:boolean;
  75. function GetIBLongint(buffer:string; var bufptr:integer):longint;overload;
  76. function GetIBString(buffer:string; var bufptr:integer):string;overload;
  77. function GetOutput(IBAdminAction:string):boolean;
  78. function IBParamSerialize(isccode:byte;value:string):string;
  79. procedure IBRaiseError(GDSErrorCode:Longint; const msg : string; const args : array of const);
  80. function IBSPBParamSerialize(isccode:byte;value:string):string;
  81. function IBSPBParamSerialize(isccode:byte;value:longint):string;
  82. function MakeBackupOptions(options:TIBBackupOptions):longint;
  83. function MakeRestoreOptions(options:TIBRestoreOptions):longint;
  84. public
  85. constructor Create(AOwner: TComponent); override;
  86. destructor Destroy; override;
  87. //Connect to service manager. Specify User,Password and, for remote databases,
  88. //Host and, if not standard, Port
  89. function Connect:boolean;
  90. //Disconnect from service manager. Done automatically when destroying component
  91. function DisConnect:boolean;
  92. //Backup database to a single file on the server.
  93. //Include IBBkpVerbose in Options to get progress feedback through the OnOutput Handler
  94. function Backup(Database,Filename:string;Options:TIBBackupOptions;RoleName:string=''):boolean;
  95. //Backup database to multiple files with length FileSize on the server.
  96. //Filenames is the list of filenames to use. The last file specified has no size limit.
  97. //Include IBBkpVerbose in Options to get progress feedback through the OnOutput Handler
  98. function BackupMultiFile(Database:string;Filenames:TStrings;FileSize:longint;
  99. Options:TIBBackupOptions;RoleName:string=''):boolean;
  100. //Restore database from a single file on the server.
  101. //Include IBResReplace to restore in and existing database or IBResCreate
  102. //to create a a new one.
  103. //Include IBResVerbose in Options to get progress feedback through the OnOutput Handler
  104. function Restore(Database,Filename:string;Options:TIBRestoreOptions;RoleName:string=''):boolean;
  105. //Restore database from multiple files on the server.
  106. //Filenames is the list of files to use.
  107. //Include IBResReplace to restore in and existing database or IBResCreate
  108. //to create a a new one.
  109. //Include IBResVerbose in Options to get progress feedback through the OnOutput Handler
  110. function RestoreMultiFile(Database:string;Filenames:TStrings;
  111. Options:TIBRestoreOptions;RoleName:string=''):boolean;
  112. //Add a new user.
  113. function AddUser(UserName,Password:string;RoleName:string='';
  114. GroupName:string='';FirstName:string='';MiddleName:string='';
  115. LastName:string='';UserID: longint = 0; GroupID: longint = 0):boolean;
  116. //Modify an existing user.
  117. function ModifyUser(UserName,Password:string;RoleName:string='';
  118. GroupName:string='';FirstName:string='';MiddleName:string='';
  119. LastName:string='';UserID: longint = 0; GroupID: longint = 0):boolean;
  120. //Delete an existing user.
  121. function DeleteUser(UserName:string;RoleName:string=''):boolean;
  122. //Get the details of an existing user.
  123. function GetUser(UserName:string;var GroupName,FirstName,MiddleName,
  124. LastName:string;var UserID, GroupID: longint):boolean;
  125. //Get the list of all users
  126. function GetUsers(Users:TStrings):boolean;
  127. //Get database server log file
  128. function GetDatabaseLog:boolean;
  129. //Get database statistics
  130. function GetDatabaseStats(Database:string;Options:TIBStatOptions;TableNames:String = ''): boolean;
  131. //Database server version
  132. property ServerVersion:string read FServerVersion;
  133. //Implementation string of the database server
  134. property ServerImplementation:string read FServerImplementation;
  135. //Setting of $FIREBIRD or $INTERBASE
  136. property ServerRootDir:string read FServerRootDir;
  137. //Setting of $FIREBIRD_LCK or $INTERBASE_LCK
  138. property ServerLockDir:string read FServerLockDir;
  139. //Setting of $FIREBIRD_MSG or $INTERBASE_MSG
  140. property ServerMsgDir:string read FServerMsgDir;
  141. //Path to the security database in use by the server
  142. property ServerSecDBDir:string read FServerSecDBDir;
  143. // FixFxxData/FixFxxMetaData code page
  144. property FixFssDataCharSet: String read FFixFssDataCharSet write FFixFssDataCharSet;
  145. published
  146. //User name to connect to service manager
  147. property User: string read FUser write FUser;
  148. //User name to connect to service manager
  149. property Password: string read FPassword write FPassword;
  150. //Database Host
  151. property Host: string read FHost write FHost;
  152. //Database Port, Default:3050
  153. property Port: word read FPort write FPort default 3050;
  154. //Protocol used to connect to service manager. One of:
  155. //IBSPLOCAL: Host and port ignored
  156. //IBSPTCPIP: Connect to Host:Port
  157. //IBSPNETBEUI: Connect to \\Host\
  158. //IBSPNAMEDPIPE: Connect to //Host/
  159. property Protocol: TServiceProtocol read FProtocol write FProtocol;
  160. //Errorcode returned in status vector or 0 for TFBAdmin errors
  161. property ErrorCode:longint read FErrorCode;
  162. //Errormsg returned in status vector or by TFBAdmin
  163. property ErrorMsg:string read FErrorMsg;
  164. //Raise exceptions when error encounterd. Default: false
  165. property UseExceptions:boolean read FUseExceptions write FUseExceptions;
  166. //Service output messages
  167. //Result from Backup and Restore operations and GetLog
  168. property Output:TStringList read FOutput;
  169. //Event handler for Service output messages
  170. //Used in Backup and Restore operations and GetLog
  171. property OnOutput: TIBOnOutput read FOnOutput write FOnOutput;
  172. end;
  173. implementation
  174. resourcestring
  175. SErrNotConnected = '%s : %s : Not connected.';
  176. SErrError = '%s : %s : %s';
  177. SErrConnected = '%s : Connect : Already connected.';
  178. SErrRestoreOptionsError = '%s : Restore : Nothing to do. Specify IBResReplace or IBResCreate in Options.';
  179. SErrRestoreMultiOptionsError = '%s : RestoreMultiFile : Nothing to do. Specify IBResReplace or IBResCreate in Options.';
  180. SErrUserDoesNotExist = '%s : GetUser : User does not exist.';
  181. SErrUserInvalidReply = '%s : GetUser : Invalid reply (%d).';
  182. SErrUsersInvalidReply = '%s : GetUsers : Invalid reply (%d).';
  183. { TFBAdmin }
  184. function TFBAdmin.IBParamSerialize(isccode: byte; value: string): string;
  185. begin
  186. result:=chr(isccode)+chr(Length(value))+value;
  187. end;
  188. procedure TFBAdmin.IBRaiseError(GDSErrorCode: Longint; const msg: string;
  189. const args: array of const);
  190. begin
  191. FErrorMsg:=Format(msg,args);
  192. FErrorCode:=GDSErrorCode;
  193. if FUseExceptions then
  194. raise EIBDatabaseError.CreateFmt(msg,args,nil,GDSErrorCode,'');
  195. end;
  196. function TFBAdmin.IBSPBParamSerialize(isccode: byte; value: string): string;
  197. begin
  198. result:=chr(isccode)+chr(Length(value) and $ff)+chr((Length(value)shr 8) and $ff)+value;
  199. end;
  200. function TFBAdmin.IBSPBParamSerialize(isccode: byte; value: longint): string;
  201. begin
  202. result:=chr(isccode)+chr(value and $ff)+chr((value shr 8) and $ff)
  203. +chr((value shr 16) and $ff)+chr((value shr 24) and $ff);
  204. end;
  205. function TFBAdmin.MakeBackupOptions(options: TIBBackupOptions): longint;
  206. begin
  207. result:=0;
  208. if IBBkpConvert in Options then
  209. result:=result or isc_spb_bkp_convert;
  210. if IBBkpIgnoreChecksums in Options then
  211. result:=result or isc_spb_bkp_ignore_checksums;
  212. if IBBkpIgnoreLimbo in Options then
  213. result:=result or isc_spb_bkp_ignore_limbo;
  214. if IBBkpMetadataOnly in Options then
  215. result:=result or isc_spb_bkp_metadata_only;
  216. if IBBkpNoGarbageCollect in Options then
  217. result:=result or isc_spb_bkp_no_garbage_collect;
  218. if IBBkpNonTransportable in Options then
  219. result:=result or isc_spb_bkp_non_transportable;
  220. if IBBkpOldDescriptions in Options then
  221. result:=result or isc_spb_bkp_old_descriptions;
  222. end;
  223. function TFBAdmin.MakeRestoreOptions(options: TIBRestoreOptions): longint;
  224. begin
  225. result:=0;
  226. if IBResCreate in Options then
  227. result:=result or isc_spb_res_create;
  228. if IBResDeactivateIdx in Options then
  229. result:=result or isc_spb_res_deactivate_idx;
  230. if IBResNoShadow in Options then
  231. result:=result or isc_spb_res_no_shadow;
  232. if IBResNoValidity in Options then
  233. result:=result or isc_spb_res_no_validity;
  234. if IBResOneAtaTime in Options then
  235. result:=result or isc_spb_res_one_at_a_time;
  236. if IBResReplace in Options then
  237. result:=result or isc_spb_res_replace;
  238. if IBResUseAllSpace in Options then
  239. result:=result or isc_spb_res_use_all_space;
  240. end;
  241. function TFBAdmin.CheckConnected(ProcName: string): boolean;
  242. begin
  243. result:=false;
  244. if FSvcHandle=FB_API_NULLHANDLE then
  245. begin
  246. IBRaiseError(0,SErrNotConnected,[self.Name,ProcName]);
  247. exit;
  248. end;
  249. result:=true;
  250. end;
  251. procedure TFBAdmin.CheckError(ProcName: string; Status: PISC_STATUS);
  252. var
  253. buf : array [0..1023] of char;
  254. Msg : string;
  255. Err : longint;
  256. begin
  257. if ((Status[0] = 1) and (Status[1] <> 0)) then
  258. begin
  259. Err := Status[1];
  260. msg := '';
  261. while isc_interprete(Buf, @Status) > 0 do
  262. Msg := Msg + LineEnding +' -' + StrPas(Buf);
  263. IBRaiseError(Err,SErrError,[self.Name,ProcName,Msg]);
  264. end;
  265. end;
  266. function TFBAdmin.GetDBInfo: boolean;
  267. function QueryInfo(isc:byte):string;
  268. var
  269. spb:string;
  270. len:integer;
  271. begin
  272. result:='';
  273. spb:=chr(isc);
  274. setlength(result,255);
  275. if (isc_service_query(@FStatus[0], @FSvcHandle, nil, 0, nil, length(spb),
  276. @spb[1],255,@result[1])=0) and (result[1]=chr(isc)) then
  277. begin
  278. len:=isc_vax_integer(@result[2],2);
  279. delete(result,1,3); // remove cmd and len
  280. setlength(result,len);
  281. end;
  282. end;
  283. begin
  284. FServerImplementation:= QueryInfo(isc_info_svc_implementation);
  285. FServerLockDir:= QueryInfo(isc_info_svc_get_env_lock);
  286. FServerMsgDir:= QueryInfo(isc_info_svc_get_env_msg);
  287. FServerRootDir:= QueryInfo(isc_info_svc_get_env);
  288. FServerSecDBDir:= QueryInfo(isc_info_svc_user_dbpath);
  289. FServerVersion:= QueryInfo(isc_info_svc_server_version);
  290. end;
  291. function TFBAdmin.GetIBLongint(buffer: string; var bufptr: integer): longint;
  292. begin
  293. bufptr:=bufptr+1;
  294. result:=isc_vax_integer(@Buffer[bufptr], 4);
  295. bufptr:=bufptr+4;
  296. end;
  297. function TFBAdmin.GetIBString(buffer: string; var bufptr: integer): string;
  298. var
  299. len:integer;
  300. begin
  301. bufptr:=bufptr+1;
  302. len:=isc_vax_integer(@buffer[bufptr], 2);
  303. bufptr:=bufptr+2;
  304. result:=copy(buffer,bufptr,len);
  305. bufptr:=bufptr+len;
  306. end;
  307. function TFBAdmin.GetOutput(IBAdminAction: string): boolean;
  308. var
  309. len:integer;
  310. buffer:string;
  311. spb:string;
  312. const
  313. BUFFERSIZE=1000;
  314. begin
  315. len:=0;
  316. FOutput.Clear;
  317. spb:=chr(isc_info_svc_line);
  318. repeat
  319. setlength(buffer,BUFFERSIZE);
  320. result:=isc_service_query(@FStatus[0], @FSvcHandle, nil, 0, nil, length(spb),
  321. @spb[1],BUFFERSIZE,@buffer[1])=0;
  322. if not result then
  323. begin
  324. CheckError('GetOutput',FStatus);
  325. exit;
  326. end;
  327. if buffer[1]=chr(isc_info_svc_line) then
  328. begin
  329. len:=isc_vax_integer(@buffer[2],2);
  330. delete(buffer,1,3); // remove cmd and len
  331. setlength(buffer,len);
  332. FOutput.Add(buffer);
  333. if assigned(FOnOutput) then
  334. begin
  335. FOnOutput(Self,buffer,IBAdminAction);
  336. end;
  337. end;
  338. until len=0;
  339. end;
  340. constructor TFBAdmin.Create(AOwner: TComponent);
  341. begin
  342. inherited Create(AOwner);
  343. FPort:= 3050;
  344. FOutput:=TStringList.Create;
  345. FFixFssDataCharSet:= '';
  346. end;
  347. destructor TFBAdmin.Destroy;
  348. begin
  349. if FSvcHandle<>FB_API_NULLHANDLE then
  350. DisConnect;
  351. FOutput.Destroy;
  352. inherited Destroy;
  353. end;
  354. function TFBAdmin.Connect: boolean;
  355. var
  356. Service:string;
  357. spb:string;
  358. begin
  359. result:=false;
  360. {$IfDef LinkDynamically}
  361. result:=InitialiseIBase60<>0;
  362. {$EndIf}
  363. if FSvcHandle<>FB_API_NULLHANDLE then
  364. raise EIBDatabaseError.CreateFmt(SErrConnected,[Self.Name],nil,0,'');
  365. Service:='service_mgr';
  366. case FProtocol of
  367. IBSPTCPIP:if FPort=3050 then
  368. service:=FHost+':'+service
  369. else
  370. service:=FHost+'/'+IntTostr(FPort)+':'+service;
  371. IBSPNETBEUI:service:='\\'+FHost+'\'+service;
  372. IBSPNAMEDPIPE:service:='//'+FHost+'/'+service;
  373. end;
  374. spb:=chr(isc_spb_version)+chr(isc_spb_current_version)+
  375. IBParamSerialize(isc_spb_user_name,FUser)+
  376. IBParamSerialize(isc_spb_password,FPassword);
  377. result:=isc_service_attach(@FStatus[0], 0,PChar(Service), @FSvcHandle,
  378. length(spb), @spb[1]) = 0;
  379. if not result then
  380. CheckError('Connect',FStatus)
  381. else
  382. GetDBInfo;
  383. end;
  384. function TFBAdmin.DisConnect: boolean;
  385. begin
  386. result:=CheckConnected('DisConnect');
  387. result:= isc_service_detach(@FStatus[0], @FSvcHandle) = 0;
  388. if not result then
  389. CheckError('DisConnect',FStatus);
  390. FSvcHandle:=FB_API_NULLHANDLE;
  391. {$IfDef LinkDynamically}
  392. ReleaseIBase60;
  393. {$EndIf}
  394. result:=true;
  395. end;
  396. function TFBAdmin.Backup(Database, Filename: string; Options: TIBBackupOptions;
  397. RoleName: string): boolean;
  398. var
  399. spb:string;
  400. begin
  401. result:=CheckConnected('Backup');
  402. spb:=chr(isc_action_svc_backup)+IBSPBParamSerialize(isc_spb_dbname,Database)
  403. +IBSPBParamSerialize(isc_spb_bkp_file,Filename);
  404. if RoleName<>'' then
  405. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  406. if IBBkpVerbose in Options then
  407. spb:=spb+chr(isc_spb_verbose);
  408. spb:=spb+IBSPBParamSerialize(isc_spb_options,MakeBackupOptions(Options));
  409. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  410. @spb[1])=0;
  411. if not result then
  412. begin
  413. CheckError('Backup',FStatus);
  414. exit;
  415. end;
  416. if IBBkpVerbose in Options then
  417. result:=GetOutput('Backup');
  418. end;
  419. function TFBAdmin.BackupMultiFile(Database: string; Filenames: TStrings;
  420. FileSize: longint; Options: TIBBackupOptions; RoleName: string): boolean;
  421. var
  422. spb:string;
  423. i:integer;
  424. begin
  425. result:=CheckConnected('BackupMultiFile');
  426. spb:=chr(isc_action_svc_backup)+IBSPBParamSerialize(isc_spb_dbname,Database);
  427. for i:=0 to Filenames.Count-1 do
  428. begin
  429. spb:=spb+IBSPBParamSerialize(isc_spb_bkp_file,Filenames[i]);
  430. spb:=spb+IBSPBParamSerialize(isc_spb_bkp_length,FileSize);
  431. end;
  432. if RoleName<>'' then
  433. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  434. if IBBkpVerbose in Options then
  435. spb:=spb+chr(isc_spb_verbose);
  436. spb:=spb+IBSPBParamSerialize(isc_spb_options,MakeBackupOptions(Options));
  437. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  438. @spb[1])=0;
  439. if not result then
  440. begin
  441. CheckError('BackupMultiFile',FStatus);
  442. exit;
  443. end;
  444. if IBBkpVerbose in Options then
  445. result:=GetOutput('BackupMultiFile');
  446. end;
  447. function TFBAdmin.Restore(Database, Filename: string;
  448. Options: TIBRestoreOptions; RoleName: string): boolean;
  449. var
  450. spb:string;
  451. begin
  452. result:=CheckConnected('Restore');
  453. if not ((IBResReplace in Options) or (IBResCreate in Options)) then
  454. begin
  455. result:=false;
  456. IBRaiseError(0,SErrRestoreOptionsError,[self.Name]);
  457. exit;
  458. end;
  459. spb:=chr(isc_action_svc_restore)+IBSPBParamSerialize(isc_spb_dbname,Database)
  460. +IBSPBParamSerialize(isc_spb_bkp_file,Filename);
  461. if RoleName<>'' then
  462. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  463. if IBResVerbose in Options then
  464. spb:=spb+chr(isc_spb_verbose);
  465. if (IBResAMReadOnly in Options) or (IBResAMReadWrite in Options) then
  466. begin
  467. if (IBResAMReadOnly in Options) then //ReadOnly overrides ReadWrite
  468. spb:=spb+chr(isc_spb_res_access_mode)+chr(isc_spb_res_am_readonly)
  469. else
  470. spb:=spb+chr(isc_spb_res_access_mode)+chr(isc_spb_res_am_readwrite);
  471. end;
  472. if (IBFixFssData in Options) and (FixFssDataCharSet > ' ') then
  473. spb:=spb+IBSPBParamSerialize(isc_spb_res_fix_fss_data, FixFssDataCharSet);
  474. if (IBFixFssMeta in Options) and (FixFssDataCharSet > ' ') then
  475. spb:=spb+IBSPBParamSerialize(isc_spb_res_fix_fss_metadata, FixFssDataCharSet);
  476. spb:=spb+IBSPBParamSerialize(isc_spb_options,MakeRestoreOptions(Options));
  477. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  478. @spb[1])=0;
  479. if not result then
  480. begin
  481. CheckError('Restore',FStatus);
  482. exit;
  483. end;
  484. if IBResVerbose in Options then
  485. result:=GetOutput('Restore');
  486. end;
  487. function TFBAdmin.RestoreMultiFile(Database: string; Filenames: TStrings;
  488. Options: TIBRestoreOptions; RoleName: string): boolean;
  489. var
  490. spb:string;
  491. i:integer;
  492. begin
  493. result:=CheckConnected('RestoreMultiFile');
  494. if not ((IBResReplace in Options) or (IBResCreate in Options)) then
  495. begin
  496. result:=false;
  497. IBRaiseError(0,SErrRestoreMultiOptionsError,[self.Name]);
  498. exit;
  499. end;
  500. spb:=chr(isc_action_svc_restore)+IBSPBParamSerialize(isc_spb_dbname,Database);
  501. for i:=0 to Filenames.Count-1 do
  502. spb:=spb+IBSPBParamSerialize(isc_spb_bkp_file,Filenames[i]);
  503. if RoleName<>'' then
  504. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  505. if IBResVerbose in Options then
  506. spb:=spb+chr(isc_spb_verbose);
  507. if (IBResAMReadOnly in Options) or (IBResAMReadWrite in Options) then
  508. begin
  509. if (IBResAMReadOnly in Options) then //ReadOnly overrides ReadWrite
  510. spb:=spb+chr(isc_spb_res_access_mode)+chr(isc_spb_res_am_readonly)
  511. else
  512. spb:=spb+chr(isc_spb_res_access_mode)+chr(isc_spb_res_am_readwrite);
  513. end;
  514. spb:=spb+IBSPBParamSerialize(isc_spb_options,MakeRestoreOptions(Options));
  515. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  516. @spb[1])=0;
  517. if not result then
  518. begin
  519. CheckError('RestoreMultiFile',FStatus);
  520. exit;
  521. end;
  522. if IBResVerbose in Options then
  523. result:=GetOutput('RestoreMultiFile');
  524. end;
  525. function TFBAdmin.AddUser(UserName, Password: string; RoleName: string;
  526. GroupName: string; FirstName: string; MiddleName: string; LastName: string;
  527. UserID: longint; GroupID: longint): boolean;
  528. var
  529. spb:string;
  530. begin
  531. result:=CheckConnected('AddUser');
  532. spb:=chr(isc_action_svc_add_user)+IBSPBParamSerialize(isc_spb_sec_username,copy(UserName,1,31))+
  533. IBSPBParamSerialize(isc_spb_sec_password,copy(Password,1,8));
  534. if RoleName<>'' then
  535. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  536. if GroupName<>'' then
  537. spb:=spb+IBSPBParamSerialize(isc_spb_sec_groupname,copy(GroupName,1,31));
  538. if FirstName<>'' then
  539. spb:=spb+IBSPBParamSerialize(isc_spb_sec_firstname,copy(FirstName,1,255));
  540. if MiddleName<>'' then
  541. spb:=spb+IBSPBParamSerialize(isc_spb_sec_middlename,copy(MiddleName,1,255));
  542. if LastName<>'' then
  543. spb:=spb+IBSPBParamSerialize(isc_spb_sec_lastname,copy(LastName,1,255));
  544. if UserID<>0 then
  545. spb:=spb+IBSPBParamSerialize(isc_spb_sec_userid,UserID);
  546. if GroupID<>0 then
  547. spb:=spb+IBSPBParamSerialize(isc_spb_sec_groupid,GroupID);
  548. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  549. @spb[1])=0;
  550. if not result then
  551. CheckError('AddUser',FStatus);
  552. end;
  553. function TFBAdmin.ModifyUser(UserName, Password: string; RoleName: string;
  554. GroupName: string; FirstName: string; MiddleName: string; LastName: string;
  555. UserID: longint; GroupID: longint): boolean;
  556. var
  557. spb:string;
  558. begin
  559. result:=CheckConnected('ModifyUser');
  560. spb:=chr(isc_action_svc_modify_user)+IBSPBParamSerialize(isc_spb_sec_username,copy(UserName,1,31))+
  561. IBSPBParamSerialize(isc_spb_sec_password,copy(Password,1,8));
  562. if RoleName<>'' then
  563. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  564. if GroupName<>'' then
  565. spb:=spb+IBSPBParamSerialize(isc_spb_sec_groupname,copy(GroupName,1,31));
  566. if FirstName<>'' then
  567. spb:=spb+IBSPBParamSerialize(isc_spb_sec_firstname,copy(FirstName,1,255));
  568. if MiddleName<>'' then
  569. spb:=spb+IBSPBParamSerialize(isc_spb_sec_middlename,copy(MiddleName,1,255));
  570. if LastName<>'' then
  571. spb:=spb+IBSPBParamSerialize(isc_spb_sec_lastname,copy(LastName,1,255));
  572. if UserID<>0 then
  573. spb:=spb+IBSPBParamSerialize(isc_spb_sec_userid,UserID);
  574. if GroupID<>0 then
  575. spb:=spb+IBSPBParamSerialize(isc_spb_sec_groupid,GroupID);
  576. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  577. @spb[1])=0;
  578. if not result then
  579. CheckError('ModifyUser',FStatus);
  580. end;
  581. function TFBAdmin.DeleteUser(UserName: string; RoleName: string): boolean;
  582. var
  583. spb:string;
  584. begin
  585. result:=CheckConnected('DeleteUser');
  586. spb:=chr(isc_action_svc_delete_user)+IBSPBParamSerialize(isc_spb_sec_username,copy(UserName,1,31));
  587. if RoleName<>'' then
  588. spb:=spb+IBSPBParamSerialize(isc_spb_sql_role_name,copy(RoleName,1,31));
  589. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  590. @spb[1])=0;
  591. if not result then
  592. CheckError('DeleteUser',FStatus);
  593. end;
  594. function TFBAdmin.GetUser(UserName: string; var GroupName, FirstName,
  595. MiddleName, LastName: string; var UserID, GroupID: longint): boolean;
  596. var
  597. spb:string;
  598. buffer:string;
  599. bufptr:integer;
  600. const
  601. BUFFERSIZE=1000;
  602. begin
  603. result:=CheckConnected('GetUser');
  604. spb:=chr(isc_action_svc_display_user)+IBSPBParamSerialize(isc_spb_sec_username,copy(UserName,1,31));
  605. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  606. @spb[1])=0;
  607. if not result then
  608. begin
  609. CheckError('GetUser',FStatus);
  610. exit;
  611. end;
  612. //retrieve result
  613. spb:=chr(isc_info_svc_get_users);
  614. setlength(buffer,BUFFERSIZE);
  615. result:=isc_service_query(@FStatus[0], @FSvcHandle, nil, 0, nil, length(spb),
  616. @spb[1],BUFFERSIZE,@buffer[1])=0;
  617. if not result then
  618. begin
  619. CheckError('GetUser',FStatus);
  620. exit;
  621. end;
  622. bufptr:=4;
  623. if buffer[1]=chr(isc_info_svc_get_users) then
  624. begin
  625. if buffer[bufptr]=chr(isc_info_end) then
  626. begin
  627. result:=false;
  628. IBRaiseError(0,SErrUserDoesNotExist,[self.Name]);
  629. exit;
  630. end;
  631. while buffer[bufptr]<>chr(isc_info_end) do
  632. begin
  633. case buffer[bufptr] of
  634. chr(isc_spb_sec_username):GetIBString(buffer,bufptr); //trash result
  635. chr(isc_spb_sec_groupname):GroupName:=GetIBString(buffer,bufptr);
  636. chr(isc_spb_sec_firstname):FirstName:=GetIBString(buffer,bufptr);
  637. chr(isc_spb_sec_middlename):MiddleName:=GetIBString(buffer,bufptr);
  638. chr(isc_spb_sec_lastname):LastName:=GetIBString(buffer,bufptr);
  639. chr(isc_spb_sec_userid):UserID:=GetIBLongint(buffer,bufptr);
  640. chr(isc_spb_sec_groupid):GroupID:=GetIBLongint(buffer,bufptr);
  641. else
  642. begin
  643. result:=false;
  644. IBRaiseError(0,SErrUserInvalidReply,[self.Name,ord(buffer[bufptr])]);
  645. exit;
  646. end;
  647. end;
  648. end;
  649. end;
  650. end;
  651. function TFBAdmin.GetUsers(Users: TStrings): boolean;
  652. var
  653. spb:string;
  654. buffer:string;
  655. bufptr:integer;
  656. const
  657. BUFFERSIZE=1000;
  658. begin
  659. result:=CheckConnected('GetUsers');
  660. spb:=chr(isc_action_svc_display_user);
  661. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  662. @spb[1])=0;
  663. if not result then
  664. begin
  665. CheckError('GetUsers',FStatus);
  666. exit;
  667. end;
  668. //retrieve result
  669. spb:=chr(isc_info_svc_get_users);
  670. setlength(buffer,BUFFERSIZE);
  671. result:=isc_service_query(@FStatus[0], @FSvcHandle, nil, 0, nil, length(spb),
  672. @spb[1],BUFFERSIZE,@buffer[1])=0;
  673. if not result then
  674. begin
  675. CheckError('GetUsers',FStatus);
  676. exit;
  677. end;
  678. bufptr:=4;
  679. Users.Clear;
  680. if buffer[1]=chr(isc_info_svc_get_users) then
  681. begin
  682. while buffer[bufptr]<>chr(isc_info_end) do
  683. begin
  684. case buffer[bufptr] of
  685. chr(isc_spb_sec_username):Users.Add(GetIBString(buffer,bufptr));
  686. chr(isc_spb_sec_groupname),
  687. chr(isc_spb_sec_firstname),
  688. chr(isc_spb_sec_middlename),
  689. chr(isc_spb_sec_lastname):GetIBString(buffer,bufptr); //trash result
  690. chr(isc_spb_sec_userid),
  691. chr(isc_spb_sec_groupid):GetIBLongint(buffer,bufptr); //trash result
  692. else
  693. begin
  694. result:=false;
  695. IBRaiseError(0,SErrUsersInvalidReply,[self.Name,ord(buffer[bufptr])]);
  696. exit;
  697. end;
  698. end;
  699. end;
  700. end;
  701. end;
  702. function TFBAdmin.GetDatabaseLog: boolean;
  703. var
  704. spb:string;
  705. begin
  706. result:=CheckConnected('GetLogFile');
  707. spb:=chr(isc_action_svc_get_ib_log);
  708. result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  709. @spb[1])=0;
  710. if not result then
  711. begin
  712. CheckError('GetLogFile',FStatus);
  713. exit;
  714. end;
  715. result:=GetOutput('GetLogFile');
  716. end;
  717. function TFBAdmin.GetDatabaseStats(Database:string;Options: TIBStatOptions; TableNames: String
  718. ): boolean;
  719. var
  720. spb:string;
  721. param: Integer;
  722. begin
  723. Result:=CheckConnected('GetDatabaseStats');
  724. param := 0;
  725. if (IBDataPages in Options) then
  726. param := param or isc_spb_sts_data_pages;
  727. if (IBDbLog in Options) then
  728. param := param or isc_spb_sts_db_log;
  729. if (IBHeaderPages in Options) then
  730. param := param or isc_spb_sts_hdr_pages;
  731. if (IBIndexPages in Options) then
  732. param := param or isc_spb_sts_idx_pages;
  733. if (IBSystemRelations in Options) then
  734. param := param or isc_spb_sts_sys_relations;
  735. if (IBRecordVersions in Options) then
  736. param := param or isc_spb_sts_record_versions;
  737. if (IBStatTables in Options) then
  738. param := param or isc_spb_sts_table;
  739. spb := Char(isc_action_svc_db_stats)+IBSPBParamSerialize(isc_spb_dbname,Database)+
  740. IBSPBParamSerialize(isc_spb_options, param);
  741. if (IBStatTables in Options) and (TableNames <> '') then
  742. spb := spb+IBSPBParamSerialize(isc_spb_command_line, TableNames);
  743. Result:=isc_service_start(@FStatus[0], @FSvcHandle, nil, length(spb),
  744. @spb[1])=0;
  745. if not Result then
  746. begin
  747. CheckError('GetDatabaseStats',FStatus);
  748. exit;
  749. end;
  750. Result:=GetOutput('GetDatabaseStats');
  751. end;
  752. end.