通常,libpq 会收集 SQL 命令的整个结果并将它作为单个 PGresult
返回给应用程序。对于返回大量行的命令来说,这是不可行的。对于这种情况,应用程序可以在单行模式或分块模式中使用 PQsendQuery
和 PQgetResult
。在这些模式中,返回给应用程序的结果行在收到时以每次一个(对于单行模式)或以组为单位(对于分块模式)的方式由服务器返回。
要进入其中一种模式,请在成功调用 PQsendQuery
(或相关函数)之后立即调用 PQsetSingleRowMode
或 PQsetChunkedRowsMode
。此模式选择仅对当前正在执行的查询有效。然后,重复调用 PQgetResult
,直至它返回 null,如 第 32.4 节 中所述。如果查询返回任何行,则它们将作为一或多个 PGresult
对象返回,看起来就像普通的查询结果,但对于单行模式,状态代码为 PGRES_SINGLE_TUPLE
;对于分块模式,状态代码为 PGRES_TUPLES_CHUNK
,而不是 PGRES_TUPLES_OK
。每个 PGRES_SINGLE_TUPLE
对象中恰好有一行结果,而 PGRES_TUPLES_CHUNK
对象至少包含一行,但最多包含指定的每个分块的行数。在最后一行后或在查询返回零行时立即返回一个状态为 PGRES_TUPLES_OK
的零行对象;这是不再有行的信号。(但请注意,仍然需要继续调用 PQgetResult
,直至它返回 null。)所有这些 PGresult
对象都将包含查询的普通 PGresult
对象会有的相同行描述数据(列名、类型等)。每个对象应像往常一样使用 PQclear
释放。
使用管道模式时,需要为管道中的每个查询在使用 PQgetResult
检索该查询的结果之前激活单行或分块模式。请参阅 第 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
对象。为了获得正确的交易行为,该应用程序的设计必须能够在查询最终失败时,丢弃或撤销对先前已处理行所做的任何操作。