非同期問い合わせ処理

シンプルな同期型のアプリケーションの場合, 問い合わせの実行は PQexec 関数で十分です. しかし,ここにはいくつか大きな問題があります.

アプリケーションにとってこのような制限が望ましくない場合は, かわりに PQexec を構成する内部関数,PQsendQuery と PQgetResult を使ってください.

PQsendQuery と PQgetResult を使うことで PQexec の問題は一つ解決します. つまり,問い合わせが複数の SQL コマンドを含んでいる場合でも, これらのコマンドの結果を個々に得ることができるわけです. (これは多重処理をシンプルな形で実現します. 単一の文字列に含まれる複数の問い合わせのうち,後にくるものが処理中でも フロントエンドは先に完了した結果から扱うことができるからです) しかしバックエンドが次の SQL コマンドの処理に入ると, それが完了するまでやはり PQgetResult の呼び出しがフロントエンドをブロックしてしまいます. これを防ぐには,さらに三つの関数をうまく使うことです.

これらの関数を使う典型的なフロントエンドは select(2) を使ったメインループを備え, 応答しなければならない全ての状態を待ちます. やがてこの状態のうちひとつ(select 関数の点から見れば, PQsocket で確認したファイルディスクリプタから読み込めるデータ) がバックエンドから入力可能になります. メインループは入力が可能になったことを検出したら, PQconsumeInput を呼び出して入力を読み込みます. 続いて PQisBusy を呼び出し,PQisBusy が FALSE を返したらさらに PQgetResult を呼び出します. あるいは PQnotifies を呼び出して通知メッセージを検出する場合もあります (後出「非同期通知」セクションを参照)

PQsendQuery/PQgetResult を使うと,バックエンドで処理中の問い合わせを フロントエンドからキャンセルするよう要求することができます.

なお,処理中の問い合わせがトランザクションの一部だと, キャンセル処理によってトランザクション全体がアボートされます.

PQrequestCancel はシグナルハンドラから起動しても大丈夫です. また単に PQexec と組み合わせて使うこともできます. たとえば psql は PQexec を通して発行された問い合わせのキャンセル処理を, SIGINT シグナルハンドラから PQrequestCancel を起動することで インタラクティブに実行できるようになっています. なお,接続がオープンされていない, あるいはバックエンドが問い合わせの処理をしていない状態では, PQrequestCancel の呼び出しは何の効果もありません.