Re: problem with PQsendQuery/PQgetResult and COPY FROM statement - Mailing list pgsql-hackers
From | max.poletto@gmail.com |
---|---|
Subject | Re: problem with PQsendQuery/PQgetResult and COPY FROM statement |
Date | |
Msg-id | 1148436791.766986.35330@j33g2000cwa.googlegroups.com Whole thread Raw |
In response to | problem with PQsendQuery/PQgetResult and COPY FROM statement (max.poletto@gmail.com) |
Responses |
Re: problem with PQsendQuery/PQgetResult and COPY FROM statement
|
List | pgsql-hackers |
Thanks for all your replies, but I must clarify some things. First, note that what I posted is just a small example that reproduces behavior that appears incorrect. The real code is a C++ wrapper around libpq that supports non-blocking queries and reuses open connections. Volkan and Martijn: I know about PQ{put,get}CopyData, but my example never gets to that point. I must first determine whether the (asynchronous) PQsendQuery() of "COPY test FROM STDIN" succeeded. That's all that retrieve() tries to do in my example. Tom: of course I should (and eventually do) use PQclear(), but I may not want to right away, because I must return to the user a vector of result objects (for example, all the result rows from a query). I do not expect PQgetResult to return millions of non-null PGresult objects after a PQsendQuery("COPY test FROM STDIN"). I expect exactly one non-null result, with a result status of PGRES_COPY_IN. Moreover, the manual says: If a COPY command is issued via PQexec in a string that could contain additional commands, the application must continue fetching results via PQgetResult after completing the COPY sequence.Only when PQgetResult returns NULL is it certain that the PQexec command string is done and it is safe to issue more commands. I assumed this to be true for PQexec or "one of the equivalent functions" mentioned in the manual, such as PQsendQuery. However, if I add the following switch statement to my example: while (!PQisBusy(conn)) { PGresult *r = PQgetResult(conn); if (r) { switch (PQresultStatus(r)) { casePGRES_COPY_IN: break; case PGRES_EMPTY_QUERY: printf("PGRES_EMPTY_QUERY\n"); break; case PGRES_COMMAND_OK: printf("PGRES_COMMAND_OK\n"); break; case PGRES_TUPLES_OK: printf("PGRES_TUPLES_OK\n"); break; case PGRES_COPY_OUT: printf("PGRES_COPY_OUT\n"); break; case PGRES_BAD_RESPONSE: printf("PGRES_BAD_RESPONSE\n"); break; case PGRES_NONFATAL_ERROR: printf("PGRES_NONFATAL_ERROR\n"); break; case PGRES_FATAL_ERROR: printf("PGRES_FATAL_ERROR\n"); break; } res.push_back(r); if (++i % 5000000 == 0) { printf("%d results\n",i); } if (r == oldr) { printf("r==oldr (%p)\n", r); } oldr = r; } else { printf("PQgetResultreturn 0 after %d results\n", i); return; } } the code still prints only: 5000000 results 10000000 results 15000000 results 20000000 results 25000000 results PQgetResult return 0 after 25649299 results In other words, there are >25M distinct non-null results, and all of them have status code PGRES_COPY_IN, and none of them have errors. So it appears that I should check whether the first PGresult object has a status code of PGRES_COPY_IN, and ignore subsequent PGresults even if they are not NULL. I don't object to this interface, but it is not what I would conclude after RTFM. max
pgsql-hackers by date: