Modified:
branches/branch_5_1/CHANGES
branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java
branches/branch_5_1/src/testsuite/regression/CallableStatementRegressionTest.java
Log:
Fixed BUG#32246 - When unpacking rows directly, we don't hand off error
message packets to the internal method which decodes them correctly, so
no exception is raised, and the driver than hangs trying to read rows
that aren't there. This tends to happen when calling stored procedures, as
normal SELECTs won't have an error in this spot in the protocol unless an
I/O error occurs.
Modified: branches/branch_5_1/CHANGES
===================================================================
--- branches/branch_5_1/CHANGES 2007-11-08 14:51:52 UTC (rev 6661)
+++ branches/branch_5_1/CHANGES 2007-11-09 21:48:42 UTC (rev 6662)
@@ -44,6 +44,13 @@
up in the query log on the server). This information is not shown
if the connection property "paranoid" has been set to "true".
+ - Fixed BUG#32246 - When unpacking rows directly, we don't hand off error
+ message packets to the internal method which decodes them correctly, so
+ no exception is raised, and the driver than hangs trying to read rows
+ that aren't there. This tends to happen when calling stored procedures, as
+ normal SELECTs won't have an error in this spot in the protocol unless an
+ I/O error occurs.
+
10-09-07 - Version 5.1.5
- Released instead of 5.1.4 to pickup patch for BUG#31053
Modified: branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java 2007-11-08 14:51:52 UTC (rev 6661)
+++ branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java 2007-11-09 21:48:42 UTC (rev 6662)
@@ -406,7 +406,7 @@
}
packet = reuseAndReadPacket(this.reusablePacket);
-
+
readServerStatusForResultSets(packet);
//
@@ -1510,11 +1510,19 @@
if (firstTime) {
if (sw == 255) {
- // error packet
- Buffer errorPacket = new Buffer(packetLength);
+ // error packet - we assemble it whole for "fidelity"
+ // in case we ever need an entire packet in checkErrorPacket()
+ // but we could've gotten away with just writing the error code
+ // and message in it (for now).
+ Buffer errorPacket = new Buffer(packetLength + HEADER_LENGTH);
+ errorPacket.setPosition(0);
+ errorPacket.writeByte(this.packetHeaderBuf[0]);
+ errorPacket.writeByte(this.packetHeaderBuf[1]);
+ errorPacket.writeByte(this.packetHeaderBuf[2]);
+ errorPacket.writeByte((byte) 1);
errorPacket.writeByte((byte)sw);
- readFully(this.mysqlInput, errorPacket.getByteBuffer(), 1, packetLength - 1);
-
+ readFully(this.mysqlInput, errorPacket.getByteBuffer(), 5, packetLength - 1);
+ errorPacket.setPosition(4);
checkErrorPacket(errorPacket);
}
Modified:
branches/branch_5_1/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
---
branches/branch_5_1/src/testsuite/regression/CallableStatementRegressionTest.java 2007-11-08
14:51:52 UTC (rev 6661)
+++
branches/branch_5_1/src/testsuite/regression/CallableStatementRegressionTest.java 2007-11-09
21:48:42 UTC (rev 6662)
@@ -1400,4 +1400,77 @@
}
}
}
+
+ /**
+ * Tests fix for Bug#32246 - When unpacking rows directly, we don't
+ * hand off error message packets to the internal method which decodes
+ * them correctly, so no exception is rasied, and the driver than hangs
+ * trying to read rows that aren't there...
+ *
+ * @throws Exception if the test fails
+ */
+ public void testBug32246() throws Exception {
+ if (!versionMeetsMinimum(5, 0)) {
+ return;
+ }
+
+ doBug32246(this.conn);
+ dropTable("test_table_2");
+ dropTable("test_table_1");
+ doBug32246(getConnectionWithProps("useDirectRowUnpack=false"));
+ }
+
+ private void doBug32246(Connection aConn) throws SQLException {
+ createTable("test_table_1", "(value_1 BIGINT PRIMARY KEY) ENGINE=InnoDB");
+ this.stmt.executeUpdate("INSERT INTO test_table_1 VALUES (1)");
+ createTable("test_table_2", "(value_2 BIGINT PRIMARY KEY) ENGINE=InnoDB");
+ this.stmt.executeUpdate("DROP FUNCTION IF EXISTS test_function");
+ createFunction("test_function", "() RETURNS BIGINT " +
+ "DETERMINISTIC MODIFIES SQL DATA BEGIN " +
+ "DECLARE max_value BIGINT; " +
+ "SELECT MAX(value_1) INTO max_value FROM test_table_2; " +
+ "RETURN max_value; END;");
+
+ CallableStatement callable = null;
+
+ try {
+ callable = aConn.prepareCall("{? = call test_function()}");
+
+ callable.registerOutParameter(1,Types.BIGINT);
+
+ try {
+ callable.executeUpdate();
+ fail("impossible; we should never get here.");
+ } catch (SQLException sqlEx) {
+ assertEquals("42S22", sqlEx.getSQLState());
+ }
+
+ createTable("test_table_1", "(value_1 BIGINT PRIMARY KEY) ENGINE=InnoDB");
+ this.stmt.executeUpdate("INSERT INTO test_table_1 VALUES (1)");
+ createTable("test_table_2", "(value_2 BIGINT PRIMARY KEY, " +
+ " FOREIGN KEY (value_2) REFERENCES test_table_1 (value_1) ON DELETE CASCADE)
ENGINE=InnoDB");
+ createFunction("test_function", "(value BIGINT) RETURNS BIGINT " +
+ "DETERMINISTIC MODIFIES SQL DATA BEGIN " +
+ "INSERT INTO test_table_2 VALUES (value); RETURN value; END;");
+
+ callable = aConn.prepareCall("{? = call test_function(?)}");
+ callable.registerOutParameter(1,Types.BIGINT);
+
+ callable.setLong(2,1);
+ callable.executeUpdate();
+
+ callable.setLong(2,2);
+
+ try {
+ callable.executeUpdate();
+ fail("impossible; we should never get here.");
+ } catch (SQLException sqlEx) {
+ assertEquals("23000", sqlEx.getSQLState());
+ }
+ } finally {
+ if (callable != null) {
+ callable.close();
+ }
+ }
+ }
}
\ No newline at end of file
| Thread |
|---|
| • Connector/J commit: r6662 - in branches/branch_5_1: . src/com/mysql/jdbc src/testsuite/regression | mmatthews | 9 Nov |