PQcancelCreate
#准备一个连接,可通过该连接发送取消请求。
PGcancelConn *PQcancelCreate(PGconn *conn);
PQcancelCreate
创建一个 PGcancelConn
对象,但不会立即开始通过此连接发送取消请求。可以通过使用 PQcancelBlocking
以阻塞方式通过此连接发送取消请求,或使用 PQcancelStart
以非阻塞方式发送。返回值可以传递给 PQcancelStatus
以检查是否成功创建了 PGcancelConn
对象。PGcancelConn
对象是不透明的结构,不供应用程序直接访问。此 PGcancelConn
对象可用于以线程安全的方式取消正在原始连接上运行的查询。
在为取消请求设置连接时,将重复使用原始客户端的许多连接参数。重要的是,如果原始连接需要加密连接和/或验证目标主机(使用 sslmode
或 gssencmode
),那么取消请求的连接也将具有相同要求。但是,会在取消请求中忽略任何仅仅在身份验证期间或客户端身份验证后才会使用的连接选项,因为取消请求不需要身份验证,且连接会在提交取消请求之后立即关闭。
请注意,当 PQcancelCreate
返回非空指针时,在使用完此指针后,必须调用 PQcancelFinish
以释放该结构以及任何关联的内存块。即使取消请求失败或放弃,也必须这样做。
PQcancelBlocking
#以阻塞方式请求服务器放弃处理当前命令。
int PQcancelBlocking(PGcancelConn *cancelConn);
该请求通过给定的 PGcancelConn
发起,该 PGcancelConn
需要使用 PQcancelCreate
创建。如果取消请求成功分派,则 PQcancelBlocking
的返回值为 1;如果不成功,则返回 0。如果请求不成功,可以使用 PQcancelErrorMessage
检索错误消息。
但是,取消 dispatch 成功并不保证该请求会产生任何效果。如果取消有效,待取消的命令会提早终止并返回错误结果。如果取消失败(例如,因为服务器已完成处理命令),那么根本不会出现可见结果。
PQcancelStart
PQcancelPoll
#请求服务器以非阻塞方式停止处理当前命令。
int PQcancelStart(PGcancelConn *cancelConn); PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);
可以通过 PGcancelConn
发起请求,需要通过 PQcancelCreate
创建该连接。如果可以发起取消请求,PQcancelStart
的返回值将为 1;否则为 0。如果此次请求不成功,可以通过 PQcancelErrorMessage
检索错误消息。
如果 PQcancelStart
成功,接下来的步骤是对 libpq 进行轮询以便继续取消连接序列。使用 PQcancelSocket
获取数据库连接底层套接字的描述符(注意:不要假设 PQcancelPoll
调用过程中套接字保持不变)。循环如下:如果 PQcancelPoll(cancelConn)
上一次返回 PGRES_POLLING_READING
,则等待套接字准备读取( select()
、poll()
或类似系统函数指示)。然后再次调用 PQcancelPoll(cancelConn)
。相反,如果 PQcancelPoll(cancelConn)
上一次返回 PGRES_POLLING_WRITING
,则等待套接字准备写入,然后再次调用 PQcancelPoll(cancelConn)
。在第一次迭代中,即如果尚未调用 PQcancelPoll(cancelConn)
,则像上一次返回 PGRES_POLLING_WRITING
一样。继续执行此循环,直到 PQcancelPoll(cancelConn)
返回 PGRES_POLLING_FAILED
(指示连接过程已失败)或返回 PGRES_POLLING_OK
(指示取消请求已成功 dispatch)。
但是,取消 dispatch 成功并不保证该请求会产生任何效果。如果取消有效,待取消的命令会提早终止并返回错误结果。如果取消失败(例如,因为服务器已完成处理命令),那么根本不会出现可见结果。
在连接过程中,可以使用 PQcancelStatus
来随时检查连接状态。如果该调用返回 CONNECTION_BAD
,则取消过程失败;如果该调用返回 CONNECTION_OK
,则已成功发送取消请求。上述状态都可从 PQcancelPoll
的返回值中检测到。此外,在异步连接过程中(以及仅在该过程中),也可能会出现其他状态。这些状态表示连接过程的当前阶段,可供用户提供反馈。这些状态是:
CONNECTION_ALLOCATED
#等待调用 PQcancelStart
或 PQcancelBlocking
实际打开套接字。这是在调用 PQcancelCreate
或 PQcancelReset
之后的连接状态。此时尚未连接到服务器。如需实际开始发送取消请求,请使用 PQcancelStart
或 PQcancelBlocking
。
CONNECTION_STARTED
#等待建立连接。
CONNECTION_MADE
#连接正常;等待发送。
CONNECTION_AWAITING_RESPONSE
#等待来自服务器的响应。
CONNECTION_SSL_STARTUP
#正在协商 SSL 加密。
CONNECTION_GSS_STARTUP
#正在协商 GSS 加密。
请注意,尽管这些常量会保留(以维持兼容性),但是应用程序不应依赖于这些常量以特定顺序或以任何方式出现,或者依赖于该状态始终为其中一个记录值。应用程序可能会执行以下操作:
switch(PQcancelStatus(conn)) { case CONNECTION_STARTED: feedback = "Connecting..."; break; case CONNECTION_MADE: feedback = "Connected to server..."; break; . . . default: feedback = "Connecting..."; }
使用 PQcancelPoll
时,将忽略 connect_timeout
连接参数;由应用程序决定是否经过了一段时间。否则,PQcancelStart
后跟一个 PQcancelPoll
循环等同于 PQcancelBlocking
。
PQcancelStatus
#返回取消连接的状态。
ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn);
状态可以是多个值中的一种。但是,只有三个值在异步取消过程中不可见:CONNECTION_ALLOCATED
、CONNECTION_OK
和 CONNECTION_BAD
。使用 PQcancelCreate
成功创建的 PGcancelConn
的初始状态是 CONNECTION_ALLOCATED
。已成功发送的取消请求状态为 CONNECTION_OK
。状态 CONNECTION_BAD
表示取消尝试失败。在调用 PQcancelFinish
或 PQcancelReset
之前,OK 状态将保持不变。
请参阅 PQcancelStart
条目以了解可能返回的其他状态代码。
但是,取消 dispatch 成功并不保证该请求会产生任何效果。如果取消有效,待取消的命令会提早终止并返回错误结果。如果取消失败(例如,因为服务器已完成处理命令),那么根本不会出现可见结果。
PQcancelSocket
#获取到服务器取消连接套接字的文件描述符编号。
int PQcancelSocket(const PGcancelConn *cancelConn);
有效的文件描述符将大于或等于 0;结果为 -1 表示当前尚未打开任何服务器连接。调用此部分中 PGcancelConn
的任何函数(PQcancelErrorMessage
和 PQcancelSocket
除外)可能会造成此状态的变化。
PQcancelErrorMessage
#返回取消连接操作最近生成错误消息。
char *PQcancelErrorMessage(const PGcancelConn *cancelconn);
如果失败,几乎所有 libpq 函数(将 PGcancelConn
作为参数的函数)都将为 PQcancelErrorMessage
设置一条消息。请注意,根据 libpq 约定,非空 PQcancelErrorMessage
结果可以包含多行并包括一个尾换行符。调用者不应直接释放此结果。当将关联的 PGcancelConn
句柄传递给 PQcancelFinish
时,它将被释放。切勿期望结果字符串在对 PGcancelConn
结构执行操作后保持不变。
PQcancelFinish
#如果尚未完成发送取消请求,关闭取消连接(Cancels the cancel connection)。还会释放PGcancelConn
对象所使用的内存。
void PQcancelFinish(PGcancelConn *cancelConn);
请注意,即使取消尝试失败(由PQcancelStatus
指示),应用程序也应调用PQcancelFinish
,以释放PGcancelConn
对象所使用的内存。在调用PQcancelFinish
之后,不得再使用PGcancelConn
指针。
PQcancelReset
#重置PGcancelConn
,以便可将其重新用于新的取消连接。
void PQcancelReset(PGcancelConn *cancelConn);
如果PGcancelConn
当前用于发送取消请求,则关闭此连接。然后,将准备PGcancelConn
对象,以便可将其用于发送新的取消请求。
可使用此功能为PGconn
创建一个PGcancelConn
,并在原始PGconn
的整个使用寿命期间多次重复使用该连接。
这些函数表示发送取消请求的旧方法。尽管它们仍然可用,但由于未以加密方式发送取消请求(即使原始连接指定sslmode
或gssencmode
以要求进行加密),因此不建议使用。因此,强烈建议不要在新代码中使用这些旧方法,并且建议更改现有代码以改用新函数。
PQgetCancel
#创建一个包含使用PQcancel
取消命令所需信息的数据结构。
PGcancel *PQgetCancel(PGconn *conn);
PQgetCancel
会根据PGconn
连接对象创建一个PGcancel
对象。如果给定的conn
为NULL
或无效连接,它会返回NULL
。PGcancel
对象是不透明结构,应用程序不应直接访问它;它只能传递给PQcancel
或PQfreeCancel
。
PQfreeCancel
#释放 PQgetCancel
创建的数据结构。
void PQfreeCancel(PGcancel *cancel);
PQfreeCancel
释放之前由 PQgetCancel
创建的数据对象。
PQcancel
#PQcancel
是 PQcancelBlocking
的已过时且不安全的变体,但可在信号处理程序之中安全使用。
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);
仅因向后兼容性的原因而存在 PQcancel
。应改用 PQcancelBlocking
。 PQcancel
拥有的唯一优点是,如果信号处理程序中的errbuf
是局部变量,那么可以从信号处理程序中安全调用它。但通常认为,这不足以弥补此函数存在的安全问题。
对于 PQcancel
来说,PGcancel
对象是只读的,因此也可以从不同于操作PGconn
对象的线程中调用它。
如果已成功发送取消请求,PQcancel
的返回值为 1;否则为 0。如果不是,errbuf
中会填充解释性错误消息。errbuf
必须是大小为errbufsize
的 char 数组(建议大小为 256 个字节)。
PQrequestCancel
#PQrequestCancel
是 PQcancelBlocking
的已过时且不安全的变体。
int PQrequestCancel(PGconn *conn);
仅因向后兼容性的原因而存在 PQrequestCancel
。应改用 PQcancelBlocking
。相对于 PQcancelBlocking
,使用 PQrequestCancel
没有任何好处。
请求服务器放弃处理当前命令。它直接在 PGconn
对象上运行,并且在失败的情况下,会将错误消息存储在 PGconn
对象中(可通过 PQerrorMessage
检索)。虽然功能相同,但此方法在多线程程序或信号处理程序中不安全,因为覆盖 PGconn
的错误消息可能会破坏当前在连接上进行的操作。