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]