PostgreSQLは、LISTEN
とNOTIFY
コマンドを使用した、非同期通知をサポートします。
クライアントセッションは、LISTEN
コマンドを使用して処理対象とする特定の通知チャネルを登録します。
(通知監視を取り止めるにはUNLISTEN
コマンドを使用します。)
任意のセッションでそのチャネル名によるNOTIFY
コマンドが実行されると、特定チャネルを監視しているすべてのセッションは非同期に通知を受け取ります。
監視者に追加データを通信するために「ペイロード」文字列を渡すことができます。
libpqアプリケーションは、通常のSQLによる問い合わせと同じようにLISTEN
、UNLISTEN
およびNOTIFY
コマンドを発行することができます。
NOTIFY
メッセージの到着は、続いてPQnotifies
を呼び出せば検出できます。
PQnotifies
関数は、サーバから受信した通知メッセージの未処理リストから次の通知を返します。
保留中の通知がなくなればヌルポインタを返します。
PQnotifies
が通知を返すと、その通知は処理済みとみなされ、通知リストから取り除かれます。
PGnotify *PQnotifies(PGconn *conn); typedef struct pgNotify { char *relname; /* 通知チャネル名 */ int be_pid; /* 通知元サーバプロセスのプロセスID */ char *extra; /* 通知ペイロード文字列 */ } PGnotify;
PQnotifies
で返されたPGnotify
オブジェクトの処理が終わったら、PQfreemem
を使用して確実に解放してください。
PGnotify
ポインタを解放することは重要です。
relname
とextra
フィールドは別の割り当てを表していません。
(これらのフィールド名は歴史的なものです。特にチャネル名はリレーション名と関係するものである必要はありません。)
例31.2「libpq サンプルプログラム 2」で非同期通知を使用したサンプルプログラムを示しています。
PQnotifies()
は実際にサーバのデータを読み出すわけではありません。
これは単に、他のlibpq関数が吸収してしまっていた通知メッセージを返すだけです。
libpqの以前のリリースでは、通知メッセージを適切な時点で確実に受け取るには、空の問い合わせでも何でも、とにかく一定時間ごとに問い合わせを送り、そしてPQexec()
を実行するたびにPQnotifies()
を検査するしかありませんでした。
今でもこの方法は動作しますが、処理能力の無駄使いをすることになるのでやめておくべきでしょう。
実行すべき問い合わせがない時に通知メッセージを検査するよい方法は、まずPQconsumeInput()
を呼び出し、それからPQnotifies()
を検査することです。
サーバからのデータの到着をselect()
で待つことができ、不必要な動作でCPUパワーを消費してしまうことがありません。
(select()
で使用するファイル記述子番号の取得については、PQsocket()
を参照してください。)
なお、これは問い合わせにPQsendQuery
とPQgetResult
を使った時でも、またはおなじみのPQexec
を使った時でも動作します。
しかし通知がコマンドの処理中に届いていないかどうか、PQgetResult
あるいはPQexec
の実行ごとにPQnotifies()
を調べることを忘れないようにしておくべきです。