Monthly Archiv: November, 2012

Resep “Jamu manjur” agar data Interbase lebih sakti

Seperti yang telah kita ketahui bersama, Interbase dengan dukungan fitur keamanan yang baru yaitu Embedded User Authentication (EUA) yang telah ada sejak Interbase versi 7.5, sebenarnya data kita sudah cukup aman.

Namun mungkin kita belum puas dan belum merasa aman dengan yang ada, berikut ini ada sedikit resep agar data kita lebih aman dan lebih kebal dari tangan orang-orang yang “mungkin” jahil/iseng.

Seperti yang kita ketahui juga sebuah object (table, procedure dll) , hanya dapat dibaca atau dijalankan oleh SYSDBA, user yang membuat atau user lain yang diberi hak, namun tidak ada batasan atau larangan bagi user lain untuk membuat object baru.

Pada “ramuan jamu” kali ini kita akan membuat agar data Interbase kita lebih aman diantaranya membatasi hanya SYSDBA yang dapat membuat object (table, procedure, trigger, view, ganerator dll)  baru, hanya SYSDBA dan user yang bersangkutan yang dapat melihat daftar user.

Pada postingan sebelumnya telah dibahas cara untuk menghapus source code pada procedure, trigger atau view.

Pada kesempatan kali ini kita bukan menghapus source codenya namun kita akan menyembunyikan daftar procedurenya sehingga user tidak tahu ada procedure apa aja dalam database.

Rasanya untuk uraian gak perlu panjang lebar langsung saja ini resepnya …

/*-------------------------------------------------------------*
 * STANDAR SECURITY FOR INTERBASE PROJECT                      *
 * BY IMAM CHALIMI FEBRUARY, 2010                              *
 * Last Update January 22, 2013                                *
 * 29/10/2012 - Prevent Other user create/delete generator     *
 * 22/01/2012 - Add DATA field for users                       *
 *-------------------------------------------------------------*/

/*--------------------------------------------------------------
 *    Revoke all access on system tables from PUBLIC
 *--------------------------------------------------------------
 */

REVOKE ALL ON RDB$CHARACTER_SETS       FROM PUBLIC;
REVOKE ALL ON RDB$COLLATIONS           FROM PUBLIC;
REVOKE ALL ON RDB$CHECK_CONSTRAINTS    FROM PUBLIC;
REVOKE ALL ON RDB$DATABASE             FROM PUBLIC;
REVOKE ALL ON RDB$DEPENDENCIES         FROM PUBLIC;
REVOKE ALL ON RDB$EXCEPTIONS           FROM PUBLIC;
REVOKE ALL ON RDB$FIELD_DIMENSIONS     FROM PUBLIC;
REVOKE ALL ON RDB$FIELDS               FROM PUBLIC;
REVOKE ALL ON RDB$FILES                FROM PUBLIC;
REVOKE ALL ON RDB$FILTERS              FROM PUBLIC;
REVOKE ALL ON RDB$FORMATS              FROM PUBLIC;
REVOKE ALL ON RDB$FUNCTION_ARGUMENTS   FROM PUBLIC;
REVOKE ALL ON RDB$FUNCTIONS            FROM PUBLIC;
REVOKE ALL ON RDB$GENERATORS           FROM PUBLIC;
REVOKE ALL ON RDB$INDEX_SEGMENTS       FROM PUBLIC;
REVOKE ALL ON RDB$INDICES              FROM PUBLIC;
REVOKE ALL ON RDB$LOG_FILES            FROM PUBLIC;
REVOKE ALL ON RDB$PAGES                FROM PUBLIC;
REVOKE ALL ON RDB$PROCEDURE_PARAMETERS FROM PUBLIC;
REVOKE ALL ON RDB$PROCEDURES           FROM PUBLIC;
REVOKE ALL ON RDB$REF_CONSTRAINTS      FROM PUBLIC;
REVOKE ALL ON RDB$RELATION_CONSTRAINTS FROM PUBLIC;
REVOKE ALL ON RDB$RELATION_FIELDS      FROM PUBLIC;
REVOKE ALL ON RDB$RELATIONS            FROM PUBLIC;
REVOKE ALL ON RDB$ROLES                FROM PUBLIC;
REVOKE ALL ON RDB$SECURITY_CLASSES     FROM PUBLIC;
REVOKE ALL ON RDB$TRANSACTIONS         FROM PUBLIC;
REVOKE ALL ON RDB$TRIGGER_MESSAGES     FROM PUBLIC;
REVOKE ALL ON RDB$TRIGGERS             FROM PUBLIC;
REVOKE ALL ON RDB$TYPES                FROM PUBLIC;
REVOKE ALL ON RDB$USER_PRIVILEGES      FROM PUBLIC;
REVOKE ALL ON RDB$USERS                FROM PUBLIC;
REVOKE ALL ON RDB$VIEW_RELATIONS       FROM PUBLIC;

/*--------------------------------------------------------------
 *    Read only access on many system tables from PUBLIC
 *--------------------------------------------------------------
 */

GRANT SELECT ON RDB$DATABASE             TO PUBLIC;
GRANT SELECT ON RDB$CHARACTER_SETS       TO PUBLIC;
GRANT SELECT ON RDB$FIELD_DIMENSIONS     TO PUBLIC;
GRANT SELECT ON RDB$FIELDS               TO PUBLIC;
GRANT SELECT ON RDB$RELATION_FIELDS      TO PUBLIC;
GRANT SELECT ON RDB$RELATIONS            TO PUBLIC;
GRANT SELECT ON RDB$USER_PRIVILEGES      TO PUBLIC;
GRANT SELECT ON RDB$PROCEDURE_PARAMETERS TO PUBLIC;
GRANT SELECT ON RDB$FILES                TO PUBLIC;
GRANT SELECT ON RDB$LOG_FILES            TO PUBLIC;

/* Required by IB-Expert */
GRANT SELECT ON RDB$DEPENDENCIES         TO PUBLIC;
GRANT SELECT ON RDB$COLLATIONS           TO PUBLIC;
GRANT SELECT ON RDB$INDEX_SEGMENTS       TO PUBLIC;
GRANT SELECT ON RDB$RELATION_CONSTRAINTS TO PUBLIC;
GRANT SELECT ON RDB$INDICES              TO PUBLIC;
GRANT SELECT ON RDB$REF_CONSTRAINTS      TO PUBLIC;

/*--------------------------------------------------------------
 *    Allow Access on Temporary Table to Public
 *--------------------------------------------------------------
 */

GRANT SELECT ON TMP$DATABASE TO PUBLIC;
GRANT SELECT ON TMP$ATTACHMENTS TO PUBLIC;

/*--------------------------------------------------------------
 *    Prevent public user to create new object
 *--------------------------------------------------------------
 */

CREATE EXCEPTION EX_SYSDBA_ONLY 'Only SYSDBA can create/delete object';

SET TERM ^ ;

CREATE TRIGGER RDB$DATABASE_BU FOR RDB$DATABASE
ACTIVE BEFORE UPDATE POSITION 0
AS
BEGIN
     IF (USER<>'SYSDBA') THEN
        EXCEPTION EX_SYSDBA_ONLY;
END
^
CREATE TRIGGER RDB$PROCEDURES_BI FOR RDB$PROCEDURES
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
     IF (USER<>'SYSDBA') THEN
     EXCEPTION EX_SYSDBA_ONLY;
END
^
CREATE TRIGGER RDB$TRIGGERS_BI FOR RDB$TRIGGERS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
     IF (USER<>'SYSDBA') THEN
     EXCEPTION EX_SYSDBA_ONLY;
END
^
CREATE TRIGGER RDB$GENERATORS_BD FOR RDB$GENERATORS
ACTIVE BEFORE DELETE POSITION 0
AS
BEGIN
     IF (USER<>'SYSDBA') THEN
        EXCEPTION EX_SYSDBA_ONLY;
END
^
CREATE TRIGGER RDB$GENERATORS_BI FOR RDB$GENERATORS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
     IF (USER<>'SYSDBA') THEN
        EXCEPTION EX_SYSDBA_ONLY;
END
^

SET TERM ; ^

ALTER TABLE RDB$USERS
ADD DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80;

CREATE VIEW RDB$VW_USERS
AS
  SELECT *
  FROM RDB$USERS
  WHERE
       USER='SYSDBA' OR
       USER=RDB$USER_NAME;

GRANT SELECT ON RDB$VW_USERS TO PUBLIC;
GRANT UPDATE(RDB$FIRST_NAME,RDB$MIDDLE_NAME,RDB$LAST_NAME,DATA) ON RDB$VW_USERS TO PUBLIC;

COMMIT;

/* ---- */

Script SQLnya dapat didownload di https://www.box.com/s/0dxp1pf9ficxxf2rm5x6

Catatan:

Resep ini hanya (lebih) cocok untuk Interbase dengan fitur Embedded User Authentication (EUA)  diaktifkan

Mengoptimalkan kemampuan VCL IBX (Interbase Express)

Seperti diketahui bersama banyak sekali vcl untuk koneksi data Interbase menggunakan Delphi, salah satunya dan yang kaya fitur adalah FIBPlus, sayangnya FIBplus ini berbayar.

Pada kesempatan kali ini kita akan mencoba mengoptimalkan VCL IBX (IBExpress) dengan pertimbangan IBX ini adalah VCL bawaan Delphi.

Kita akan mencoba memasukkan beberapa fitur yang ada di FIBPlus kedalam IBX.

Beberapa fitur yang akan kita tambahkan diantaranya :

  • Auto Commit .. Commit otomatis setelah Post
  • Simple Query .. Query sederhana tanpa komponen
  • GetServerTime .. Membaca jam pada server
  • Gen_ID  .. Mengambil nilai generator (Auto Number)
  • Default Value .. Nilai default akan terisi otomatis
  • Numeric Format .. Field Numeric akan ditampilkan berformat
  • Show Memo Text .. Text asli akan ditampilkan di Field Memo
  • Konfirmasi penghapusan (pada Actionlist)

Langsung saja ini source kodenya ..

unit IBXPlus;
(*
  Advanced IBExpress by Imam Chalimi
  First Release November 11, 2012
  Last Update November 24, 2012

  Feature :
  - Delete Confirmation (ActionList)
  - Simple Query
  - Gen_ID
  - GetServerTime
  - AutoCommit
  - AutoFill Default Value
  - AutoFormat Numeric Field
  - Show Memo Text
*)

interface

uses Windows, IBCustomDataSet, IBDataBase, DB, SysUtils,
     Classes, Variants, DBActns, Forms, VsrWindows;

type
  TDataSetDelete = class(DBActns.TDataSetDelete)
  public
    procedure ExecuteTarget(Target: TObject); override;
  end;
  TIBDataBase = class(IBDataBase.TIBDataBase)
  public
    function QueryValue(sSQL:string;sParam:array of Variant):Variant;
    function QueryValues(sSQL:string;sParam:array of Variant):Variant;
    function Gen_ID(sGenID:string;iStep:Int64):Int64;
    function Execute(sSQL:string;sParam:array of Variant):Boolean;
    function GetServerTime:TDateTime;
  end;
  TIBDataSet = class(IBCustomDataSet.TIBDataSet)
  private
    procedure InternalCommit;
  public
    procedure AutoGenerateSQLs;
  published
    procedure DoAfterPost; override;
    procedure DoOnNewRecord; override;
    procedure DoAfterDelete; override;
    procedure DoAfterOpen; override;
  end;
  TIBBCDField = class(IBCustomDataSet.TIBBCDField)
  public
    constructor Create(AOwner: TComponent); override;
  end;
  TMemoField = class(DB.TMemoField)
    procedure GetText(var Text: string;
              DisplayText: Boolean); override;
  end;

{Global Variable}
var
   IBX_AutoComit,
   IBX_ShowID,
   IBX_ShowBlob,
   IBX_DefaultValue: Boolean;

implementation

{ TIBDataSet }

procedure TIBDataSet.AutoGenerateSQLs;
begin
(*
  == Menyusul ... ==
*)
//     InsertSQL.Text:='';
//     DeleteSQL.Text:='';
//     ModifySQL.Text:='';
//     RefreshSQL.Text:='';
end;

procedure TIBDataSet.DoAfterDelete;
begin
  inherited;
  InternalCommit;
end;

procedure TIBDataSet.DoAfterOpen;
var
   i: Integer;
begin
  inherited;
  for i:=0 to Fields.Count-1 do
  with Fields[i] do
  case DataType of
       ftInteger: if ((FieldName='ID') or
                     (Copy(FieldName,Length(FieldName)-3,3)='_ID')) then
                  begin
                       DisplayWidth:=5;
                       if FieldName='ID' then
                          ReadOnly:=True;
                       Visible:=IBX_ShowID;
                  end;
       ftBlob: Visible:=IBX_ShowBlob;
       ftDate: EditMask:='99/99/9999';
  end;
end;

procedure TIBDataSet.DoAfterPost;
begin
  inherited;
  InternalCommit;
end;

procedure TIBDataSet.DoOnNewRecord;
var
   i: Integer;
   s: string;
begin
  if IBX_DefaultValue then
  for i:=0 to FieldCount-1 do
  begin
       s:='SELECT F.RDB$DEFAULT_SOURCE ' +
          'FROM RDB$RELATION_FIELDS F ' +
          'WHERE F.RDB$RELATION_NAME=:X ' +
          'AND F.RDB$FIELD_NAME=:Y ' +
          'AND F.RDB$DEFAULT_SOURCE STARTING WITH ''DEFAULT''';
          s:=TIBDataBase(Database).
             QueryValue(s,[PSGetTableName,Fields[i].FieldName]);
          System.Delete(s,1,8);
          s:='SELECT '+Trim(s)+' FROM RDB$DATABASE';
          try
             Fields[i].Value:=TIBDataBase(Database).QueryValue(s,[]);
          except
          end;
  end;
  inherited;
end;

procedure TIBDataSet.InternalCommit;
begin
  if IBX_AutoComit and
     (Tag<>999) then
     Transaction.CommitRetaining;
end;

{ TIBBCDField }

constructor TIBBCDField.Create(AOwner: TComponent);
begin
  inherited;
  DisplayFormat:='#,##0.00';
end;

{ TIBDataBase }

function TIBDataBase.Execute(sSQL: string; sParam: array of Variant): Boolean;
var
   i: Integer;
begin
     with TIBDataSet.Create(nil) do
     begin
          Database:=Self;
          SelectSQL.Text:=sSQL;
          Prepare;
          if Length(sParam)>0 then
          begin
               for i:=0 to Length(sParam)-1 do
                   Params[i].Value:=sParam[i];
               Prepare;
          end;
          ExecSQL;
          InternalCommit;
          Free;
     end;
end;

function TIBDataBase.Gen_ID(sGenID: string; iStep: Int64): Int64;
begin
     with TIBDataSet.Create(nil) do
     begin
          Database:=Self;
          SelectSQL.Text:=Format('SELECT GEN_ID(%s,%d) ' +
                                 'FROM RDB$DATABASE',[sGenID,iStep]);
          Open;
          Result:=Fields[0].AsInteger;
          Close;
          Free;
     end;
end;

function TIBDataBase.QueryValue(sSQL: string;sParam:array of Variant): Variant;
var
   i: Integer;
begin
     with TIBDataSet.Create(nil) do
     begin
          Database:=Self;
          SelectSQL.Text:=sSQL;
          if Length(sParam)>0 then
          begin
               for i:=0 to Length(sParam)-1 do
                   Params[i].Value:=sParam[i];
               Prepare;
          end;
          Open;
          Result:=Fields[0].Value;
          Close;
          Free;
     end;
end;

function TIBDataBase.QueryValues(sSQL: string;
  sParam: array of Variant): Variant;
var
   i: Integer;
begin
     with TIBDataSet.Create(nil) do
     begin
          Database:=Self;
          SelectSQL.Text:=sSQL;
          if Length(sParam)>0 then
          begin
               for i:=0 to Length(sParam)-1 do
                   Params[i].Value:=sParam[i];
               Prepare;
          end;
          Open;
          Result:=VarArrayCreate([0,FieldCount-1],varVariant);
          for i:=0 to Fields.Count-1 do
              Result[i]:=Fields[i].Value;
          Close;
          Free;
     end;
end;

function TIBDataBase.GetServerTime: TDateTime;
begin
     with TIBDataSet.Create(nil) do
     begin
          Database:=Self;
          SelectSQL.Text:='SELECT CURRENT_TIMESTAMP ' +
                          'FROM RDB$DATABASE';
          Open;
          Result:=Fields[0].AsDateTime;
          Close;
          Free;
     end;
end;

{ TDataSetDelete }

procedure TDataSetDelete.ExecuteTarget(Target: TObject);
begin
     if MessageBox(Application.Handle,'Yakin Dihapus ?','Konfirmasi',MB_YESNO)=IDYES then
        inherited;
end;

{ TMemoField }

procedure TMemoField.GetText(var Text: string; DisplayText: Boolean);
begin
  Text:=GetAsString;
end;

initialization
  IBX_AutoComit:=True;
  IBX_ShowID:=False;
  IBX_ShowBlob:=False;
  IBX_DefaultValue:=False;

end.

Untuk menggunakan unit ini cukup mudah, tambahkan IBXPlus pada klausa uses.

Yang perlu diperhatikan penulisan IBXPlus pada klausa uses harus diletakkan paling belakang atau setelah unit uses IBxxxx.

contoh:

Windows, Messages, SysUtils, Variants, Classes, Graphics, 
Controls, Forms, Dialogs, ExtCtrls, DBCtrls, Grids, DBGrids, 
DB, IBCustomDataSet, IBDatabase, IBXPlus;

Unit yang sudah siap pakai (khusus delphi 7 dan Delphi 2006/Turbo Delphi) dapat di download di:

Semoga bermanfaat

Mengamankan source code procedure & trigger pada Interbase

Procedure dan trigger sangat membantu sekali dalam melakukan optimasi pada database sehingga penggunakan query yang rumit dapat dikurangi dan tentunya akan meningkatkan performa.

Namun ada kalanya dalam sebuah procedure atau trigger kita menggunakan “resep rahasia” yang tidak boleh diketahui oleh orang lain.

Pada saat membuat procedure/trigger Interbase melakukan kompilasi dari source code yang kita buat menjadi sebuah binary code atau yang disebut BLR (Binary Language Representation), disisi lain akan mencadangkan source code aslinya untuk memudahkan bila kita ingin memodifikasi di kemudian hari.

Cara mengamankan supaya tidak dapat dilihat orang lain yaitu dengan menghapus source codenya.

Apakah dengan menghapus source codenya tidak berpengaruh pada database ? Tidak, Source code tidak dibutuhkan oleh Interbase, Interbase hanya membutuhkan code yang telah dikomplasi (BLR).

OK, langsung saja …
Sebelum melakukan hal ini ada baiknya membuat backup dalam bentuk metadata atau textfile agar bila suatu saat ingin mengedit procedure tidak kesulitan.

Untuk menghapus source code dari procedure …

UPDATE RDB$PROCEDURES
SET RDB$PROCEDURE_SOURCE = NULL

bila hanya ingin menghapus source code dari procedure tertentu bisa ditambahkan

WHERE RDB$PROCEDURE_NAME = 'blablabla';

Sedangkan untuk menghapus source code dari trigger …

UPDATE RDB$TRIGGERS
SET RDB$TRIGGER_SOURCE=NULL
WHERE UPPER(RDB$TRIGGER_SOURCE) STARTING WITH 'AS'

bila hanya ingin menghapus source code dari trigger tertentu bisa ditambahkan

AND RDB$TRIGGER_NAME = 'blablabla';

Semoga bermanfaat

Agar Firebird Server dapat jalan berdampingan dengan Interbase Server

Bagaimana caranya agar Firebird Server dapat jalan berdampingan dengan Interbase Server dalam satu komputer.

Tulisan berikut ini mungkin bisa  menjadi sebuah solusi bagi yang ingin mencoba Interbase namun belum bisa meninggalkan Firebird.

Seperti kita ketahui bersama Firebird dan Interbase secara default menggunakan alamat port (3050) dan nama library yang sama (gds32.dll).

Untuk alamat port  sebenarnya baik Interbase maupun Firebird sama2 bisa dirubah, namun karena tujuan akhir adalah menggunakan Interbase maka yang kita bahas dalam tulisan berikut ini adalah mengganti port firebird menjadi 3051 dan mengembalikan nama library firebird menjadi nama dia sendiri yaitu fbclient.dll (optional, bisa juga tidak dirubah tapi nantinya gds32 punya firebird harus dicopykan jadi satu folder dengan client aplikasi yang menggunakan firebird).

Ada sedikit perubahan untuk mengakses database firebird dari sisi client, jika sebelumnya data diakses menggunakan alamat 192.168.0.1:c:\data.fb\dataku.fdb maka untuk selanjutnya dipanggil dengan menggunakan  192.168.0.1/3051:c:\data.fb\dataku.fdb

kita mulai sajalah, cuman perlu beberapa langkah …

  • buka file firebird.conf (ada di folder tempat firebird diinstall) dengan menggunakan notepad.
  • cari baris #RemoteServicePort = 3050 (bisa gunakan Ctrl+F)
  • buang tanda # dan rubah angka 3050 menjadi 3051
  • sehingga setelah dirubah akan menjadi  RemoteServicePort = 3051
  • rubah file gds32.dll yang ada di windowssystem32 menjadi fbclient.dll
  • Restart Firebird server atau sekalian restart komputernya jika kesulitan
  • Install Interbase Server

Sekarang kita dapat menggunakan Interbase Server dan Firebird server dalam satu komputer.

Beberapa komponen koneksi vcl seperti FIBPlus/DBExpress memang memperbolehkan kita mendefinisikan client library yang berbeda, namun pada konenksi vcl seperti IBExpress dan Zeos kita tidak dapat merubahnya, kita dipaksa untuk menggunakan library standar yaitu gds32.dll.

Bila kita menggunakan vcl yang tidak mengijinkan client librarynya dirubah atau kita tidak mau compile ulang project Firebird yang sudah jadi solusinya adalah dengan mengcopy gds32.dll punya Firebird ke folder tempat projectnya berada, begitu juga dengan Project Interbase juga dicopykan gds32.dll punya Intebase ke folder tempat projectnya berada.

Jadi nantinya pemanggilan database dengan cara seperti ini …

192.168.0.1:c:\data.ib\dataku.ib => Interbase
 192.168.0.1/3051:c:\data.fb\dataku.fdb => Firebird

Membuat sendiri aplikasi Online Dump menggunakan Delphi

Online Dump atau Incremental backup merupakan salah satu variant backup dalam Interbase.

Yang membedakan dengan backup biasa adalah, pada Online Dump backupnya bisa nyambung tidak selalu dimulai dari awal, ini sangat berguna untuk data yang besar tapi harus sering backup.

Selain bisa nyambung hasil dari Online Dump bisa langsung dipakai hanya dengan merubah attributnya, tanpa harus ada proses restore yang memakan waktu lama.

Sebenarnya Interbase sudah menyediakan tool untuk melakukan Online Backup ini yaitu dengan commandline

gbak.exe -d 127.0.0.1:DATA_AKTIF d:\backupdata_aktif.dump -user SYSDBA -pass masterkey

Pada Delphi kita bisa langsung memanggil commandline diatas menggunakan WinExec, ShellExecute atau Create prosess.

Namun yang kita bahas kali ini adalah menjalankan Online menggunakan Interbase API, menggunakan Delphi tanpa bantuan VCL apapun.

Sebenarnya fitur ini sudah include di VCL IBExpress versi 10.11 keatas (VCL bawaan delphi yang dibundling dengan Interbase 2007),  tapi gpplah itung belajar.

Dengan menggunakan API hasilnya akan lebih “bersih” karena user/password bisa diencrypt, tidak seperti menjalankan commandline yang parameternya masih bisa “di-intip” menggunakan software sejenis Proccess Explorer.

Untuk melakukan  Online dump kita menggunakan fungsi  isc_attach_database yang ada di library gds32.dll.

Dalam melakukan pemanggilan Interbase API, sebelumnya kita perlu mengirimkan parameter dalam format block, dikirim berurutan dalam bentuk character/string.

Untuk Online Dump, parameter block yang dikirim sbb:

     
#01 1/isc_dpb_version1 sebagai tanda awal parameter block
#1C 28/isc_dpb_user_name sebagai tanda akan mengirim user
#06 6 adalah panjang user
'sysdba' nama user
#1D 29/isc_dpb_password sebagai tanda akan mengirim password
#09 9 adalah panjang password
'masterkey' ini passwordnya
#21 33/isc_dpb_online_dump proses yang akan dikerjakan
#01 panjang perintah = 1
#01 (1) nilainya selalu 1
#36 54/isc_dpb_overwrite disambung/ditindih
#01 panjang perintah = 1
#00 (0) diisi 0 untuk menyambung atau 1 untuk menindih
#24 36/isc_dpb_old_file_name sebagai tanda akan mengirim nama file tujuan backup
#0E 14 panjang nama file
'c:barang.dump' ini nama filenya
#22 34/isc_dpb_old_file_size jumlah filenya
#01 panjang perintah = 1
#01 diisi 1

Untuk lebih jelasnya dapat dilihat pada contoh coding berikut

program VsrOnLineDump;
uses
    Windows;

const
     ISC_SPB_CURRENT_VERSION    = #2;
     ISC_SPB_VERSION            = #2;
     ISC_SPB_USER_NAME          = #28;
     ISC_SPB_PASSWORD           = #29;

     ISC_DPB_VERSION1           = #1;
     ISC_DPB_USER_NAME          = ISC_SPB_USER_NAME;
     ISC_DPB_PASSWORD           = ISC_SPB_PASSWORD;

     ISC_DPB_ONLINE_DUMP        = #33;
     ISC_DPB_OLD_FILE_SIZE      = #34;
     ISC_DPB_OLD_FILE_NAME      = #36;
     ISC_DPB_OVERWRITE          = #54;

     DLL                        = 'gds32.dll';

type
    ISC_HANDLE          = HWND;
    TISC_DB_HANDLE      = ^ISC_HANDLE;
    ISC_STATUS          = Longint;
    PISC_STATUS         = ^ISC_STATUS;
    PISC_DB_HANDLE      = ^TISC_DB_HANDLE;

var
   FDPB: string;
   FDBHandle: TISC_DB_HANDLE;
   FStatus: PISC_STATUS;
   FDBName, FTargetDB, FUser, FPass: string;
   bOverwrite: Boolean;

function AddDPB(cKey: char; sItem: string): Integer;
begin
     if sItem='' then
        FDPB:=FDPB+cKey
     else
         FDPB:=FDPB+cKey+chr(Length(sItem))+sItem;
     Result:=Length(FDPB);
end;

function isc_attach_database(status_vector:PISC_STATUS;
         db_name_length:Short;
         db_name:PChar;
         db_handle:PISC_DB_HANDLE;
         parm_buffer_length: Short;
         parm_buffer:PChar):ISC_STATUS;
         stdcall;external DLL;

begin
     FDBName:='127.0.0.1:DATA_AKTIF';
     FTargetDB:='d:\backupdata_aktif.dump';
     FUser:='SYSDBA';
     FPass:='masterkey';
     bOverwrite:=False;
     FDPB:=ISC_DPB_VERSION1;
     AddDPB(ISC_DPB_USER_NAME,FUser);
     AddDPB(ISC_DPB_PASSWORD,FPass);
     FDBHandle:=nil;
     AddDPB(ISC_DPB_ONLINE_DUMP,#1);
     AddDPB(ISC_DPB_OVERWRITE,chr(Byte(bOverwrite)));
     AddDPB(ISC_DPB_OLD_FILE_NAME,FTargetDB);
     AddDPB(ISC_DPB_OLD_FILE_SIZE,#1);
     if isc_attach_database(@FStatus,
        0,PChar(FDBName), @FDBHandle,
        Length(FDPB),PChar(FDPB))=0 then
        // MessageBox jika diperlukan
        ;
end.

Dengan membuat coding sendiri menggunakan delphi kita dapat dengan leluasa mengatur jadwal Online Dump, misalnya kita buat per 10 menit, per 30 menit, dibuat perhari dibackup dengan tujuan beda-beda (ada 7 file tujuan sesuai dengan jumlah hari).

Selain itu dengan membuat coding sendiri akan sedikit lebih keren dan punya nilai sendri dimata pengguna (klien).