Category Archives: Interbase

Membuat Realtime Search menggunakan Delphi & Firebird


Assalamu’alaikum Wr Wb,
Beberapa waktu yang lalu saya pernah berbagi Aplikasi RealTime Search menggunakan database Interbase di media sosial Facebook https://www.facebook.com/notes/komunitas-programmer-delphi-dan-interbase-indonesia/contoh-aplikasi-realtime-search-menggunakan-interbase/480900875287982.
Kali ini saya ingin berbagi aplikasi yang sama dengan menggunakan database Firebird dengan beberapa perbaikan yaitu dengan menambahkan beberapa komentar di source code sehingga lebih mudah di pelajari.
Apa fungsi aplikasi ini, tentunya sudah banyak yang tahu yaitu sebuah aplikasi yang secara otomatis akan melakukan pencarian setelah kita mengetikkan beberapa huruf tanpa menunggu kita menekan enter atau klik button.
Aplikasi ini saya buat menggunakan Turbo Delphi (Delphi 2006) dan insya Alloh tidak masalah dibuka menggunakan Delphi versi lain.
Komponen yang digunakan pada aplikasi ini adalah IBX (Interbase) bawaan delphi dan Alpha Skin.
Untuk databasenya menggunakan Firebird 2.54 yang bisa didownload gratis di situs resminya ( http://www.firebirdsql.org/en/firebird-2-5-4/ ) bila belum punya.
Untuk yang belum punya Firebird dan belum ingin menginstall Firebird bisa mencoba Firebird versi Embeded (tanpa install).
Oke dah, langsung saja sedot aplikasinya di https://app.box.com/s/5oi1saxu1ob7qo7a4nwmfbddsxh37470
Untuk versi FB Embeded silahkan download https://app.box.com/s/l58u0a18hp2gy8rxy44xn50djzlf5tfp dan copykan menjadi satu folder dengan aplikasinya.
Demikian semoga bermanfaat.
Bila ada kesulitan bisa ditulis dikolom komentar atau diposting ke grup Komunitas programmer Delphi dan Interbase Indonesia

Cara menginisialisasi manajemen user perdatabase pada Firebird 3.0

Bismillahirrohmanirrohim.
Assalamu’alaikum Wr Wb.

Lama tidak berbagi, kali ini saya ingin berbagi sedikit yang saya ketahui yaitu cara menginisialisasi manajemen user perdatabase pada Firebird 3.0.

Pada Interbase kita mengenal istilah EUA (Embedded User Authentication) dimana manajemen user (daftar user yang berhak mengakses database) dapat diatur menyatu didalam database, tidak lagi nempel pada server. Sehingga masing-masing database mempunyai user sendiri-sendiri.

Pada Firebird sebelum 3.0, manajemen user disimpan dalam server (pada file security2.fdb), ini agak merepotkan jika ada banyak aplikasi yang mengakses database yang berbeda, mungkin itulah sebabnya umumnya aplikasi yang kita jumpai sangat jarang yang menggunakan hak akses bawaan, sebagai gantinya mereka membuat sendiri table user untuk mengatur hak akses.

Pada Firebird 3.0 selain menggunakan manajemen user default yaitu menempel pada server kita diberikan alternatif untuk menyimpan manajemen user pada database file ataupun database itu sendiri (mirip dengan EUA pada Interbase).

Kalau dibandingkan dengan EUA pada Interbase, manajemen user perdatabase ini masih mempunyai kelemahan pada sisi kelemahan yaitu karena harus didaftarkan dulu di file databases.conf.

Pada EUA seseorang yang menemukan (terlalu kasar kalo disebut mencuri), praktis tidak dapat membuka database kalo tidak tahu passwordnya, sedangkan pada security perdatabase ala firebird ini database tetap bisa dibuka kalo tidak didaftarkan (unreg) pada database.conf.

Ibarat “tiada akar arangpun jadi”, dengan kelemahan diatas bukan berarti kita tidak dapat mengamankan database kita jika menggunakan Firebird.

Database akan aman selama orang yang tidak berwenang tidak dapat menjangkau secara fisik, bagaimana caranya?
Letakkan database pada partisi NTFS dan berikan hak baca/tulis selain system, lindungi server dengan firewall dan matikan filesharing terutama pada folder tempat database tersebut berada.

Banyak sekali keutungan jika kita menggunakan manajemen user bawaan database dibanding dengan membuat table user akal-akalan, diantaranya :
– Setiap user akan hanya dapat melakukan aktifitas ke database sesuai hak yang diberikan baik melalui aplikasi yang kita buat maupun menggunakan tool lain.

Dengan menggunakan table user akal-akalan ada 2 kemungkinan bila seorang user akan mengakses database tidak melalui aplikasi yaitu tidak bisa masuk sama sekali atau bisa masuk dengan bebas keseluruh area didalam database walaupun dia tidak mempunyai wewenang dalam aplikasi.

Namun semua kembali kepada anda, apa yang kita pakai tergantung selera masing-masing, apa yang menurut saya baik belum tentu menurut orang lain baik, apa yang menurut saya mudah belum tentu menurut orang lain mudah, begitu juga sebaliknya.

Okelah segini aja prakatanya, lebih jelasnya silahkan lihat pada gambar dibawah ini.
Semoga bermanfaat.

Yang butuh Firebird 3.0 dapat di download di …
http://www.firebirdsql.org/en/firebird-3-0-0-beta1/ (Installer)
http://web.firebirdsql.org/download/snapshot_builds/win/3.0/ (Snapshot Build)

Menyimpan gambar pada field blob menggunakan firebird embeded

Bismillahirrohmanirrohim,
Assalamu’alaikum Wr Wb,

Banyak contoh aplikasi “menyimpan gambar didatabase”, baik menggunakan database desktop maupun database client server.
Namun yang banyak kita temui sebenarnya tidak menyimpan didatabase karena yang disimpan di database/table hanya nama file nya saja.
Kali ini akan kami tunjukkan cara menyimpan gambar pada database lebih tepatnya pada field type blob.

Ada mitos atau anggapakan keliru (khususnya pada database interbase/firebird, kurang tau untuk database lain) yang mengatakan bahwa menyimpan gambar di blob akan membebani database/server, database akan menjadi berat dan besar.

Kalo jadi besar bener karena memang butuh tempat untuk menyimpan gambar tersebut, tapi bukankah kalo disimpan dalam bentuk file juga butuh tempat.
Kalo jadi berat, ini yang keliru karena pada saat kita select record yang mengandung blob, dia hanya memuat blob_idnya saja yang besarnya hanya 8 byte, isi sebenarnya akan dimuat saat kita melakukan getsegmen, inipun dilakukan secara streaming per segmen dengan ukuran kecil sesuai yang ditentukan.

Untuk pembacaan dikomputer lain penyimpanan diblob ini malah lebih efisien, kalo kita menyimpan gambar di field blob kita hanya pelu mengatur firewall untuk port database saja,

namun kalo kita menyimpan hanya pathnya saja berarti kita masih perlu jalan lain untuk membaca file gambar tersebut, umumnya menggunakan file sharing.

Ada beberapa kelemahan kalo kita menggunakan file sharing, terutama masalah keamanan data.
Karena hak akses file sharing ini terpisah dengan hak akses database, hal ini memungkinkan seseorang yang tidak punya hak akses ke database bisa meng obok2 gambar, seperti menghapus atau mengganti gambar.
Masalah lain bisa aplikasi error karena alamat masih ada tapi file gambar sudah terhapus, atau sebaliknya record sudah dihapus tapi file gambar lupa/gagal dihapus akhir menjadi sampah.

Kita tidak perlu kuatir untuk menyimpan gambar atau media lain di field blob interbase/firbird karena batasannya lumayan besar yaitu 32GB untuk firebird dan 256GB untuk interbase.
Selain untuk menyimpan data binary field blob juga bisa untuk menyimpan data text.

Ukuran maksimal sebuah record pada interbase/firebird adalah 64KB, dengan adanya field blob batasan tersebut tidak perlu dirisaukan lagi karena sebuah field blob hanya menempati 8 byte pada sebuah record.

Hingga saat ini ada beberapa jenis firebird server, diantaranya classic, super server, super classic dan embeded server.

Pada contoh kali ini kita menggunakan Firebird 2.5 versi embeded server, dengan pertimbangan karena pada versi ini kita tidak perlu menginstall atau menjalan firebird untuk membaca database, dengan demikian yang bukan pengguna firebird pun bisa mencoba aplikasi ini.

Kelebihan versi ini seperti yang di sebutkan diatas adalah kita tidak perlu menginstall atau menjalan firebird untuk membaca database, disamping kelebihan tentunya juga ada kekurangan yaitu pada versi ini adalah database tidak bisa dibaca bersama2 atau dibaca dari komputer lain.

Untuk databasenya sendiri tidak ada perbedaan pada masing-masing versi, jadi database yang kita buat untuk client server juga bisa dibaca versi embeded dan sebaliknya.

Selain penggunaan blob pada aplikasi ini juga ditunjukkan teknik pembuatan tumbnails secara otomatis, disini gambar disimpan pada 2 field blob, 1 field untuk menyimpan gambar asli, 1 field lagi untuk menyimpan gambar yang dikecilkan.

Lho .. bukannya jadi lebih boros space …. memang, namun pemborosan ini akan tergantikan dengan performa yang bagus.
Dengan adanya field tumbnail ini maka gambar akan tampil lebih cepat dan hemat bandwidth, kita juga masih mempunyai gambar ukuran asli nantinya mungkin dibutuhkan untuk melihat detail atau untuk keperluan pencetakan.

Disini ditunjukkan juga penggunaan Actionlist untuk meminimalkan penggunaan koding, beberapa fungsi kontrol database seperti insert, update, post, delete kita menggunakan Actionlist sehingga tidak perlu bikin koding sendiri.

Pada contoh ini kita gunakan FIBPlus sebagai komponen koneksi databasenya, menurut pengalaman kami FIBPlus adalah yang paling banyak mendukung fitur2 interbase dan firebird.
Selain FIBPlus kita juga bisa menggunakan komponen lain seperti IBExpress, IBObject, Zeos dan DBExpress, untuk Ado tidak kami rekomendasikan karena Ado sifatnya umum dan hanya mendukung fitur2 umum saja.

Disini juga ditunjukkan penggunaan skin internal pada alpha skin sehingga kita tidak perlu menyertakan file skin saat mendistribusikan.
Untuk menampilkan gambar asli kita gunakan form lain yang dimuat secara runtime dengan tujuan menghemat resource karena memang tidak selalu dibutuhkan.

Alamat database juga dimuat secara runtime yang diambil dari file FBBlobPictureEmbed.ini sehingga mudah untuk mengganti tanpa harus compile ulang.

Aplikasi ini juga bisa untuk membaca versi client server dengan mengganti file ini tersebut.
Untuk mendistribusikan secara portable kita cukup menyertakan semua file yang ada di folder dist dan tidak perlu menginstall firebird.

Catatan:
Bagi teman-teman yang sudah mencicipi versi awal yang pernah saya share secara private, ada sedikit bug bahwa tumbnails yang dibuat ukurannya masih sama dengan ukuran sebenarnya belum diperkecil, solusinya mudah sekali cukup hapus field “SmallFoto” kemudian baca dengan aplikasi yang baru maka dia akan bikin field dan generate tumbnails secara otomatis.

Contoh aplikasi lengkap dengan source code dapat di download di
https://app.box.com/s/pa67uv2mfhp0qnykhxyq

Komponen 3Party yang dibutuhkan :
– FIBPlus
– Alphaskin

Bagi yang gak pake FIBPlus jangan kuatir

Disediakan juga versi Zeos bagi yang tidak menggunakan FIBPlus,
Contoh aplikasi lengkap dengan source code dapat di download di
https://app.box.com/s/cgow5tfuiyxpmk9cjzj0

Juga ada versi IBX (Interbase Express bawaan delphi),
Contoh aplikasi lengkap dengan source code dapat di download di
https://app.box.com/s/fkogbmj0ficnlxoc9zb8

Demikian Semoga bermanfaat.

Memperbaiki “bug” property RecordCount pada TIBDataSet

Pada komponen TIBDataSet terdapat property RecordCount, yang merupakan warisan dari class TDataSet.
Namun sayangnya property RecordCount yang ada di TIBDataSet kurang memenuhi kebutuhan informasi yang kita butuhkan.
property RecordCount yang ada di TIBDataSet hanya menampilkan record yang sudah dimuat (fetch row), bukan keseluruhan record hasil query.
Kali ini kita akan melakukan override untuk memperbaiki bug/kelemahan property RecordCount agar sesuai dengan yang kita harapkan.
Berikut ini contoh kodenya …

uses
  SysUtils, Classes, DB, IBCustomDataSet, IBDatabase,
  IBXPlus, DBTables;

type
  // Tambahkan ini ...
  TIBDataSet = class(IBCustomDataSet.TIBDataSet)
  private
    function GetRecordCountPlus: Integer;
  published
    property RecordCount: Integer read GetRecordCountPlus;
  end;
  // Sampai sini .. Tekan Ctrl+Shift C untuk menulis codenya
  Tdm = class(TDataModule)
    db: TIBDatabase;
    tr: TIBTransaction;
    tb: TIBDataSet;

...
...
...
...

{ TIBDataSet }

function TIBDataSet.GetRecordCountPlus: Integer;
var
   s: string;
begin
     s:=SelectSQL.Text;
     System.Delete(s,1,pos('from ',LowerCase(s))-1);
     s:='select count(*) '+s;
     with IBCustomDataSet.TIBDataSet.Create(nil) do
     begin
          Database:=Self.Database;
          SelectSQL.Text:=s;
          Open;
          Result:=Fields[0].AsInteger;
          Close;
          Free;
     end;
end;

Setelah melakukan perbaikan diatas, maka property RecordCount akan menghasilkan informasi sesuai dengan yang kita butuhkan yaitu jumlah record sesuai hasil query.

Semoga bermanfaat

Memanfaatkan drag-drop untuk membantu mempercepat penulisan kode di IBExpert

Drag drop IBExpert

Bismillahirrohmannirrohim,

Pada IBExpert versi Personal tidak disediakan tool “Query Builder” sebagaimana yang ada di versi berbayar.

Tidak tersedianya tool “Query Builder” bukan berarti kalo menggunakan IBExpert Personal Edition maka semua harus mengetik koding secara manual.

Kita dapat menggunakan fitur drag drop untuk mengambil nama field yang ada di table untuk keperluan query select, insert, delete dan juga untuk mendeklarasikan variable atau menuliskan parameter pada storage procedure tanpa harus mengetik secara manual, sehingga bisa lebih cepat dan minim kesalahan.

Tanpa penjelasan panjang lebar, berikut ini ada video sederhana tentang penggunaan fitur drag-drop tersebut.

Download aja deh langsung videonya di https://app.box.com/s/istye0u1cjyi6oty9oo7

Semoga bermanfaat, Aamiin

Cara menyambung data Interbase ke lokasi lain

Sebuah tempat penyimpanan data (Database), dengan berjalannya waktu pastinya lambat laun semakin lama akan semakin besar ukurannya.

Pada saat pertama kali memasang aplikasi mungkin kita menganggap bahwa dengan HDD sebesar 80GB sudah lebih dari cukup karena memang untuk saat ini datanya belum banyak dan rasanya mubadzir juga kalo harus memasang HDD ukuran 500GB kalo memang belum diperlukan.

Dengan perkembangan data / informasi yang disimpan, pada suatu saat HDD 80GB mungkin hanya tersisa untuk menyimpan data satu minggu kedepan.

Untuk mengatasi hal ini umumnya adalah dengan membeli HDD yang ukurannya minimal lebih besar dari HDD semua, copy semua datanya ke HDD yang baru.

Tentunya hal ini akan membutuhkan biaya yg cukup besar karena HDD baru harus selalu lebih besar dari HDD lama, juga akan membutuhkan waktu cukup lama untuk melakukan backup (pencopyan data dari HDD lama ke HDD baru) yang sedikit banyak akan mengganggu operasional.

Padahal dalam beberapa kasus sebuah database server dituntut untuk selalu Online (siap diakses 24 jam), boleh berhenti dengan waktu semimimal mungkin.

Beruntung Interbase memberikan solusi yang mudah dan nyaman untuk masalah ini.

Data bisa menyambung ke HDD lain tanpa memindahkan data lama ke HDD baru sehingga HDD lama masih tetap dipakai, hal ini tentunya akan menghemat biaya karena kita bisa membeli HDD baru seukuran HDD lama tidak harus lebih besar.

Dari segi waktu juga menghemat, karena mematikan server hanya dibutuhkan waktu memasang HDD baru saja, untuk proses penyambungannya bisa dilakukan walaupun server sedang dipakai.

Kalo pemasangan HDD baru bisa dilakukan secara “hot swapping”, artinya memasang HDD tanpa mematikan komputer, maka proses ini sama sekali tidak mengganggu operasional.

langsung aja deh caranya, mudah kok …

Untuk ini kita gunakan tool isql.exe bawaan Interbase.

c:\ib2007\bin>isql d:\data.interbase\databank.ib
Database: d:\data.interbase\databank.ib
SQL>

berikan perintah show database;

SQL>show database;
Database: d:\data.interbase\databank.ib
Owner: SYSDBA

PAGE_SIZE 4096
Number of DB pages allocated = 18123456
Sweep interval = 20000
SQL>

disitu tertera jumlah pages sebesar 18123456, kalo kita kalikan dengan pagesizenya (4096) maka akan ketemu hampir mendekati 70GB.

selanjutnya berikan perintah berikut ini ..

SQL> alter database add file 'e:\data.interbase\databank2.ib'
CON> starting at page 18350080;
SQL>

perintah diatas artinya memerintahkan Interbase untuk meneruskan penyimpanan ke e:\data.interbase\databank2.ib (HDD baru), jika data sudah mencapai 18350080 pages (70GB).

Proses ini tidak membutuhkan waktu yang lama (hanya hitungan detik-menit) dan sama sekali tidak mengganggu operasional (tidak perlu mematikan server).

Demikian semoga bermanfaat.

Manfaatkan Selectable Procedure untuk query lebih dari satu field kata kunci

Pada sebuah aplikasi penjualan (POS) biasanya untuk mencari sebuah barang dilakukan dengan melakukan pencarian (query) yang tidak hanya berdasar pada satu field saja.

Metode pencarian yang diinginkan ..

Pertama dicari dulu berdasarkan Barcode, kalo tidak ada kemudian dicari berdasarkan Kode Barang, kalo tidak ada juga maka kata yg dimasukkan dianggap merupakan bagian dari Nama Barang.

Contoh ..

Nama Barang : AGAR2 SWALLOW PUTIH
Kode Barang : 01.0078
Barcode : 8991689168001

Dalam melakukan pencarian diharapkan dengan hanya satu kali proses dengan memasukkan salah satu kriteria diatas.

Kita dapat memasukkan kata dengan mengabaikan kata itu Nama, Kode, atau Barcode.

Sebenarnya kita bisa juga menggunakan query SQL biasa  seperti dibawah ini

SELECT ID,KODEBRG,BARKODE,"Nama Barang",
       SATUAN_K, SATUAN_B,JML_SAT_B,HRG_JUAL
FROM BARANG
WHERE BARKODE=:CARI
OR KODEBRG=:CARI
OR "Nama Barang" CONTAINING :CARI

dan hasilnya seperti gambar berikut


Namun untuk data yg besar query seperti diatas akan memakan waktu lama karena walaupun dia sudah menemukan Kode Barang dia masih akan mencari Barcode dan Nama Barang.
Dan akan jadi masalah juga bila didalam Nama Barang mengandung angka yang ada di Bardcode atau Kode Barang.
Sebagai solusinya kita akan membuat Selectable Procedure (yaitu procedure yang dapat diselect sebagaimana table biasa), dimana pencariannya menggunakan prioritas seperti yang disebutkan diatas, jika kata yang dicari sama dengan Barcode maka dia tidak akan mencari Kode Barang atau Nama Barang lagi, sehingga tidak membuang waktu.

SELECT * FROM SP_CARI('8991689168001');

SELECT * FROM SP_CARI('01.0078');

SELECT * FROM SP_CARI('PUTIH');

OK, langsung saya ini dia procedurenya …

CREATE PROCEDURE SP_CARI (
    KATA VARCHAR(30) CHARACTER SET NONE)
RETURNS (
    ID INTEGER,
    KODEBRG VARCHAR(7) CHARACTER SET NONE,
    BARKODE VARCHAR(20) CHARACTER SET NONE,
    "Nama Barang" VARCHAR(20) CHARACTER SET NONE,
    SATUAN_K VARCHAR(10) CHARACTER SET NONE,
    SATUAN_B VARCHAR(10) CHARACTER SET NONE,
    JML_SAT_B NUMERIC(18,2),
    HRG_JUAL NUMERIC(18,2)
)
AS
BEGIN
     SELECT ID, KODEBRG, BARKODE, "Nama Barang",
            SATUAN_K, SATUAN_B, JML_SAT_B, HRG_JUAL
     FROM BARANG
     WHERE BARKODE=:KATA
     INTO :ID, :KODEBRG, :BARKODE, :"Nama Barang",
          :SATUAN_K, :SATUAN_B, :JML_SAT_B, :HRG_JUAL;
     IF (ID IS NULL) THEN
     SELECT ID, KODEBRG, BARKODE, "Nama Barang",
            SATUAN_K, SATUAN_B, JML_SAT_B, HRG_JUAL
     FROM BARANG
     WHERE KODEBRG=:KATA
     INTO :ID, :KODEBRG, :BARKODE, :"Nama Barang",
          :SATUAN_K, :SATUAN_B, :JML_SAT_B, :HRG_JUAL;
     IF (ID IS NULL) THEN
     BEGIN
          FOR SELECT ID, KODEBRG, BARKODE, "Nama Barang",
              SATUAN_K, SATUAN_B, JML_SAT_B, HRG_JUAL
          FROM BARANG
          WHERE "Nama Barang" CONTAINING :KATA
          ROWS 25
          INTO :ID, :KODEBRG, :BARKODE, :"Nama Barang",
               :SATUAN_K, :SATUAN_B, :JML_SAT_B, :HRG_JUAL DO
               SUSPEND;
     END ELSE
         SUSPEND;
END

Semoga bermanfaat.

Contoh aplikasi validasi input pada interbase

Dalam menyimpan data kedalam database ada kalanya kita perlu untuk memvalidasi dulu sebelum benar-benar menyimpannya.
Misalnya data baru disimpan setelah semua/sebagian field diisi seperti gambar dibawah ini:
Alamat belum diisi
Tanggal diluar range

Untuk membuat record tidak bisa disimpan bila field belum diisi caranya dengan menambahkan klausa NOT NULL (saya yakin tidak asing lagi).

CREATE TABLE BIODATA (
    ID               INTEGER NOT NULL,
    "Nama Lengkap"   VARCHAR(30) CHARACTER SET NONE NOT NULL,
    "Alamat"         VARCHAR(50) CHARACTER SET NONE NOT NULL,
    "Tanggal Lahir"  DATE DEFAULT CURRENT_DATE NOT NULL
);

Sedangkan untuk membatasi input Tanggal kita menggunakan Check constraint.

ALTER TABLE BIODATA ADD CONSTRAINT "mulai 01/01/1910 s/d hari ini" CHECK ("Tanggal Lahir" between '01.01.1910' and current_date);

Pada sisi Delphinya untuk keperluan tersebut diatas kita memanfaatkan event OnFIBErrorEvent pada TpFibErrorHandler (komponen FIBPlus) dan OnPostError punya DataSet.

procedure TForm1.pFibEHFIBErrorEvent(Sender: TObject; ErrorValue: EFIBError;
  KindIBError: TKindIBError; var DoRaise: Boolean);
var
   s: string;
begin
     s:=ErrorValue.IBMessage;
     case ErrorValue.IBErrorCode of
          335544347: // Not Null
            begin
                 // Validation error for column Alamat, value "*** null ***".
                 Delete(s,1,pos('column',s)+6); // hapus .. column
                 SetLength(s,pos(', value',s)-1); // ambil nama fieldnya
                 CariDBEdit(s); // fokus ke field ybs
            end;
          335544558: // Check
            begin
                 // Operation violates CHECK constraint mulai 01/01/1910 s/d hari ini on view or table BIODATA.
                 Delete(s,1,pos('constraint',s)+10); // hapus .. constraint
                 SetLength(s,pos('on view',s)-1); // ambil pesannya aja
                 DBEdit3.SetFocus; // fokus manual krn sdh pasti
                 ShowInfo(DBEdit3,s); // tampilkan pesan
            end;
     else
         ShowMessage(s);
     end;
end;
procedure TForm1.tbPostError(DataSet: TDataSet; E: EDatabaseError;
  var Action: TDataAction);
begin
     Action:=daAbort;
end;

Source Code dapat didownload di https://www.box.com/s/0mmrv8i7776ikpxul06h

Semoga bermanfaat

Two Phase Commit di Interbase

Two Phase Commit berguna untuk menjamin transaksi pada 2 database atau lebih (bisa beda server) pada status commit semua atau rollback semua.

Misalnya kita mau mengurangi saldo tabungan seseorang di database-1 kemudian dimasukkan ke database-2, berarti ada 2 proses yaitu mengurangi database-1 dan menambah database-2. Tiba-2 sebelum kedua proses selesai koneksi terputus, apa yang terjadi?

Kalo prosesnya mengurangi dulu baru menambah, jelas nasabah akan rugi dan protes karena saldonya hilang, sementara kalo prosesnya menambah dulu baru mengurangi maka nasabah akan diuntungkan dan koperasi/bank rugi.

Dengan adanya fitur Two Phase Commit kejadian seperti kasus diatas dapat dihindari, hanya ada dua kondisi transfer berhasil atau gagal. Saldo pindah dari database-1 ke database-2 atau tetap pada posisi semua bila ada masalah.

Two Phase commit ini juga sangat berperan dalam proses replikasi/sinkronisasi data antar database/antar cabang, sehingga dapat dijamin akurasi datanya.

Contoh implementasi Two Phase Comit pada coding delphi menyusul.

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