postgresql-jdbc.git / summary / log / commit / refs
commit 7bcdbcc5ea7e1758e71d841c17ecabed4055249b
Author: Kris Jurka <books@ejurka.com>
Date: Tue Aug 31 18:07:39 2010 +0000
Work around a bug in the server's implementation of the copy
protocol. It returns command complete immediately upon receiving
the EOF marker in a binary copy, potentially before we've issued
CopyDone/Fail. Fix this by simply not processing the command
complete message until we believe that we are done with the copy
as well.
Issue originally reported by Matthew Wakeling.
org/postgresql/core/PGStream.java | 17 ++++++++++++++++-
org/postgresql/core/VisibleBufferedInputStream.java | 12 +++++++++++-
org/postgresql/core/v3/QueryExecutorImpl.java | 21 ++++++++++++++++++++-
3 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/org/postgresql/core/PGStream.java b/org/postgresql/core/PGStream.java
index 41a2a2e3..9b5d1132 100644
--- a/org/postgresql/core/PGStream.java
+++ b/org/postgresql/core/PGStream.java
@@ -3,7 +3,7 @@
* Copyright (c) 2003-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/core/PGStream.java,v 1.21 2007/02/28 06:10:59 jurka Exp $
+* $PostgreSQL: pgjdbc/org/postgresql/core/PGStream.java,v 1.22 2008/01/08 06:56:27 jurka Exp $
*
*-------------------------------------------------------------------------
*/
@@ -248,6 +248,21 @@ public class PGStream
}
}
+ /**
+ * Receives a single character from the backend, without
+ * advancing the current protocol stream position.
+ *
+ * @return the character received
+ * @exception IOException if an I/O Error occurs
+ */
+ public int PeekChar() throws IOException
+ {
+ int c = pg_input.peek();
+ if (c < 0)
+ throw new EOFException();
+ return c;
+ }
+
/**
* Receives a single character from the backend
*
diff --git a/org/postgresql/core/VisibleBufferedInputStream.java b/org/postgresql/core/VisibleBufferedInputStream.java
index 0db65233..18438289 100644
--- a/org/postgresql/core/VisibleBufferedInputStream.java
+++ b/org/postgresql/core/VisibleBufferedInputStream.java
@@ -3,7 +3,7 @@
* Copyright (c) 2006-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgjdbc/org/postgresql/core/VisibleBufferedInputStream.java,v 1.2 2007/12/15 15:32:37 jurka Exp $
+ * $PostgreSQL: pgjdbc/org/postgresql/core/VisibleBufferedInputStream.java,v 1.3 2008/01/08 06:56:27 jurka Exp $
*
*-------------------------------------------------------------------------
*/
@@ -76,6 +76,16 @@ public class VisibleBufferedInputStream extends InputStream {
return -1;
}
+ /**
+ * Reads a byte from the buffer without advancing the index pointer.
+ */
+ public int peek() throws IOException {
+ if (ensureBytes(1)) {
+ return buffer[index] & 0xFF;
+ }
+ return -1;
+ }
+
/**
* Reads byte from the buffer without any checks. This method never
* reads from the underlaying stream.
diff --git a/org/postgresql/core/v3/QueryExecutorImpl.java b/org/postgresql/core/v3/QueryExecutorImpl.java
index da628806..1918d2db 100644
--- a/org/postgresql/core/v3/QueryExecutorImpl.java
+++ b/org/postgresql/core/v3/QueryExecutorImpl.java
@@ -4,7 +4,7 @@
* Copyright (c) 2004, Open Cloud Limited.
*
* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/core/v3/QueryExecutorImpl.java,v 1.48 2010/03/21 07:13:37 jurka Exp $
+* $PostgreSQL: pgjdbc/org/postgresql/core/v3/QueryExecutorImpl.java,v 1.49 2010/07/22 21:21:44 jurka Exp $
*
*-------------------------------------------------------------------------
*/
@@ -906,6 +906,25 @@ public class QueryExecutorImpl implements QueryExecutor {
int len;
while( !endReceiving && (block || pgStream.hasMessagePending()) ) {
+
+ // There is a bug in the server's implementation of the copy
+ // protocol. It returns command complete immediately upon
+ // receiving the EOF marker in the binary protocol,
+ // potentially before we've issued CopyDone. When we are not
+ // blocking, we don't think we are done, so we hold off on
+ // processing command complete and any subsequent messages
+ // until we actually are done with the copy.
+ //
+ if (!block) {
+ int c = pgStream.PeekChar();
+ if (c == 'C') // CommandComplete
+ {
+ if (logger.logDebug())
+ logger.debug(" <=BE CommandStatus, Ignored until CopyDone");
+ break;
+ }
+ }
+
int c = pgStream.ReceiveChar();
switch(c) {
[parent: 365928303e12]