From: Date: September 26 2006 9:22pm Subject: Connector/J commit: r5771 - branches/branch_5_0/connector-j branches/branch_5_0/connector-j/src/com/mysql/jdbc branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional branches/branch_5_0/connector-j/src/testsuite/regression trunk/connector-j trunk/connector-j/src/com/mysql/jdbc trunk/connector-j/src/testsuite/regression List-Archive: http://lists.mysql.com/commits/12565 X-Bug: 22290 Message-Id: <200609261922.k8QJMEnj001332@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/.MysqlConnectionPoolDataSource.java.swp Modified: 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/com/mysql/jdbc/ServerPreparedStatement.java branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java trunk/connector-j/CHANGES trunk/connector-j/src/com/mysql/jdbc/Connection.java trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java Log: 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). Modified: branches/branch_5_0/connector-j/CHANGES =================================================================== --- branches/branch_5_0/connector-j/CHANGES 2006-09-26 00:01:23 UTC (rev 5770) +++ branches/branch_5_0/connector-j/CHANGES 2006-09-26 19:22:11 UTC (rev 5771) @@ -37,6 +37,10 @@ - Added new _ci collations to CharsetMapping, fixing Bug#22456 - utf8_unicode_ci not working. + - 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). + 07-26-06 - Version 5.0.3 - Fixed BUG#20650 - Statement.cancel() causes NullPointerException @@ -256,6 +260,10 @@ - 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 + it shouldn't (due to sending big decimal incorrectly to server with + server-side prepared statement). 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-09-26 00:01:23 UTC (rev 5770) +++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java 2006-09-26 19:22:11 UTC (rev 5771) @@ -4109,12 +4109,14 @@ private void setupServerForTruncationChecks() throws SQLException { if (getJdbcCompliantTruncation()) { if (versionMeetsMinimum(5, 0, 2)) { + String currentSqlMode = (String)this.serverVariables.get("sql_mode"); + boolean strictTransTablesIsSet = StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") != -1; + if (currentSqlMode == null || - currentSqlMode.length() == 0 || - StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") == -1) { + currentSqlMode.length() == 0 || !strictTransTablesIsSet) { StringBuffer commandBuf = new StringBuffer("SET sql_mode='"); if (currentSqlMode != null && currentSqlMode.length() > 0) { @@ -4130,6 +4132,9 @@ this.database, true, false); setJdbcCompliantTruncation(false); // server's handling this for us now + } else if (strictTransTablesIsSet) { + // We didn't set it, but someone did, so we piggy back on it + setJdbcCompliantTruncation(false); // server's handling this for us now } } @@ -5459,13 +5464,27 @@ } /** - * DOCUMENT ME! - * - * @param level - * DOCUMENT ME! - * @throws SQLException - * DOCUMENT ME! - */ + * Attempts to change the transaction isolation level for this + * Connection object to the one given. + * The constants defined in the interface Connection + * are the possible transaction isolation levels. + *

+ * Note: If this method is called during a transaction, the result + * is implementation-defined. + * + * @param level one of the following Connection constants: + * Connection.TRANSACTION_READ_UNCOMMITTED, + * Connection.TRANSACTION_READ_COMMITTED, + * Connection.TRANSACTION_REPEATABLE_READ, or + * Connection.TRANSACTION_SERIALIZABLE. + * (Note that Connection.TRANSACTION_NONE cannot be used + * because it specifies that transactions are not supported.) + * @exception SQLException if a database access error occurs + * or the given parameter is not one of the Connection + * constants + * @see DatabaseMetaData#supportsTransactionIsolationLevel + * @see #getTransactionIsolation + */ public synchronized void setTransactionIsolation(int level) throws SQLException { checkClosed(); Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java =================================================================== --- branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java 2006-09-26 00:01:23 UTC (rev 5770) +++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java 2006-09-26 19:22:11 UTC (rev 5771) @@ -1531,8 +1531,18 @@ if (x == null) { setNull(parameterIndex, java.sql.Types.DECIMAL); } else { - setString(parameterIndex, StringUtils.fixDecimalExponent(x - .toString())); + + BindValue binding = getBinding(parameterIndex, false); + + if (this.connection.versionMeetsMinimum(5, 0, 3)) { + setType(binding, MysqlDefs.FIELD_TYPE_NEW_DECIMAL); + } else { + setType(binding, this.stringTypeCode); + } + + binding.value = StringUtils.fixDecimalExponent(x.toString()); + binding.isNull = false; + binding.isLongData = false; } } @@ -2111,6 +2121,8 @@ case MysqlDefs.FIELD_TYPE_VAR_STRING: case MysqlDefs.FIELD_TYPE_STRING: case MysqlDefs.FIELD_TYPE_VARCHAR: + case MysqlDefs.FIELD_TYPE_DECIMAL: + case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: if (value instanceof byte[]) { packet.writeLenBytes((byte[]) value); } else if (!this.isLoadDataQuery) { Added: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/.MysqlConnectionPoolDataSource.java.swp =================================================================== (Binary files differ) Property changes on: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/.MysqlConnectionPoolDataSource.java.swp ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java =================================================================== --- branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-09-26 00:01:23 UTC (rev 5770) +++ branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-09-26 19:22:11 UTC (rev 5771) @@ -3431,4 +3431,54 @@ } } } + + /** + * Tests fix for 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). + * + * @throws Exception if the test fails. + */ + public void testBug22290() throws Exception { + if (!versionMeetsMinimum(5, 0)) { + return; + } + + createTable( + "testbug22290", + "(`id` int(11) NOT NULL default '1',`cost` decimal(10,2) NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8"); + assertEquals( + this.stmt + .executeUpdate("INSERT INTO testbug22290 (`id`,`cost`) VALUES (1,'1.00')"), + 1); + + Connection configuredConn = null; + + try { + Properties props = new Properties(); + props.setProperty("sessionVariables", "sql_mode='STRICT_TRANS_TABLES'"); + + + configuredConn = getConnectionWithProps(props); + + this.pstmt = configuredConn + .prepareStatement("update testbug22290 set cost = cost + ? where id = 1"); + this.pstmt.setBigDecimal(1, new BigDecimal("1.11")); + assertEquals(this.pstmt.executeUpdate(), 1); + + assertEquals(this.stmt + .executeUpdate("UPDATE testbug22290 SET cost='1.00'"), 1); + this.pstmt = ((com.mysql.jdbc.Connection)configuredConn) + .clientPrepareStatement("update testbug22290 set cost = cost + ? where id = 1"); + this.pstmt.setBigDecimal(1, new BigDecimal("1.11")); + assertEquals(this.pstmt.executeUpdate(), 1); + } finally { + closeMemberJDBCResources(); + + if (configuredConn != null) { + configuredConn.close(); + } + } + } + } Modified: trunk/connector-j/CHANGES =================================================================== --- trunk/connector-j/CHANGES 2006-09-26 00:01:23 UTC (rev 5770) +++ trunk/connector-j/CHANGES 2006-09-26 19:22:11 UTC (rev 5771) @@ -36,7 +36,11 @@ - Added new _ci collations to CharsetMapping, fixing Bug#22456 - utf8_unicode_ci not working. - + + - 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). + 07-26-06 - Version 5.0.3 - Fixed BUG#20650 - Statement.cancel() causes NullPointerException @@ -257,6 +261,10 @@ 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 + it shouldn't (due to sending big decimal incorrectly to server with + server-side prepared statement). + 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-09-26 00:01:23 UTC (rev 5770) +++ trunk/connector-j/src/com/mysql/jdbc/Connection.java 2006-09-26 19:22:11 UTC (rev 5771) @@ -3241,9 +3241,10 @@ String currentSqlMode = (String)this.serverVariables.get("sql_mode"); + boolean strictTransTablesIsSet = StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") != -1; + if (currentSqlMode == null || - currentSqlMode.length() == 0 || - StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") == -1) { + currentSqlMode.length() == 0 || !strictTransTablesIsSet) { StringBuffer commandBuf = new StringBuffer("SET sql_mode='"); if (currentSqlMode != null && currentSqlMode.length() > 0) { @@ -3259,6 +3260,9 @@ this.database, true, false); setJdbcCompliantTruncation(false); // server's handling this for us now + } else if (strictTransTablesIsSet) { + // We didn't set it, but someone did, so we piggy back on it + setJdbcCompliantTruncation(false); // server's handling this for us now } } Modified: trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java =================================================================== --- trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java 2006-09-26 00:01:23 UTC (rev 5770) +++ trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java 2006-09-26 19:22:11 UTC (rev 5771) @@ -1528,8 +1528,18 @@ if (x == null) { setNull(parameterIndex, java.sql.Types.DECIMAL); } else { - setString(parameterIndex, StringUtils.fixDecimalExponent(x - .toString())); + + BindValue binding = getBinding(parameterIndex, false); + + if (this.connection.versionMeetsMinimum(5, 0, 3)) { + setType(binding, MysqlDefs.FIELD_TYPE_NEW_DECIMAL); + } else { + setType(binding, this.stringTypeCode); + } + + binding.value = StringUtils.fixDecimalExponent(x.toString()); + binding.isNull = false; + binding.isLongData = false; } } @@ -2108,6 +2118,8 @@ case MysqlDefs.FIELD_TYPE_VAR_STRING: case MysqlDefs.FIELD_TYPE_STRING: case MysqlDefs.FIELD_TYPE_VARCHAR: + case MysqlDefs.FIELD_TYPE_DECIMAL: + case MysqlDefs.FIELD_TYPE_NEW_DECIMAL: if (value instanceof byte[]) { packet.writeLenBytes((byte[]) value); } else if (!this.isLoadDataQuery) { Modified: trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java =================================================================== --- trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-09-26 00:01:23 UTC (rev 5770) +++ trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-09-26 19:22:11 UTC (rev 5771) @@ -3435,4 +3435,53 @@ } } } + + /** + * Tests fix for 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). + * + * @throws Exception if the test fails. + */ + public void testBug22290() throws Exception { + if (!versionMeetsMinimum(5, 0)) { + return; + } + + createTable( + "testbug22290", + "(`id` int(11) NOT NULL default '1',`cost` decimal(10,2) NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8"); + assertEquals( + this.stmt + .executeUpdate("INSERT INTO testbug22290 (`id`,`cost`) VALUES (1,'1.00')"), + 1); + + Connection configuredConn = null; + + try { + Properties props = new Properties(); + props.setProperty("sessionVariables", "sql_mode='STRICT_TRANS_TABLES'"); + + + configuredConn = getConnectionWithProps(props); + + this.pstmt = configuredConn + .prepareStatement("update testbug22290 set cost = cost + ? where id = 1"); + this.pstmt.setBigDecimal(1, new BigDecimal("1.11")); + assertEquals(this.pstmt.executeUpdate(), 1); + + assertEquals(this.stmt + .executeUpdate("UPDATE testbug22290 SET cost='1.00'"), 1); + this.pstmt = ((com.mysql.jdbc.Connection)configuredConn) + .clientPrepareStatement("update testbug22290 set cost = cost + ? where id = 1"); + this.pstmt.setBigDecimal(1, new BigDecimal("1.11")); + assertEquals(this.pstmt.executeUpdate(), 1); + } finally { + closeMemberJDBCResources(); + + if (configuredConn != null) { + configuredConn.close(); + } + } + } }