Modified:
branches/branch_5_0/connector-j/CHANGES
branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java
branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java
branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java
branches/branch_5_1/connector-j/CHANGES
branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java
branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java
branches/branch_5_1/connector-j/src/com/mysql/jdbc/StringUtils.java
branches/branch_5_1/connector-j/src/testsuite/regression/StatementRegressionTest.java
Log:
Fixed BUG#28469 - PreparedStatement.getMetaData() for statements containing leading
one-line comments is not returned correctly.
As part of this fix, we also overhauled detection of DML for executeQuery() and SELECTs
for executeUpdate() in plain and prepared statements to be aware of the same types of
comments.
Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES 2007-05-16 03:31:15 UTC (rev 6429)
+++ branches/branch_5_0/connector-j/CHANGES 2007-05-16 21:33:00 UTC (rev 6430)
@@ -3,14 +3,23 @@
nn-nn-07 - Version 5.0.7
- - The configuration "useCursorFetch" (for MySQL-5.0+, which enables
- the use of cursors that allow Connector/J to save memory by fetching
- result set rows in chunks, set by Statement.setFetchSize() by using
- fully-materialized cursors on the server) will now automatically
- set "useServerPrepStmts" to "true" when it has been set to "true",
- since it requires server-side prepared statements in order to
- function correctly.
+ - Setting the configuration parameter "useCursorFetch" to "true" for
+ MySQL-5.0+ enables the use of cursors that allow Connector/J to save
+ memory by fetching result set rows in chunks (where the chunk size
+ is set by calling setFetchSize() on a Statement or ResultSet) by
+ using fully-materialized cursors on the server.
+ The driver will will now automatically set "useServerPrepStmts" to
+ "true" when "useCursorFetch" has been set to "true", since the feature
+ requires server-side prepared statements in order to function.
+
+ - Fixed BUG#28469 - PreparedStatement.getMetaData() for statements
+ containing leading one-line comments is not returned correctly.
+
+ As part of this fix, we also overhauled detection of DML for
+ executeQuery() and SELECTs for executeUpdate() in plain and
+ prepared statements to be aware of the same types of comments.
+
05-15-07 - Version 5.0.6
- Fixed BUG#25545 - Client options not sent correctly when using SSL,
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2007-05-16
03:31:15 UTC (rev 6429)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -186,17 +186,8 @@
// skip comments at the beginning of statements, as frameworks
// such as Hibernate use them to aid in debugging
- if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) {
- statementStartPos = sql.indexOf("*/");
-
- if (statementStartPos == -1) {
- statementStartPos = 0;
- } else {
- statementStartPos += 2;
- }
- }
+ statementStartPos = findStartOfStatement(sql);
-
for (i = statementStartPos; i < this.statementLength; ++i) {
char c = sql.charAt(i);
@@ -1516,8 +1507,7 @@
}
if ((this.firstCharOfStmt == 'S')
- && StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
- "SELECT")) { //$NON-NLS-1$
+ && isSelectQuery()) { //$NON-NLS-1$
throw SQLError.createSQLException(Messages.getString("PreparedStatement.37"),
//$NON-NLS-1$
"01S03"); //$NON-NLS-1$
}
@@ -1948,8 +1938,18 @@
public java.sql.ResultSetMetaData getMetaData()
throws SQLException {
- if (!StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(
- this.originalSql, "SELECT")) {
+ //
+ // We could just tack on a LIMIT 0 here no matter what the
+ // statement, and check if a result set was returned or not,
+ // but I'm not comfortable with that, myself, so we take
+ // the "safer" road, and only allow metadata for _actual_
+ // SELECTS (but not SHOWs).
+ //
+ // CALL's are trapped further up and you end up with a
+ // CallableStatement anyway.
+ //
+
+ if (!isSelectQuery()) {
return null;
}
@@ -2012,6 +2012,13 @@
return this.pstmtResultMetaData;
}
+ protected boolean isSelectQuery() {
+ return StringUtils.startsWithIgnoreCaseAndWs(
+ StringUtils.stripComments(this.originalSql,
+ "'\"", "'\"", true, false, true, true),
+ "SELECT");
+ }
+
/**
* @see PreparedStatement#getParameterMetaData()
*/
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java 2007-05-16 03:31:15
UTC (rev 6429)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java 2007-05-16 21:33:00
UTC (rev 6430)
@@ -400,12 +400,15 @@
if ((firstStatementChar == 'I') || (firstStatementChar == 'U')
|| (firstStatementChar == 'D') || (firstStatementChar == 'A')
|| (firstStatementChar == 'C')) {
- if (StringUtils.startsWithIgnoreCaseAndWs(sql, "INSERT") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "UPDATE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "DELETE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "DROP") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "CREATE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "ALTER")) { //$NON-NLS-1$
+ String noCommentSql = StringUtils.stripComments(sql,
+ "'\"", "'\"", true, false, true, true);
+
+ if (StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "INSERT") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "UPDATE") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DELETE") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DROP") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "CREATE") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "ALTER")) { //$NON-NLS-1$
throw SQLError.createSQLException(Messages
.getString("Statement.57"), //$NON-NLS-1$
SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
@@ -1106,7 +1109,8 @@
}
}
- char firstStatementChar = StringUtils.firstNonWsCharUc(sql);
+ char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
+ findStartOfStatement(sql));
checkForDml(sql, firstStatementChar);
@@ -1272,7 +1276,8 @@
Connection locallyScopedConn = this.connection;
- char firstStatementChar = StringUtils.firstNonWsCharUc(sql);
+ char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
+ findStartOfStatement(sql));
ResultSet rs = null;
@@ -2280,4 +2285,31 @@
&& this.resultSetConcurrency == ResultSet.CONCUR_READ_ONLY
&& this.resultSetType == ResultSet.TYPE_FORWARD_ONLY;
}
+
+ protected int findStartOfStatement(String sql) {
+ int statementStartPos = 0;
+
+ if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) {
+ statementStartPos = sql.indexOf("*/");
+
+ if (statementStartPos == -1) {
+ statementStartPos = 0;
+ } else {
+ statementStartPos += 2;
+ }
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "--")
+ || StringUtils.startsWithIgnoreCaseAndWs(sql, "#")) {
+ statementStartPos = sql.indexOf('\n');
+
+ if (statementStartPos == -1) {
+ statementStartPos = sql.indexOf('\r');
+
+ if (statementStartPos == -1) {
+ statementStartPos = 0;
+ }
+ }
+ }
+
+ return statementStartPos;
+ }
}
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java 2007-05-16
03:31:15 UTC (rev 6429)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -316,13 +316,17 @@
* @return the first non-whitespace character, upper cased.
*/
public static char firstNonWsCharUc(String searchIn) {
+ return firstNonWsCharUc(searchIn, 0);
+ }
+
+ public static char firstNonWsCharUc(String searchIn, int startAt) {
if (searchIn == null) {
return 0;
}
int length = searchIn.length();
- for (int i = 0; i < length; i++) {
+ for (int i = startAt; i < length; i++) {
char c = searchIn.charAt(i);
if (!Character.isWhitespace(c)) {
Modified:
branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java
===================================================================
---
branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java 2007-05-16
03:31:15 UTC (rev 6429)
+++
branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -3981,4 +3981,75 @@
}
}
}
+
+ /**
+ * Tests fix for BUG#28469 - PreparedStatement.getMetaData()
+ * for statements containing leading one-line comments
+ * is not returned correctly.
+ *
+ * As part of this fix, we also overhauled detection of
+ * DML for executeQuery() and SELECTs for executeUpdate() in
+ * plain and prepared statements to be aware of the same
+ * types of comments.
+ *
+ * @throws Exception
+ */
+ public void testBug28469() throws Exception {
+ PreparedStatement commentStmt = null;
+
+ try {
+ String[] statementsToTest = {"-- COMMENT\nSELECT 1",
+ "# COMMENT\nSELECT 1",
+ "/* comment */ SELECT 1"};
+
+ for (int i = 0; i < statementsToTest.length; i++) {
+ commentStmt = this.conn.prepareStatement(statementsToTest[i]);
+
+ assertNotNull(commentStmt.getMetaData());
+
+ try {
+ commentStmt.executeUpdate();
+ fail("Should not be able to call executeUpdate() on a SELECT statement!");
+ } catch (SQLException sqlEx) {
+ // expected
+ }
+
+ this.rs = commentStmt.executeQuery();
+ this.rs.next();
+ assertEquals(1, this.rs.getInt(1));
+ }
+
+ createTable("testBug28469", "(field1 INT)");
+
+ String[] updatesToTest = {"-- COMMENT\nUPDATE testBug28469 SET field1 = 2",
+ "# COMMENT\nUPDATE testBug28469 SET field1 = 2",
+ "/* comment */ UPDATE testBug28469 SET field1 = 2"};
+
+ for (int i = 0; i < updatesToTest.length; i++) {
+ commentStmt = this.conn.prepareStatement(updatesToTest[i]);
+
+ assertNull(commentStmt.getMetaData());
+
+ try {
+ commentStmt.executeQuery();
+ fail("Should not be able to call executeQuery() on a SELECT statement!");
+ } catch (SQLException sqlEx) {
+ // expected
+ }
+
+ try {
+ this.stmt.executeQuery(updatesToTest[i]);
+ fail("Should not be able to call executeQuery() on a SELECT statement!");
+ } catch (SQLException sqlEx) {
+ // expected
+ }
+ }
+ } finally {
+ closeMemberJDBCResources();
+
+ if (commentStmt != null) {
+ commentStmt.close();
+ }
+ }
+ }
}
\ No newline at end of file
Modified: branches/branch_5_1/connector-j/CHANGES
===================================================================
--- branches/branch_5_1/connector-j/CHANGES 2007-05-16 03:31:15 UTC (rev 6429)
+++ branches/branch_5_1/connector-j/CHANGES 2007-05-16 21:33:00 UTC (rev 6430)
@@ -82,14 +82,23 @@
nn-nn-07 - Version 5.0.7
- - The configuration "useCursorFetch" (for MySQL-5.0+, which enables
- the use of cursors that allow Connector/J to save memory by fetching
- result set rows in chunks, set by Statement.setFetchSize() by using
- fully-materialized cursors on the server) will now automatically
- set "useServerPrepStmts" to "true" when it has been set to "true",
- since it requires server-side prepared statements in order to
- function correctly.
-
+ - Setting the configuration parameter "useCursorFetch" to "true" for
+ MySQL-5.0+ enables the use of cursors that allow Connector/J to save
+ memory by fetching result set rows in chunks (where the chunk size
+ is set by calling setFetchSize() on a Statement or ResultSet) by
+ using fully-materialized cursors on the server.
+
+ The driver will will now automatically set "useServerPrepStmts" to
+ "true" when "useCursorFetch" has been set to "true", since the feature
+ requires server-side prepared statements in order to function.
+
+ - Fixed BUG#28469 - PreparedStatement.getMetaData() for statements
+ containing leading one-line comments is not returned correctly.
+
+ As part of this fix, we also overhauled detection of DML for
+ executeQuery() and SELECTs for executeUpdate() in plain and
+ prepared statements to be aware of the same types of comments.
+
05-15-07 - Version 5.0.6
- Fixed BUG#25545 - Client options not sent correctly when using SSL,
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2007-05-16
03:31:15 UTC (rev 6429)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -225,17 +225,8 @@
// skip comments at the beginning of statements, as frameworks
// such as Hibernate use them to aid in debugging
- if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) {
- statementStartPos = sql.indexOf("*/");
-
- if (statementStartPos == -1) {
- statementStartPos = 0;
- } else {
- statementStartPos += 2;
- }
- }
+ statementStartPos = findStartOfStatement(sql);
-
for (i = statementStartPos; i < this.statementLength; ++i) {
char c = sql.charAt(i);
@@ -1644,8 +1635,7 @@
}
if ((this.firstCharOfStmt == 'S')
- && StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
- "SELECT")) { //$NON-NLS-1$
+ && isSelectQuery()) { //$NON-NLS-1$
throw SQLError.createSQLException(Messages.getString("PreparedStatement.37"),
//$NON-NLS-1$
"01S03"); //$NON-NLS-1$
}
@@ -2100,8 +2090,18 @@
public java.sql.ResultSetMetaData getMetaData()
throws SQLException {
- if (!StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(
- this.originalSql, "SELECT")) {
+ //
+ // We could just tack on a LIMIT 0 here no matter what the
+ // statement, and check if a result set was returned or not,
+ // but I'm not comfortable with that, myself, so we take
+ // the "safer" road, and only allow metadata for _actual_
+ // SELECTS (but not SHOWs).
+ //
+ // CALL's are trapped further up and you end up with a
+ // CallableStatement anyway.
+ //
+
+ if (!isSelectQuery()) {
return null;
}
@@ -2164,6 +2164,13 @@
return this.pstmtResultMetaData;
}
+ protected boolean isSelectQuery() {
+ return StringUtils.startsWithIgnoreCaseAndWs(
+ StringUtils.stripComments(this.originalSql,
+ "'\"", "'\"", true, false, true, true),
+ "SELECT");
+ }
+
/**
* @see PreparedStatement#getParameterMetaData()
*/
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java 2007-05-16
03:31:15 UTC (rev 6429)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -389,12 +389,15 @@
if ((firstStatementChar == 'I') || (firstStatementChar == 'U')
|| (firstStatementChar == 'D') || (firstStatementChar == 'A')
|| (firstStatementChar == 'C')) {
- if (StringUtils.startsWithIgnoreCaseAndWs(sql, "INSERT") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "UPDATE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "DELETE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "DROP") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "CREATE") //$NON-NLS-1$
- || StringUtils.startsWithIgnoreCaseAndWs(sql, "ALTER")) { //$NON-NLS-1$
+ String noCommentSql = StringUtils.stripComments(sql,
+ "'\"", "'\"", true, false, true, true);
+
+ if (StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "INSERT") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "UPDATE") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DELETE") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "DROP") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "CREATE") //$NON-NLS-1$
+ || StringUtils.startsWithIgnoreCaseAndWs(noCommentSql, "ALTER")) { //$NON-NLS-1$
throw SQLError.createSQLException(Messages
.getString("Statement.57"), //$NON-NLS-1$
SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
@@ -1141,7 +1144,8 @@
}
}
- char firstStatementChar = StringUtils.firstNonWsCharUc(sql);
+ char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
+ findStartOfStatement(sql));
checkForDml(sql, firstStatementChar);
@@ -1307,7 +1311,8 @@
ConnectionImpl locallyScopedConn = this.connection;
- char firstStatementChar = StringUtils.firstNonWsCharUc(sql);
+ char firstStatementChar = StringUtils.firstNonWsCharUc(sql,
+ findStartOfStatement(sql));
ResultSet rs = null;
@@ -2374,4 +2379,31 @@
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
+
+ protected int findStartOfStatement(String sql) {
+ int statementStartPos = 0;
+
+ if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) {
+ statementStartPos = sql.indexOf("*/");
+
+ if (statementStartPos == -1) {
+ statementStartPos = 0;
+ } else {
+ statementStartPos += 2;
+ }
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "--")
+ || StringUtils.startsWithIgnoreCaseAndWs(sql, "#")) {
+ statementStartPos = sql.indexOf('\n');
+
+ if (statementStartPos == -1) {
+ statementStartPos = sql.indexOf('\r');
+
+ if (statementStartPos == -1) {
+ statementStartPos = 0;
+ }
+ }
+ }
+
+ return statementStartPos;
+ }
}
Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/StringUtils.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/StringUtils.java 2007-05-16
03:31:15 UTC (rev 6429)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/StringUtils.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -320,13 +320,17 @@
* @return the first non-whitespace character, upper cased.
*/
public static char firstNonWsCharUc(String searchIn) {
+ return firstNonWsCharUc(searchIn, 0);
+ }
+
+ public static char firstNonWsCharUc(String searchIn, int startAt) {
if (searchIn == null) {
return 0;
}
int length = searchIn.length();
- for (int i = 0; i < length; i++) {
+ for (int i = startAt; i < length; i++) {
char c = searchIn.charAt(i);
if (!Character.isWhitespace(c)) {
Modified:
branches/branch_5_1/connector-j/src/testsuite/regression/StatementRegressionTest.java
===================================================================
---
branches/branch_5_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 2007-05-16
03:31:15 UTC (rev 6429)
+++
branches/branch_5_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 2007-05-16
21:33:00 UTC (rev 6430)
@@ -3976,4 +3976,75 @@
}
}
}
+
+ /**
+ * Tests fix for BUG#28469 - PreparedStatement.getMetaData()
+ * for statements containing leading one-line comments
+ * is not returned correctly.
+ *
+ * As part of this fix, we also overhauled detection of
+ * DML for executeQuery() and SELECTs for executeUpdate() in
+ * plain and prepared statements to be aware of the same
+ * types of comments.
+ *
+ * @throws Exception
+ */
+ public void testBug28469() throws Exception {
+ PreparedStatement commentStmt = null;
+
+ try {
+ String[] statementsToTest = {"-- COMMENT\nSELECT 1",
+ "# COMMENT\nSELECT 1",
+ "/* comment */ SELECT 1"};
+
+ for (int i = 0; i < statementsToTest.length; i++) {
+ commentStmt = this.conn.prepareStatement(statementsToTest[i]);
+
+ assertNotNull(commentStmt.getMetaData());
+
+ try {
+ commentStmt.executeUpdate();
+ fail("Should not be able to call executeUpdate() on a SELECT statement!");
+ } catch (SQLException sqlEx) {
+ // expected
+ }
+
+ this.rs = commentStmt.executeQuery();
+ this.rs.next();
+ assertEquals(1, this.rs.getInt(1));
+ }
+
+ createTable("testBug28469", "(field1 INT)");
+
+ String[] updatesToTest = {"-- COMMENT\nUPDATE testBug28469 SET field1 = 2",
+ "# COMMENT\nUPDATE testBug28469 SET field1 = 2",
+ "/* comment */ UPDATE testBug28469 SET field1 = 2"};
+
+ for (int i = 0; i < updatesToTest.length; i++) {
+ commentStmt = this.conn.prepareStatement(updatesToTest[i]);
+
+ assertNull(commentStmt.getMetaData());
+
+ try {
+ commentStmt.executeQuery();
+ fail("Should not be able to call executeQuery() on a SELECT statement!");
+ } catch (SQLException sqlEx) {
+ // expected
+ }
+
+ try {
+ this.stmt.executeQuery(updatesToTest[i]);
+ fail("Should not be able to call executeQuery() on a SELECT statement!");
+ } catch (SQLException sqlEx) {
+ // expected
+ }
+ }
+ } finally {
+ closeMemberJDBCResources();
+
+ if (commentStmt != null) {
+ commentStmt.close();
+ }
+ }
+ }
}
| Thread |
|---|
| • Connector/J commit: r6430 - in branches: branch_5_0/connector-j branch_5_0/connector-j/src/com/mysql/jdbc branch_5_0/connector-j/src/testsuite/regress... | mmatthews | 16 May |