When using new protocol, PQexec can get out of a COPY IN or COPY OUT
authorTom Lane
Sat, 28 Jun 2003 00:06:01 +0000 (00:06 +0000)
committerTom Lane
Sat, 28 Jun 2003 00:06:01 +0000 (00:06 +0000)
state by itself, so do so.

src/interfaces/libpq/fe-exec.c

index a1ae2612569c1444acae4b6a250a84b6ad714057..9285adc4599a36a739779e59730b75774baa4d62 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.140 2003/06/23 19:20:24 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.141 2003/06/28 00:06:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1083,13 +1083,48 @@ PQexecStart(PGconn *conn)
     */
    while ((result = PQgetResult(conn)) != NULL)
    {
-       if (result->resultStatus == PGRES_COPY_IN ||
-           result->resultStatus == PGRES_COPY_OUT)
+       if (result->resultStatus == PGRES_COPY_IN)
        {
-           PQclear(result);
-           printfPQExpBuffer(&conn->errorMessage,
-                libpq_gettext("COPY state must be terminated first\n"));
-           return false;
+           if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+           {
+               /* In protocol 3, we can get out of a COPY IN state */
+               if (PQputCopyEnd(conn,
+                   libpq_gettext("COPY terminated by new PQexec")) < 0)
+               {
+                   PQclear(result);
+                   return false;
+               }
+               /* keep waiting to swallow the copy's failure message */
+           }
+           else
+           {
+               /* In older protocols we have to punt */
+               PQclear(result);
+               printfPQExpBuffer(&conn->errorMessage,
+                   libpq_gettext("COPY IN state must be terminated first\n"));
+               return false;
+           }
+       }
+       else if (result->resultStatus == PGRES_COPY_OUT)
+       {
+           if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+           {
+               /*
+                * In protocol 3, we can get out of a COPY OUT state: we
+                * just switch back to BUSY and allow the remaining COPY
+                * data to be dropped on the floor.
+                */
+               conn->asyncStatus = PGASYNC_BUSY;
+               /* keep waiting to swallow the copy's completion message */
+           }
+           else
+           {
+               /* In older protocols we have to punt */
+               PQclear(result);
+               printfPQExpBuffer(&conn->errorMessage,
+                   libpq_gettext("COPY OUT state must be terminated first\n"));
+               return false;
+           }
        }
        PQclear(result);
    }