あなたのコードを変更しないと機能がエラーにNULL
を返すようにしたい場合は、あなたがトラップし、エラーをBEGIN ... EXCEPTION
ブロックを使用してPL/pgSQL関数でそれらをラップすることによってこれを行うことができます。これを行うには
、最初に私はエラーのSQLSTATEを取得する:私はエラーハンドラ内で直接これを使用することができ
regress=# \set VERBOSITY verbose
regress=# SELECT pgp_sym_decrypt('fred','key');
ERROR: 39000: Wrong key or corrupt data
LOCATION: decrypt_internal, pgp-pgsql.c:607
が、私はシンボリック名を使用することを好むので、私は、エラー名を検索Appendix A - Error codesの39000に関連付けられており、それが汎用関数呼び出しエラーexternal_routine_invocation_exception
であることがわかります。私たちが気に入ったほど具体的ではありませんが、そうするでしょう。
ラッパー機能が必要です。このような何かを定義する必要があります。オーバーロードされた署名のそれぞれについて、サポートしたいpgp_sym_decrypt
の関数を1つ指定してください。例えば、text
を返す(bytea,text)
フォームの:
CREATE OR REPLACE FUNCTION pgp_sym_decrypt_null_on_err(data bytea, psw text) RETURNS text AS $$
BEGIN
RETURN pgp_sym_decrypt(data, psw);
EXCEPTION
WHEN external_routine_invocation_exception THEN
RAISE DEBUG USING
MESSAGE = format('Decryption failed: SQLSTATE %s, Msg: %s',
SQLSTATE,SQLERRM),
HINT = 'pgp_sym_encrypt(...) failed; check your key',
ERRCODE = 'external_routine_invocation_exception';
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
IはDEBUG
レベルメッセージに元のエラーをpreseveすることを選択しました。ここでは、完全なメッセージの冗長性とデバッグレベルの出力を元のラッパーと比較します。
デバッグ出力を有効にして、RAISE
を表示します。パラメータを含むpgp_decrypt_sym
呼び出しの元のクエリテキストも表示されます。
regress=# SET client_min_messages = DEBUG;
新機能は、まだ詳細なログが有効になっている場合にエラーを報告しますが、NULL
を返しラップ:これが失敗した、オリジナルに比べ
regress=# SELECT pgp_sym_decrypt_null_on_err('redsdfsfdsfd','bobsdf');
LOG: 00000: statement: SELECT pgp_sym_decrypt_null_on_err('redsdfsfdsfd','bobsdf');
LOCATION: exec_simple_query, postgres.c:860
DEBUG: 39000: Decryption failed: SQLSTATE 39000, Msg: Wrong key or corrupt data
HINT: pgp_sym_encrypt(...) failed; check your key
LOCATION: exec_stmt_raise, pl_exec.c:2806
pgp_sym_decrypt_null_on_err
-----------------------------
(1 row)
:
regress=# SELECT pgp_sym_decrypt('redsdfsfdsfd','bobsdf');
LOG: 00000: statement: SELECT pgp_sym_decrypt('redsdfsfdsfd','bobsdf');
LOCATION: exec_simple_query, postgres.c:860
ERROR: 39000: Wrong key or corrupt data
LOCATION: decrypt_internal, pgp-pgsql.c:607
注両方のことフォームは、関数が失敗したときに呼び出されたパラメータを示します。。バインドパラメータ(「プリペアドステートメント」)を使用した場合、パラメータは表示されませんが、データベース内の暗号化を使用している場合は、ログをセキュリティクリティカルとみなす必要があります。
個人的には、私はアプリで暗号を行うほうが良いと思うので、DBはキーにアクセスできません。
あなたの答えに感謝します。私は最後の手段としてこの種の機能を実装することに決めました。確かに非常に便利です。私は、ビルド中のpgsql関数を最大限に活用しようとしています。それがどのように役立つのかを見てみましょう。 また、アプリ内のすべての暗号を行うことをお祈りしています。私は既に、アプリでいくつかの重要な機能を変更する予定だったのです。私は後ですべてを変える。 –
@ user1365983良い - これはとても良いアイデアだとは思わないので、あなたはそれをやることを計画していないのでうれしい。それが役に立つと答えた場合は、左上のアンサースコアの下のチェックマークを使用して受け入れてください。 –