他のバージョンの文書 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

32.7. 処理中の問い合わせのキャンセル #

32.7.1. キャンセル要求の送信関数 #

PQcancelCreate #

キャンセル要求を送信できる接続を準備します。

PGcancelConn *PQcancelCreate(PGconn *conn);

PQcancelCreatePGcancelConnオブジェクトを作成しますが、この接続を介して直ちにキャンセルリクエストを送信し始めることはありません。 キャンセル要求は、PQcancelBlockingを使用してブロッキング方式で、あるいはPQcancelStartを使用して非ブロッキング方式でこの接続を介して送信できます。 返り値はPQcancelStatusに渡して、PGcancelConnオブジェクトが正常に作成されたかどうかを調べることができます。 PGcancelConnオブジェクトは、アプリケーションが直接アクセスすることを意図していない不透明な構造体です。 このPGcancelConnオブジェクトは、スレッドセーフな方法で元の接続で実行中の問い合わせをキャンセルするために使用できます。

元のクライアントの多くの接続パラメータは、キャンセル要求の接続を設定するときに再利用されます。 重要な点として、元の接続が接続の暗号化とターゲットホストの検証(sslmodeまたはgssencmodeを使用)を必要とする場合、キャンセル要求の接続はこれらの同じ要件を使用して作成されます。 ただし、クライアントの認証中または認証後にのみ使用される接続オプションは無視されます。取り消し要求では認証は必要なく、接続は取り消し要求が送信された直後に閉じられるためです。

PQcancelCreateがNULL以外のポインタを返した場合、構造体と関連するメモリブロックを始末するために、PQcancelFinishを呼び出す必要があります。 これは、キャンセル要求が失敗したか、あるいは放棄された場合でも必要です。

PQcancelBlocking #

サーバがブロック方式で現在のコマンドの処理を中止するように要求します。

int PQcancelBlocking(PGcancelConn *cancelConn);

この要求は、PQcancelCreateで作成する必要がある指定されたPGcancelを介して行われます。 取り消し要求が正常にディスパッチされた場合、PQcancelBlockingの返却値は1です。 失敗した場合、エラーメッセージは PQcancelErrorMessage を使用して取得できます。

キャンセルの送信が成功しても、要求が有効になるとは限りません。 キャンセルが有効な場合、キャンセルされるコマンドは早期に終了し、エラー結果を返します。 キャンセルが失敗した場合 (サーバがコマンドの処理をすでに完了していた場合など)、目に見える結果はまったくありません。

PQcancelStart
PQcancelPoll #

サーバが非ブロッキング方式で現在のコマンドの処理を中止するように要求します。

int PQcancelStart(PGcancelConn *cancelConn);

PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);

この要求は、PQcancelCreateを使用して作成する必要がある指定されたPGcancelを介して行われます。 取り消し要求が開始できた場合、PQcancelStartの返却値は1です。 開始できなかった場合、エラーメッセージは PQcancelErrorMessage を使用して取得できます。

PQcancelStartが成功した場合、次の段階はlibpqをポーリングして、接続解除シーケンスを続行できるようにすることです。 データベース接続の基礎となるソケットの記述子を取得するには、PQcancelSocketを使用します。 (注意: ソケットはPQcancelPoll呼び出しの間は同じままだと仮定しないでください)。 ループを次のように実行します。 PQcancelPoll(cancelConn)が最後にPGRES_POLLING_READINGを返した場合、ソケットが読み込みの準備ができるまで待ちます(select()poll()などのシステム関数で指定します)。 その後、再度PQcancelPoll(cancelConn)を呼び出します。 逆に、PQcancelPoll(cancelConn)が最後にPGRES_POLLING_WRITINGを返した場合、ソケットが書き込み可能になるまで待ってから、再度PQcancelPoll(cancelConn)を呼び出します。 最初の反復では、つまりPQcancelPoll(cancelConn)をまだ呼び出していない場合は、最後にPGRES_POLLING_WRITINGを返したかのように振る舞います。 接続手続きが失敗したことを示すPGRES_POLLING_FAILEDを返すか、または、PGRES_POLLING_OKを返して、キャンセル要求が正常にディスパッチされたことを示すまで、このループを続けます。

キャンセルの送信が成功しても、要求が有効になるとは限りません。 キャンセルが有効な場合、キャンセルされるコマンドは早期に終了し、エラー結果を返します。 キャンセルが失敗した場合 (サーバがコマンドの処理をすでに完了していた場合など)、目に見える結果はまったくありません。

接続中はいつでも、PQcancelStatusを呼び出すことで接続の状態を確認できます。 この呼び出しがCONNECTION_BADを返した場合、キャンセル手続きは失敗です。 この呼び出しがCONNECTION_OKを返した場合、キャンセル要求は正常にディスパッチされました。 これらの状態はどちらも、上記のPQcancelPollの戻り値から等しく検出できます。 他の状態は、非同期接続手順の間(およびその間のみ)に発生することもあります。 これらは、接続手順の現在の段階を示し、例えばユーザにフィードバックを提供するのに有用です。 これらのステータスは次のとおりです。

CONNECTION_ALLOCATED #

PQcancelStartPQcancelBlockingへの呼び出しを待って、実際にソケットを開いています。 これはPQcancelCreatePQcancelResetを呼んだ直後の接続の状態です。 この時点ではサーバへの接続はまだ開始されていません。 実際にキャンセルリクエストの送信を開始するにはPQcancelStartPQcancelBlockingを使います。

CONNECTION_STARTED #

接続の確立待ち状態です。

CONNECTION_MADE #

接続はOKです。送信待ち状態です。

CONNECTION_AWAITING_RESPONSE #

サーバからの応答待ち状態です。

CONNECTION_SSL_STARTUP #

SSL暗号化の調停状態です。

CONNECTION_GSS_STARTUP #

GSS暗号化の調停状態です。

これらの定数は(互換性を保つため)なくなることはありませんが、アプリケーションは、これらが特定の順で出現したり、本書に書いてある値のどれかに必ずステータス値が該当するということを決して当てにしてはいけません。 アプリケーションは、以下に示すようにするべきです。

switch(PQcancelStatus(conn))
{
        case CONNECTION_STARTED:
            feedback = "Connecting...";
            break;

        case CONNECTION_MADE:
            feedback = "Connected to server...";
            break;
.
.
.
        default:
            feedback = "Connecting...";
}

PQcancelPollを使用する場合、connect_timeout接続パラメータは無視されます。 経過時間が長過ぎるかどうかの判定はアプリケーションの責任で行ないます。 そうでない場合、PQcancelStartとそれに続くPQcancelPollループはPQcancelBlockingと同等です。

PQcancelStatus #

キャンセル接続の状態を返します。

ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn);

ステータスは、いくつかの値のいずれかになります。 しかし、非同期キャンセル手続きの外で見られるのは、CONNECTION_ALLOCATEDCONNECTION_OKCONNECTION_BADの3つだけです。 PQcancelCreateを使用して正常に作成されたPGcancelConnの初期状態はCONNECTION_ALLOCATEDです。 正常にディスパッチされたキャンセル要求はCONNECTION_OKの状態になります。 キャンセルが失敗した場合、状態CONNECTION_BADが通知されます。 PQcancelFinishまたはPQcancelResetが呼び出されるまで、OK状態はそのまま残ります。

返される可能性がある他の状態コードについてはPQcancelStartの項目を参照してください。

キャンセルの送信が成功しても、要求が有効になるとは限りません。 キャンセルが有効な場合、キャンセルされるコマンドは早期に終了し、エラー結果を返します。 キャンセルが失敗した場合 (サーバがコマンドの処理をすでに完了していた場合など)、目に見える結果はまったくありません。

PQcancelSocket #

サーバへのキャンセル接続ソケットのファイル記述子番号を取得する。

int PQcancelSocket(const PGcancelConn *cancelConn);

有効なディスクリプタは0以上です。 -1 の結果は、現在オープンしているサーバ接続がないことを示します。 このセクションの関数をPGcancelConn PQcancelErrorMessage PQcancelSocket自身を除く)で呼び出すと、この値が変わる可能性があります。

PQcancelErrorMessage #

接続解除操作で最後に生成されたエラーメッセージを返します。

char *PQcancelErrorMessage(const PGcancelConn *cancelconn);

PGcancelConnを取得するlibpq関数のほとんどは、失敗した場合に PQcancelErrorMessage にメッセージを設定します。 libpqの規則では、空でない PQcancelErrorMessage 結果は複数行からなる可能性があり、最後に改行を含むことに注意してください。 呼び出し元は、結果を直接解放しないでください。 関連するPGcancelConnハンドルがPQcancelFinishに渡されると解放されます。 結果の文字列はPGcancelConn構造体に対する操作を通じて同じままになることは期待されません。

PQcancelFinish #

キャンセル接続を閉じます(キャンセル要求の送信がまだ完了していない場合)。 また、PGcancelConnオブジェクトが使用するメモリを解放します。

void PQcancelFinish(PGcancelConn *cancelConn);

取り消しの試みが失敗した場合(PQcancelStatusで示されるように)でも、アプリケーションはPQcancelFinishを呼び出してPGcancelConnオブジェクトが使用したメモリを解放するようにしてください。 PGcancelConnポインタはPQcancelFinishが呼び出された後は再度使用してはなりません。

PQcancelReset #

新しいキャンセル接続で再利用できるようにPGcancelConnをリセットします。

void PQcancelReset(PGcancelConn *cancelConn);

PGcancelConnが現在キャンセル要求を送信するために使用されている場合、この接続は閉じられます。 次に、新しいキャンセル要求を送信するために使用できるようにPGcancelConnオブジェクトを準備します。

これはPGconnに対して1つのPGcancelConnを作成し、元のPGconnの存続期間中に何度も再利用することができます。

32.7.2. キャンセル要求を送るための廃れた関数 #

これらの関数は古い方法でキャンセル要求を送信するものです。 これらはまだ動作しますが、元の接続が暗号化を要求するためにsslmodeまたはgssencmodeを指定した場合でも、キャンセル要求を暗号化された方法で送信しないため、推奨されません。 したがって、これらの古い方法は新しいコードではほとんど使用されず、既存のコードを変更して新しい関数を使用することをお勧めします。

PQgetCancel #

PQcancelを使用してコマンドをキャンセルするために必要な情報を含むデータ構造体を作成します。

PGcancel *PQgetCancel(PGconn *conn);

PQgetCancelPGconn接続オブジェクトを与えられたPGcancelオブジェクトを作成します。 指定されたconnNULLか、または無効な接続である場合、NULLを返します。 PGcancelオブジェクトは不透明な構造体で、アプリケーションが直接アクセスするためのものではありません。これはPQcancelまたはPQfreeCancelに渡すことができるだけです。

PQfreeCancel #

PQgetCancelで作成されたデータ構造を解放します。

void PQfreeCancel(PGcancel *cancel);

PQfreeCancelは事前にPQgetCancelで作成されたデータオブジェクトを解放します。

PQcancel #

PQcancelは、PQcancelBlockingの非推奨で安全でない変種ですが、シグナルハンドラ内から安全に使用できます。

int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);

PQcancelが存在するのは、下位互換性のためだけです。 代わりにPQcancelBlockingを使用してください。 PQcancelの唯一の利点は、errbufがシグナルハンドラ内のローカル変数である場合に、シグナルハンドラから安全に呼び出すことができることです。 しかし、一般的には、この関数が持つセキュリティ問題に見合うほど大きな利点とは考えられていません。

PGcancelオブジェクトはPQcancelに関しては読み取り専用であるため、PGconnオブジェクトを操作するスレッドとは別のスレッドからも呼び出すことができます。

取り消し要求が正常にディスパッチされた場合、PQcancelの戻り値は1で、そうでなければ0です。 ディスパッチされなかった場合、errbufに説明的なエラーメッセージが入ります。 errbuferrbufsizeのサイズ(推奨サイズは256バイト)の文字配列でなければなりません。

PQrequestCancel #

PQrequestCancelは、PQcancelBlockingの非推奨で安全でない変種です。

int PQrequestCancel(PGconn *conn);

PQrequestCancelは下位互換性のために存在します。 代わりにPQcancelBlockingを使用してください。 PQrequestCancelPQcancelBlockingよりも使用する利益はありません。

サーバに現在のコマンドの廃棄処理を要求します。 これはPGconnオブジェクトを直接扱い、また、失敗した場合エラーメッセージはPGconnオブジェクト内に収納されます。 ( PQerrorMessage により取り出すことができます。) 機能的には同一ですが、この方法は複数スレッドプログラムやシグナルハンドラでは安全ではありません。PGconnのエラーメッセージが上書きされることにより、その接続で現在進行中の操作を台無しにする可能性があるからです。