Modified:
branches/branch_3_1/connector-j/CHANGES
branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java
branches/branch_3_1/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
branches/branch_5_0/connector-j/CHANGES
branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
branches/branch_5_0/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
trunk/connector-j/CHANGES
trunk/connector-j/src/com/mysql/jdbc/Connection.java
trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
Log:
Fixed BUG#23281 - Downed slave caused round-robin load balance to
not cycle back to first host in list.
Modified: branches/branch_3_1/connector-j/CHANGES
===================================================================
--- branches/branch_3_1/connector-j/CHANGES 2006-10-19 15:21:33 UTC (rev 5906)
+++ branches/branch_3_1/connector-j/CHANGES 2006-10-19 15:40:51 UTC (rev 5907)
@@ -1,6 +1,11 @@
# Changelog
# $Id$
+nn-nn-06 - Version 3.1.15
+
+ - Fixed BUG#23281 - Downed slave caused round-robin load balance to
+ not cycle back to first host in list.
+
10-19-06 - Version 3.1.14
- Fixed BUG#20479 - Updatable result set throws ClassCastException
Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-19 15:21:33
UTC (rev 5906)
+++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-19 15:40:51
UTC (rev 5907)
@@ -2521,6 +2521,9 @@
try {
if (!getHighAvailability() && !this.failedOver) {
+ boolean connectionGood = false;
+ Exception connectionNotEstablishedBecause = null;
+
int hostIndex = 0;
//
@@ -2535,11 +2538,12 @@
}
for (; hostIndex < this.hostListSize; hostIndex++) {
+
+ if (hostIndex == 0) {
+ this.hasTriedMasterFlag = true;
+ }
+
try {
- if (hostIndex == 0) {
- this.hasTriedMasterFlag = true;
- }
-
String newHostPortPair = (String) this.hostList
.get(hostIndex);
@@ -2569,6 +2573,7 @@
this.io = new MysqlIO(newHost, newPort, mergedProps,
getSocketFactoryClassName(), this,
getSocketTimeout());
+
this.io.doHandshake(this.user, this.password,
this.database);
this.isClosed = false;
@@ -2609,44 +2614,56 @@
}
}
+ connectionGood = true;
+
break; // low-level connection succeeded
- } catch (SQLException sqlEx) {
+ } catch (Exception EEE) {
if (this.io != null) {
this.io.forceClose();
}
- String sqlState = sqlEx.getSQLState();
-
- if ((sqlState == null)
- || !sqlState
- .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
- throw sqlEx;
+ connectionNotEstablishedBecause = EEE;
+
+ connectionGood = false;
+
+ if (EEE instanceof SQLException) {
+ SQLException sqlEx = (SQLException)EEE;
+
+ String sqlState = sqlEx.getSQLState();
+
+ // If this isn't a communications failure, it will probably never succeed, so
+ // give up right here and now ....
+ if ((sqlState == null)
+ || !sqlState
+ .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
+ throw sqlEx;
+ }
}
// Check next host, it might be up...
if (getRoundRobinLoadBalance()) {
hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
+ this.hostList) - 1 /* incremented by for loop next time around */;
} else if ((this.hostListSize - 1) == hostIndex) {
- throw sqlEx;
- }
- } catch (Exception unknownException) {
- if (this.io != null) {
- this.io.forceClose();
- }
-
- // Check next host, it might be up...
- if (getRoundRobinLoadBalance()) {
- hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
- } else if ((this.hostListSize - 1) == hostIndex) {
throw new CommunicationsException(this,
(this.io != null) ? this.io
.getLastPacketSentTimeMs() : 0,
- unknownException);
+ EEE);
}
}
}
+
+ if (!connectionGood) {
+ // We've really failed!
+ throw new SQLException(
+ "Could not create connection to database server due to underlying exception: '"
+ + connectionNotEstablishedBecause
+ + "'."
+ + (getParanoid() ? ""
+ : Util
+ .stackTraceToString(connectionNotEstablishedBecause)),
+ SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
+ }
} else {
double timeout = getInitialTimeout();
boolean connectionGood = false;
@@ -2661,7 +2678,6 @@
}
for (; (hostIndex < this.hostListSize) && !connectionGood; hostIndex++) {
-
if (hostIndex == 0) {
this.hasTriedMasterFlag = true;
}
@@ -2758,7 +2774,7 @@
// Check next host, it might be up...
if (getRoundRobinLoadBalance()) {
hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
+ this.hostList) - 1 /* incremented by for loop next time around */;
}
}
Modified:
branches/branch_3_1/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
===================================================================
---
branches/branch_3_1/connector-j/src/testsuite/regression/ConnectionRegressionTest.java 2006-10-19
15:21:33 UTC (rev 5906)
+++
branches/branch_3_1/connector-j/src/testsuite/regression/ConnectionRegressionTest.java 2006-10-19
15:40:51 UTC (rev 5907)
@@ -1665,8 +1665,8 @@
}
/**
- * Tests fix for BUG#6966, connections starting up failed-over (due to down
- * master) never retry master.
+ * Tests bug where downed slave caused round robin load balance not to
+ * cycle back to first host in the list.
*
* @throws Exception
* if the test fails...Note, test is timing-dependent, but
@@ -1674,25 +1674,26 @@
*/
public void testBug23281() throws Exception {
Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
- props.setProperty("autoReconnect", "true");
+ props.setProperty("autoReconnect", "false");
props.setProperty("roundRobinLoadBalance", "true");
props.setProperty("failoverReadOnly", "false");
+ props.setProperty("connectTimeout", "5000");
// Re-build the connection information
int firstIndexOfHost = BaseTestCase.dbUrl.indexOf("//") + 2;
int lastIndexOfHost = BaseTestCase.dbUrl.indexOf("/", firstIndexOfHost);
-
+
String hostPortPair = BaseTestCase.dbUrl.substring(firstIndexOfHost,
lastIndexOfHost);
-
+
StringTokenizer st = new StringTokenizer(hostPortPair, ":");
-
+
String host = null;
String port = null;
-
+
if (st.hasMoreTokens()) {
String possibleHostOrPort = st.nextToken();
-
+
if (Character.isDigit(possibleHostOrPort.charAt(0)) &&
(possibleHostOrPort.indexOf(".") == -1 /* IPV4 */) &&
(possibleHostOrPort.indexOf("::") == -1 /* IPV6 */)) {
@@ -1702,19 +1703,19 @@
host = possibleHostOrPort;
}
}
-
+
if (st.hasMoreTokens()) {
port = st.nextToken();
}
-
+
if (host == null) {
host = "";
}
-
+
if (port == null) {
port = "3306";
}
-
+
StringBuffer newHostBuf = new StringBuffer();
newHostBuf.append(host);
@@ -1722,16 +1723,17 @@
newHostBuf.append(":");
newHostBuf.append(port);
}
-
+
newHostBuf.append(",");
- newHostBuf.append(host);
+ //newHostBuf.append(host);
+ newHostBuf.append("192.0.2.1"); // non-exsitent machine from RFC3330 test network
newHostBuf.append(":65532"); // make sure the slave fails
props.remove("PORT");
props.remove("HOST");
-
+
Connection failoverConnection = null;
-
+
try {
failoverConnection = getConnectionWithProps("jdbc:mysql://"
+ newHostBuf.toString() + "/", props);
Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES 2006-10-19 15:21:33 UTC (rev 5906)
+++ branches/branch_5_0/connector-j/CHANGES 2006-10-19 15:40:51 UTC (rev 5907)
@@ -223,8 +223,13 @@
for a cancel request to block other cancel requests if all run from the
same thread.
-nn-nn-06 - Version 3.1.14
+nn-nn-06 - Version 3.1.15
+ - Fixed BUG#23281 - Downed slave caused round-robin load balance to
+ not cycle back to first host in list.
+
+10-19-06 - Version 3.1.14
+
- Fixed BUG#20479 - Updatable result set throws ClassCastException
when there is row data and moveToInsertRow() is called.
@@ -244,7 +249,7 @@
- Fixed BUG#20687 - Can't pool server-side prepared statements, exception
raised when re-using them.
-
+
- Fixed BUG#21062 - ResultSet.getSomeInteger() doesn't work for BIT(>1).
- Fixed BUG#18880 - ResultSet.getFloatFromString() can't retrieve
@@ -257,39 +262,48 @@
- Fixed BUG#19993 - ReplicationDriver does not always round-robin load
balance depending on URL used for slaves list.
-
+
- Fixed calling toString() on ResultSetMetaData for driver-generated
(i.e. from DatabaseMetaData method calls, or from getGeneratedKeys())
result sets would raise a NullPointerException.
- - Fixed Bug#21207 - Driver throws NPE when tracing prepared statements
- that have been closed (in asSQL()).
+ - Fixed Bug#21207 - Driver throws NPE when tracing prepared statements that
+ have been closed (in asSQL()).
- Removed logger autodectection altogether, must now specify logger
explitly if you want to use a logger other than one that logs
to STDERR.
- - Fixed BUG#22290 - Driver issues truncation on write exception when
+ - Fixed BUG#22290 - Driver issues truncation on write exception when
it shouldn't (due to sending big decimal incorrectly to server with
server-side prepared statement).
-
+
+ - Driver now sends numeric 1 or 0 for client-prepared statement
+ setBoolean() calls instead of '1' or '0'.
+
- Fixed bug where driver would not advance to next host if
roundRobinLoadBalance=true and the last host in the list is down.
- Fixed BUG#18258 - DatabaseMetaData.getTables(), columns() with bad
catalog parameter threw exception rather than return empty result
set (as required by spec).
-
+
- Check and store value for continueBatchOnError property in constructor
of Statements, rather than when executing batches, so that Connections
closed out from underneath statements don't cause NullPointerExceptions
when it's required to check this property.
-
+
- Fixed bug when calling stored functions, where parameters weren't
numbered correctly (first parameter is now the return value, subsequent
parameters if specified start at index "2").
- Fixed BUG#21814 - time values outside valid range silently wrap.
+
+ - Fixed bug when calling stored functions, where parameters weren't
+ numbered correctly (first parameter is now the return value, subsequent
+ parameters if specified start at index "2").
+
+ - Fixed BUG#21814 - time values outside valid range silently wrap.
05-26-06 - Version 3.1.13
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-19 15:21:33
UTC (rev 5906)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-19 15:40:51
UTC (rev 5907)
@@ -2614,6 +2614,9 @@
try {
if (!getHighAvailability() && !this.failedOver) {
+ boolean connectionGood = false;
+ Exception connectionNotEstablishedBecause = null;
+
int hostIndex = 0;
//
@@ -2628,6 +2631,7 @@
}
for (; hostIndex < this.hostListSize; hostIndex++) {
+
if (hostIndex == 0) {
this.hasTriedMasterFlag = true;
}
@@ -2662,6 +2666,7 @@
this.io = new MysqlIO(newHost, newPort, mergedProps,
getSocketFactoryClassName(), this,
getSocketTimeout());
+
this.io.doHandshake(this.user, this.password,
this.database);
this.isClosed = false;
@@ -2702,44 +2707,56 @@
}
}
+ connectionGood = true;
+
break; // low-level connection succeeded
- } catch (SQLException sqlEx) {
+ } catch (Exception EEE) {
if (this.io != null) {
this.io.forceClose();
}
- String sqlState = sqlEx.getSQLState();
-
- if ((sqlState == null)
- || !sqlState
- .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
- throw sqlEx;
+ connectionNotEstablishedBecause = EEE;
+
+ connectionGood = false;
+
+ if (EEE instanceof SQLException) {
+ SQLException sqlEx = (SQLException)EEE;
+
+ String sqlState = sqlEx.getSQLState();
+
+ // If this isn't a communications failure, it will probably never succeed, so
+ // give up right here and now ....
+ if ((sqlState == null)
+ || !sqlState
+ .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
+ throw sqlEx;
+ }
}
// Check next host, it might be up...
if (getRoundRobinLoadBalance()) {
hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
+ this.hostList) - 1 /* incremented by for loop next time around */;
} else if ((this.hostListSize - 1) == hostIndex) {
- throw sqlEx;
- }
- } catch (Exception unknownException) {
- if (this.io != null) {
- this.io.forceClose();
- }
-
- // Check next host, it might be up...
- if (getRoundRobinLoadBalance()) {
- hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
- } else if ((this.hostListSize - 1) == hostIndex) {
throw new CommunicationsException(this,
(this.io != null) ? this.io
.getLastPacketSentTimeMs() : 0,
- unknownException);
+ EEE);
}
}
}
+
+ if (!connectionGood) {
+ // We've really failed!
+ throw SQLError.createSQLException(
+ "Could not create connection to database server due to underlying exception: '"
+ + connectionNotEstablishedBecause
+ + "'."
+ + (getParanoid() ? ""
+ : Util
+ .stackTraceToString(connectionNotEstablishedBecause)),
+ SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
+ }
} else {
double timeout = getInitialTimeout();
boolean connectionGood = false;
@@ -2850,7 +2867,7 @@
// Check next host, it might be up...
if (getRoundRobinLoadBalance()) {
hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
+ this.hostList) - 1 /* incremented by for loop next time around */;
}
}
Modified:
branches/branch_5_0/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
===================================================================
---
branches/branch_5_0/connector-j/src/testsuite/regression/ConnectionRegressionTest.java 2006-10-19
15:21:33 UTC (rev 5906)
+++
branches/branch_5_0/connector-j/src/testsuite/regression/ConnectionRegressionTest.java 2006-10-19
15:40:51 UTC (rev 5907)
@@ -1699,8 +1699,8 @@
}
/**
- * Tests fix for BUG#6966, connections starting up failed-over (due to down
- * master) never retry master.
+ * Tests bug where downed slave caused round robin load balance not to
+ * cycle back to first host in the list.
*
* @throws Exception
* if the test fails...Note, test is timing-dependent, but
@@ -1708,9 +1708,10 @@
*/
public void testBug23281() throws Exception {
Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
- props.setProperty("autoReconnect", "true");
+ props.setProperty("autoReconnect", "false");
props.setProperty("roundRobinLoadBalance", "true");
props.setProperty("failoverReadOnly", "false");
+ props.setProperty("connectTimeout", "5000");
// Re-build the connection information
int firstIndexOfHost = BaseTestCase.dbUrl.indexOf("//") + 2;
@@ -1758,7 +1759,8 @@
}
newHostBuf.append(",");
- newHostBuf.append(host);
+ //newHostBuf.append(host);
+ newHostBuf.append("192.0.2.1"); // non-exsitent machine from RFC3330 test network
newHostBuf.append(":65532"); // make sure the slave fails
props.remove("PORT");
Modified: trunk/connector-j/CHANGES
===================================================================
--- trunk/connector-j/CHANGES 2006-10-19 15:21:33 UTC (rev 5906)
+++ trunk/connector-j/CHANGES 2006-10-19 15:40:51 UTC (rev 5907)
@@ -223,8 +223,13 @@
for a cancel request to block other cancel requests if all run from the
same thread.
-nn-nn-06 - Version 3.1.14
+nn-nn-06 - Version 3.1.15
+ - Fixed BUG#23281 - Downed slave caused round-robin load balance to
+ not cycle back to first host in list.
+
+10-19-06 - Version 3.1.14
+
- Fixed BUG#20479 - Updatable result set throws ClassCastException
when there is row data and moveToInsertRow() is called.
@@ -244,7 +249,7 @@
- Fixed BUG#20687 - Can't pool server-side prepared statements, exception
raised when re-using them.
-
+
- Fixed BUG#21062 - ResultSet.getSomeInteger() doesn't work for BIT(>1).
- Fixed BUG#18880 - ResultSet.getFloatFromString() can't retrieve
@@ -262,29 +267,38 @@
(i.e. from DatabaseMetaData method calls, or from getGeneratedKeys())
result sets would raise a NullPointerException.
- - Fixed Bug#21207 - Driver throws NPE when tracing prepared statements
- that have been closed (in asSQL()).
+ - Fixed Bug#21207 - Driver throws NPE when tracing prepared statements that
+ have been closed (in asSQL()).
- Removed logger autodectection altogether, must now specify logger
explitly if you want to use a logger other than one that logs
to STDERR.
- - Fixed BUG#22290 - Driver issues truncation on write exception when
+ - Fixed BUG#22290 - Driver issues truncation on write exception when
it shouldn't (due to sending big decimal incorrectly to server with
server-side prepared statement).
+ - Driver now sends numeric 1 or 0 for client-prepared statement
+ setBoolean() calls instead of '1' or '0'.
+
- Fixed bug where driver would not advance to next host if
roundRobinLoadBalance=true and the last host in the list is down.
- Fixed BUG#18258 - DatabaseMetaData.getTables(), columns() with bad
catalog parameter threw exception rather than return empty result
set (as required by spec).
-
+
- Check and store value for continueBatchOnError property in constructor
of Statements, rather than when executing batches, so that Connections
closed out from underneath statements don't cause NullPointerExceptions
when it's required to check this property.
-
+
+ - Fixed bug when calling stored functions, where parameters weren't
+ numbered correctly (first parameter is now the return value, subsequent
+ parameters if specified start at index "2").
+
+ - Fixed BUG#21814 - time values outside valid range silently wrap.
+
05-26-06 - Version 3.1.13
- Fixed BUG#15464 - INOUT parameter does not store IN value.
Modified: trunk/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-19 15:21:33 UTC (rev
5906)
+++ trunk/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-19 15:40:51 UTC (rev
5907)
@@ -1743,6 +1743,9 @@
try {
if (!getHighAvailability() && !this.failedOver) {
+ boolean connectionGood = false;
+ Exception connectionNotEstablishedBecause = null;
+
int hostIndex = 0;
//
@@ -1757,6 +1760,7 @@
}
for (; hostIndex < this.hostListSize; hostIndex++) {
+
if (hostIndex == 0) {
this.hasTriedMasterFlag = true;
}
@@ -1791,6 +1795,7 @@
this.io = new MysqlIO(newHost, newPort, mergedProps,
getSocketFactoryClassName(), this,
getSocketTimeout());
+
this.io.doHandshake(this.user, this.password,
this.database);
this.isClosed = false;
@@ -1831,44 +1836,56 @@
}
}
+ connectionGood = true;
+
break; // low-level connection succeeded
- } catch (SQLException sqlEx) {
+ } catch (Exception EEE) {
if (this.io != null) {
this.io.forceClose();
}
- String sqlState = sqlEx.getSQLState();
-
- if ((sqlState == null)
- || !sqlState
- .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
- throw sqlEx;
- }
+ connectionNotEstablishedBecause = EEE;
- // Check next host, it might be up...
- if (getRoundRobinLoadBalance()) {
- hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
- } else if ((this.hostListSize - 1) == hostIndex) {
- throw sqlEx;
+ connectionGood = false;
+
+ if (EEE instanceof SQLException) {
+ SQLException sqlEx = (SQLException)EEE;
+
+ String sqlState = sqlEx.getSQLState();
+
+ // If this isn't a communications failure, it will probably never succeed, so
+ // give up right here and now ....
+ if ((sqlState == null)
+ || !sqlState
+ .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
+ throw sqlEx;
+ }
}
- } catch (Exception unknownException) {
- if (this.io != null) {
- this.io.forceClose();
- }
// Check next host, it might be up...
if (getRoundRobinLoadBalance()) {
hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
+ this.hostList) - 1 /* incremented by for loop next time around */;
} else if ((this.hostListSize - 1) == hostIndex) {
throw new CommunicationsException(this,
(this.io != null) ? this.io
.getLastPacketSentTimeMs() : 0,
- unknownException);
+ EEE);
}
}
}
+
+ if (!connectionGood) {
+ // We've really failed!
+ throw SQLError.createSQLException(
+ "Could not create connection to database server due to underlying exception: '"
+ + connectionNotEstablishedBecause
+ + "'."
+ + (getParanoid() ? ""
+ : Util
+ .stackTraceToString(connectionNotEstablishedBecause)),
+ SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
+ }
} else {
double timeout = getInitialTimeout();
boolean connectionGood = false;
@@ -1979,8 +1996,8 @@
// Check next host, it might be up...
if (getRoundRobinLoadBalance()) {
hostIndex = getNextRoundRobinHostIndex(getURL(),
- this.hostList);
- }
+ this.hostList) - 1 /* incremented by for loop next time around */;
+ }
}
if (connectionGood) {
Modified: trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
===================================================================
--- trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java 2006-10-19
15:21:33 UTC (rev 5906)
+++ trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java 2006-10-19
15:40:51 UTC (rev 5907)
@@ -1701,8 +1701,8 @@
}
/**
- * Tests fix for BUG#6966, connections starting up failed-over (due to down
- * master) never retry master.
+ * Tests bug where downed slave caused round robin load balance not to
+ * cycle back to first host in the list.
*
* @throws Exception
* if the test fails...Note, test is timing-dependent, but
@@ -1710,9 +1710,10 @@
*/
public void testBug23281() throws Exception {
Properties props = new Driver().parseURL(BaseTestCase.dbUrl, null);
- props.setProperty("autoReconnect", "true");
+ props.setProperty("autoReconnect", "false");
props.setProperty("roundRobinLoadBalance", "true");
props.setProperty("failoverReadOnly", "false");
+ props.setProperty("connectTimeout", "5000");
// Re-build the connection information
int firstIndexOfHost = BaseTestCase.dbUrl.indexOf("//") + 2;
@@ -1760,7 +1761,8 @@
}
newHostBuf.append(",");
- newHostBuf.append(host);
+ //newHostBuf.append(host);
+ newHostBuf.append("192.0.2.1"); // non-exsitent machine from RFC3330 test network
newHostBuf.append(":65532"); // make sure the slave fails
props.remove("PORT");
| Thread |
|---|
| • Connector/J commit: r5907 - branches/branch_3_1/connector-j branches/branch_3_1/connector-j/src/com/mysql/jdbc branches/branch_3_1/connector-j/src/tes... | mmatthews | 19 Oct |