Re: Trouble with COPY IN - Mailing list pgsql-jdbc

From Matthew Wakeling
Subject Re: Trouble with COPY IN
Date
Msg-id alpine.DEB.2.00.1007201548270.8895@aragorn.flymine.org
Whole thread Raw
In response to Re: Trouble with COPY IN  (Matthew Wakeling <matthew@flymine.org>)
Responses Re: Trouble with COPY IN
List pgsql-jdbc
On Tue, 20 Jul 2010, Matthew Wakeling wrote:
> So, should the unlocking happen elsewhere, or should endCopy not require a
> lock?

Or a third option. We should delay the processing of the "Z" (Ready for
query) message until after the endCopy has been called.

I have still not been able to create a test that provokes this bug. I do
not understand under what conditions the server will do this, but
sometimes it will respond with a "C" and a "Z" before the endCopy message
has actually been sent to it. Maybe it is keying off the "-1" (no further
rows) part of the binary copy. In any case, I am including a patch here
which seems to fix the driver for my application. When the driver receives
a "C" message (command finished), and block is set to false, then we can
assume that a little later on we will call processCopyResults again very
soon with block set to true. Instead of setting block to true, finish
processing of messages in order to delay seeing the "Z" message until
after the endCopy method has been called.

The patch also contains a simple test for binary copy in, although it does
not exercise this bug.

Index: org/postgresql/core/v3/QueryExecutorImpl.java
===================================================================
RCS file:
/cvsroot/jdbc/pgjdbc/org/postgresql/core/v3/QueryExecutorImpl.java,v
retrieving revision 1.48
diff -u -r1.48 QueryExecutorImpl.java
--- org/postgresql/core/v3/QueryExecutorImpl.java    21 Mar 2010 07:13:37 -0000    1.48
+++ org/postgresql/core/v3/QueryExecutorImpl.java    20 Jul 2010 14:48:03 -0000
@@ -931,7 +931,9 @@
                      error = se;
                  }

-                block = true;
+                if (!block) {
+                    endReceiving = true;
+                }
                  break;

              case 'E': // ErrorMessage (expected response to CopyFail)
Index: org/postgresql/test/jdbc2/CopyTest.java
===================================================================
RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/test/jdbc2/CopyTest.java,v
retrieving revision 1.4
diff -u -r1.4 CopyTest.java
--- org/postgresql/test/jdbc2/CopyTest.java    8 Apr 2010 16:18:05 -0000    1.4
+++ org/postgresql/test/jdbc2/CopyTest.java    20 Jul 2010 14:48:03 -0000
@@ -15,6 +15,7 @@
  import java.sql.Statement;
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.PrintStream;
@@ -272,4 +273,35 @@
          assertEquals(0, getCount());
      }

+    public void testBinaryCopyIn() throws Exception {
+        con.setAutoCommit(true);
+        String sql = "COPY copytest FROM STDIN BINARY";
+        ByteArrayOutputStream data = new ByteArrayOutputStream();
+        DataOutputStream dos = new DataOutputStream(data);
+        dos.writeBytes("PGCOPY\n");
+        dos.writeByte(255);
+        dos.writeBytes("\r\n");
+        dos.writeByte(0); // Signature done
+        dos.writeInt(0); // Flags - we aren't supplying OIDS
+        dos.writeInt(0); // Length of header extension
+        for (int row = 0; row < 99700; row++) {
+            dos.writeShort(3); // Three rows
+            dos.writeInt(5); // String length
+            dos.writeByte('H');
+            dos.writeByte('e');
+            dos.writeByte('l');
+            dos.writeByte('l');
+            dos.writeByte('o');
+            dos.writeInt(4); // int length
+            dos.writeInt(row); // Second argument
+            dos.writeInt(-1); // Null third argument
+        }
+        dos.writeShort(-1); // End of rows
+        dos.flush();
+        dos.close();
+        byte[] byteArray = data.toByteArray();
+        //System.err.println("Data length: " + byteArray.length);
+        long count = copyAPI.copyIn(sql, new ByteArrayInputStream(byteArray));
+        assertEquals(99700, count);
+    }
  }



Hope this helps,

Matthew

--
 There once was a limerick .sig
 that really was not very big
 It was going quite fine
 Till it reached the fourth line

pgsql-jdbc by date:

Previous
From: Matthew Wakeling
Date:
Subject: Re: Trouble with COPY IN
Next
From: Kris Jurka
Date:
Subject: Re: Trouble with COPY IN