1.3. 非同期問い合わせ関数

シンプルな同期型のアプリケーションの場合。問い合わせの実行は PQexec 関数で十分です。しかし、大きな問題をいくつ か抱えています。

アプリケーションにとってこのような制限が望ましくない場合は、代わりに PQexec を構成する関数 PQsendQueryPQgetResultを 使用してください。

PQputlinePQputnbytes と 同様に、この機能性を使っている古いプログラムは、バックエンドへのデータ 送信待ちをブロックしてしまう可能性がありました。この問題に対応するため に、PQsetnonblocking が追加されました。

古めのアプリケーションでは、PQsetnonblocking が使 われていなかったり、昔の潜在的にブロックする挙動を得ていなかったりしま した。 新しいプログラムでは、PQsetnonblocking を使うこと で、バックエンドと完全にブロックされない接続をすることが出来るようにな りました。

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

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

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

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

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