4.2. プロトコル

この章ではメッセージの流れに付いて記載します。接続の状況、つまり、開始、 問い合わせ、関数呼び出し、終了フェーズによって4つの 異なった流れがあります。 開始フェーズ以降の任意の時点で発生し得る通知回答 と命令取り消しには、特別な 規定が存在します。

4.2.1. 開始

開始フェーズは、認証フェーズとバックエンド開始フェーズに分割されます。

始めにフロントエンドは StartupPacket を送ります。 postmaster はこのパケット の 情報と gp_hba.conf ファイルの内容から、フロントエンドが使用すべき 認証方法を 決定し、続いて以下のメッセージのどれか一つを返します。

ErrorResponse

この後すぐ postmaster は接続を解除します。

AuthenticationOk

この後 postmaster はバックエンドに引き継ぎます。 postmaster は以降通信に関与しません。

AuthenticationKerberosV4

この後フロントエンドは postmaster と Kerberos V4 の認証手続き (ここでは説明しません)を開始しなければなりません。成功する と、 postmaster は AuthenticationOk を返します。 不成功の場合は ErrorResponse を返します。

AuthenticationKerberosV5

この後フロントエンドは postmaster と Kerberos V5 の認証手続き (ここでは説明しません)を開始しなければなりません。成功する と、 postmaster は AuthenticationOk を返します。不成功の場合は ErrorResponse を返します。

AuthenticationUnencryptedPassword

この後フロントエンドは UnencryptedPasswordPacket を 送出しなければなりません。もしこのパスワードが正しければ、 postmaster は AuthenticationOk を返します。不成功の場合は ErrorResponse を返します。

AuthenticationEncryptedPassword

この後フロントエンドは EncryptedPasswordPacket を 送出しなければなりません。もしこのパスワードが正しければ、 postmaster は AuthenticationOk を返します。 不成功の場合は ErrorResponse を返します。

postmaster が要求する認証方式をフロントエンドがサポートしない場合、 接続を即座 に解除しなければなりません。

AuthenticationOk を送出後 postmaster はバックエンドプロセスの立ち上げにかか ります。これに失敗するかまたはバックエンドに起動段階 で不首尾があった場合、 フロントエンドはバックエンドが正常に起動するのを 待たなければなりません。 この時点ではフロントエンドは 何のメッセージも送りません。この段階でバックエンド から送られるメッセージ としては以下のものがあります。

BackendKeyData

このメッセージはバックエンドが起動に成功した時に送出されます。 これは、後にフロントエンドが取り消しリクエストを出す事が 出来るようにするために、保存しておくべき秘密鍵データを提供します。 フロントエンドはこのメッセージに応答してはいけませんが、 ReadyForQuery メッセージを受信し続ける必要があります。

ReadyForQuery

バックエンドの開始が成功しました。フロントエンドは問い合わせ または関数呼び出しメッセージを送ることが出来ます。

ErrorResponse

バックエンドの起動に失敗しました。このメッセージ送出後、 接続は解除されます。

NoticeResponse

警告メッセージが出されました。フロントエンドはこのメッセージ を表示しなくてはなりませんが、引続き ReadyForQuery または ErrorResponse を受信し続けます。

ReadyForQuery メッセージは各問い合わせサイクルの後にバックエンドが出すものと 同じものです。フロントエンドのコーディングにおい て必要であれば、ReadyForQuery を問い合わせサイクルの開始と見なしてもよい (そして BackendKeyData により開始 フェーズの正常終了が 通知されます)し、開始フェーズとそれに続く各問い合わせサイクルの終了と 見なしてもよいでしょう。

4.2.2. 問い合わせ

一つの問い合わせサイクルはフロントエンドがバックエンドに問い合わせメッセージ を送ることで起動されます。そこでバックエンドは問い合わせ命令の文字列の内容 に基づいて一つまたは複数の回答メッセージを送り、最終的に ReadyForQuery 回答 メッセージを送出します。ReadyForQuery はフロントエンドに確実に新規の問い合わ せまたは関数呼び出しを行っても良いことを伝えます。

バックエンドから送られるメッセージとしては以下のものがあげられます。

CompletedResponse

SQL コマンドが正常に終了しました。

CopyInResponse

バックエンドがフロントエンドからのデータをリレーションに コピーする準備が出来ました。フロントエンドはここで CopyDataRows メッセージを送出しなければなりません。そこで、 バックエンドは "COPY" と言う文字列のタグを付けた CompletedResponse メッセージを返します。

CopyOutResponse

バックエンドがデータをリレーションからフロントエンドに コピーする準備が出来ました。バックエンドはここで CopyDataRows メッセージに引き続き、「COPY」と言う文字列のタグを付けた CompletedResponse メッセージを返します。

CursorResponse

問い合わせは insert(l)、 delete(l)、 update(1)、fetch(l) または select(l) 命令のいずれかです。トランザクションが 中断された場合、 バックエンドは 「*ABORT STATE*」 という 文字列のタグを付けた CompletedResponse メッセージを送ります。 それ以外では、以下の応答があります。

insert(l) 命令に対し、バックエンドは「INSERT oid rows」 と言う文字列の タグを付けた CompleteResponse メッセージを 送出します。 ここで、rows は挿入された行の数で、 rows が 1 の場合 oid は挿入された行の オブジェクト識別子で、それ以外の場合は oid は 0 です。

delete(l) 命令に対し、バックエンドは 「DELETE rows 」と言う文字列のタグを付けた CompletedResponse メッ セージを返します。ここで、 rows は削除された行数です。

update(l) 命令対し、バックエンドは 「UPDATE rows 」と言う文字列のタグを付けた CompletedResponse メッセージを返します。ここで、 rows は削除された行数です。

fetch(l) または select(l) コマンドに対し、バックエンドは RowDescription メッセージを返します。この後続いて (バイナリカーソルが指定されているかどうかにより)フロントエンド に返されるそれぞれの行に対して AsciiRow または BinaryRow メッセージが続きます。最後にバックエンドは 「SELECT」と言う 文字列のタグを付けた CompletedResponse メッセージを送出します。

EmptyQueryResponse

空の問い合わせ文字列が検出されました。 (特別にこのケースを識別する 必要性は現在ありません。)

ErrorResponse

エラーが起こりました。

ReadyForQuery

問い合わせ文字列の処理が完了しました。問い合わせ文字列は複数 の SQL 命令を含む場合もあるため、別個のメッセージがこの結 果を示すために送出されます。(CompletedResponse は全ての文字列 では無く、一つの SQL 命令の処理の終了の印です。) ReadyForQuery は 処理が正常に終ったかエラーとなったかに関らず、 常に送られます。

NoticeResponse

警告メッセージは特定の問い合わせに関連して出されます。 警告はバックエンドが命令の処理を引続き行うという、 他の応答に対する 追加のメッセージです。

フロントエンドは他の種類のメッセージを待っているかどうかに関わらず、 ErrorResponse と NoticeResponse メッセージを受け取れる状態 になっていなければなりません。

実際には、フロントエンドがメッセージの到着を全く予期していないような状態でも、 NoticeResponse が送られて来ることがあります。 これはバックエンドのアイドル状態が、文字どおりの「待機状態」であるとは 限らない、ということです。(特に、バックエンドは自身 が対応する postmaster によって終了させられることがあり、この場合、バックエンド は接続を解除する前に NoticeResponse を送ります。)フロントエンドには新しい命令 を出す直前に、 このような非同期の通知の検証をすることを推奨します。

時に、フロントエンドが listen(l) 命令を出した場合、いつでも NotificationResponse メッセージを受け取る準備が出来ていることが必要で す。 以下を参照

4.2.3. 関数呼び出し

関数呼び出しサイクルはフロントエンドが FunctionCall メッセージをバックエンド に送ることで起動されます。バックエンドは一つ又はそれ以上の応答メッセージ を関数呼び出しの結果に基づいて送り、最終的に ReadyForQuery メッセージを 送出します。 ReadyForQuery はフロントエンドに対し新規の問い合わせ又は 関数呼び出しを行っても安全確実であることを通知します。

バックエンドからの応答メッセージとして以下があげられます。

ErrorResponse

エラーが起こりました。

FunctionResultResponse

関数呼び出しが処理され結果が返されました。

FunctionVoidResponse

関数呼び出しは処理されましたが結果は返されませんでした。

ReadyForQuery

関数呼び出しの処理が終了しました。 処理が成功またはエラーで 終了したかどうかに関わらず ReadyForQuery が常に送出されます。

NoticeResponse

関数呼び出しに関して警告メッセージが出されました。 警告メッセージ はバックエンドが命令を引続き処理するという 他の応答に対する追加のメッセージです。

フロントエンドは他の種類のメッセージの到着を待機しているかどうかに関わらず、 ErrorResponse と NoticeResponse メッセージを受け取る準備が出来ていなければ なりません。同時に listen(l) コマンドを送出した場合、常時 NotificationResponse メッセージを受け取れる準備が 出来ていなくてはなりません。下記を参照して下さい。

4.2.4. 通知応答

フロントエンドが listen(l) 命令を送出し、その後これと同じ通知名に対し notify(l) 命令が実行されると、バックエンドは NofificationResponse メッセージ (NoticeResponse と間違えないように!)を送出します。

(起動後において)通知応答は、他のバックエンドメッセージの処理シーケンスの途中 でない限り、任意の時点で発行出来ます。 従って、フロントエンドは他の メッセージを待機しているかどうかに関らず NotificationResponse メッセージを 受け取れる準備が出来ていなければなりません。実際、問い合わせに関与して いない時でも NotificationResponse を処理することが出来なければなりません。

NotificationResponse

前の listen(l) 命令が実行された名前に対し notify(l) 命令が 実行されました。通知メッセージはいつでも出せる状態です。

listen および notify 命令で使用される名前は、SQL データベース内のリレー ション(テーブル)の名前とは関係ない事を指摘しておいたほうが 良いでしょう。 通知名は単に勝手に選択された状態の名称です。

4.2.5. 処理中リクエストの取消

問い合わせの処理中に、フロントエンドは postmaster に対し適切なリクエストを 送る ことによりその問い合わせを取り消すことが出来ま す。取り消しリクエストは効率性を 高めるために直接バックエンドに送られません。 問い合わせ処理中にバックエンドが 定期的にフロ ントエンドからの入力を確かめる事は、好ましくないからです。取り消し リクエストは大抵の場合、頻繁には起こらないので、通常の状態 においての不便を避けるため、多少扱いにくくなっています。

取り消しリクエストを出す場合、フロントエンドは通常の新規接続の時に一般的に 送出 される StartupPacket ではなくて CancelRequest メッセージを postmaster に送り、 新規接続を開始します。 postmaster はこのリクエストを 処理し接続を解除します。 セキュリティ上の理由 から、取り消し要求メッセージに対し直接の回答はありません。

CancelRequest メッセージは、接続開始段階でフロントエンドに送られたのと同一 の鍵 データ(PID と秘密鍵)を含んでいない場合無視されます。 現在バックエンドが実行中の 処理に対しする PID と秘密鍵がリクエストと 一致した場合、 postmaster はバックエン ドに対し現在の問い合わせ処理の中止を 警告します。

取り消しの警告は何の効果も生まないことがあります。たとえば、バックエンドが問 い合わせの処理を完了した後に届いた場合、効果がありません。 もし取り消し命令が有効であれば、エラーメッセージとともに、 現在の命令も終了されます。

セキュリティと効率性の理由によるこれらの結論として、フロントエンドは取り消し リクエストが受け付けられたかどうかを知る方法が無いと言うことです。 フロントエンドは バックエンドからの問い合わせの回答を待ち続けなければ なりません。取り消しを要求 することは単に現在の問い合わせを早めに終らせ、 成功ではなくエラーメッセージを出し て不成功とする可能性を多少高める程度です。

取り消しリクエストは、通常のフロントエンドとバックエンドの通信接続を通してで はなく postmaster に送られるため、その問い合わせが 取り消されるフロントエンド だけでなくどんなプロセスによっても出される 可能性があります。このことはマルチ処理アプリケーション を作るに当たって柔軟性を提供します。同時に、承認されてい ない者が問い合わせを 取り消そうとするといったセキュリティ上のリスクも 持ち込みます。 セキュリティ上のリスクは取り消しリクエストの際に供給される 動的に生成される秘密キー を要求することによって回避さ れます。

4.2.6. 終了

通常の洗練された終了手順はフロントエンドが Terminate メッセージを出し、 すぐに接続を閉じることです。メッセージを受け取るとすぐ にバックエンドは接続を閉じ終了します。

洗練されていない終了はどちらかの側のソフトウエアの失敗(例えばコアダンプ) によって 起こることがあります。フロントエンドかバック エンドいずれかが予期しない接続の中断 を検知した時、問題を片付けて終了しなくて はなりません。フロントエンドはもし自身が 終了を 望まない場合、 postmaster に再交信し新規のバックエンドを立ち上げる選択権を 持っています。