PostgreSQL は、LISTEN と NOTIFY コマンドを使用した、非同期通知をサポートします。 バックエンドはLISTENコマンドを受け取ると、特定の通知条件に関心を持ったことを登録します(これを止めるには UNLISTEN コマンドを使います)。 特定の条件を待っているすべてのバックエンドは、同じ条件名の NOTIFY コマンドが任意のバックエンドによって実行された時点で非同期的に通知を受けます。他の情報は通知元から監視先へ渡されません。 したがって、典型的には両者の間で受け渡す必要のある実際のデータは、データベースリレーションを通じて転送することになります。 一般的に、条件名は関連するリレーション名と同じものですが、必ず関連するリレーションが必要とされるわけではありません。
libpqアプリケーションは、通常のSQLによる問い合わせと同じようにLISTEN/UNLISTENコマンドを発行することができます。 NOTIFYメッセージの到着は、続いてPQnotifiesを呼び出せば検出できます。
PQnotifies バックエンドから受信した通知メッセージのうち、まだ処理されていないもののリストから次の通知を返します。 保留中の通知がなくなれば NULLを返します。PQnotifies が通知を返すと、その通知はもはや処理が済んだものとみなされ、通知リストから取り除かれます。
PGnotify* PQnotifies(PGconn *conn); typedef struct pgNotify { char *relname; /* データを含むリレーションの名前 */ int be_pid; /* バックエンドのプロセス ID */ } PGnotify;
メモリリークを防ぐため、PQnotifies が返したPGnotify オブジェクトの処理が終わったら、必ず free() で領域を解放してください。
Note: 6.4 より前のバージョンでは、be_pid が常に接続しているバックエンドの PID だったのに対し、6.4 とそれ以降の PostgreSQL では通知を発行したバックエンドの PID になります。
2 番目のサンプルプログラムにて、非同期通知の使用例を示します。
PQnotifies() は実際にバックエンドのデータを読み出すわけではありません。 これは単に、他のlibpq 関数が吸収してしまっていた通知メッセージを返すだけです。 libpq の以前のリリースでは、通知メッセージを適切な時点で確実に受け取るには、空の問い合わせでもなんでも、とにかく一定時間ごとに問い合わせを送り、そして PQexec() を実行するたびに PQnotifies() をチェックするしかありませんでした。 今でもこの方法は動作しますが、処理能力の無駄使いをすることになるのでやめておくべきでしょう。
実行するべき問い合わせがないときに通知メッセージをチェックするよい方法は、まず PQconsumeInput() を呼び出し、それから PQnotifies() をチェックすることです。 バックエンドからのデータの到着を select で待つことができ、不必要な動作で CPU パワーを消費してしまうことがありません (select()で使用するファイル識別子番号の取得については、PQsocket() を参照してください)。 なお、これは問い合わせに PQsendQuery と PQgetResult を使ったときでも、またはおなじみの PQexec を使ったときでも動作します。 しかし通知が問い合わせの処理中に届いていないかどうか、PQgetResult あるいは PQexec の実行ごとに PQnotifies() を調べることを忘れないようにしておくべきです。