バージョンごとのドキュメント一覧

55.2. メッセージの流れ #

<title>Message Flow</title>

This section describes the message flow and the semantics of each message type. (Details of the exact representation of each message appear in <xref linkend="protocol-message-formats"/>.) There are several different sub-protocols depending on the state of the connection: start-up, query, function call, <command>COPY</command>, and termination. There are also special provisions for asynchronous operations (including notification responses and command cancellation), which can occur at any time after the start-up phase. 本節では、メッセージの流れと各メッセージ種類のセマンティクスを説明します。 (各メッセージの正確な表現の詳細については55.7で説明します。) 開始、問い合わせ、関数呼び出し、COPY、終了といった接続状態に応じて、複数の異なるサブプロトコルがあります。 また、開始段階の後の任意の時点で発生する可能性がある、非同期操作(通知応答やコマンドのキャンセルを含む)用の特別な準備もあります。

55.2.1. 開始 #

<title>Start-up</title>

To begin a session, a frontend opens a connection to the server and sends a startup message. This message includes the names of the user and of the database the user wants to connect to; it also identifies the particular protocol version to be used. (Optionally, the startup message can include additional settings for run-time parameters.) The server then uses this information and the contents of its configuration files (such as <filename>pg_hba.conf</filename>) to determine whether the connection is provisionally acceptable, and what additional authentication is required (if any). セッションを開始するために、フロントエンドはサーバへの接続を開き、開始メッセージを送信します。 このメッセージには、ユーザ名と接続を希望するデータベース名が含まれます。 これはまた、使用する特定のプロトコルバージョンを識別します。 (オプションとして、開始メッセージに、実行時パラメータの追加設定を含めることもできます。) サーバはその後、この情報と設定ファイル(pg_hba.confなど)の内容を使用して、接続が暫定的に受け付けられるかどうか、そして(もしあれば)どのような追加認証が必要かを決定します。

The server then sends an appropriate authentication request message, to which the frontend must reply with an appropriate authentication response message (such as a password). For all authentication methods except GSSAPI, SSPI and SASL, there is at most one request and one response. In some methods, no response at all is needed from the frontend, and so no authentication request occurs. For GSSAPI, SSPI and SASL, multiple exchanges of packets may be needed to complete the authentication. サーバはその後、適切な認証要求メッセージを送信します。 フロントエンドはこれに適切な認証応答メッセージ(パスワードなど)で答えなければなりません。 GSSAPI、SSPI、SASLを除くすべての認証方式では、多くても1つの要求と1つの応答が存在します。 認証方式の中には、フロントエンドからの応答をまったく必要としないものもあり、その場合、認証要求も発生しません。 GSSAPI、SSPI、SASLでは認証を完了するために複数のパケットの交換が必要となるかもしれません。

The authentication cycle ends with the server either rejecting the connection attempt (ErrorResponse), or sending AuthenticationOk. 認証サイクルは、サーバによって接続要求を拒絶する(ErrorResponse)か、あるいはAuthenticationOkを送信することで終わります。

The possible messages from the server in this phase are: この段階でサーバから送信される可能性があるメッセージを以下に示します。

ErrorResponse

The connection attempt has been rejected. The server then immediately closes the connection. 接続試行が拒絶されました。 サーバはその後即座に接続を閉ざします。

AuthenticationOk

The authentication exchange is successfully completed. 認証情報の交換が正常に完了しました。

AuthenticationKerberosV5

The frontend must now take part in a Kerberos V5 authentication dialog (not described here, part of the Kerberos specification) with the server. If this is successful, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. This is no longer supported. フロントエンドはここでサーバとのKerberos V5認証ダイアログ(ここでは説明しません。Kerberos仕様の一部)に参加する必要があります。 これが成功すれば、サーバはAuthenticationOk応答を行います。 失敗すれば、ErrorResponse応答を行います。 これはもはやサポートされていません。

AuthenticationCleartextPassword

The frontend must now send a PasswordMessage containing the password in clear-text form. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. フロントエンドはここで平文形式のパスワードを含むPasswordMessageを送信する必要があります。 これが正しいパスワードであればサーバはAuthenticationOk応答を行います。 さもなくば、ErrorResponse応答を行います。

AuthenticationMD5Password

The frontend must now send a PasswordMessage containing the password (with user name) encrypted via MD5, then encrypted again using the 4-byte random salt specified in the AuthenticationMD5Password message. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. The actual PasswordMessage can be computed in SQL as <literal>concat('md5', md5(concat(md5(concat(password, username)), random-salt)))</literal>. (Keep in mind the <function>md5()</function> function returns its result as a hex string.) フロントエンドはここでMD5で暗号化したパスワード(とユーザ名)を再度AuthenticationMD5Passwordメッセージで指定されたランダムな4バイトのソルトを使用して暗号化したものを含むPasswordMessageを送信する必要があります。 これが正しいパスワードであればサーバはAuthenticationOk応答を行います。 さもなくば、ErrorResponse応答を行います。 実際のPasswordMessageをconcat('md5', md5(concat(md5(concat(password, username)), random-salt)))というSQLで計算することができます。 (md5()関数がその結果を16進数表記で返すことに注意してください。)

AuthenticationGSS

The frontend must now initiate a GSSAPI negotiation. The frontend will send a GSSResponse message with the first part of the GSSAPI data stream in response to this. If further messages are needed, the server will respond with AuthenticationGSSContinue. ここでフロントエンドはGSSAPIの調停を開始しなければなりません。 これに対する応答におけるGSSAPIデータストリームの最初の部分で、フロントエンドはGSSResponseを送信します。 さらにメッセージが必要となる場合、サーバはAuthenticationGSSContinueで応答します。

AuthenticationSSPI

The frontend must now initiate an SSPI negotiation. The frontend will send a GSSResponse with the first part of the SSPI data stream in response to this. If further messages are needed, the server will respond with AuthenticationGSSContinue. ここでフロントエンドはSSPI調停を開始しなければなりません。 これに対する応答におけるSSPIデータストリームの最初の部分で、フロントエンドはGSSResponseを送信します。 さらにメッセージが必要となる場合、サーバはAuthenticationGSSContinueで応答します。

AuthenticationGSSContinue

This message contains the response data from the previous step of GSSAPI or SSPI negotiation (AuthenticationGSS, AuthenticationSSPI or a previous AuthenticationGSSContinue). If the GSSAPI or SSPI data in this message indicates more data is needed to complete the authentication, the frontend must send that data as another GSSResponse message. If GSSAPI or SSPI authentication is completed by this message, the server will next send AuthenticationOk to indicate successful authentication or ErrorResponse to indicate failure. このメッセージには、GSSAPIまたはSSPI調停の直前の段階(AuthenticationGSS、AuthenticationSSPIまたは前回のAuthenticationGSSContinue)についての応答データが含まれます。 このメッセージ内のGSSAPIまたはSSPIデータが認証を完結させるため、更なる追加データが必要であることを指示している場合、フロントエンドは他のGSSResponseとしてデータを送信しなければなりません。 このメッセージでGSSAPIまたはSSPI認証が完了すれば、次にサーバはAuthenticationOkを送信して認証が成功したことを示すか、あるいはErrorResponseを送信して失敗したことを示します。

AuthenticationSASL

The frontend must now initiate a SASL negotiation, using one of the SASL mechanisms listed in the message. The frontend will send a SASLInitialResponse with the name of the selected mechanism, and the first part of the SASL data stream in response to this. If further messages are needed, the server will respond with AuthenticationSASLContinue. See <xref linkend="sasl-authentication"/> for details. ここでフロントエンドはメッセージ内に列挙されているSASL機構の1つを使ってSASL調停を開始しなければなりません。 これに応答するSASLデータストリームの最初の部分で、フロントエンドはSASLInitialResponseと選択した機構の名前を送信します。 さらにメッセージが必要な場合、サーバはAuthenticationSASLContinueで応答します。 詳細については55.3を参照してください。

AuthenticationSASLContinue

This message contains challenge data from the previous step of SASL negotiation (AuthenticationSASL, or a previous AuthenticationSASLContinue). The frontend must respond with a SASLResponse message. このメッセージには、SASL調停における直前の段階(AuthenticationSASLまたは以前のAuthenticationSASLContinue)のチャレンジデータが含まれます。 フロントエンドはSASLResponseメッセージで応答しなければなりません。

AuthenticationSASLFinal

SASL authentication has completed with additional mechanism-specific data for the client. The server will next send AuthenticationOk to indicate successful authentication, or an ErrorResponse to indicate failure. This message is sent only if the SASL mechanism specifies additional data to be sent from server to client at completion. 機構固有のクライアント用の追加データを伴ってSASL認証が完了します。 サーバは次に認証成功を示すAuthenticationOkを送信するか、あるいは失敗を示すErrorResponseを送信します。 このメッセージはSASLの機構が完了時にサーバからクライアントに送信する追加データを指定しているときにのみ送信されます。

NegotiateProtocolVersion

The server does not support the minor protocol version requested by the client, but does support an earlier version of the protocol; this message indicates the highest supported minor version. This message will also be sent if the client requested unsupported protocol options (i.e., beginning with <literal>_pq_.</literal>) in the startup packet. This message will be followed by an ErrorResponse or a message indicating the success or failure of authentication. サーバはクライアントが要求したマイナープロトコルバージョンをサポートしませんが、それ以前のバージョンをサポートします。 このメッセージは、サポートしている最も高いマイナーバージョンを示します。 このメッセージは、クライアントがサポートされないプロトコルオプション(つまり_pq_.で始まる)をスタートアップパケットの中で指定した場合にも送られます。 このメッセージの後に、ErrorResponseか、認証が成功あるいは失敗したことを示すメッセージが続きます。

If the frontend does not support the authentication method requested by the server, then it should immediately close the connection. サーバが要求した認証方式をフロントエンドがサポートしていない場合、フロントエンドは即座に接続を閉ざします。

After having received AuthenticationOk, the frontend must wait for further messages from the server. In this phase a backend process is being started, and the frontend is just an interested bystander. It is still possible for the startup attempt to fail (ErrorResponse) or the server to decline support for the requested minor protocol version (NegotiateProtocolVersion), but in the normal case the backend will send some ParameterStatus messages, BackendKeyData, and finally ReadyForQuery. AuthenticationOkを受け取った後、フロントエンドはさらにサーバからのメッセージを待機する必要があります。 この段階で、バックエンドプロセスが起動し、このフロントエンドは単なる関心を有する第三者となります。 開始試行が失敗(ErrorResponse)するか、サーバが要求されたマイナープロトコルバージョンを拒否する(NegotiateProtocolVersion)可能性がまだありますが、通常、バックエンドは何らかのParameterStatusメッセージ、BackendKeyData、そして最後にReadyForQueryを送信します。

During this phase the backend will attempt to apply any additional run-time parameter settings that were given in the startup message. If successful, these values become session defaults. An error causes ErrorResponse and exit. この段階の期間中、バックエンドは開始メッセージで与えられた任意の実行時パラメータの追加設定を適用しようとします。 成功した場合は、これらの値はセッションのデフォルトになります。 エラーが発生した場合はErrorResponseを行い、終了します。

The possible messages from the backend in this phase are: この段階でバックエンドから送信される可能性があるメッセージを以下に示します。

BackendKeyData

This message provides secret-key data that the frontend must save if it wants to be able to issue cancel requests later. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message. このメッセージは、フロントエンドがキャンセル要求を後で送信できるようにしたい場合に保存しなければならない、秘密キーデータを用意します。 フロントエンドはこのメッセージに応答してはいけませんが、ReadyForQueryメッセージの監視を続けなくてはなりません。

ParameterStatus

This message informs the frontend about the current (initial) setting of backend parameters, such as <xref linkend="guc-client-encoding"/> or <xref linkend="guc-datestyle"/>. The frontend can ignore this message, or record the settings for its future use; see <xref linkend="protocol-async"/> for more details. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message. このメッセージは、フロントエンドに現在(初期)のclient_encodingDateStyleなどのバックエンドパラメータの設定情報を通知します。 フロントエンドはこのメッセージを無視しても、将来の使用に備えてその設定を記録しても構いません。 詳細は55.2.7を参照してください。 フロントエンドはこのメッセージに応答してはいけませんが、ReadyForQueryメッセージの監視を続けなくてはなりません。

ReadyForQuery

Start-up is completed. The frontend can now issue commands. 開始処理が完了しました。 フロントエンドはここでコマンドを発行することができます。

ErrorResponse

Start-up failed. The connection is closed after sending this message. 開始処理が失敗しました。 接続はこのメッセージの送信後に閉ざされます。

NoticeResponse

A warning message has been issued. The frontend should display the message but continue listening for ReadyForQuery or ErrorResponse. 警告メッセージが発行されました。 フロントエンドはこのメッセージを表示し、ReadyForQueryもしくはErrorResponseメッセージの監視を続けなければなりません。

The ReadyForQuery message is the same one that the backend will issue after each command cycle. Depending on the coding needs of the frontend, it is reasonable to consider ReadyForQuery as starting a command cycle, or to consider ReadyForQuery as ending the start-up phase and each subsequent command cycle. ReadyForQueryメッセージは各コマンドサイクルの後にバックエンドが発行するものと同じものです。 フロントエンドのコーディングにおいて必要であれば、ReadyForQueryをコマンドサイクルの開始とみなしても構いませんし、ReadyForQueryを開始段階とその後の各コマンドサイクルの終端とみなしても構いません。

55.2.2. 簡易問い合わせ #

<title>Simple Query</title>

A simple query cycle is initiated by the frontend sending a Query message to the backend. The message includes an SQL command (or commands) expressed as a text string. The backend then sends one or more response messages depending on the contents of the query command string, and finally a ReadyForQuery response message. ReadyForQuery informs the frontend that it can safely send a new command. (It is not actually necessary for the frontend to wait for ReadyForQuery before issuing another command, but the frontend must then take responsibility for figuring out what happens if the earlier command fails and already-issued later commands succeed.) フロントエンドがQueryメッセージをバックエンドに送信することで、簡易問い合わせサイクルが開始されます。 このメッセージには、テキスト文字列で表現されたSQLコマンド(またはコマンド)が含まれます。 そうすると、バックエンドは、問い合わせコマンド文字列の内容に応じて1つ以上の応答を送信し、最終的にReadyForQueryを応答します。 ReadyForQueryは、新しいコマンドを安全に送信できることをフロントエンドに知らせます。 (実際には、フロントエンドが他のコマンドを発行する前にReadyForQueryを待機することは不要です。 しかし、フロントエンドは、前のコマンドが失敗し、発行済みの後のコマンドが成功した場合に何が起きるかを了解する責任を持たなければなりません。)

The possible response messages from the backend are: バックエンドから送信される可能性がある応答メッセージを以下に示します。

CommandComplete

An SQL command completed normally. SQLコマンドが正常に終了しました。

CopyInResponse

The backend is ready to copy data from the frontend to a table; see <xref linkend="protocol-copy"/>. バックエンドがフロントエンドからのデータをテーブルにコピーする準備ができました。 55.2.6を参照してください。

CopyOutResponse

The backend is ready to copy data from a table to the frontend; see <xref linkend="protocol-copy"/>. バックエンドがデータをテーブルからフロントエンドにコピーする準備ができました。 55.2.6を参照してください。

RowDescription

Indicates that rows are about to be returned in response to a <command>SELECT</command>, <command>FETCH</command>, etc. query. The contents of this message describe the column layout of the rows. This will be followed by a DataRow message for each row being returned to the frontend. SELECTFETCHなどの問い合わせの応答の行がまさに返されようとしていることを示します。 このメッセージには、行の列レイアウトに関する説明が含まれます。 このメッセージの後に、フロントエンドに返される各行に対するDataRowメッセージが続きます。

DataRow

One of the set of rows returned by a <command>SELECT</command>, <command>FETCH</command>, etc. query. SELECTFETCHなどの問い合わせで返される行の集合の1つです。

EmptyQueryResponse

An empty query string was recognized. 空の問い合わせ文字列が検知されました。

ErrorResponse

An error has occurred. エラーが起こりました。

ReadyForQuery

Processing of the query string is complete. A separate message is sent to indicate this because the query string might contain multiple SQL commands. (CommandComplete marks the end of processing one SQL command, not the whole string.) ReadyForQuery will always be sent, whether processing terminates successfully or with an error. 問い合わせ文字列の処理が終了しました。 問い合わせ文字列は複数のSQLコマンドが含まれる場合があるため、このことを通知するために分離したメッセージが送出されます。 (CommandCompleteは文字列全体ではなく、1つのSQLコマンドの処理の終了を明らかにします。) 処理が成功またはエラーで終了したかどうかにかかわらずReadyForQueryは常に送出されます。

NoticeResponse

A warning message has been issued in relation to the query. Notices are in addition to other responses, i.e., the backend will continue processing the command. 問い合わせに関して警告メッセージが発行されました。 警告メッセージは他の応答に対する追加のメッセージです。 したがって、バックエンドはそのコマンドの処理を続行します。

The response to a <command>SELECT</command> query (or other queries that return row sets, such as <command>EXPLAIN</command> or <command>SHOW</command>) normally consists of RowDescription, zero or more DataRow messages, and then CommandComplete. <command>COPY</command> to or from the frontend invokes special protocol as described in <xref linkend="protocol-copy"/>. All other query types normally produce only a CommandComplete message. SELECT問い合わせ(あるいは、EXPLAINSHOWなどの行集合を返す他の問い合わせ)に対する応答は、通常、RowDescription、0個以上のDataRowメッセージ、そしてその後のCommandCompleteから構成されます。 フロントエンドへのCOPYもしくはフロントエンドからのCOPY55.2.6で説明する特別なプロトコルを呼び出します。 他の種類の問い合わせは通常CommandCompleteメッセージのみを生成します。

Since a query string could contain several queries (separated by semicolons), there might be several such response sequences before the backend finishes processing the query string. ReadyForQuery is issued when the entire string has been processed and the backend is ready to accept a new query string. 問い合わせ文字列には(セミコロンで区切られた)複数の問い合わせが含まれることがありますので、バックエンドが問い合わせ文字列の処理を完了する前に、こうした応答シーケンスが複数発生する可能性があります。 ReadyForQueryは、文字列全体が処理され、バックエンドが新しい問い合わせ文字列を受け付ける準備が整った時点で発行されます。

If a completely empty (no contents other than whitespace) query string is received, the response is EmptyQueryResponse followed by ReadyForQuery. 完全に空の(空白文字以外の文字がない)問い合わせ文字列を受け取った場合、その応答は、EmptyQueryResponse、続いて、ReadyForQueryとなります。

In the event of an error, ErrorResponse is issued followed by ReadyForQuery. All further processing of the query string is aborted by ErrorResponse (even if more queries remained in it). Note that this might occur partway through the sequence of messages generated by an individual query. エラーが発生した場合、ErrorResponse、続いて、ReadyForQueryが発行されます。 その問い合わせ文字列に対する以降の処理は(複数の問い合わせが残っていたとしても)すべて、ErrorResponseによって中断されます。 これは、個々の問い合わせで生成されるメッセージの並びの途中で発生する可能性があることに注意してください。

In simple Query mode, the format of retrieved values is always text, except when the given command is a <command>FETCH</command> from a cursor declared with the <literal>BINARY</literal> option. In that case, the retrieved values are in binary format. The format codes given in the RowDescription message tell which format is being used. 簡易問い合わせモードでは、読み出される値の書式は常にテキストです。 ただし、与えられたコマンドがBINARYオプション付きで宣言されたカーソルからのFETCHであった場合は例外です。 この場合は、読み出される値はバイナリ書式になります。 RowDescriptionメッセージ内で与えられる書式コードは、どの書式が使用されているかを通知します。

A frontend must be prepared to accept ErrorResponse and NoticeResponse messages whenever it is expecting any other type of message. See also <xref linkend="protocol-async"/> concerning messages that the backend might generate due to outside events. 他の種類のメッセージの受信を待機している時、フロントエンドは常にErrorResponseとNoticeResponseメッセージを受け取る準備ができていなければなりません。 また、外部イベントのためにバックエンドが生成する可能性があるメッセージの扱いについては55.2.7を参照してください。

Recommended practice is to code frontends in a state-machine style that will accept any message type at any time that it could make sense, rather than wiring in assumptions about the exact sequence of messages. メッセージの正しい並びを前提としてコーディングするのではなく、任意のメッセージ種類を、そのメッセージが意味を持つ任意の時点で受け付ける状態マシン形式でフロントエンドのコーディングを行うことを推奨します。

55.2.2.1. 簡易問い合わせでの複文 #

<title>Multiple Statements in a Simple Query</title>

When a simple Query message contains more than one SQL statement (separated by semicolons), those statements are executed as a single transaction, unless explicit transaction control commands are included to force a different behavior. For example, if the message contains 簡易Queryメッセージが二つ以上の(セミコロンで区切られた)SQL文を含むとき、振る舞いを変えるように明示的なトランザクション制御コマンドが含まれていない限り、これらの文は単一トランザクションで実行されます。 例えばメッセージが以下を含む場合、

INSERT INTO mytable VALUES(1);
SELECT 1/0;
INSERT INTO mytable VALUES(2);

then the divide-by-zero failure in the <command>SELECT</command> will force rollback of the first <command>INSERT</command>. Furthermore, because execution of the message is abandoned at the first error, the second <command>INSERT</command> is never attempted at all. SELECTでのゼロ除算エラーは最初のINSERTのロールバックを強制します。 さらに、メッセージの実行が最初のエラー時点で中止されるので、二番目のINSERTは全く試みられません。

If instead the message contains 代わりにメッセージが以下を含んでいる場合、

BEGIN;
INSERT INTO mytable VALUES(1);
COMMIT;
INSERT INTO mytable VALUES(2);
SELECT 1/0;

then the first <command>INSERT</command> is committed by the explicit <command>COMMIT</command> command. The second <command>INSERT</command> and the <command>SELECT</command> are still treated as a single transaction, so that the divide-by-zero failure will roll back the second <command>INSERT</command>, but not the first one. 最初のINSERTは明示的なCOMMITコマンドによりコミットされます。 二番目のINSERTSELECTは、やはり単一トランザクションとして処理されます。 そのためゼロ除算エラーが二番目のINSERTをロールバックしますが、最初のINSERTはロールバックされません。

This behavior is implemented by running the statements in a multi-statement Query message in an <firstterm>implicit transaction block</firstterm> unless there is some explicit transaction block for them to run in. The main difference between an implicit transaction block and a regular one is that an implicit block is closed automatically at the end of the Query message, either by an implicit commit if there was no error, or an implicit rollback if there was an error. This is similar to the implicit commit or rollback that happens for a statement executed by itself (when not in a transaction block). この振る舞いは、暗黙トランザクションブロックで複文Queryメッセージ内の文を実行することで、その中に明示的なトランザクションブロックがある場合を除き、発現します。 暗黙トランザクションブロックと通常のトラザクションブロックとの主な違いは、暗黙ブロックは自動的にQueryメッセージの最後にて、エラーが無いなら暗黙のコミット、エラーがあるなら暗黙のロールバックで、自動的に閉じられることです。 これは(トランザクションブロック内に無いときの)文の単体実行に対して生じる暗黙のコミットあるいはロールバックに似ています。

If the session is already in a transaction block, as a result of a <command>BEGIN</command> in some previous message, then the Query message simply continues that transaction block, whether the message contains one statement or several. However, if the Query message contains a <command>COMMIT</command> or <command>ROLLBACK</command> closing the existing transaction block, then any following statements are executed in an implicit transaction block. Conversely, if a <command>BEGIN</command> appears in a multi-statement Query message, then it starts a regular transaction block that will only be terminated by an explicit <command>COMMIT</command> or <command>ROLLBACK</command>, whether that appears in this Query message or a later one. If the <command>BEGIN</command> follows some statements that were executed as an implicit transaction block, those statements are not immediately committed; in effect, they are retroactively included into the new regular transaction block. 何らか手前のメッセージでのBEGINの結果として、セッションが既にトランザクションブロック内である場合、Queryメッセージは、含まれるのが単一文でもいくつかの文でも、単にそのトランザクションを継続します。 しかしながら、Queryメッセージが既存トランザクションブロックを閉じるCOMMITROLLBACKを含む場合、続く全ての文は暗黙トランザクションブロックで実行されます。 逆に言えば、複文QueryメッセージでBEGINが現れたなら、このQueryメッセージ内または後のメッセージのいずれかにあらわれる明示的なCOMMITROLLBACKでのみ終了する、通常のトランザクションブロックが開始されます。 BEGINが暗黙トランザクションブロックとして実行されたいくつかの文に続く場合、これらの文が直ちにコミットされることはありません。 結果として、これらは遡って新たな通常のトランザクションブロックに含められます。

A <command>COMMIT</command> or <command>ROLLBACK</command> appearing in an implicit transaction block is executed as normal, closing the implicit block; however, a warning will be issued since a <command>COMMIT</command> or <command>ROLLBACK</command> without a previous <command>BEGIN</command> might represent a mistake. If more statements follow, a new implicit transaction block will be started for them. 暗黙トランザクションブロック内に現れたCOMMITROLLBACKは通常通り実行され、暗黙ブロックを閉じますが、手前のBEGIN無しのCOMMITROLLBACKは誤りであるかもしれないので警告が発行されます。 さらに文が続く場合、それらに対して新たな暗黙トランザクションブロックが開始されます。

Savepoints are not allowed in an implicit transaction block, since they would conflict with the behavior of automatically closing the block upon any error. エラー時の自動ブロッククローズの振る舞いと競合するので暗黙トランザクションブロックでセーブポイントは使えません。

Remember that, regardless of any transaction control commands that may be present, execution of the Query message stops at the first error. Thus for example given 現状のいかなるトランザクション制御コマンドでも、Queryメッセージの実行は最初のエラー時点で打ち切られることに留意してください。 例を示します。

BEGIN;
SELECT 1/0;
ROLLBACK;

in a single Query message, the session will be left inside a failed regular transaction block, since the <command>ROLLBACK</command> is not reached after the divide-by-zero error. Another <command>ROLLBACK</command> will be needed to restore the session to a usable state. 上記が単一Queryメッセージにあるとして、ゼロ除算エラーの後にROLLBACKに達することがないため、このセッションは失敗した通常のトランザクション内のままとなります。 このセッションを通常の状態に回復させるには別のROLLBACKが必要となります。

Another behavior of note is that initial lexical and syntactic analysis is done on the entire query string before any of it is executed. Thus simple errors (such as a misspelled keyword) in later statements can prevent execution of any of the statements. This is normally invisible to users since the statements would all roll back anyway when done as an implicit transaction block. However, it can be visible when attempting to do multiple transactions within a multi-statement Query. For instance, if a typo turned our previous example into その他の注意すべき振る舞いは、初期の字句および構文解析が少しも実行されない段階で問い合わせ文字列全体に対して行われることです。 従って、後ろの分にある(スペルミスしたキーワードなどの)単純なエラーは全ての文の実行を妨げることがあります。 暗黙トランザクションブロックとして起きたとき、いずれにせよ全ての文はロールバックされるので、これは通常はユーザに見えません。 しかしながら、複文問い合わせの中で複数のトランザクションを実行しようとするとき、この挙動が明らかになることがあります。 例えば、タイプミスで先の例を以下のようにします。

BEGIN;
INSERT INTO mytable VALUES(1);
COMMIT;
INSERT INTO mytable VALUES(2);
SELCT 1/0; this typo is intentional 

then none of the statements would get run, resulting in the visible difference that the first <command>INSERT</command> is not committed. Errors detected at semantic analysis or later, such as a misspelled table or column name, do not have this effect. そうすると、含まれる文は一つも実行されず、最初のINSERTがコミットされないという違いが明らかになります。 エラーは、ミススペルしたテーブルやカラム名など、語彙の解析かその後に検出され、コマンドの効力はありません。

55.2.3. 拡張問い合わせ #

<title>Extended Query</title>

The extended query protocol breaks down the above-described simple query protocol into multiple steps. The results of preparatory steps can be re-used multiple times for improved efficiency. Furthermore, additional features are available, such as the possibility of supplying data values as separate parameters instead of having to insert them directly into a query string. 拡張問い合わせプロトコルは、上述の簡易問い合わせプロトコルを複数段階に分解します。 予備段階の結果は複数回再利用できますので、効率が上がります。 さらに、問い合わせ文字列に直接埋め込むのではなく、データ値をパラメータとして分離して提供できる機能など、利用できる追加機能があります。

In the extended protocol, the frontend first sends a Parse message, which contains a textual query string, optionally some information about data types of parameter placeholders, and the name of a destination prepared-statement object (an empty string selects the unnamed prepared statement). The response is either ParseComplete or ErrorResponse. Parameter data types can be specified by OID; if not given, the parser attempts to infer the data types in the same way as it would do for untyped literal string constants. 拡張プロトコルでは、フロントエンドはまず、テキストの問い合わせ文字列とオプションとしてパラメータプレースホルダのデータ型情報やプリペアド文のオブジェクトの宛先名(空文字列は無名のプリペアド文を選択)を含む、Parseメッセージを送信します。 この応答はParseCompleteまたはErrorResponseです。 パラメータデータ型はそのOIDで指定することができます。 指定がなければ、パーサは型指定のないリテラル文字列定数に対する方法と同じ方法でデータ型を推定します。

注記

A parameter data type can be left unspecified by setting it to zero, or by making the array of parameter type OIDs shorter than the number of parameter symbols (<literal>$</literal><replaceable>n</replaceable>) used in the query string. Another special case is that a parameter's type can be specified as <type>void</type> (that is, the OID of the <type>void</type> pseudo-type). This is meant to allow parameter symbols to be used for function parameters that are actually OUT parameters. Ordinarily there is no context in which a <type>void</type> parameter could be used, but if such a parameter symbol appears in a function's parameter list, it is effectively ignored. For example, a function call such as <literal>foo($1,$2,$3,$4)</literal> could match a function with two IN and two OUT arguments, if <literal>$3</literal> and <literal>$4</literal> are specified as having type <type>void</type>. パラメータデータ型をゼロと設定する、または、問い合わせ文字列内で使用されているパラメータ記号($n)の数より短くパラメータ型のOIDの配列を作成することで、指定しないまま残すことができます。 他にも、パラメータの型をvoid(つまりvoid仮想型のOID)と指定するという特別な場合があります。 これは、パラメータ記号を、実際のOUTパラメータである関数パラメータとして使用することができることを意味します。 通常では、voidパラメータが使用される文脈はありませんが、関数パラメータリストにこうしたパラメータ記号があると、実質的には無視されます。 例えば、$3$4void型を持つと指定された場合、foo($1,$2,$3,$4)といった関数呼び出しは、2つのINと2つのOUT引数を持つ関数に一致します。

注記

The query string contained in a Parse message cannot include more than one SQL statement; else a syntax error is reported. This restriction does not exist in the simple-query protocol, but it does exist in the extended protocol, because allowing prepared statements or portals to contain multiple commands would complicate the protocol unduly. Parseメッセージ内の問い合わせ文字列には、複数のSQL文を含めることはできません。 さもないと、構文エラーが報告されます。 この制限は簡易問い合わせプロトコルにはありませんが、複数のコマンドを持つプリペアド文やポータルを許すと、プロトコルが複雑になり過ぎるため、拡張プロトコルではこの制限があります。

If successfully created, a named prepared-statement object lasts till the end of the current session, unless explicitly destroyed. An unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued. (Note that a simple Query message also destroys the unnamed statement.) Named prepared statements must be explicitly closed before they can be redefined by another Parse message, but this is not required for the unnamed statement. Named prepared statements can also be created and accessed at the SQL command level, using <command>PREPARE</command> and <command>EXECUTE</command>. 作成に成功すると、名前付きプリペアド文オブジェクトは明示的に破棄されない限り現在のセッションが終わるまで残ります。 無名のプリペアド文オブジェクトは、次に無名のプリペアド文を宛先に指定したParse文が発行されるまでの間のみに残ります。 (単なるQueryメッセージでも無名のプリペアド文オブジェクトは破壊されることに注意してください。) 名前付きプリペアド文は、他のParseメッセージで再定義する前に明示的に閉じなければなりません。 しかし、これは無名のプリペアド文では必要ありません。 名前付きプリペアド文はまた、SQLコマンドレベルでPREPAREEXECUTEを使用して作成しアクセスすることができます。

Once a prepared statement exists, it can be readied for execution using a Bind message. The Bind message gives the name of the source prepared statement (empty string denotes the unnamed prepared statement), the name of the destination portal (empty string denotes the unnamed portal), and the values to use for any parameter placeholders present in the prepared statement. The supplied parameter set must match those needed by the prepared statement. (If you declared any <type>void</type> parameters in the Parse message, pass NULL values for them in the Bind message.) Bind also specifies the format to use for any data returned by the query; the format can be specified overall, or per-column. The response is either BindComplete or ErrorResponse. プリペアド文が存在すると、Bindメッセージを使用してそれを実行可能状態にすることができます。 Bindメッセージは、元となるプリペアド文(空文字列は無名のプリペアド文を表します)の名前、宛先となるポータル(空文字列は無名ポータルを表します)の名前、およびプリペアド文内のパラメータプレースホルダに使用する値を与えます。 与えられたパラメータ集合はプリペアド文で必要とするものと一致しなければなりません。 (Parseメッセージ内でvoidパラメータを1つでも宣言した場合、BindメッセージではそれらにはNULLを渡します。) また、Bindは問い合わせで返されるデータに使用する書式を指定します。 書式は全体に対して指定することも、列単位で指定することも可能です。 応答はBindCompleteもしくはErrorResponseです。

注記

The choice between text and binary output is determined by the format codes given in Bind, regardless of the SQL command involved. The <literal>BINARY</literal> attribute in cursor declarations is irrelevant when using extended query protocol. テキスト出力とバイナリ出力との選択は、含まれるSQLコマンドに関係なく、Bindで与えられた書式コードで決定されます。 拡張問い合わせプロトコルを使用する場合、カーソル宣言のBINARY属性は役に立ちません。

Query planning typically occurs when the Bind message is processed. If the prepared statement has no parameters, or is executed repeatedly, the server might save the created plan and re-use it during subsequent Bind messages for the same prepared statement. However, it will do so only if it finds that a generic plan can be created that is not much less efficient than a plan that depends on the specific parameter values supplied. This happens transparently so far as the protocol is concerned. 典型的に問い合わせ計画はBindメッセージが処理される時に作成されます。 プリペアド文がパラメータを持たない場合、または繰り返し実行される場合、サーバは作成した計画を保管し、その後の同じプリペアド文に対するBindメッセージの際に再利用する可能性があります。 しかし、作成できる汎用的な計画が提供された特定のパラメータ値に依存する計画より効率が大して劣化しないことが分かった場合のみ、このように動作します。 プロトコルに注目している限り、これは透過的に行われます。

If successfully created, a named portal object lasts till the end of the current transaction, unless explicitly destroyed. An unnamed portal is destroyed at the end of the transaction, or as soon as the next Bind statement specifying the unnamed portal as destination is issued. (Note that a simple Query message also destroys the unnamed portal.) Named portals must be explicitly closed before they can be redefined by another Bind message, but this is not required for the unnamed portal. Named portals can also be created and accessed at the SQL command level, using <command>DECLARE CURSOR</command> and <command>FETCH</command>. 作成に成功すると、名前付きポータルオブジェクトは明示的に破棄されない限り現在のセッションが終わるまで残ります。 無名ポータルは、トランザクションの終わり、もしくは、次に無名ポータルを宛先に指定したBind文が発行されるまでの間のみに残ります。 (単なるQueryメッセージでも無名ポータルは破壊されることに注意してください。) 名前付きポータルは、他のBindメッセージで再定義する前に明示的に閉じなければなりません。 しかし、これは無名ポータルでは必要ありません。 名前付きポータルはまた、SQLコマンドレベルでDECLARE CURSORFETCHを使用して作成しアクセスすることができます。

Once a portal exists, it can be executed using an Execute message. The Execute message specifies the portal name (empty string denotes the unnamed portal) and a maximum result-row count (zero meaning <quote>fetch all rows</quote>). The result-row count is only meaningful for portals containing commands that return row sets; in other cases the command is always executed to completion, and the row count is ignored. The possible responses to Execute are the same as those described above for queries issued via simple query protocol, except that Execute doesn't cause ReadyForQuery or RowDescription to be issued. ポータルが存在すると、Executeメッセージを使用してそれを実行することができます。 Executeメッセージは、ポータル名(空文字列は無名ポータルを表します)と結果行数の最大値(ゼロはfetch all rowsを意味します)を指定します。 結果行数は、ポータルが行集合を返すコマンドを含む場合のみ意味があります。 その他の場合では、コマンドは常に終わりまで実行され、行数は無視されます。 Executeで起こり得る応答は、ExecuteではReadyForQueryやRowDescriptionが発行されない点を除き、上述の簡易問い合わせプロトコル経由で発行された問い合わせの場合と同じです。

If Execute terminates before completing the execution of a portal (due to reaching a nonzero result-row count), it will send a PortalSuspended message; the appearance of this message tells the frontend that another Execute should be issued against the same portal to complete the operation. The CommandComplete message indicating completion of the source SQL command is not sent until the portal's execution is completed. Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended. Executeがポータルの実行を完了する前に(非ゼロの結果行数に達したために)終了した場合、PortalSuspendedを送信します。 このメッセージの出現は、フロントエンドに操作を完了させるためには同一のポータルに対して、別のExecuteを発行しなければならないことを通知します。 元となったSQLコマンドが完了したことを示すCommandCompleteメッセージはポータルが完了するまで送信されません。 したがって、Execute段階は常にCommandComplete、EmptyQueryResponse(空の問い合わせ文字列からポータルが作成された場合)、ErrorResponse、またはPortalSuspendedの中の、正確にどれかが出現することによって常に終了します。

At completion of each series of extended-query messages, the frontend should issue a Sync message. This parameterless message causes the backend to close the current transaction if it's not inside a <command>BEGIN</command>/<command>COMMIT</command> transaction block (<quote>close</quote> meaning to commit if no error, or roll back if error). Then a ReadyForQuery response is issued. The purpose of Sync is to provide a resynchronization point for error recovery. When an error is detected while processing any extended-query message, the backend issues ErrorResponse, then reads and discards messages until a Sync is reached, then issues ReadyForQuery and returns to normal message processing. (But note that no skipping occurs if an error is detected <emphasis>while</emphasis> processing Sync &mdash; this ensures that there is one and only one ReadyForQuery sent for each Sync.) 拡張問い合わせメッセージの一連の流れのそれぞれの終了時、フロントエンドはSyncメッセージを発行しなければなりません。 このパラメータのないメッセージにより、もしBEGIN/COMMITトランザクションブロックの内部でなければ、バックエンドは現在のトランザクションを閉ざします (閉ざすとは、エラーがなければコミット、エラーがあればロールバックすることを意味します)。 そして、ReadyForQuery応答が発行されます。 Syncの目的は、エラーからの復旧用の再同期を行う時点を提供することです。 拡張問い合わせメッセージの処理中にエラーが検出されると、バックエンドはErrorResponseを発行し、Syncが届くまでメッセージを読み、それを破棄します。 その後、ReadyForQueryを発行し、通常のメッセージ処理に戻ります。 (しかし、Sync処理中にエラーが検出された場合に処理が飛ばされないことに注意してください。 これにより、各Syncに対してReadyForQueryが1つのみであることを保証します。)

注記

Sync does not cause a transaction block opened with <command>BEGIN</command> to be closed. It is possible to detect this situation since the ReadyForQuery message includes transaction status information. Syncによって、BEGINで開かれたトランザクションブロックが閉ざされることはありません。 ReadyForQueryメッセージにはトランザクションの状態情報が含まれていますので、この状況を検出することができます。

In addition to these fundamental, required operations, there are several optional operations that can be used with extended-query protocol. これらの基本的な必要操作に加え、拡張問い合わせプロトコルで使用することができる、複数の省略可能な操作があります。

The Describe message (portal variant) specifies the name of an existing portal (or an empty string for the unnamed portal). The response is a RowDescription message describing the rows that will be returned by executing the portal; or a NoData message if the portal does not contain a query that will return rows; or ErrorResponse if there is no such portal. Describeメッセージ(ポータルの亜種)は、既存のポータルの名前(もしくは、無名ポータル用の空文字)を指定します。 応答は、実行中のポータルで返される予定の行を記述するRowDescriptionメッセージです。 ポータルが行を返す問い合わせを含まない場合はNoDataメッセージです。 指定したポータルが存在しない場合はErrorResponseです。

The Describe message (statement variant) specifies the name of an existing prepared statement (or an empty string for the unnamed prepared statement). The response is a ParameterDescription message describing the parameters needed by the statement, followed by a RowDescription message describing the rows that will be returned when the statement is eventually executed (or a NoData message if the statement will not return rows). ErrorResponse is issued if there is no such prepared statement. Note that since Bind has not yet been issued, the formats to be used for returned columns are not yet known to the backend; the format code fields in the RowDescription message will be zeroes in this case. Describeメッセージ(ステートメントの亜種)は、既存のプリペアド文の名前(もしくは無名のプリペアド文用の空文字)を指定します。 応答は、文で必要とされるパラメータを記述するParameterDescriptionメッセージ、続いて、文が実行された場合に返される予定の行を記述するRowDescriptionメッセージ(もしくは文が行を返さない場合のNoDataメッセージ)です。 指定したプリペアド文が存在しない場合はErrorResponseが発行されます。 Bindがまだ発行されていませんので、返される列の書式はまだバックエンドでは不明であることに注意してください。 RowDescriptionメッセージ内の書式コードフィールドはこの場合はゼロになります。

ヒント

In most scenarios the frontend should issue one or the other variant of Describe before issuing Execute, to ensure that it knows how to interpret the results it will get back. ほとんどの状況では、フロントエンドはExecuteを発行する前に、返ってくる結果を解釈する方法を確実に判断できるように、Describeもしくはその亜種を実行すべきです。

The Close message closes an existing prepared statement or portal and releases resources. It is not an error to issue Close against a nonexistent statement or portal name. The response is normally CloseComplete, but could be ErrorResponse if some difficulty is encountered while releasing resources. Note that closing a prepared statement implicitly closes any open portals that were constructed from that statement. Closeメッセージは、既存のプリペアド文、もしくはポータルを閉ざし、リソースを解放します。 存在しない文やポータルに対してCloseを発行してもエラーになりません。 応答は通常CloseCompleteですが、リソースの解放に何らかの問題が発生した場合はErrorResponseになります。 プリペアド文を閉じると、そこから構築され、開いたポータルが暗黙的に閉ざされることに注意してください。

The Flush message does not cause any specific output to be generated, but forces the backend to deliver any data pending in its output buffers. A Flush must be sent after any extended-query command except Sync, if the frontend wishes to examine the results of that command before issuing more commands. Without Flush, messages returned by the backend will be combined into the minimum possible number of packets to minimize network overhead. Flushメッセージにより特定の出力が生成されることはありません。 しかし、バックエンドに対して、出力バッファ内で待機しているデータを強制的に配送させます。 フロントエンドが他のコマンドを発行する前にコマンドの結果を検証したい場合に、FlushはSync以外の拡張問い合わせコマンドの後に送信される必要があります。 Flushを行わないと、バックエンドで返されるメッセージは、ネットワークオーバーヘッドを最小化する、最小限のパケット数にまとめられます。

注記

The simple Query message is approximately equivalent to the series Parse, Bind, portal Describe, Execute, Close, Sync, using the unnamed prepared statement and portal objects and no parameters. One difference is that it will accept multiple SQL statements in the query string, automatically performing the bind/describe/execute sequence for each one in succession. Another difference is that it will not return ParseComplete, BindComplete, CloseComplete, or NoData messages. 簡易問い合わせメッセージは、おおよそ、無名のプリペアド文とポータルオブジェクトを使用したパラメータなしのParse、Bind、ポータル用Describe、Execute、Close、Syncの流れと同一です。 違いは、問い合わせ文字列内に複数のSQL文を受け付けられ、bind/describe/executeという流れがそれぞれが成功すれば自動的に行われる点です。 他の違いとして、ParseCompleteやBindComplete、CloseComplete、NoDataメッセージが返されない点があります。

55.2.4. パイプライン化 #

<title>Pipelining</title>

Use of the extended query protocol allows <firstterm>pipelining</firstterm>, which means sending a series of queries without waiting for earlier ones to complete. This reduces the number of network round trips needed to complete a given series of operations. However, the user must carefully consider the required behavior if one of the steps fails, since later queries will already be in flight to the server. 拡張問い合わせプロトコルの利用により、パイプライン化(pipelining)が可能となります。 これは、先に送った問い合わせの完了を待つことなく一連の問い合わせを送るということです。 これにより、指定された操作を完了するためのネットワークのやり取りの回数が減ります。 しかし、ある段階が失敗した時に必要とされる振る舞いを、ユーザは注意深く検討しなければなりません。 それ以降の問い合わせはすでにサーバに送信中だからです。

One way to deal with that is to make the whole query series be a single transaction, that is wrap it in <command>BEGIN</command> ... <command>COMMIT</command>. However, this does not help if one wishes for some of the commands to commit independently of others. これに対処するための一つの方法は、一連の問い合わせ全体を単一のトランザクションにすることです。 すなわち、BEGIN ... COMMITで囲みます。 しかし、あるコマンドを他のコマンドとは独立してコミットしたい時にはこの方法は役に立ちません。

The extended query protocol provides another way to manage this concern, which is to omit sending Sync messages between steps that are dependent. Since, after an error, the backend will skip command messages until it finds Sync, this allows later commands in a pipeline to be skipped automatically when an earlier one fails, without the client having to manage that explicitly with <command>BEGIN</command> and <command>COMMIT</command>. Independently-committable segments of the pipeline can be separated by Sync messages. 拡張問い合わせプロトコルは、この問題に対応する別の方法を提供しています。 これは、お互いに依存するステップの間ではSyncメッセージを送るのを省略するというものです。 エラーが起こると、バックエンドはがyncが見つかるまでコマンドメッセージをスキップすることにより、それよりも前のコマンドが失敗した時に、クライアントが明示的にBEGINCOMMITで管理することなく、パイプラインの中の後続のコマンドが自動的にスキップされるからです。 パイプラインの中の独立してコミットできる部分は、Syncメッセージで分けておくことができます。

If the client has not issued an explicit <command>BEGIN</command>, then each Sync ordinarily causes an implicit <command>COMMIT</command> if the preceding step(s) succeeded, or an implicit <command>ROLLBACK</command> if they failed. However, there are a few DDL commands (such as <command>CREATE DATABASE</command>) that cannot be executed inside a transaction block. If one of these is executed in a pipeline, it will fail unless it is the first command in the pipeline. Furthermore, upon success it will force an immediate commit to preserve database consistency. Thus a Sync immediately following one of these commands has no effect except to respond with ReadyForQuery. クライアントが明示的なBEGINを発行しないと、先行のステップが成功した場合は各々のSyncは通常暗黙的なCOMMIT、失敗した場合には暗黙的なROLLBACKをもたらします。 しかし、トランザクションブロックの内側で実行できない少数のDDLコマンド(CREATE DATABASEのような)があります。 これらのいずれかがパイプラインで実行されると、それがパイプラインの最初のコマンドでないかぎり失敗します。 さらに、成功した場合は、即時のコミットによってデータベース一貫性が保持されます。 したがって、これらのコマンドのいずれかの直後に続くSyncは、ReadyForQueryで応答することを除き、何の効果もありません。

When using this method, completion of the pipeline must be determined by counting ReadyForQuery messages and waiting for that to reach the number of Syncs sent. Counting command completion responses is unreliable, since some of the commands may be skipped and thus not produce a completion message. この方法を使うときには、パイプラインの終了は、ReadyForQueryメッセージの数が送信したSyncメッセージの数と一致することで決定しなければなりません。 コマンドのうちいくつかはスキップされたかも知れず、その場合は完了メッセージを生成しないので、コマンド完了メッセージを数えるのは信頼性に欠けます。

55.2.5. 関数呼び出し #

<title>Function Call</title>

The Function Call sub-protocol allows the client to request a direct call of any function that exists in the database's <structname>pg_proc</structname> system catalog. The client must have execute permission for the function. 関数呼び出しサブプロトコルにより、クライアントはデータベースのpg_procシステムカタログに存在する任意の関数を直接呼び出す要求を行うことができます。 クライアントはその関数を実行する権限を持たなければなりません。

注記

The Function Call sub-protocol is a legacy feature that is probably best avoided in new code. Similar results can be accomplished by setting up a prepared statement that does <literal>SELECT function($1, ...)</literal>. The Function Call cycle can then be replaced with Bind/Execute. 関数呼び出しサブプロトコルは、おそらく新しく作成するコードでは使用すべきではない古い機能です。 同様の結果は、SELECT function($1, ...)を行うプリペアド文を設定することで得ることができます。 そして、この関数呼び出しサイクルをBind/Executeで置き換えることができます。

A Function Call cycle is initiated by the frontend sending a FunctionCall message to the backend. The backend then sends one or more response messages depending on the results of the function call, and finally a ReadyForQuery response message. ReadyForQuery informs the frontend that it can safely send a new query or function call. 関数呼び出しサイクルはフロントエンドがFunctionCallメッセージをバックエンドに送ることで起動されます。 バックエンドは1つまたは複数の応答メッセージを関数呼び出しの結果に基づいて送り、最終的にReadyForQueryメッセージを送出します。 ReadyForQueryはフロントエンドに対し新規の問い合わせまたは関数呼び出しを行っても安全確実であることを通知します。

The possible response messages from the backend are: バックエンドから送信される可能性がある応答メッセージを以下に示します。

ErrorResponse

An error has occurred. エラーが起こりました。

FunctionCallResponse

The function call was completed and returned the result given in the message. (Note that the Function Call protocol can only handle a single scalar result, not a row type or set of results.) 関数呼び出しが完了し、メッセージで与えられた結果が返されました。 (関数呼び出しプロトコルは単一のスカラ結果のみを扱うことができます。行型や結果集合を扱うことはできません。)

ReadyForQuery

Processing of the function call is complete. ReadyForQuery will always be sent, whether processing terminates successfully or with an error. 関数呼び出しの処理が終了しました。 処理が成功またはエラーで終了したかどうかにかかわらずReadyForQueryは常に送出されます。

NoticeResponse

A warning message has been issued in relation to the function call. Notices are in addition to other responses, i.e., the backend will continue processing the command. 関数呼び出しに関して警告メッセージが出されました。 警告メッセージは他の応答に対する追加のメッセージです。 したがって、バックエンドはそのコマンドの処理を続行します。

55.2.6. COPY操作 #

<title>COPY Operations</title>

The <command>COPY</command> command allows high-speed bulk data transfer to or from the server. Copy-in and copy-out operations each switch the connection into a distinct sub-protocol, which lasts until the operation is completed. COPYコマンドにより、サーバとの間で高速な大量データ転送を行うことができます。 コピーインとコピーアウト操作はそれぞれ接続を別のサブプロトコルに切り替えます。 これは操作が完了するまで残ります。

Copy-in mode (data transfer to the server) is initiated when the backend executes a <command>COPY FROM STDIN</command> SQL statement. The backend sends a CopyInResponse message to the frontend. The frontend should then send zero or more CopyData messages, forming a stream of input data. (The message boundaries are not required to have anything to do with row boundaries, although that is often a reasonable choice.) The frontend can terminate the copy-in mode by sending either a CopyDone message (allowing successful termination) or a CopyFail message (which will cause the <command>COPY</command> SQL statement to fail with an error). The backend then reverts to the command-processing mode it was in before the <command>COPY</command> started, which will be either simple or extended query protocol. It will next send either CommandComplete (if successful) or ErrorResponse (if not). コピーインモード(サーバへのデータ転送)は、バックエンドがCOPY FROM STDIN SQL文を実行した時に起動されます。 バックエンドはフロントエンドにCopyInResponseメッセージを送信します。 フロントエンドはその後、ゼロ個以上のCopyDataメッセージを送信し、入力データのストリームを形成します。 (このメッセージの境界は行の境界に何かしら合わせる必要ありませんが、往々にしてそれが合理的な選択となります。) フロントエンドは、CopyDoneメッセージ(正常に終了させる)、もしくは、CopyFailメッセージ(COPY SQL文をエラーで失敗させる)を送信することで、コピーインモードを終了させることができます。 そして、バックエンドは、COPYが始まる前の、簡易もしくは拡張問い合わせプロトコルを使用するコマンド処理モードに戻ります。 そして次に、CommandComplete(成功時)またはErrorResponse(失敗時)のどちらかを送信します。

In the event of a backend-detected error during copy-in mode (including receipt of a CopyFail message), the backend will issue an ErrorResponse message. If the <command>COPY</command> command was issued via an extended-query message, the backend will now discard frontend messages until a Sync message is received, then it will issue ReadyForQuery and return to normal processing. If the <command>COPY</command> command was issued in a simple Query message, the rest of that message is discarded and ReadyForQuery is issued. In either case, any subsequent CopyData, CopyDone, or CopyFail messages issued by the frontend will simply be dropped. コピーインモードの期間中にバックエンドがエラー(CopyFailメッセージの受信を含む)を検知すると、バックエンドはErrorResponseメッセージを発行します。 拡張問い合わせメッセージ経由でCOPYコマンドが発行された場合、バックエンドはSyncメッセージを受け取るまでフロントエンドのメッセージを破棄するようになります。 Syncメッセージを受け取ると、ReadyForQueryを発行し、通常処理に戻ります。 簡易問い合わせメッセージでCOPYが発行された場合、メッセージの残りは破棄され、ReadyForQueryメッセージを発行します。 どちらの場合でも、その後にフロントエンドによって発行されたCopyData、CopyDone、CopyFailは単に削除されます。

The backend will ignore Flush and Sync messages received during copy-in mode. Receipt of any other non-copy message type constitutes an error that will abort the copy-in state as described above. (The exception for Flush and Sync is for the convenience of client libraries that always send Flush or Sync after an Execute message, without checking whether the command to be executed is a <command>COPY FROM STDIN</command>.) バックエンドは、コピーインモード期間中、FlushとSyncメッセージを無視します。 その他の種類の非コピーメッセージを受け取ると、エラーになり、上述のようにコピーイン状態を中断します (クライアントライブラリがExecuteメッセージの後に、実行したコマンドがCOPY FROM STDINかどうかを検査することなく、常にFlushまたはSyncを送信できる、という便利さのためにFlushとSyncは例外です)。

Copy-out mode (data transfer from the server) is initiated when the backend executes a <command>COPY TO STDOUT</command> SQL statement. The backend sends a CopyOutResponse message to the frontend, followed by zero or more CopyData messages (always one per row), followed by CopyDone. The backend then reverts to the command-processing mode it was in before the <command>COPY</command> started, and sends CommandComplete. The frontend cannot abort the transfer (except by closing the connection or issuing a Cancel request), but it can discard unwanted CopyData and CopyDone messages. コピーアウトモード(サーバからのデータ転送)は、バックエンドがCOPY TO STDOUT SQL文を実行した時に起動します。 バックエンドはCopyOutResponseメッセージをフロントエンドに送信し、その後、ゼロ個以上のCopyDataメッセージ(常に行ごとに1つ)を、そして、CopyDoneを送信します。 その後、バックエンドはCOPYが始まる前のコマンド処理モードに戻り、CommandCompleteを送信します。 フロントエンドは(接続の切断やCancel要求の発行は例外ですが)転送を中断することはできません。 しかし、不要なCopyDataとCopyDoneメッセージを破棄することは可能です。

In the event of a backend-detected error during copy-out mode, the backend will issue an ErrorResponse message and revert to normal processing. The frontend should treat receipt of ErrorResponse as terminating the copy-out mode. コピーアウトモード期間中バックエンドはエラーを検知すると、ErrorResponseメッセージを発行し、通常処理に戻ります。 フロントエンドはErrorResponseの受信をコピーアウトモードの終了として扱うべきです。

It is possible for NoticeResponse and ParameterStatus messages to be interspersed between CopyData messages; frontends must handle these cases, and should be prepared for other asynchronous message types as well (see <xref linkend="protocol-async"/>). Otherwise, any message type other than CopyData or CopyDone may be treated as terminating copy-out mode. NoticeResponseおよびParameterStatusメッセージがCopyDataメッセージ間に散在することがあります。 フロントエンドはこのような場合も扱わなければなりません。 また、他の種類の非同期メッセージ(55.2.7を参照)も同様に準備すべきです。 さもなくば、CopyDataまたはCopyDone以外の種類のメッセージがコピーアウトモードの終了として扱われてしまう可能性があります。

There is another Copy-related mode called copy-both, which allows high-speed bulk data transfer to <emphasis>and</emphasis> from the server. Copy-both mode is initiated when a backend in walsender mode executes a <command>START_REPLICATION</command> statement. The backend sends a CopyBothResponse message to the frontend. Both the backend and the frontend may then send CopyData messages until either end sends a CopyDone message. After the client sends a CopyDone message, the connection goes from copy-both mode to copy-out mode, and the client may not send any more CopyData messages. Similarly, when the server sends a CopyDone message, the connection goes into copy-in mode, and the server may not send any more CopyData messages. After both sides have sent a CopyDone message, the copy mode is terminated, and the backend reverts to the command-processing mode. In the event of a backend-detected error during copy-both mode, the backend will issue an ErrorResponse message, discard frontend messages until a Sync message is received, and then issue ReadyForQuery and return to normal processing. The frontend should treat receipt of ErrorResponse as terminating the copy in both directions; no CopyDone should be sent in this case. See <xref linkend="protocol-replication"/> for more information on the subprotocol transmitted over copy-both mode. 他にも、サーバへ、およびサーバからの高速な一括データ転送を行うことができるコピーボースというコピーに関連したモードがあります。 コピーボースモードは、walsenderモードのバックエンドがSTART_REPLICATION文を実行した時に初期化されます。 バックエンドはCopyBothResponseメッセージをフロントエンドに送信します。 この後バックエンドとフロントエンドの両方が、接続が終了するまでの間にCopyDataメッセージを送信できるようになります。 同様に、サーバがCopyDoneメッセージを送信した場合、接続はコピーインモードとなり、サーバはそれ以上のCopyDataメッセージを送信できません。 両方の側がCopyDoneメッセージを送信した後、コピーモードは終了し、バックエンドはコマンド処理モードに戻ります。 コピーボースモード中にバックエンドが検出したエラーのイベントにおいては、バックエンドはErrorResponseメッセージを発行し、Syncメッセージの受信までフロントエンドのメッセージを破棄し、その後ReadyForQueryを発行して通常の処理に戻ります。 フロントエンドは両方向のコピーを終了するように、ErrorResponse受理の処理をするべきです。 この場合CopyDoneを送信するべきではありません。 コピーボースモードにおけるサブプロトコル転送の詳細は55.4を参照してください。

The CopyInResponse, CopyOutResponse and CopyBothResponse messages include fields that inform the frontend of the number of columns per row and the format codes being used for each column. (As of the present implementation, all columns in a given <command>COPY</command> operation will use the same format, but the message design does not assume this.) CopyInResponse、CopyOutResponse、CopyBothResponseメッセージには、フロントエンドに1行当たりの列数と各列で使用する書式コードを通知するためのフィールドが含まれています。 (現在の実装では、COPY操作で与えられるすべての列は同一の書式を使用します。 しかし、メッセージ設計においては、これを前提としていません。)

55.2.7. 非同期操作 #

<title>Asynchronous Operations</title>

There are several cases in which the backend will send messages that are not specifically prompted by the frontend's command stream. Frontends must be prepared to deal with these messages at any time, even when not engaged in a query. At minimum, one should check for these cases before beginning to read a query response. バックエンドが、フロントエンドのコマンドストリームで特に依頼されていないメッセージを送信する場合が複数あります。 フロントエンドは、問い合わせ作業を行っていない時であっても常に、これらのメッセージを扱う準備をしなければなりません。 少なくとも、問い合わせの応答の読み込みを始める前にこれらを検査すべきです。

It is possible for NoticeResponse messages to be generated due to outside activity; for example, if the database administrator commands a <quote>fast</quote> database shutdown, the backend will send a NoticeResponse indicating this fact before closing the connection. Accordingly, frontends should always be prepared to accept and display NoticeResponse messages, even when the connection is nominally idle. 外部の活動によって、NoticeResponseメッセージが生成されることがあり得ます。 例えば、データベース管理者が高速データベース停止コマンドを実行した場合、バックエンドは接続を閉ざす前にこれを通知するためにNoticeResponseを送信します。 したがって、たとえ接続が名目上待機状態であったとしても、フロントエンドは常にNoticeResponseメッセージを受け付け、表示する準備をすべきです。

ParameterStatus messages will be generated whenever the active value changes for any of the parameters the backend believes the frontend should know about. Most commonly this occurs in response to a <command>SET</command> SQL command executed by the frontend, and this case is effectively synchronous &mdash; but it is also possible for parameter status changes to occur because the administrator changed a configuration file and then sent the <systemitem>SIGHUP</systemitem> signal to the server. Also, if a <command>SET</command> command is rolled back, an appropriate ParameterStatus message will be generated to report the current effective value. ParameterStatusメッセージは、任意のパラメータの実際の値が変更され、それをバックエンドがフロントエンドに通知するべきであるとみなした場合は常に生成されます。 ほとんどの場合、これはフロントエンドによるSET SQLコマンド実行に対する応答の中で起こります。 これは実質的には同期していますが、管理者が設定ファイルを変更し、SIGHUPシグナルをサーバに送った場合にも、パラメータ状態の変更が発生することがあります。 また、SETコマンドがロールバックされた場合、現在の有効値を報告するために適切なParameterStatusメッセージが生成されます。

At present there is a hard-wired set of parameters for which ParameterStatus will be generated: they are <varname>server_version</varname>, <varname>server_encoding</varname>, <varname>client_encoding</varname>, <varname>application_name</varname>, <varname>default_transaction_read_only</varname>, <varname>in_hot_standby</varname>, <varname>is_superuser</varname>, <varname>session_authorization</varname>, <varname>DateStyle</varname>, <varname>IntervalStyle</varname>, <varname>TimeZone</varname>, <varname>integer_datetimes</varname>, and <varname>standard_conforming_strings</varname>. (<varname>server_encoding</varname>, <varname>TimeZone</varname>, and <varname>integer_datetimes</varname> were not reported by releases before 8.0; <varname>standard_conforming_strings</varname> was not reported by releases before 8.1; <varname>IntervalStyle</varname> was not reported by releases before 8.4; <varname>application_name</varname> was not reported by releases before 9.0; <varname>default_transaction_read_only</varname> and <varname>in_hot_standby</varname> were not reported by releases before 14.) Note that <varname>server_version</varname>, <varname>server_encoding</varname> and <varname>integer_datetimes</varname> are pseudo-parameters that cannot change after startup. This set might change in the future, or even become configurable. Accordingly, a frontend should simply ignore ParameterStatus for parameters that it does not understand or care about. 現時点では、ParameterStatusを生成するパラメータ群は固定されています。 それらはserver_versionserver_encodingclient_encodingapplication_namedefault_transaction_read_onlyin_hot_standbyis_superusersession_authorizationDateStyleIntervalStyleTimeZoneinteger_datetimes、およびstandard_conforming_stringsです。 (8.0より前までのリリースでは、server_encodingTimeZoneおよびinteger_datetimesは送信されませんでした。 8.1より前までのリリースでは、standard_conforming_stringsは送信されませんでした。 8.4より前のリリースでは、IntervalStyleは送信されませんでした。 9.0より前のリリースでは、application_nameは送信されませんでした。 14より前のリリースでは、default_transaction_read_onlyin_hot_standbyは送信されませんでした。) server_versionserver_encodingおよびinteger_datetimesは仮想的なパラメータであり、起動後に変更することができないことに注意してください。 これは今後変更される、あるいは設定変更可能になる可能性があります。 したがって、フロントエンドは未知または注目していないParameterStatusを単に無視すべきです。

If a frontend issues a <command>LISTEN</command> command, then the backend will send a NotificationResponse message (not to be confused with NoticeResponse!) whenever a <command>NOTIFY</command> command is executed for the same channel name. フロントエンドがLISTENコマンドを発行した場合、同じチャネル名に対しNOTIFYコマンドが実行された時にバックエンドはNotificationResponseメッセージ(NoticeResponseと間違えないように!)を送出します。

注記

At present, NotificationResponse can only be sent outside a transaction, and thus it will not occur in the middle of a command-response series, though it might occur just before ReadyForQuery. It is unwise to design frontend logic that assumes that, however. Good practice is to be able to accept NotificationResponse at any point in the protocol. 現在、NotificationResponseをトランザクションの外部でのみ送信することができます。 このため、これはコマンド応答の流れの途中では起こりませんが、ReadyForQueryの直前に発生する可能性があります。 しかし、これを前提にフロントエンドのロジックを設計することは避けてください。 プロトコル内の任意の時点でNotificationResponseを受け付けられるようにすることを勧めます。

55.2.8. 処理中のリクエストの取り消し #

<title>Canceling Requests in Progress</title>

During the processing of a query, the frontend might request cancellation of the query. The cancel request is not sent directly on the open connection to the backend for reasons of implementation efficiency: we don't want to have the backend constantly checking for new input from the frontend during query processing. Cancel requests should be relatively infrequent, so we make them slightly cumbersome in order to avoid a penalty in the normal case. 問い合わせの処理中に、フロントエンドが問い合わせを取り消す可能性があります。 取り消し要求は、効率を高めるために、接続を開いたバックエンドに対して直接送信されません。 その問い合わせを処理中のバックエンドが、フロントエンドからの新しい入力があるかどうかを定期的に確認することは好ましくありません。 取り消し要求はたいていの場合、頻繁には起こらないので、通常の状態においての負担を避けるため、多少扱いにくくなっています。

To issue a cancel request, the frontend opens a new connection to the server and sends a CancelRequest message, rather than the StartupMessage message that would ordinarily be sent across a new connection. The server will process this request and then close the connection. For security reasons, no direct reply is made to the cancel request message. 取り消し要求を出す場合、フロントエンドは通常の新規接続の時に送出されるStartupMessageメッセージではなくCancelRequestメッセージをサーバに送り、新規接続を開始します。 サーバはこの要求を処理し、接続を切断します。 セキュリティ上の理由から、取り消し要求メッセージに対し直接の回答はありません。

A CancelRequest message will be ignored unless it contains the same key data (PID and secret key) passed to the frontend during connection start-up. If the request matches the PID and secret key for a currently executing backend, the processing of the current query is aborted. (In the existing implementation, this is done by sending a special signal to the backend process that is processing the query.) CancelRequestメッセージは、接続開始段階でフロントエンドに送られたものと同一の鍵データ(PIDと秘密鍵)を含んでいない場合は無視されます。 現在バックエンドが実行中の処理に対するPIDと秘密鍵が要求と一致した場合、その現在の問い合わせ処理は中断されます。 (現状では、これは、その問い合わせを処理しているバックエンドプロセスに対し特別なシグナルを送ることで実装されています。)

The cancellation signal might or might not have any effect &mdash; for example, if it arrives after the backend has finished processing the query, then it will have no effect. If the cancellation is effective, it results in the current command being terminated early with an error message. この取り消しシグナルは何の効果も生まないことがあります。 例えば、バックエンドが問い合わせの処理を完了した後に届いた場合、効果がありません。 もし取り消し処理が有効であれば、エラーメッセージとともに、現在のコマンドは終了されます。

The upshot of all this is that for reasons of both security and efficiency, the frontend has no direct way to tell whether a cancel request has succeeded. It must continue to wait for the backend to respond to the query. Issuing a cancel simply improves the odds that the current query will finish soon, and improves the odds that it will fail with an error message instead of succeeding. セキュリティと効率上の理由による上述の実装の結果、フロントエンドは取り消し要求が成功したかどうかを直接判断することはできません。 フロントエンドはバックエンドからの問い合わせの回答を待ち続けなければいけません。 取り消しを要求することは単に現在の問い合わせを早めに終わらせ、成功ではなくエラーメッセージを出して不成功とする可能性を単に高める程度のものです。

Since the cancel request is sent across a new connection to the server and not across the regular frontend/backend communication link, it is possible for the cancel request to be issued by any process, not just the frontend whose query is to be canceled. This might provide additional flexibility when building multiple-process applications. It also introduces a security risk, in that unauthorized persons might try to cancel queries. The security risk is addressed by requiring a dynamically generated secret key to be supplied in cancel requests. 取り消し要求は、通常のフロントエンドとバックエンドの通信接続を通してではなく新規のサーバとの接続に送られるため、取り消される問い合わせを実行したフロントエンドだけでなく、任意のプロセスによっても送信することができます。 このことはマルチプロセスアプリケーションを作るに当たって柔軟性を提供します。 同時に、権限のない者が問い合わせを取り消そうとするといったセキュリティ上のリスクも持ち込みます。 このセキュリティ上のリスクは、取り消し要求内に動的に生成される秘密キーを供給することを必須とすることで回避されます。

55.2.9. 終了 #

<title>Termination</title>

The normal, graceful termination procedure is that the frontend sends a Terminate message and immediately closes the connection. On receipt of this message, the backend closes the connection and terminates. 通常の洗練された終了手順はフロントエンドがTerminateメッセージを出し、すぐに接続を閉じることです。 このメッセージを受け取るとすぐにバックエンドは接続を閉じ終了します。

In rare cases (such as an administrator-commanded database shutdown) the backend might disconnect without any frontend request to do so. In such cases the backend will attempt to send an error or notice message giving the reason for the disconnection before it closes the connection. まれに(管理者によるデータベース停止コマンドなど)、バックエンドはフロントエンドからの要求なしに切断することがあります。 こうした場合、バックエンドは、接続を閉ざす前に切断理由を通知するエラーまたは警報メッセージの送信を試みます。

Other termination scenarios arise from various failure cases, such as core dump at one end or the other, loss of the communications link, loss of message-boundary synchronization, etc. If either frontend or backend sees an unexpected closure of the connection, it should clean up and terminate. The frontend has the option of launching a new backend by recontacting the server if it doesn't want to terminate itself. Closing the connection is also advisable if an unrecognizable message type is received, since this probably indicates loss of message-boundary sync. 他にも、どちらかの側のコアダンプ、通信リンクの消失、メッセージ境界の同期の消失など各種失敗によって終了する状況があります。 フロントエンドかバックエンドいずれかが予期しない接続の中断を検知した場合、後始末を行い終了しなければいけません。 フロントエンドはもし自身が終了を望まない場合、サーバに再交信し新規のバックエンドを立ち上げる選択権を持っています。 解釈できないメッセージ種類を受け取った時、おそらくメッセージ境界の同期が消失したことを示しますので、接続を閉ざすことを勧めます。

For either normal or abnormal termination, any open transaction is rolled back, not committed. One should note however that if a frontend disconnects while a non-<command>SELECT</command> query is being processed, the backend will probably finish the query before noticing the disconnection. If the query is outside any transaction block (<command>BEGIN</command> ... <command>COMMIT</command> sequence) then its results might be committed before the disconnection is recognized. 通常の終了、異常な終了のどちらの場合でも、開いているトランザクションはすべてコミットされずにロールバックされます。 しかし、フロントエンドがSELECT以外の問い合わせを処理中に切断した場合、バックエンドはおそらく切断に気付く前にその問い合わせを完了させてしまうでしょう。 その問い合わせがトランザクションブロック(BEGIN ... COMMITの並び)外部であった場合、切断に気付く前にその結果はコミットされる可能性があります。

55.2.10. SSLセッション暗号化 #

<title><acronym>SSL</acronym> Session Encryption</title>

If <productname>PostgreSQL</productname> was built with <acronym>SSL</acronym> support, frontend/backend communications can be encrypted using <acronym>SSL</acronym>. This provides communication security in environments where attackers might be able to capture the session traffic. For more information on encrypting <productname>PostgreSQL</productname> sessions with <acronym>SSL</acronym>, see <xref linkend="ssl-tcp"/>. PostgreSQLSSLサポート付きで構築された場合、フロントエンドとバックエンド間の通信をSSLで暗号化することができます。 攻撃者がセッショントラフィックをキャプチャできるような環境における通信を安全にすることができます。 SSLを使用したPostgreSQLセッションの暗号化に関する詳細は19.9を参照してください。

To initiate an <acronym>SSL</acronym>-encrypted connection, the frontend initially sends an SSLRequest message rather than a StartupMessage. The server then responds with a single byte containing <literal>S</literal> or <literal>N</literal>, indicating that it is willing or unwilling to perform <acronym>SSL</acronym>, respectively. The frontend might close the connection at this point if it is dissatisfied with the response. To continue after <literal>S</literal>, perform an <acronym>SSL</acronym> startup handshake (not described here, part of the <acronym>SSL</acronym> specification) with the server. If this is successful, continue with sending the usual StartupMessage. In this case the StartupMessage and all subsequent data will be <acronym>SSL</acronym>-encrypted. To continue after <literal>N</literal>, send the usual StartupMessage and proceed without encryption. (Alternatively, it is permissible to issue a GSSENCRequest message after an <literal>N</literal> response to try to use <acronym>GSSAPI</acronym> encryption instead of <acronym>SSL</acronym>.) SSL暗号化接続を開始するには、フロントエンドはまず、StartupMessageではなくSSLRequestを送信します。 その後サーバはそれぞれSSLの実行を行うか行わないかを示すSNかを持つ1バイトの応答を返します。 フロントエンドはその応答に満足できなければ、この時点で接続を切断することができます。 Sの後に継続するのであれば、サーバと間でSSL起動ハンドシェーク(ここではSSLの仕様に関しては説明しません)を行います。 これが成功した場合、続いて通常のStartupMessageの送信を行います。 この場合、StartupMessageおよびその後のデータはSSLにより暗号化されます。 Nの後に、通常のStartupMessageを送信することで暗号化なしで進みます。 (他に、SSLの代わりにGSSAPI暗号化の利用を試行するために、N応答の後にGSSENCRequestメッセージを送信することが認められています。)

The frontend should also be prepared to handle an ErrorMessage response to SSLRequest from the server. This would only occur if the server predates the addition of <acronym>SSL</acronym> support to <productname>PostgreSQL</productname>. (Such servers are now very ancient, and likely do not exist in the wild anymore.) In this case the connection must be closed, but the frontend might choose to open a fresh connection and proceed without requesting <acronym>SSL</acronym>. また、フロントエンドはサーバからのSSLRequestに対するErrorMessage応答を取り扱うための用意もすべきです。 これは、PostgreSQLSSLサポートが追加される前のサーバの場合のみで発生します。 (現在ではこうしたサーバは非常に古いものといえ、ほとんど存在しません。) この場合接続を切断しなければなりませんが、フロントエンドはSSL要求なしで新しく接続を開き、処理を進めることもできます。

When <acronym>SSL</acronym> encryption can be performed, the server is expected to send only the single <literal>S</literal> byte and then wait for the frontend to initiate an <acronym>SSL</acronym> handshake. If additional bytes are available to read at this point, it likely means that a man-in-the-middle is attempting to perform a buffer-stuffing attack (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>). Frontends should be coded either to read exactly one byte from the socket before turning the socket over to their SSL library, or to treat it as a protocol violation if they find they have read additional bytes. SSL暗号化が実行可能なら、サーバはSバイトだけを送信し、フロントエンドがSSLハンドシェイクを開始するのを待つことが期待されます。 この段階でそれ以上のバイトが読み取り可能であるなら、中間者がバッファスタッフィング攻撃(CVE-2021-23222)を開始しようとしている可能性が高いです。 フロントエンドは、ソケットをSSLライブラリに渡す前に正確に1バイトだけをソケットから読み出すべきです。 でなければ、追加のバイトが読み取られた場合には、プロトコル違反として扱うべきです。

An initial SSLRequest can also be used in a connection that is being opened to send a CancelRequest message. 最初のSSLRequestはCancelRequestメッセージを送信するために開いた接続で使用することもできます。

While the protocol itself does not provide a way for the server to force <acronym>SSL</acronym> encryption, the administrator can configure the server to reject unencrypted sessions as a byproduct of authentication checking. プロトコル自体には、サーバにSSL暗号化を強制する方法は用意されていませんが、管理者は認証検査の一方法として、暗号化されていないセッションを拒否するようにサーバを設定することができます。

55.2.11. GSSAPIセッション暗号化 #

<title><acronym>GSSAPI</acronym> Session Encryption</title>

If <productname>PostgreSQL</productname> was built with <acronym>GSSAPI</acronym> support, frontend/backend communications can be encrypted using <acronym>GSSAPI</acronym>. This provides communication security in environments where attackers might be able to capture the session traffic. For more information on encrypting <productname>PostgreSQL</productname> sessions with <acronym>GSSAPI</acronym>, see <xref linkend="gssapi-enc"/>. PostgreSQLGSSAPIサポートを有効にして構築されていれば、GSSAPIを使ってフロントエンド/バックエンド通信を暗号化できます。 これにより、攻撃者がセッションのやり取りを読み取れるかもしれない環境における通信のセキュリティが提供されます。 PostgreSQLでの通信をGSSAPIで暗号化するための情報に関しては、19.10をご覧ください。

To initiate a <acronym>GSSAPI</acronym>-encrypted connection, the frontend initially sends a GSSENCRequest message rather than a StartupMessage. The server then responds with a single byte containing <literal>G</literal> or <literal>N</literal>, indicating that it is willing or unwilling to perform <acronym>GSSAPI</acronym> encryption, respectively. The frontend might close the connection at this point if it is dissatisfied with the response. To continue after <literal>G</literal>, using the GSSAPI C bindings as discussed in <ulink url="https://tools.ietf.org/html/rfc2744">RFC 2744</ulink> or equivalent, perform a <acronym>GSSAPI</acronym> initialization by calling <function>gss_init_sec_context()</function> in a loop and sending the result to the server, starting with an empty input and then with each result from the server, until it returns no output. When sending the results of <function>gss_init_sec_context()</function> to the server, prepend the length of the message as a four byte integer in network byte order. To continue after <literal>N</literal>, send the usual StartupMessage and proceed without encryption. (Alternatively, it is permissible to issue an SSLRequest message after an <literal>N</literal> response to try to use <acronym>SSL</acronym> encryption instead of <acronym>GSSAPI</acronym>.) GSSAPI暗号化接続を開始するには、フロントエンドは最初にStartupMessageではなく、GSSENCRequestメッセージを送ります。 次にサーバは、それぞれGSSAPI暗号化を希望する、しないを意味するGまたはNを含む1バイトを送信します。 このレスポンスに満足できなければ、この時点でフロントエンドは接続を打ち切って構いません。 Gの受信後継続するには、RFC 2744あるいは同様の文書で議論されているGSSAPI Cバインディングを使い、ループの中でgss_init_sec_context()を呼び出してGSSAPIを初期化し、結果をサーバに送信し、空の入力を受け取ることから始めて、サーバが出力を返さなくなるまでサーバからの出力を受け取ります。 gss_init_sec_context()の結果をサーバに送る際には、ネットワークバイトオーダーで4バイトの整数にメッセージ長を先頭に付与します。 Nの後継続するには、通常のStartupMessageを送信し、暗号化せずに続けてください。 (他に、GSSAPIの代わりにSSL暗号化の使用を試行するために、N応答の後にSSLRequestメッセージを送信することが認められています。)

The frontend should also be prepared to handle an ErrorMessage response to GSSENCRequest from the server. This would only occur if the server predates the addition of <acronym>GSSAPI</acronym> encryption support to <productname>PostgreSQL</productname>. In this case the connection must be closed, but the frontend might choose to open a fresh connection and proceed without requesting <acronym>GSSAPI</acronym> encryption. また、フロントエンドはサーバからのGSSENCRequestへのErrorMessage応答に備えるべきです。 これはサーバがPostgreSQLへのGSSAPI暗号化サポートを追加する以前だったときにのみ発生します。 この場合は接続を切断しなければなりませんが、フロントエンドは新しい接続を開いてGSSAPI暗号化を要求せずに進めることを選択するかもしれません。

When <acronym>GSSAPI</acronym> encryption can be performed, the server is expected to send only the single <literal>G</literal> byte and then wait for the frontend to initiate a <acronym>GSSAPI</acronym> handshake. If additional bytes are available to read at this point, it likely means that a man-in-the-middle is attempting to perform a buffer-stuffing attack (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>). Frontends should be coded either to read exactly one byte from the socket before turning the socket over to their GSSAPI library, or to treat it as a protocol violation if they find they have read additional bytes. GSSAPI暗号化が実行可能なら、サーバはGバイトだけを送信し、フロントエンドがGSSAPIハンドシェイクを開始するのを待つことが期待されます。 この段階でそれ以上のバイトが読み取り可能であるなら、中間者がバッファスタッフィング攻撃(CVE-2021-23222)を開始しようとしている可能性が高いです。 フロントエンドは、ソケットをGSSAPIライブラリに渡す前に正確に1バイトだけをソケットから読み出すべきです。 でなければ、追加のバイトが読み取られた場合には、プロトコル違反として扱うべきです。

An initial GSSENCRequest can also be used in a connection that is being opened to send a CancelRequest message. 最初のGSSENCRequestは、CancelRequestメッセージを送信するために開いている接続でも利用できます。

Once <acronym>GSSAPI</acronym> encryption has been successfully established, use <function>gss_wrap()</function> to encrypt the usual StartupMessage and all subsequent data, prepending the length of the result from <function>gss_wrap()</function> as a four byte integer in network byte order to the actual encrypted payload. Note that the server will only accept encrypted packets from the client which are less than 16kB; <function>gss_wrap_size_limit()</function> should be used by the client to determine the size of the unencrypted message which will fit within this limit and larger messages should be broken up into multiple <function>gss_wrap()</function> calls. Typical segments are 8kB of unencrypted data, resulting in encrypted packets of slightly larger than 8kB but well within the 16kB maximum. The server can be expected to not send encrypted packets of larger than 16kB to the client. GSSAPI暗号化の確立に成功したら、gss_wrap()を使って通常のStartupMessageと後続のすべてのメッセージを暗号化します。 実際に暗号化した送信データの前に、gss_wrap()の結果をネットワークバイトオーダーで4バイトの整数にしたものを付与します。 サーバは16kB未満のクライアントからの暗号化パケットだけを受け付けることに注意してください。 クライアントはgss_wrap_size_limit()を使って暗号化前のメッセージの大きさがこの制限に収まるかどうかを確認し、それより大きなメッセージは複数のgss_wrap()呼び出しに分解すべきです。 典型的なセグメントは暗号化前で8kBのデータで、暗号化後のパケットは8kBより少し大きくなりますが、最大長の16kB以内には問題なく収まります。 サーバは16kBよりも大きな暗号化パケットをクライアントに送らないものと期待することができます。

While the protocol itself does not provide a way for the server to force <acronym>GSSAPI</acronym> encryption, the administrator can configure the server to reject unencrypted sessions as a byproduct of authentication checking. プロトコル自身はサーバにGSSAPI暗号化を強制する方法を提供していませんが、管理者は認証チェックの副次的効果として暗号化されていないセッションをサーバが拒否するように設定できます。