postgresql-jdbc.git / summary / log / commit / refs
commit dd128d2495af9e8a9eb28b0bab0c46da96a1cdcd
Author: Kris Jurka <books@ejurka.com>
Date: Thu Feb 04 00:48:47 2010 +0000
Protocol sync is lost when a batch statement parameter has an
embedded null byte. When the server responds with an error message,
the batch error handler tries to construct the equivalent original
query text with the parameters substituted in. This conversion
fails on the driver side with an IllegalArgumentException complaining
about the null byte. There isn't a catch block in place to handle
that exception, so it returns all the way to the user without
processing the remainder of the protocol stream. Later queries
get confused because they see the leftover messages from the
failed batch execution instead of their own results.
Avoid throwing the IllegalArgumentException and instead don't bother
being strictly accurate with the query text escaping as it's just
informational.
org/postgresql/core/v3/SimpleParameterList.java | 10 +++++---
org/postgresql/test/jdbc2/BatchExecuteTest.java | 33 ++++++++++++++++++++++++-
2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/org/postgresql/core/v3/SimpleParameterList.java b/org/postgresql/core/v3/SimpleParameterList.java
index c93824da..44084d7a 100644
--- a/org/postgresql/core/v3/SimpleParameterList.java
+++ b/org/postgresql/core/v3/SimpleParameterList.java
@@ -4,7 +4,7 @@
* Copyright (c) 2004, Open Cloud Limited.
*
* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/core/v3/SimpleParameterList.java,v 1.16 2008/01/08 06:56:27 jurka Exp $
+* $PostgreSQL: pgjdbc/org/postgresql/core/v3/SimpleParameterList.java,v 1.17 2008/09/30 23:41:23 jurka Exp $
*
*-------------------------------------------------------------------------
*/
@@ -155,12 +155,16 @@ class SimpleParameterList implements V3ParameterList {
p.append('\'');
try {
- p = Utils.appendEscapedLiteral(p, paramValues[index].toString(), protoConnection.getStandardConformingStrings());
+ p = Utils.appendEscapedLiteral(p, param, protoConnection.getStandardConformingStrings());
} catch (SQLException sqle) {
// This should only happen if we have an embedded null
// and there's not much we can do if we do hit one.
//
- throw new IllegalArgumentException(sqle.toString());
+ // The goal of toString isn't to be sent to the server,
+ // so we aren't 100% accurate (see StreamWrapper), put
+ // the unescaped version of the data.
+ //
+ p.append(param);
}
p.append('\'');
return p.toString();
diff --git a/org/postgresql/test/jdbc2/BatchExecuteTest.java b/org/postgresql/test/jdbc2/BatchExecuteTest.java
index 11531448..b5dac632 100644
--- a/org/postgresql/test/jdbc2/BatchExecuteTest.java
+++ b/org/postgresql/test/jdbc2/BatchExecuteTest.java
@@ -3,7 +3,7 @@
* Copyright (c) 2004-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/test/jdbc2/BatchExecuteTest.java,v 1.15 2007/07/27 09:01:45 jurka Exp $
+* $PostgreSQL: pgjdbc/org/postgresql/test/jdbc2/BatchExecuteTest.java,v 1.16 2008/01/08 06:56:30 jurka Exp $
*
*-------------------------------------------------------------------------
*/
@@ -281,4 +281,35 @@ public class BatchExecuteTest extends TestCase
stmt.close();
}
+ public void testBatchWithEmbeddedNulls() throws SQLException
+ {
+ Statement stmt = con.createStatement();
+ stmt.execute("CREATE TEMP TABLE batchstring (a text)");
+
+ con.commit();
+
+ PreparedStatement pstmt = con.prepareStatement("INSERT INTO batchstring VALUES (?)");
+
+ pstmt.setString(1, "a");
+ pstmt.addBatch();
+ pstmt.setString(1, "\u0000");
+ pstmt.addBatch();
+ pstmt.setString(1, "b");
+ pstmt.addBatch();
+
+ try {
+ pstmt.executeBatch();
+ fail("Should have thrown an exception.");
+ } catch (SQLException sqle) {
+ con.rollback();
+ }
+ pstmt.close();
+
+ ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM batchstring");
+ assertTrue(rs.next());
+ assertEquals(0, rs.getInt(1));
+ rs.close();
+ stmt.close();
+ }
+
}
[parent: fd376458849a]