通常,
libpq
会收集一条 SQL 命令的完整结果,
并把它作为单个
PGresult
返回给应用程序。
对于返回大量行的命令来说,
这可能行不通。
对于这样的情况,
应用程序可以以
单行模式或
分块模式使用
PQsendQuery 和
PQgetResult。
在这些模式中,
结果行会在它们从服务器被收到时返回给应用程序:
单行模式一次一行,
分块模式则成组返回。
要进入这些模式之一,
在一次成功的
PQsendQuery
(或其兄弟函数)
调用之后立即调用
PQsetSingleRowMode
或 PQsetChunkedRowsMode。
这种模式选择只对当前正在执行的查询有效。
然后反复调用
PQgetResult
直到它返回空,
如 Section 32.4
中所记录的那样。
如果查询返回了任何行,
它们会作为一个或多个
PGresult
对象返回,
这些对象看起来就像普通的查询结果,
只是它们的状态码是单行模式的
PGRES_SINGLE_TUPLE
或分块模式的
PGRES_TUPLES_CHUNK,
而非
PGRES_TUPLES_OK。
每个
PGRES_SINGLE_TUPLE
对象中恰好有一个结果行,
而一个
PGRES_TUPLES_CHUNK
对象至少包含一行,
但不超过指定的每块行数。
在最后一行之后,
或者如果查询返回零行则立即,
会返回一个具有状态
PGRES_TUPLES_OK
的零行对象;
这就是不会再有更多行到来的信号。
(但请注意,
仍然有必要继续调用
PQgetResult
直到它返回空。)
所有这些
PGresult
对象都将包含与该查询的普通
PGresult
对象相同的行描述数据
(列名、类型等)。
每个对象都应当照常用
PQclear
释放。
在使用管道模式时,
需要为管道中的每条查询激活单行或分块模式,
然后才能用
PQgetResult
检索该查询的结果。
更多信息请参见
Section 32.5。
PQsetSingleRowMode #为当前正在执行的查询选择单行模式。
int PQsetSingleRowMode(PGconn *conn);
这个函数只能在
PQsendQuery
或其兄弟函数之一之后立即被调用,
并且在对连接进行任何其他操作
(例如
PQconsumeInput
或
PQgetResult)
之前。
如果在正确的时刻被调用,
该函数会为当前查询激活单行模式并返回 1。
否则该模式保持不变,
并且该函数返回 0。
无论如何,
在当前查询完成之后该模式都会恢复为正常。
PQsetChunkedRowsMode #为当前正在执行的查询选择分块模式。
int PQsetChunkedRowsMode(PGconn *conn, int chunkSize);
这个函数类似于
PQsetSingleRowMode,
只是它指定每个
PGresult
检索至多
chunkSize
行,
而不一定只有一行。
这个函数只能在
PQsendQuery
或其兄弟函数之一之后立即被调用,
并且在对连接进行任何其他操作
(例如
PQconsumeInput
或
PQgetResult)
之前。
如果在正确的时刻被调用,
该函数会为当前查询激活分块模式并返回 1。
否则该模式保持不变,
并且该函数返回 0。
无论如何,
在当前查询完成之后该模式都会恢复为正常。
在处理一条查询时,
服务器可能返回了一些行,
然后遇到一个错误,
导致该查询被中止。
通常,
libpq
会丢弃任何这样的行,
并且只报告该错误。
但在单行或分块模式中,
某些行可能已经被返回给应用程序。
因此,
应用程序将看到一些
PGRES_SINGLE_TUPLE 或
PGRES_TUPLES_CHUNK
的
PGresult
对象后面跟着一个
PGRES_FATAL_ERROR
对象。
为了得到正确的事务行为,
应用程序必须被设计为:
如果查询最终失败,
则丢弃或撤销对之前处理的行所做的一切。