Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 81233 invoked from network); 17 Jan 2011 16:53:41 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 17 Jan 2011 16:53:41 -0000 Received: (qmail 35497 invoked by uid 500); 17 Jan 2011 16:53:40 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 35432 invoked by uid 500); 17 Jan 2011 16:53:38 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 35425 invoked by uid 99); 17 Jan 2011 16:53:38 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 17 Jan 2011 16:53:38 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 17 Jan 2011 16:53:36 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 9E77A23889E0; Mon, 17 Jan 2011 16:53:10 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1059984 - in /db/derby/code/branches/10.7: ./ java/client/org/apache/derby/client/am/ java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/ Date: Mon, 17 Jan 2011 16:53:10 -0000 To: derby-commits@db.apache.org From: kahatlen@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110117165310.9E77A23889E0@eris.apache.org> Author: kahatlen Date: Mon Jan 17 16:53:10 2011 New Revision: 1059984 URL: http://svn.apache.org/viewvc?rev=1059984&view=rev Log: DERBY-4964: Client driver fails to convert string to boolean with setObject(col, str, Types.BIT) Merged revision 1059888 from trunk. Modified: db/derby/code/branches/10.7/ (props changed) db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/CrossConverters.java db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/Types.java db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java Propchange: db/derby/code/branches/10.7/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Mon Jan 17 16:53:10 2011 @@ -1 +1 @@ -/db/derby/code/trunk:1035603,1036769,1038514,1038813,1039084,1039268,1040658,1041338,1043227,1043389,1044096,1051026,1053724,1055169 +/db/derby/code/trunk:1035603,1036769,1038514,1038813,1039084,1039268,1040658,1041338,1043227,1043389,1044096,1051026,1053724,1055169,1059888 Modified: db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/CrossConverters.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/CrossConverters.java?rev=1059984&r1=1059983&r2=1059984&view=diff ============================================================================== --- db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/CrossConverters.java (original) +++ db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/CrossConverters.java Mon Jan 17 16:53:10 2011 @@ -25,6 +25,7 @@ import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; +import java.util.Locale; import org.apache.derby.shared.common.reference.SQLState; // All currently supported derby types are mapped to one of the following jdbc types: @@ -113,6 +114,10 @@ final class CrossConverters { // In support of PS.setShort() final Object setObject(int targetType, short source) throws SqlException { switch (targetType) { + case Types.BIT: + case Types.BOOLEAN: + return Boolean.valueOf(source != 0); + case Types.SMALLINT: return new Short(source); @@ -147,6 +152,10 @@ final class CrossConverters { // In support of PS.setInt() final Object setObject(int targetType, int source) throws SqlException { switch (targetType) { + case Types.BIT: + case Types.BOOLEAN: + return Boolean.valueOf(source != 0); + case Types.SMALLINT: if (Configuration.rangeCheckCrossConverters && (source > Short.MAX_VALUE || source < Short.MIN_VALUE)) { @@ -237,6 +246,10 @@ final class CrossConverters { // In support of PS.setLong() final Object setObject(int targetType, long source) throws SqlException { switch (targetType) { + case Types.BIT: + case Types.BOOLEAN: + return Boolean.valueOf(source != 0); + case Types.SMALLINT: if (Configuration.rangeCheckCrossConverters && (source > Short.MAX_VALUE || source < Short.MIN_VALUE)) { @@ -279,6 +292,10 @@ final class CrossConverters { // In support of PS.setFloat() final Object setObject(int targetType, float source) throws SqlException { switch (targetType) { + case Types.BIT: + case Types.BOOLEAN: + return Boolean.valueOf(source != 0); + case Types.SMALLINT: if (Configuration.rangeCheckCrossConverters && (source > Short.MAX_VALUE || source < Short.MIN_VALUE)) { @@ -354,6 +371,10 @@ final class CrossConverters { // In support of PS.setDouble() final Object setObject(int targetType, double source) throws SqlException { switch (targetType) { + case Types.BIT: + case Types.BOOLEAN: + return Boolean.valueOf(source != 0); + case Types.SMALLINT: if (Configuration.rangeCheckCrossConverters && (source > Short.MAX_VALUE || source < Short.MIN_VALUE)) { @@ -417,6 +438,11 @@ final class CrossConverters { // In support of PS.setBigDecimal() final Object setObject(int targetType, java.math.BigDecimal source) throws SqlException { switch (targetType) { + case Types.BIT: + case Types.BOOLEAN: + return Boolean.valueOf( + java.math.BigDecimal.valueOf(0L).compareTo(source) != 0); + case Types.SMALLINT: if (Configuration.rangeCheckCrossConverters && (source.compareTo(bdMaxShortValue__) == 1 || source.compareTo(bdMinShortValue__) == -1)) { @@ -543,6 +569,23 @@ final class CrossConverters { final Object setObject(int targetDriverType, String source) throws SqlException { try { switch (targetDriverType) { + case Types.BIT: + case Types.BOOLEAN: + { + String cleanSource = source.trim().toUpperCase(Locale.ENGLISH); + if (cleanSource.equals("UNKNOWN")) { + return null; + } else if (cleanSource.equals("TRUE")) { + return Boolean.TRUE; + } else if (cleanSource.equals("FALSE")) { + return Boolean.FALSE; + } else { + throw new SqlException(agent_.logWriter_, + new ClientMessageId(SQLState.LANG_FORMAT_EXCEPTION), + Types.getTypeString(targetDriverType)); + } + } + case Types.SMALLINT: return Short.valueOf(source); @@ -604,8 +647,6 @@ final class CrossConverters { */ public static int getInputJdbcType(int jdbcType) { switch (jdbcType) { - case java.sql.Types.BIT: - case java.sql.Types.BOOLEAN: case java.sql.Types.TINYINT: case java.sql.Types.SMALLINT: return java.sql.Types.INTEGER; Modified: db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/Types.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/Types.java?rev=1059984&r1=1059983&r2=1059984&view=diff ============================================================================== --- db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/Types.java (original) +++ db/derby/code/branches/10.7/java/client/org/apache/derby/client/am/Types.java Mon Jan 17 16:53:10 2011 @@ -29,8 +29,7 @@ import org.apache.derby.iapi.reference.J public class Types { // -------------------------------- Driver types ------------------------------------------------- - // Not currently supported as a DERBY column type. Mapped to SMALLINT. - // public final static int BIT = java.sql.Types.BIT; // -7; + public final static int BIT = java.sql.Types.BIT; // -7; // Not currently supported as a DERBY column type. Mapped to SMALLINT. //public final static int TINYINT = java.sql.Types.TINYINT; // -6; @@ -90,6 +89,7 @@ public class Types { case BIGINT: return "BIGINT"; case BINARY: return "BINARY"; case BLOB: return "BLOB"; + case BIT: case BOOLEAN: return "BOOLEAN"; case CHAR: return "CHAR"; case CLOB: return "CLOB"; Modified: db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java?rev=1059984&r1=1059983&r2=1059984&view=diff ============================================================================== --- db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java (original) +++ db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/ParameterMappingTest.java Mon Jan 17 16:53:10 2011 @@ -3123,52 +3123,81 @@ public class ParameterMappingTest extend } } + /** + * Do the {@code setObject()} tests for {@code setXXX()}. Test both for + * the two-argument {@code setObject(int,Object)} method and the + * three-argument {@code setObject(int,Object,int)} method. + */ private static void setXXX_setObject(Statement s, PreparedStatement psi, PreparedStatement psq, int type, Object value, String className, int b5o) throws SQLException, java.io.IOException { - { - s.execute("DELETE FROM PM.TYPE_AS"); - SQLException sqleResult = null; - boolean worked; - try { - // setObject(" + className + ") + // Test setObject(int, Object) + setXXX_setObject_doWork( + s, psi, psq, type, value, className, b5o, false, false); + + // Test setObject(int, Object) with batch execution + setXXX_setObject_doWork( + s, psi, psq, type, value, className, b5o, false, true); + + // Test setObject(int, Object, int) + setXXX_setObject_doWork( + s, psi, psq, type, value, className, b5o, true, false); + + // Test setObject(int, Object, int) with batch execution + setXXX_setObject_doWork( + s, psi, psq, type, value, className, b5o, true, true); + + } + + /** + * Helper method that does all the work for setXXX_setObject(). + * + * @param withTypeFlag if true, use the setObject() method that takes a + * type parameter; otherwise, use the two-argument type-less setObject() + * method + * @param batchExecution if true, do batch execution; otherwise, do + * normal execution + */ + private static void setXXX_setObject_doWork( + Statement s, PreparedStatement psi, PreparedStatement psq, + int type, Object value, String className, int b5o, + boolean withTypeFlag, boolean batchExecution) + throws SQLException, IOException + { + int jdbcType = jdbcTypes[type]; + String method = "setObject(" + className + ")"; + + s.execute("DELETE FROM PM.TYPE_AS"); + + SQLException sqleResult = null; + boolean worked; + try { + // Set the parameter value, either with or without explicit type + if (withTypeFlag) { + psi.setObject(1, value, jdbcType); + } else { psi.setObject(1, value); - psi.executeUpdate(); - getValidValue(psq, jdbcTypes[type], "setObject(" + className - + ")"); - worked = true; - - } catch (SQLException sqle) { - sqleResult = sqle; - worked = false; } - judge_setObject(worked, sqleResult, b5o, type); - } - { - s.execute("DELETE FROM PM.TYPE_AS"); - SQLException sqleResult = null; - boolean worked; - try { - // setObject(" + className + ") as batch - psi.setObject(1, value); + // Execute the statement, either single execution or batch + if (batchExecution) { psi.addBatch(); psi.executeBatch(); - getValidValue(psq, jdbcTypes[type], "setObject(" + className - + ")"); - - worked = true; - - } catch (SQLException sqle) { - sqleResult = sqle; - worked = false; - } catch (Throwable t) { - fail("FAIL " + t.getMessage()); - return; + } else { + psi.executeUpdate(); } - judge_setObject(worked, sqleResult, b5o, type); + + // Check if we got a valid value back + getValidValue(psq, jdbcType, method); + worked = true; + } catch (SQLException sqle) { + sqleResult = sqle; + worked = false; } + + // Check if the we got the correct response + judge_setObject(worked, sqleResult, b5o, type); } /** Modified: db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java?rev=1059984&r1=1059983&r2=1059984&view=diff ============================================================================== --- db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java (original) +++ db/derby/code/branches/10.7/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java Mon Jan 17 16:53:10 2011 @@ -1655,6 +1655,101 @@ public class BooleanValuesTest extends } + /** + * Verify fix for DERBY-4964 - failure to convert string to boolean with + * the client driver. + */ + public void test_4964() throws SQLException { + PreparedStatement ps = prepareStatement("values cast(? as boolean)"); + + // These should work + test_4964_minion(ps, null, null); + test_4964_minion(ps, "unknown", null); + test_4964_minion(ps, "UNKNOWN", null); + test_4964_minion(ps, "unKnoWn", null); + test_4964_minion(ps, " unknown ", null); + test_4964_minion(ps, "true", Boolean.TRUE); + test_4964_minion(ps, "TRUE", Boolean.TRUE); + test_4964_minion(ps, "TrUe", Boolean.TRUE); + test_4964_minion(ps, " true ", Boolean.TRUE); + test_4964_minion(ps, "false", Boolean.FALSE); + test_4964_minion(ps, "FALSE", Boolean.FALSE); + test_4964_minion(ps, "FaLsE", Boolean.FALSE); + test_4964_minion(ps, "FaLsE", Boolean.FALSE); + test_4964_minion(ps, " false ", Boolean.FALSE); + + // These should fail + test_4964_minion(ps, "0", BAD_CAST); + test_4964_minion(ps, "1", BAD_CAST); + test_4964_minion(ps, "2", BAD_CAST); + test_4964_minion(ps, "null", BAD_CAST); + test_4964_minion(ps, "true true", BAD_CAST); + test_4964_minion(ps, "false false", BAD_CAST); + } + + /** + * Set a boolean parameter using a string value and verify that we get + * the expected result. + * + * @param ps a prepared statement that takes a boolean parameter + * @param input input string for the parameter + * @param expectedValue the expected result; either the expected Boolean return + * value if the operation is expected to succeed, or the SQLState of the + * exception if it is expected to fail + */ + private void test_4964_minion( + PreparedStatement ps, String input, Object expectedValue) + throws SQLException + { + // If the expected value is a string, it denotes the SQLState of an + // expected failure + boolean shouldFail = expectedValue instanceof String; + + Object[][] rows = { { expectedValue } }; + + // test setString(int, String) + try { + ps.setString(1, input); + JDBC.assertFullResultSet(ps.executeQuery(), rows, false); + assertFalse(shouldFail); + } catch (SQLException sqle) { + if (shouldFail) { + assertSQLState((String) expectedValue, sqle); + } else { + throw sqle; + } + } + + // test setObject(int, Object) + try { + ps.setObject(1, input); + JDBC.assertFullResultSet(ps.executeQuery(), rows, false); + assertFalse(shouldFail); + } catch (SQLException sqle) { + if (shouldFail) { + assertSQLState((String) expectedValue, sqle); + } else { + throw sqle; + } + } + + // test setObject(int, Object, int) with various target types + int[] types = { Types.BIT, Types.BOOLEAN, Types.CHAR, Types.VARCHAR }; + for (int i = 0; i < types.length; i++) { + try { + ps.setObject(1, input, types[i]); + JDBC.assertFullResultSet(ps.executeQuery(), rows, false); + assertFalse(shouldFail); + } catch (SQLException sqle) { + if (shouldFail) { + assertSQLState((String) expectedValue, sqle); + } else { + throw sqle; + } + } + } + } + /////////////////////////////////////////////////////////////////////////////////// // // SQL ROUTINES