PostgreSQL7.0手册-开发者手册 -64. 前端/后端协议
"COPY" 的 CompletedResponse 消息.
CursorResponse
查询可以是一条 insert(l),delete(l),update(l),fetch(l) 或一个 select(l) 命令.如果事务被终止,那么后端发送一条带有标记 "*ABORT STATE*" 的 CompletedResponse 消息.否则发送下面的响应.
对一条 insert(l) 命令,后端发送一条带有 "INSERT oidrows" 标记的 CompletedResponse 消息,这里的 rows 是插入的行数,而 oid 在插入的函数 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 消息;见下文.
函数调用
一个函数调用循环是由前端向后端发送一条 FunctionCall 消息初始化的.然后后端根据函数调用的结果发送一条或者更多响应消息,并且在最后是一条 ReadyForQuery 响应消息.ReadyForQuery 通知前端它可以安全地发送一条新的查询或者函数调用了.
从后端来的可能的响应信息是:
ErrorResponse
发生了一个错误.
FunctionResultResponse
函数调用被执行并且返回一个结果.
FunctionVoidResponse
函数调用被执行并且没有返回一个结果.
ReadyForQuery
函数调用处理完成.ReadyForQuery 将总是被发送,不管是成功完成处理还是发生一个错误.
NoticeResponse
发出了一条有关该函数调用的警告信息.通知是附加在其他响应上的,也就是说,后端将继续处理命令.
前端在等待其他类型的消息时必须准备接收 ErrorResponse 和 NoticeResponse 消息.同样,如果前端发出了任何 listen(l) 命令,那么它必须在任何时候准备接收 NotificationResponse 消息;见下文.
通知响应
如果前端发出了一条 listen(l) 命令,那么每当为同样名称的通知执行一条 notify(l) 命令,后端都会发送一条 NotificationResponse 消息 (不要与 NoticeResponse 弄混了!).
除了在另外一个后端的消息里以外,在协议里的任何地方(启动后)都允许通知响应.因此,前端在等待任何消息的时候都必须准备识别 NotificationResponse 消息.实际上,前端甚至在不能进行查询的时候都要能够处理 NotificationResponse 消息.
NotificationResponse
一条 notify(l) 命令为前面执行的 listen(l) 命令的名称被执行.通知可以在任何时候发送.
有一点值得我们指出来,就是在 listen 和 notify 里面的名称不必与 SQL 数据库里的关系(表)的名称有任何关系.通知名只是一个独立选出来的条件名.
取消正在处理的请求
在一条查询正在处理的时候,前端可以通过发送合适的消息给 postmaster 取消该查询的处理.这样的取消不直接发送给后端是因为实现的有效性:我们不希望后端在处理查询的过程中不停地检查前端来的输入.取消请求应该相对而言比较少见,所以我们把取消做得稍微笨拙一些,以便不影响正常状况的性能.
要发送一条取消请求,前端打开一个与 postmaster 的新的联接并且发送一条 CancelRequest 消息,而不是通常在新联接中经常发送的 StartupPacket 消息.postmaster 将处理这个请求然后关闭联接.出于安全原因,对取消请求消息不做直接的响应.
除非 CancelRequest 消息包含与联接启动过程中传递给前端的相同的键数据(PID 和 安全键字),否则它将被忽略.如果该请求与当前运行着的后端匹配了 PID 和安全键字,postmaster 将给后端发送信号以退出当前查询.
取消信号可能有也可能没有做用 -- 例如,如果它在后端完成查询的处理后到达,那么它就没有做用.如果取消起作用了,它将导致当前命令带着一个错误信息被提前退出.
这么做的结果是对安全和有效性通盘考虑的结果,前端没有直接的方法获知一个取消请求是否成功.它必须继续等待后端对查询响应.执行取消仅仅是增加了当前查询快些结束的可能性,以及增加了当前查询会带着一条错误信息失败而不是成功执行的可能性.
因为取消请求是发送给 postmaster 而不是通过通常的前端/后端通讯链接,所以取消请求可能是任意过程执行的,而不仅仅是要取消查询的前端.这样可能对创建多进程应用有某种灵活性的好处.但是同时这样也带来了安全风险,因为这样任何一个非认证用户都可能试图取消查询.这个安全风险通过要求在取消请求中提供一个动态生成的安全键字排除.
终止
通常的和优雅的终止过程是前端发送一条 Terminate (终止)消息并且立刻关闭联接.一旦收到消息,后端马上关闭联接并且退出.
一
CursorResponse
查询可以是一条 insert(l),delete(l),update(l),fetch(l) 或一个 select(l) 命令.如果事务被终止,那么后端发送一条带有标记 "*ABORT STATE*" 的 CompletedResponse 消息.否则发送下面的响应.
对一条 insert(l) 命令,后端发送一条带有 "INSERT oidrows" 标记的 CompletedResponse 消息,这里的 rows 是插入的行数,而 oid 在插入的函数 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 消息;见下文.
函数调用
一个函数调用循环是由前端向后端发送一条 FunctionCall 消息初始化的.然后后端根据函数调用的结果发送一条或者更多响应消息,并且在最后是一条 ReadyForQuery 响应消息.ReadyForQuery 通知前端它可以安全地发送一条新的查询或者函数调用了.
从后端来的可能的响应信息是:
ErrorResponse
发生了一个错误.
FunctionResultResponse
函数调用被执行并且返回一个结果.
FunctionVoidResponse
函数调用被执行并且没有返回一个结果.
ReadyForQuery
函数调用处理完成.ReadyForQuery 将总是被发送,不管是成功完成处理还是发生一个错误.
NoticeResponse
发出了一条有关该函数调用的警告信息.通知是附加在其他响应上的,也就是说,后端将继续处理命令.
前端在等待其他类型的消息时必须准备接收 ErrorResponse 和 NoticeResponse 消息.同样,如果前端发出了任何 listen(l) 命令,那么它必须在任何时候准备接收 NotificationResponse 消息;见下文.
通知响应
如果前端发出了一条 listen(l) 命令,那么每当为同样名称的通知执行一条 notify(l) 命令,后端都会发送一条 NotificationResponse 消息 (不要与 NoticeResponse 弄混了!).
除了在另外一个后端的消息里以外,在协议里的任何地方(启动后)都允许通知响应.因此,前端在等待任何消息的时候都必须准备识别 NotificationResponse 消息.实际上,前端甚至在不能进行查询的时候都要能够处理 NotificationResponse 消息.
NotificationResponse
一条 notify(l) 命令为前面执行的 listen(l) 命令的名称被执行.通知可以在任何时候发送.
有一点值得我们指出来,就是在 listen 和 notify 里面的名称不必与 SQL 数据库里的关系(表)的名称有任何关系.通知名只是一个独立选出来的条件名.
取消正在处理的请求
在一条查询正在处理的时候,前端可以通过发送合适的消息给 postmaster 取消该查询的处理.这样的取消不直接发送给后端是因为实现的有效性:我们不希望后端在处理查询的过程中不停地检查前端来的输入.取消请求应该相对而言比较少见,所以我们把取消做得稍微笨拙一些,以便不影响正常状况的性能.
要发送一条取消请求,前端打开一个与 postmaster 的新的联接并且发送一条 CancelRequest 消息,而不是通常在新联接中经常发送的 StartupPacket 消息.postmaster 将处理这个请求然后关闭联接.出于安全原因,对取消请求消息不做直接的响应.
除非 CancelRequest 消息包含与联接启动过程中传递给前端的相同的键数据(PID 和 安全键字),否则它将被忽略.如果该请求与当前运行着的后端匹配了 PID 和安全键字,postmaster 将给后端发送信号以退出当前查询.
取消信号可能有也可能没有做用 -- 例如,如果它在后端完成查询的处理后到达,那么它就没有做用.如果取消起作用了,它将导致当前命令带着一个错误信息被提前退出.
这么做的结果是对安全和有效性通盘考虑的结果,前端没有直接的方法获知一个取消请求是否成功.它必须继续等待后端对查询响应.执行取消仅仅是增加了当前查询快些结束的可能性,以及增加了当前查询会带着一条错误信息失败而不是成功执行的可能性.
因为取消请求是发送给 postmaster 而不是通过通常的前端/后端通讯链接,所以取消请求可能是任意过程执行的,而不仅仅是要取消查询的前端.这样可能对创建多进程应用有某种灵活性的好处.但是同时这样也带来了安全风险,因为这样任何一个非认证用户都可能试图取消查询.这个安全风险通过要求在取消请求中提供一个动态生成的安全键字排除.
终止
通常的和优雅的终止过程是前端发送一条 Terminate (终止)消息并且立刻关闭联接.一旦收到消息,后端马上关闭联接并且退出.
一

