6

我正在使用 PostgreSQL C API。阅读文档,它指出当 PQgetResult 返回 NULL 时查询已完成,如果 PQisBusy 不返回 0,则 PQgetResult 将阻塞。但是,如果没有更多输入,PQisBusy 将返回 1,因此我无法调用 PQgetResult 并获取 NULL。因此我不知道查询是否结束。有没有其他方法可以知道查询是否完成?我误解了异步 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 一次。

4

3 回答 3

4

我认为你需要的是PQsetSingleRowModePQgetResult每次返回一行。

来自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

于 2012-12-10T15:56:26.913 回答
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 */

}
于 2012-12-07T14:54:31.010 回答
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;
        }
    }
}
于 2012-12-04T09:32:47.597 回答