Eksekusi Formula//Rumus Dalam Bentuk String (Postgres)

Beberapa waktu yang lalu, aku mengerjakan sebuah system untuk perhitungan hasil produksi menggunakan php + extjs, dengan postgres sebagai  databasenya. Ada banyak rumus/formula yang digunakan dalam sekali produksi, awalnya aku langsung menempatkan rumus-rumus itu dalam script karena aku berpikir formula tidak akan berubah. Pemikiranku itu ternyata salah, formula bisa berubah sewaktu-waktu, dan menempatkan formula pada script langsung dengan situasi seperti ini akan konyol, mengingat system akan di handover oleh user awam.


Sempat mendapak kendala bagaimana melakukan eksekusi rumus yang disimpan dalam format string dalam field tabel. Setelah mencoba berbagai cara dan juga search permasalahan serupa akhirnya masalah terpecahkan. Berikut ini adalah cara-cara yang aku gunakan.

 1. Buat sebuah fungsi di postgres (a function handler):
perintahnya:

CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS
'$libdir/plpgsql' LANGUAGE C;
 kemungkina akan terjadi error jika postgres belum install language 'plpgsql'2.

2.  Buat  language 'plpgsql'
CREATE TRUSTED LANGUAGE plpgsql
HANDLER "plpgsql_call_handler";

3.  Jika perlu jalankan perintah dibawah ini:
GRANT USAGE ON LANGUAGE plpgsql TO public;

Selanjutnya, memulai membuat fungsi yang menjalankan rumus/formula yang disimpan dalam string tersebut:
contoh:
1. untuk kembalian fungsi hanya 1 nilai (value) saja
-- DROP FUNCTION gaji(integer);
CREATE OR REPLACE FUNCTION gaji(integer)
  RETURNS numeric AS
$BODY$
declare g text;
ret numeric(10,2);
begin
select into g rumus from view_karyawan where id=$1;
execute 'select ' || g || ' from view_karyawan where id=' || $1 into ret;
return ret;
end;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;
ALTER FUNCTION gaji(integer) OWNER TO postgres;

Setelah function dibuat, letakkan item-item nilai yang akan di kalkulasi beserta  rumusnya sejajar dalam 1 baris/row, jika ada relasi dengan banyak tabel bisa disederhanakan menggunakan query view  atau temporary table sehingga dapat
menyatukan semua field yang dibutuhkan dalam 1 record data.

Contoh:
test=# select * from view_karyawan ;
id | hari | pokok |uang_makan| bonus |tunjangan|rumus
----+-----+-------+----------+-------+---------+------------------------------------
1   |  25 |750000 |5000      | 50000 |    0    |(hari*uang_makan)+pokok+bonus
2   |  25 |750000 |5000      | 50000 |50000    |(hari*uang_makan)+pokok+bonus+tunjangan


(2 rows)

ex.1=*# selec id, nama, (select * from gaji(1))::numeric(9,2) as gaji from karyawan where id=1;
id| nama | gaji
--+------+------------
 1| si X | 925000.00
(1 row) 

ex.2=*# selec id, nama, (select * from gaji(2))::numeric(9,2) as gaji from karyawan where id=1;
id| nama | gaji
--+------+------------
2| si Y | 975000.00
(1 row)



2. Untuk kembalian fungsi lebih dari 1 (array)

CREATE OR REPLACE FUNCTION fo_saco_warp(IN x integer, OUT te_warp numeric, OUT yc_lbs numeric, OUT yc_bales numeric, OUT sizing numeric)
  RETURNS record AS
$BODY$
declare 

 -- Declare aliases for user input.
      e_id ALIAS FOR $1;
-- Declare variables to hold the formula.
     fte_warp TEXT;
     fyc_lbs TEXT;
     fyc_bales TEXT;
     fsizing TEXT;


begin
select INTO fte_warp, fyc_lbs, fyc_bales, fsizing f_te_warp, f_yc_warp_lbs, f_yc_warp_bales, sizing_length from saco_formula_dynamic_warp where seq_yarn_id=e_id;
execute 'select ' || fte_warp ||',' || fyc_lbs ||',' || fyc_bales ||',' || fsizing ||' from saco_formula_dynamic_warp where seq_yarn_id=' || e_id into te_warp,yc_lbs,yc_bales,sizing;

end;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;
ALTER FUNCTION fo_saco_warp(integer) OWNER TO postgres;





Contoh untuk hasil eksekusi dengan kembalian lebih dari 1:

execute "string" formula



















Dengan kombinasi function postgres dan interface sederhana (kalkulator aneh) bisa menyesesaikan masalah kecil dengan system yang kubuat.



Komentar

Postingan populer dari blog ini

Pivot Tabel Postgres

Numbers to Words Bahasa Indonesia dengan PHP

Seputar Post Polio