これの続きです。
さて、いったいどこまで行くつもりなのか自分でもわからなくなってきましたが、
一つ分かったことは、かなりの獣道を歩いているってことかと。
3回も書いているのにまだ準備です。ええ。
注意:この作業を行うにあたって、心構えとしては
・運用中のzabbixが不安定になる覚悟をする。
・バックアップを取ったデータベースがなければ、過去データはすべて破棄する覚悟。
・作業を行った直後は問題がなかったとしても、特殊なデータや状況が発生した時に、データ破損してしまうことを受け入れる覚悟。
これらのことが許容できる環境の持ち主か、どうにもせっぱつまっていて、上記のリスクに比べたら相当に致命的な状況まで追い込まれている人じゃない限り、やらないほうが良い作業だと思っています。※技術力向上のためにやれるなら幸せかもですが。
いい加減、この注意喚起文も見飽きたような気がします。
とりあえず、PL/pgSQLで関数を作るのは初めてなので、簡単なものから作っては
テストし、実現に向けて作りこんでいきたいななんて考えで下記のfunctionを作りました。
この形になるまでかなりエラーを出しながらつくったのですが、とりあえず、動く状態で。
これで調査したzabbix本体の関数をPL/pgSQL
にて実現しようというのが本懐です。シェルスクリプトで演算とかDB接続とかやるのはしんどいので…
■テストで作った関数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | CREATE OR REPLACE FUNCTION insert_past_trends(TEXT,bigint,INTEGER,numeric(20,0)) RETURNS TEXT AS $$ DECLARE f_table ALIAS FOR $1; f_itemid ALIAS FOR $2; f_clock ALIAS FOR $3; f_value ALIAS FOR $4; t_num trends.num%TYPE; t_value_min trends.value_min%TYPE; t_value_avg trends.value_avg%TYPE; t_value_max trends.value_max%TYPE; tu_num trends_uint.num%TYPE; tu_value_min trends_uint.value_min%TYPE; tu_value_avg trends_uint.value_avg%TYPE; tu_value_max trends_uint.value_max%TYPE; SQL TEXT; BEGIN SQL := 'SELECT num,value_min,value_avg,value_max FROM '|| f_table ||' AS t WHERE t.itemid= '|| f_itemid ||' AND t.clock = '|| f_clock; EXECUTE SQL; IF NOT FOUND THEN RAISE NOTICE '% 1 FOUND ',f_itemid; RETURN 'OK'; END IF; END; $$ LANGUAGE plpgsql; |
■呼び出し方(テキスト型は特殊だっていうことを知りました。)
SELECT insert_past_trends('trends_uint'::text,22497,1309870800,3333); |
■出力結果
NOTICE: 22497 1 FOUND insert_past_trends -------------------- OK (1 ROW) |
とりあえず、現在のデータと合致する入力があったら制御するという事ができるようになったので
ひとまずテストは成功。この後、合致するデータからmax,min,avgを作ったりできるようになって、
INSERTやUPDATEを発行(テンポラリーテーブルに)できるようになったら、
xx_tempにINSERTを発行していたシェルスクリプトを書き換えて終了です。
って先が長いな!
■上の状態に到達するまでのエラーメッセージいろいろ。
https://www.sraoss.co.jp/technology/postgresql/8.3/
上記を見ると、::textを付けないとだめみたい。参考にした本が8.1時代だったから…という言い訳。
HINT: No FUNCTION matches the given name AND argument types. You might need TO add explicit TYPE casts. |
sqlの変数をコメントアウトしてたのでEXECUTEの時に何も実行するものがないというもの。
ERROR: query string argument OF EXECUTE IS NULL CONTEXT: PL/pgSQL FUNCTION "insert_past_trends" line 21 AT EXECUTE statement |
変数が展開されてない!→全部’ ‘ で囲ってたから。これは変数の部分だけ|| (vars) ||こんな風に分離して対応。
QUERY: SELECT num,value_min,value_avg,value_max FROM f_table AS t WHERE t.itemid=f_itemid AND t.clock = f_clock |
クォーテーションの閉じ忘れ
ERROR: unterminated quoted string AT END OF input LINE 29: $$ LANGUAGE plpgsql; |
::text が??いやFROMとASのところにスペース入れてないだけ
ERROR: syntax error AT OR near "::" LINE 1: ... num,value_min,value_avg,value_max FROMtrends_uint::textAS t... |
RAISE の部分の記述ミス
ERROR: column "itemid" does NOT exist LINE 1: SELECT itemid ^ QUERY: SELECT itemid |
RETURN 入れないとね。
zabbix=# SELECT insert_past_trends('trends_uint'::text,22497,1309870800,3333); NOTICE: 22497 1 FOUND ERROR: control reached END OF FUNCTION without RETURN CONTEXT: PL/pgSQL FUNCTION "insert_past_trends" |