Monday, April 19, 2010

PENGHAPUSAN RECORD DI DBF = Ingat: SET DELETED ON!

DBF adalah format standard table yang mulai dikembangkan sejak pertengahan tahun 1960-an (Wow! Selama ini banyak yang bilang DBF dikembangkan sejak tahun 80-an! --- Saya gak akan cerita panjang. Silahkan baca di http://www.foxprohistory.org ). Pada waktu itu (jujur- saya juga belum lahir), semua mengenai komputer identik dengan MAHAL. Harga mengakses komputer mahal. Media penyimpanan mahal. Operasional komputer mahal. Dan proses-proses yang sekarang sederhana, waktu itu juga MAHAL. Kata MAHAL (expensive) disini, bukan hanya berarti uang. MAHAL juga bisa berarti membutuhkan proses yang panjang, sedemikian rupa sehingga si komputer tidak dapat mengerjakan hal lain kecuali hal yang ‘mahal’ itu. Nah, penghapusan record adalah salah satu dari proses yang mahal itu. Kenapa?

Coba lihat diagram di samping. Katakanlah ada file database dengan 8 record. (Catatan: untuk menyederhanakan, kita akan mengasumsi data setiap record disimpan secara sequential. Kita juga tidak akan membahas struktur index, jadi diasumsi file database ini adalah file sequential tanpa index).
Nah, coba bayangkan apabila ada penghapusan record. Katakanlah, record 3 dan record 5 dihapus. Kira-kira apa yang akan terjadi?









Okay. Anda bisa lihat efeknya pada gambar di sebelah ini? Tempatnya jadi kosong alias bolong. Nah, karena record-record ini ada di dalam satu file, apa yang akan dilakukan oleh operating system untuk meng-klaim space kosong ini?













Yup. Operating system akan 'menulis ulang' file tersebut dan menyusun ulang isinya seperti pada gambar di samping.

Okay. Anda lihat efeknya? Berapa besar 'biaya' untuk membangun ulang sebuah file? Yang pasti, lupakan multi user. Bagaimana caranya bisa ada dua user yang mengakses satu file kalau file itu dihapus lalu ditulis ulang oleh salah satu user? Atau, gak usah ngomong jauh-jauh multi user deh... Katakanlah hanya satu user. Tapi record yang ada bukan 8; melainkan 800,000 record. Na lho! Anda bisa bayangkan berapa banyak rewrite yang harus dilakukan hanya untuk menghapus satu record (yang di mata orang awam/client, "sistem kita sederhana kok!" --- sounds familiar?)
Jadi, apa yang dilakukan oleh orang-orang yang menciptakan system logic database xBase pada jaman kuda belum ada buntut dulu? Anda pasti bisa menebak! YUP. Mereka membuat sistem database sedemikian rupa sehingga apabila ada penghapusan, record yang dihapus TIDAK dihapus secara fisik, melainkan HANYA DITANDAI bahwa record tersebut sudah dihapus. Tujuannya, pada saat yang dianggap aman, atau saat sistem komputer tidak sedang bekerja, barulah proses penghapusan secara fisik dilakukan (ini yang kita kenal sekarang dengan proses PACK).
Sekarang kita kembali ke dunia VFP yang kita kenal. Database VFP juga masih menggunakan dasar-dasar xBase, jadi tetap ada kasus seperti di atas. Record pada table DBF yang dihapus, juga hanya akan 'ditandai' oleh VFP. Record tersebut masih bisa dikembalikan dengan perintah RECALL. Kalau kita ingin sistem menampilkan record yang sudah ditandai tersebut, berarti kita beritahu VFP dengan perintah SET DELETED OFF. Kalau kita ingin 'menyembunyikan' record yang sudah ditandai, berarti kita berikan perintah SET DELETED ON. Nah, sejauh ini simple kan? Jadi apa yang menyebabkan begitu banyak pertanyaan dan kasus-kasus di forum yang berhubungan dengan record yang ditandai-tapi-belum-dihapus ini? Biasanya masalah yang muncul tidak jauh dari kasus berikut:

1. Record yang sudah dihapus, masih ngotot muncul

2. Record yang sudah dihapus ikut terhitung

3. Mau masukin record baru jadi gak bisa karena katanya record tersebut sudah ada. Saat di-check... ternyata sudah di-delete -- tapi belum di-pack....

4. Perintah SET DELETED ON sudah diberikan di awal program, tapi kok gak ngefek ya?

5. Ini lebih aneh lagi... SET DELETED ON sudah diberikan, udah jalan dengan baik... Tapi kok tiba-tiba VFP mengembalikan SET DELETED ke OFF??? Wah.. ini sih pasti bug VFP!

Programmer-programmer VFP sangat terkenal dengan kelihaiannya ngulik sana-sini. Maklum... maskot VFP kan rubah, jadi gak heran kalau lihai. Apa saja kelihaian programmer VFP untuk mengakali kasus di atas?
1. Habis DELETE, langsung PACK.

2. Keluar program/masuk program = PACK dulu dong.... Bisa kita akalin dengan proses PACK wajib dilakukan saat mau posting harian (keren banget namanya = posting... padahal kita cuman minjem istilah akuntansi untuk ngebersihin sampah kan?)

3. Yang ini sedikit lebih advance; JANGAN gunakan DELETE! bikin field sebagai flag untuk record-record yang dihapus.

4. Ada cara satu lagi yang cukup mantap: "Di sistem kami, semua transaksi langsung dibukukan. Tidak ada istilah DELETE. Yang ada adalah RETUR. Jadi apabila ada kesalahan, sistem tetap memiliki catatan"

Gak tau apa lagi deh... tapi yang pasti, masalah utama adalah programmer tidak tau atau gagal menggunakan SET DELETED ON/OFF untuk mengelola record yang dihapus.  Kenapa gagal? Karena banyak programmer VFP yang tidak tau bahwa:
1. SET DELETED OFF adalah nilai default VFP

2. Perintah SET DELETED ON/OFF hanya memiliki scope di data session dimana perintah tersebut diberikan. Jadi kalau Anda menggunakan Private Data Session di form Anda, setiap kali Anda harus menset preferensi Anda dengan memberikan perintah SET DELETED ON (atau OFF -- biarpun sebenarnya kalau preferensi Anda OFF ya jelas tidak perlu -- kan sudah default?)

3. Setelah SET DELETED ON atau OFF berlaku, maka semua table dan perintah yang digunakan akan mengikuti aturan tersebut. Ini berarti, apabila Anda membuat SELECT query saat SET DELETED OFF, maka record yang sudah terhapus akan... YUP. AKAN TERBAWA - dan tidak ada tanda bahwa record itu sudah di-delete! Bagaimana bila setelah query tersebut Anda memberikan SET DELETED ON? Apakah hasil query (cursor) akan terpengaruh? NOPE! Record di cursor tidak diberi tanda deleted kan? Jadi ya dianggap itu adalah record yang valid. Nah.. satu lagi nih yang sering dilupakan... Local view pada dasarnya adalah... SELECT QUERY! Jadi kasus SET DELETED ON yang gak ngefek juga dengan mudah terjadi di Local View. Gimana ngakalinnya? Silahkan lihat point berikut....

4. Karena peletakkan SET DELETED ON sangat penting, pastikan Anda sudah men-set preferensi SET DELETED ON ini sebelum Anda membaca data. Karena umumnya aplikasi kita menggunakan form (tentu saja pengecualian bila Anda membuat COM+ -- Tapi kalau Anda udah bisa bikin aplikasi COM+ dan masih bingung dengan SET DELETED, itu namanya kebangeten), jadi saya akan membahas penggunaan SET DELETED di form.

Apa yang dijalankan dulu waktu form VFP dipanggil? Yang pertama adalah event BeforeOpenTable yang ada di Data Environment. Setelah itu, event Load dari form. Kemudian berturut-turut: Init, Show, dan Activate. Untuk mempermudah mengingat, biasanya saya bilang urutannya mBOk-LISA.
Jadi, kalau Anda menggunakan Data Environment, berarti Anda membuka table dari Data Environment, ada dua alternatif:
1. Berikan perintah SET DELETED ON di event BeforeOpenTable yang ada di Data Environment
2. Kalau Anda membuka local view dari DE, Set property NoDataOnLoad di Data Environment table. Lalu, setelah Anda secara eksplisit memberikan perintah SET DELETED ON, refresh data dengan fungsi REQUERY()
Saya pribadi, lebih suka me-load data (table atau view) dari event Load. Jadi, sebelum me-load table atau view apa-pun, berikan dulu perintah SET DELETED ON. Setelah perintah itu, baru berikan perintah USE... untuk membuka table atau view.

Okay. Saya rasa segini saja yang bisa saya share. Untuk membuat post ini saja sudah hampir satu setengah jam. Jadi sudah melewati batas break saya... Ha-ha-ha... Ya ndapapalah... sekali-kali.
Sebagai penutup, saya berharap artikel yang saya buat ini bisa bermanfaat untuk rekan-rekan programmer Microsoft Visual FoxPro. VFP ROCKS!