Per discussion and investigation on the -jdbc list, the server appears to violate the frontend/backend protocol when binary copy data is sent to the server. Upon receiving the binary copy end of data marker (a -1 field count), the server immediately responds with CommandComplete and ReadyForQuery without waiting for the frontend to issue CopyDone or CopyFail. This confuses the JDBC driver as it doesn't think the command sequence should have finished yet.

Attached is a patch to make the server continue to consume protocol data until instructed to stop by the client in the same way as copying text data to the server currently works.

http://www.postgresql.org/docs/8.4/static/protocol-flow.html#PROTOCOL-COPY
http://www.postgresql.org/docs/8.4/static/sql-copy.html

Kris Jurka
*** a/src/backend/commands/copy.c
--- b/src/backend/commands/copy.c
***************
*** 2058,2069 **** CopyFrom(CopyState cstate)
                        int16           fld_count;
                        ListCell   *cur;
  
!                       if (!CopyGetInt16(cstate, &fld_count) ||
!                               fld_count == -1)
                        {
                                done = true;
                                break;
                        }
  
                        if (fld_count != attr_count)
                                ereport(ERROR,
--- 2058,2087 ----
                        int16           fld_count;
                        ListCell   *cur;
  
!                       if (!CopyGetInt16(cstate, &fld_count))
                        {
                                done = true;
                                break;
                        }
+                       
+                       if (fld_count == -1)
+                       {
+                               /*
+                                * Reached EOF.  In protocol version 3, we 
should ignore
+                                * anything after the end of copy data marker 
up to the
+                                * protocol end of copy data (CopyDone/Fail).
+                                */
+                               if (cstate->copy_dest == COPY_NEW_FE)
+                               {
+                                       do
+                                       {
+                                               cstate->raw_buf_index = 
cstate->raw_buf_len;
+                                       } while (CopyLoadRawBuf(cstate));
+                                               continue;
+                               }
+                               done = true;
+                               break;
+                       }
  
                        if (fld_count != attr_count)
                                ereport(ERROR,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to