プロトコル

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

開始

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

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

ErrorResponse

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

AuthenticationOk

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

AuthenticationKerberosV4

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

AuthenticationKerberosV5

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

AuthenticationUnencryptedPassword

<-- The frontend must then send an UnencryptedPasswordPacket. If this is the correct password, the postmaster responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. --> この後フロントエンドは UnencryptedPasswordPacket を送出しなければ なりません。もしこのパスワードが正しければ、 postmaster は AuthenticationOk を返します。不成功の場合は ErrorResponse を返し ます。

AuthenticationEncryptedPassword

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

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

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

BackendKeyData

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

ReadyForQuery

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

ErrorResponse

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

NoticeResponse

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

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

問い合わせ

一つの問い合わせサイクルはフロントエンドがバックエンドに問い合わせメッセージ を送ることで起動されます。そこでバックエンドは問い合わせ命令の文字列の内容 に基づいて一つまたは複数の回答メッセージを送り、最終的に 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 が送られて来ることがあります。すなわち、実際にはフロント エンドがメッセージの到着を全く予期していないような状況でも、NoticeResponse が送られてくることがあり得ます。これはバックエンドのアイドル状態が、文字どお りの「待機状態」であるとは限らない、ということです。(特に、バックエンドは自身 が対応する postmaster によって終了させられることがあり、この場合、バックエンド は接続を解除する前に NoticeResponse を送ります。)フロントエンドには新しい命令 を出す直前に、このような非同期の通知の検証をすることを推奨します。

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

関数呼び出し

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

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

ErrorResponse

エラーが起こりました。

FunctionResultResponse

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

FunctionVoidResponse

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

ReadyForQuery

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

NoticeResponse

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

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

通知応答

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

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

NotificationResponse

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

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

処理中リクエストの取消

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

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

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

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

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

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

終了

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

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