PostgreSQLはLISTENと NOTIFYコマンドによる非同期通知機能をサポートしています。バックエンドはLISTENコマンドを受け取ると、特定の通知条件に関心を持ったことを登録します(これを止めるには UNLISTENコマンドを使います)。特定の条件を待っているすべてのバックエンドは、同じ条件名のNOTIFYコマンドが任意のバックエンドによって実行された時点で非同期的に通知を受けます。ただし通知の発行側から受信側へ渡される付加的な情報はありません。したがって、典型的には両者の間で受け渡す必要のある実際のデータは、データベースリレーションを通じて転送することになります。一般的に、条件名は関連するリレーション名と同じものですが、必ず関連するリレーションが必要とされるわけではありません。
libpqアプリケーションは、通常のSQLによる問い合わせと同じようにLISTEN/UNLISTEN コマンドを発行することができます。NOTIFYメッセージの到着は、続いてPQnotifiesを呼び出せば検出できます。
PQnotifies バックエンドから受信した通知メッセージのうち、まだ処理されていないもののリストから次の通知を返します。保留中の通知がなくなれば NULLを返します。PQnotifiesが通知を返すとその通知はもはや処理が済んだものとみなされ、通知リストから取り除かれます。
PGnotify* PQnotifies(PGconn *conn); typedef struct pgNotify { char relname[NAMEDATALEN]; /* データを含むリレーションの名前 */ 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() を調べることを忘れないようにしておくべきです。