Re: problem with PQsendQuery/PQgetResult and COPY FROM statement

Поиск
Список
Период
Сортировка
От max.poletto@gmail.com
Тема Re: problem with PQsendQuery/PQgetResult and COPY FROM statement
Дата
Msg-id 1148436791.766986.35330@j33g2000cwa.googlegroups.com
обсуждение исходный текст
Ответ на problem with PQsendQuery/PQgetResult and COPY FROM statement  (max.poletto@gmail.com)
Ответы Re: problem with PQsendQuery/PQgetResult and COPY FROM statement
Список 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 по дате отправления:

Предыдущее
От: Hannu Krosing
Дата:
Сообщение: Re: Updatable views/with check option parsing
Следующее
От: Simon Riggs
Дата:
Сообщение: Re: error-free disabling of individual child partition