オプションは次のとおりです。
接続を開くと、CREATE TEMPORARY TABLE current_app_user(username text); INSERT INTO current_app_user(username) VALUES ('the_user');。次に、トリガーでSELECT username FROM current_app_user、おそらくサブクエリとして、現在のユーザー名を取得します。
のようなカスタムGUCpostgresql.confのエントリを作成します。接続を作成するときはいつでも実行します。次に、トリガーで、関数を使用して値を取得します。事実上、セッション変数を提供するためにGUC機構を悪用しています。カスタムGUCは9.2で変更されたため、サーバーのバージョンに適したドキュメントをお読みください。my_app.username = 'unknown';SET my_app.username = 'the_user';current_setting('my_app.username')
すべてのアプリケーションユーザーのデータベースロールを持つようにアプリケーションを調整します。SET ROLE仕事をする前にそのユーザーに。これにより、組み込みのcurrent_user変数のような関数を使用できるだけでなく、データベースのセキュリティSELECT current_user;を強化することもできます。この質問を参照してください。を使用する代わりにユーザーとして直接ログインすることもできますが、それでは接続プールが困難になる傾向があります。SET ROLE
DISCARD ALL;3つのケースすべてで接続プールを使用している場合は、接続をプールに戻すときに注意する必要があります。(そうするように文書化されていませんが、そうDISCARD ALLしますRESET ROLE)。
デモの一般的な設定:
CREATE TABLE tg_demo(blah text);
INSERT INTO tg_demo(blah) VALUES ('spam'),('eggs');
-- Placeholder; will be replaced by demo functions
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT 'unknown';
$$ LANGUAGE sql;
CREATE OR REPLACE FUNCTION tg_demo_trigger() RETURNS trigger AS $$
BEGIN
RAISE NOTICE 'Current user is: %',get_app_user();
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tg_demo_tg
AFTER INSERT OR UPDATE OR DELETE ON tg_demo
FOR EACH ROW EXECUTE PROCEDURE tg_demo_trigger();
GUCの使用:
- の
CUSTOMIZED OPTIONSセクションにpostgresql.conf、のような行を追加しmyapp.username = 'unknown_user'ます。9.2より古いバージョンのPostgreSQLでは、も設定する必要がありますcustom_variable_classes = 'myapp'。
- PostgreSQLを再起動します。
SHOW myapp.usernameこれで、値を取得できるようになりますunknown_user。
SET myapp.username = 'the_user';これで、接続を確立するとき、またはトランザクションをローカルにしたい場合はトランザクションを実行したSET LOCAL myapp.username = 'the_user';後に使用できます。これは、プールされた接続に便利です。BEGIN
関数のget_app_user定義:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
SELECT current_setting('myapp.username');
$$ LANGUAGE sql;
トランザクションに使用するデモSET LOCAL-ローカルの現在のユーザー名:
regress=> BEGIN;
BEGIN
regress=> SET LOCAL myapp.username = 'test_user';
SET
regress=> INSERT INTO tg_demo(blah) VALUES ('42');
NOTICE: Current user is: test_user
INSERT 0 1
regress=> COMMIT;
COMMIT
regress=> SHOW myapp.username;
myapp.username
----------------
unknown_user
(1 row)
SET代わりにを使用するとSET LOCAL、設定はコミット/ロールバック時に元に戻されないため、セッション全体で持続します。それはまだによってリセットされDISCARD ALLます:
regress=> SET myapp.username = 'test';
SET
regress=> SHOW myapp.username;
myapp.username
----------------
test
(1 row)
regress=> DISCARD ALL;
DISCARD ALL
regress=> SHOW myapp.username;
myapp.username
----------------
unknown_user
(1 row)
また、サーバー側のバインドパラメータを使用しSETたり使用したりすることはできないことに注意してください。SET LOCALバインドパラメータ(「プリペアドステートメント」)を使用する場合は、関数フォームの使用を検討してset_config(...)ください。システム管理機能を参照してください
一時テーブルの使用
このアプローチでは、すべてのセッションで必要な一時テーブルから値を読み取ろうとするトリガー(またはトリガーによって呼び出されるヘルパー関数が望ましい)を使用する必要があります。一時テーブルが見つからない場合は、デフォルト値が提供されます。これはやや遅い可能性があります。注意深くテストしてください。
get_app_user()定義:
CREATE OR REPLACE FUNCTION get_app_user() RETURNS text AS $$
DECLARE
cur_user text;
BEGIN
BEGIN
cur_user := (SELECT username FROM current_app_user);
EXCEPTION WHEN undefined_table THEN
cur_user := 'unknown_user';
END;
RETURN cur_user;
END;
$$ LANGUAGE plpgsql VOLATILE;
デモ:
regress=> CREATE TEMPORARY TABLE current_app_user(username text);
CREATE TABLE
regress=> INSERT INTO current_app_user(username) VALUES ('testuser');
INSERT 0 1
regress=> INSERT INTO tg_demo(blah) VALUES ('42');
NOTICE: Current user is: testuser
INSERT 0 1
regress=> DISCARD ALL;
DISCARD ALL
regress=> INSERT INTO tg_demo(blah) VALUES ('42');
NOTICE: Current user is: unknown_user
INSERT 0 1
安全なセッション変数
PostgreSQLに「セキュアセッション変数」を追加する提案もあります。これらはパッケージ変数に少し似ています。PostgreSQL 12の時点では、この機能は含まれていませんが、これが必要な場合は、ハッカーリストに注意して発言してください。
高度:共有メモリ領域を備えた独自の拡張機能
高度な使用法では、独自のC拡張機能に共有メモリ領域を登録させ、DSAセグメントの値を読み書きするC関数呼び出しを使用してバックエンド間で通信することもできます。詳細については、PostgreSQLプログラミングの例を参照してください。Cの知識、時間、そして忍耐力が必要です。