スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PL/pgSQLでデフォルト値に関数を書いてはまった話

毎日定期的にpg_dumpでDBのバックアップを取っているのですが、ある日突然バックアップがとれなくなっていました。
あわてて手動でpg_dumpを実行してみると、以下のようなエラーが発生していました

$ pg_dump -U user test
pg_dump: SQLコマンドが失敗しました
pg_dump: サーバのエラーメッセージ: ERROR:
cache lookup failed for function 20715
pg_dump: 次のコマンドでした: SELECT proretset, prosrc, probin,
pg_catalog.pg_get_function_arguments(oid) AS funcargs,
pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs,
pg_catalog.pg_get_function_result(oid) AS funcresult, proiswindow, provolatile,
proisstrict, prosecdef, proconfig, procost, prorows, (SELECT lanname FROM
pg_catalog.pg_language WHERE oid = prolang) AS lanname FROM
pg_catalog.pg_proc WHERE oid = '20716'::pg_catalog.oid

色々調べてみたところ、
pg_catalog.pg_get_function_identity_arguments(oid)
がエラーを吐いている模様です。
pg_catalog.pg_procはそもそも、関数を管理するテーブルです。
上の関数は定義した関数の引数を返すようです。
そもそも、以下のような関数を定義していました。

DROP FUNCTION IF EXISTS test1();
CREATE OR REPLACE FUNCTION test1() RETURNS text AS $$
BEGIN
RETURN '1';
END;
$$ LANGUAGE plpgsql;

DROP FUNCTION IF EXISTS test2();
CREATE OR REPLACE FUNCTION test2(
p_param text DEFAULT test1()
) RETURNS text AS $$
BEGIN
RETURN '2' || p_param;
END;
$$ LANGUAGE plpgsql;

oid = '20716'の関数はtest2の方です。
test2の引数に注目なのですが、ここでデフォルト値をtest1で定義しています。
この関数が管理しているtest1のoidが見つからなくて、上記のエラーが発生していました。
何故oidが変わってしまったのか・・・

実はtest1を修正した時にoidが変わってしまったのです。
本来ならば、関数を修正してもoidは変わらないはずです。
ですがDROP FUNCTION IF EXISTSが悪さをしていました。
これを呼び出してからCREATE OR REPLACE FUNCTIONを呼び出すとoidが変わってしまいます。
おそらく一度削除したために新しいoidがふられているのだと思います。
本来、DROP FUNCTION IF EXISTSは呼び出す必要がありません。
なのに、なんかおまじないのように書いていたんですよね・・・

一行入魂サイトにアップしてあるストアードプロシージャのファイルから、DROP FUNCTION IF EXISTSを削除しておきました。
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。