Postgres Async API detecting end of request

I am working with the PostgreSQL C API. While reading the documentation, she declares that the query is completed when PQgetResult returns NULL, and PQgetResult will block if PQisBusy does not return 0. However, PQisBusy returns 1 if it is no longer entered, so I cannot call PQgetResult and get NULL So I can’t know if the request has ended. Is there any other way to know if a request is being executed? Did I misunderstand the asynchronous API?

---- edit -----

The basic idea is as C code:

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

The result will be printed, but the loop never ends. Because PQisBusy returns 0 only once.

+6
source share
3 answers

I think you need PQsetSingleRowMode so that PQgetResult returns one row each time.

from http://www.postgresql.org/docs/9.2/static/libpq-single-row-mode.html

Usually libpq collects the result of the entire SQL command and returns this application as a single PGresult. This may be inoperative for teams that return a large number of rows. For such cases, applications can use PQsendQuery and PQgetResult in single-line mode. In this mode, the result line (s) are returned to the application at the time they were received from the server.

If the query returns any rows, they are returned as separate PGresult Objects that look like normal query results, except with the status code PGRES_SINGLE_TUPLE instead of PGRES_TUPLES_OK. After the last line or immediately, if the request returns zero lines, an object with a zero line with the status PGRES_TUPLES_OK is returned; this is a signal that no more lines will arrive.

check the sample code: https://github.com/markokr/libpq-rowproc-demos/blob/master/demo-onerow-async.c

+3
source

Based on what I understood from the link in my comment, I would try something like this (the select() parameters and other function calls can be completely different):

 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 */ } 
+1
source

I see one problem with the code. You do not check the return of the PQconsumeInput (conn) function. Because PQconsumeInput is responsible for clearing the busy flag. What could happen is that PQconsumeInput will fail without processing any data and resetting the busy flag.

I think that checking the result of PQconsumeInput before calling PQisBusy should work fine.

 while (PQconsumeInput(conn) == 1) { if(PQisBusy(conn) == 0) { PGresult* res = PQgetResult(conn); if(res) { //print result } else { //res == NULL //indicates query is over break; } } } 
0
source

All Articles