Postgres Async API检测查询结束

时间:2012-12-01 19:56:22

标签: sql c postgresql asynchronous

我正在使用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一次。

3 个答案:

答案 0 :(得分:3)

我认为您需要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

答案 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;
        }
    }
}