我正在使用PostgreSQL C API。读取documentation它表示当PQgetResult返回NULL时查询结束,如果PQisBusy没有返回0,PQgetResult将阻塞。但是如果没有更多输入,PQisBusy返回1,所以我不能调用PQgetResult并得到空值。因此我不知道查询是否结束。有没有其他方法可以知道查询是否完成?我是否误解了异步API?
---- -----编辑
C代码的基本思想是:
PQsendQuery(conn, query)
while(true)
{
PQconsumeInput(conn)
if(PQisBusy(conn) == 0)
{
PGresult* res = PQgetResult(conn);
if(res)
{
//print result
}
else
{
//res == NULL
//indicates query is over
break;
}
}
}
结果将被打印,但循环永远不会终止。因为PQisBusy只返回0一次。
答案 0 :(得分:3)
我认为您需要PQsetSingleRowMode
让PQgetResult
每次都返回一行。
来自http://www.postgresql.org/docs/9.2/static/libpq-single-row-mode.html
通常,libpq会收集SQL命令的整个结果并返回 它作为一个单独的PGresult应用程序。这可能是行不通的 返回大量行的命令。对于这种情况, 应用程序可以在单行模式下使用PQsendQuery和PQgetResult。 在此模式下,结果行将返回到应用程序 从服务器收到的时间。
如果查询返回任何行,则它们将作为个体返回 PGresult对象,看起来像普通的查询结果,除了 具有状态代码PGRES_SINGLE_TUPLE而不是PGRES_TUPLES_OK。 在最后一行之后,或者如果查询返回零行,则立即执行 返回状态为PGRES_TUPLES_OK的零行对象;这是 表示不再有行会到达。
查看示例代码: https://github.com/markokr/libpq-rowproc-demos/blob/master/demo-onerow-async.c
答案 1 :(得分:1)
基于我从评论中的链接中理解的内容,我会尝试这样的事情(select()
的参数和其他函数调用可能完全不同):
if (select(sock 1, &input_mask, NULL, NULL, NULL) < 0) {
fprintf(stderr, "select() failed: %s\n", strerror(errno));
exit_nicely(conn);
}
PQconsumeInput(conn);
while (PQisBusy(conn) != 0) {
/* wait here */
}
while (PGresult* res = PQgetResult(conn)) { /* not sure this is OK, test for not null */
/* do something with res */
}
答案 2 :(得分:0)
我可以看到代码有一个问题,你没有检查PQconsumeInput(conn)函数的返回。因为PQconsumeInput有责任清除繁忙的旗帜。可能发生的是PQconsumeInput将在没有处理任何数据并清除忙标志的情况下失败。
我认为在调用PQisBusy之前检查PQconsumeInput的结果应该可以正常工作。
while (PQconsumeInput(conn) == 1)
{
if(PQisBusy(conn) == 0)
{
PGresult* res = PQgetResult(conn);
if(res)
{
//print result
}
else
{
//res == NULL
//indicates query is over
break;
}
}
}