web-dev-qa-db-ja.com

PostgreSQLでpg_notify(text、text)を使用してLISTEN / NOTIFY

私はPostgreSQLの通知システムで遊んでいますが、pg_notify(text、text)が機能しない理由を一生理解できません。この機能は過度に文書化されておらず、実際に使用されている例は多くないので、ここで質問しても構わないと思いました。

以下を実行すると、期待どおりに機能します。

LISTEN my_channel;

NOTIFY my_channel, 'my message text';

ただし、pg_notify()関数を使用すると、null値が返され、通知は送信されません。エラーも発生しません。使用例は次のとおりです。

SELECT pg_notify('my_channel', 'my message text');

NOTIFY関数を使用することもできますが、私の目標は、通知を次のようなクエリに合理化することです。

select pg_notify(get_player_error_channel(username)::TEXT, 'test'::TEXT)
    from player;

ばかげた何かが欠けているに違いないと思いますが、その理由を理解することはできませんでした。 NOTIFYについて説明しているページは、次の場所にあります。 http://www.postgresql.org/docs/9.0/static/sql-notify.html

その上で、pg_notify()についてこれについて言及しているので、大幅な違いはないと思います。

pg_notify通知を送信するには、関数pg_notify(text、text)を使用することもできます。この関数は、最初の引数としてチャネル名を取り、2番目の引数としてペイロードを取ります。一定でないチャネル名とペイロードを操作する必要がある場合、この関数はNOTIFYコマンドよりもはるかに簡単に使用できます。

いつも助けてくれてありがとう

編集:データベースのバージョンは次のとおりです。「i686-pc-linux-gnu上のPostgreSQL 9.0.3、GCC gcc(GCC)4.2.4、32ビットでコンパイル」

17
Abstrct

これについては、PostgreSQLメーリングリスト(http://archives.postgresql.org/pgsql-bugs/2011-03/msg00041.php)で説明し、動作の理由について通知を受けました。

彼らの答えは、「.. relnamesを二重引用符で囲む必要があります(「Test」をリッスンします)。サーバーで大文字と小文字を区別しないようにするには、pg_notifyはrelnameではなく文字列を取ります。 (マーリンとトムに感謝します)

これは、チャネルが常に小文字に強制されるため、以下が機能することを意味します

LISTEN ERRORCHANNEL;

NOTIFY ERRORCHANNEL, 'something!';
NOTIFY eRrorChanNel, 'something!';

チャネル名を二重引用符で囲む場合は、大文字と小文字が区別されます。

したがって、次の場合、最初の通知は受信されますが、2番目の通知は受信されません。

LISTEN "ERRORCHANNEL";

NOTIFY "ERRORCHANNEL", 'something!'; 
NOTIFY "eRrorChanNel", 'something!';

同様に、二重引用符はERRORCHANNELのケースを強制的に維持するため、以下が機能します。

LISTEN "ERRORCHANNEL";

SELECT pg_notify('ERRORCHANNEL', 'something!');

これは機能しませんが:

LISTEN ERRORCHANNEL;

SELECT pg_notify('ERRORCHANNEL', 'something!');

この状況では、ERRORCHANNELはLISTENコマンドで二重引用符で囲まれていないため、PostgreSQLはそれを小文字に強制します。チャネルパラメータはrelnameではなくtext型であるため、pg_notify()関数では大文字と小文字は変更されません。一緒にチャネルが一致しないため(ERRORCHANNE!= errorchannel)、通知が受信されることはありません。

29
Abstrct