1.3. 异步查询处理

PQexec 函数对简单的同步应用里提交查询已经是足够用的了. 但是它却有几个主要的缺陷:

不想受到这些限制的应用可以改用下面的函数,这些函数也是构造 PQexec 的函数: PQsendQueryPQgetResult

使用这些(异步)功能以及 PQputlinePQputnbytes 的老一些的程序可能在等待数据发送给后端时阻塞住, 为解决这样的问题,增加了函数 PQsetnonblocking

旧应用可以忽略 PQsetnonblocking 的使用, 维持原有的阻塞特征。 新的程序可以利用 PQsetnonblocking 获得与后端完全非阻塞的联接。

使用 PQsendQueryPQgetResult 解决了 PQexec的一个问题: 如果一个查询字符串包含多个 SQL 命令, 这些命令的结果可以独立的获得.(顺便说一句:这样就允许一种简单的重叠处理模式, 前端可以处理一个查询的结果而后端可以仍然在处理同一查询字符串的后面的查询.) 但是,调用 PQgetResult 将仍然导致前端被阻塞住直到后端完成下一个 SQL 命令.这一点可以通过合理的使用下面三个函数来避免:

一个使用这些函数的典型的前端将有一个主循环使用 select(2) 等待所有它必须处理的条件.其中一个条件将会是后端来的数据已准备好, 从 select 的角度来看就是 PQsocket 标识的文件描述符上已经有可读取的数据. 当主循环侦测到输入准备好,它将调用PQconsumeInput 读取输入.然后可以调用 PQisBusy 返回 false (0)后面可以跟着 PQgetResult。同样它(用户应用)可以调用 PQnotifies测 NOTIFY 信息(参阅下面的 "异步通知"). 例子程序节里面给出了一个例子程序.

一个使用 PQsendQuery/PQgetResult 的前端同样也可以试图取消一个正在被后端处理的查询.

注意:如果当前的查询是事务的一部分,取消动作将退出整个事务.

PQrequestCancel 可以很安全地从一个信号句柄里调用. 所以,如果取消动作可以从信号句柄里发出的话,它也可以与简单的 PQexec一起使用.例如, psql 从一个 SIGINT 信号句柄里调用 PQrequestCancel ,因此允许交互地取消通过 PQexec 发出的查询. 注意,如果没有与后端建立联接或者后端当前没有处理查询, PQrequestCancel 将不发生做用.