非同期問い合わせ処理

90) The PQexec function is adequate for submitting queries in simple synchronous applications. It has a couple of major deficiencies however:

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

94) Applications that do not like these limitations can instead use the underlying functions that PQexec is built from: PQsendQuery and PQgetResult.

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

99) Using PQsendQuery and PQgetResult solves one of PQexec's problems: if a query string contains multiple SQL commands, the results of those commands can be obtained individually. (This allows a simple form of overlapped processing, by the way: the frontend can be handling the results of one query while the backend is still working on later queries in the same query string.) However, calling PQgetResult will still cause the frontend to block until the backend completes the next SQL command. This can be avoided by proper use of three more functions:

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

106) A typical frontend using these functions will have a main loop that uses select(2) to wait for all the conditions that it must respond to. One of the conditions will be input available from the backend, which in select's terms is readable data on the file descriptor identified by PQsocket. When the main loop detects input ready, it should call PQconsumeInput to read the input. It can then call PQisBusy, followed by PQgetResult if PQisBusy returns FALSE. It can also call PQnotifies to detect NOTIFY messages (see "Asynchronous Notification", below).

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

107) A frontend that uses PQsendQuery/PQgetResult can also attempt to cancel a query that is still being processed by the backend.

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

110) Note that if the current query is part of a transaction, cancellation will abort the whole transaction.

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

111) PQrequestCancel can safely be invoked from a signal handler. So, it is also possible to use it in conjunction with plain PQexec, if the decision to cancel can be made in a signal handler. For example, psql invokes PQrequestCancel from a SIGINT signal handler, thus allowing interactive cancellation of queries that it issues through PQexec. Note that PQrequestCancel will have no effect if the connection is not currently open or the backend is not currently processing a query.

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