From be29264276d30f0e8d420b577557210c3d6bad06 Mon Sep 17 00:00:00 2001 From: Afsaneh Rafighi Date: Wed, 16 Aug 2017 09:39:32 -0700 Subject: [PATCH 1/3] Fixed issue with throwing error message for unsupported datatype. Fixed issue with returning class type of time object in sql_variant --- src/main/java/com/microsoft/sqlserver/jdbc/DDC.java | 3 ++- .../microsoft/sqlserver/jdbc/SQLServerResource.java | 1 + src/main/java/com/microsoft/sqlserver/jdbc/dtv.java | 11 ++++++----- .../jdbc/datatypes/BulkCopyWithSqlVariantTest.java | 2 +- .../jdbc/datatypes/SQLVariantResultSetTest.java | 6 +++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java index 562b958c8..c42dae286 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java @@ -922,7 +922,8 @@ static final Object convertTemporalToObject(JDBCType jdbcType, } // Convert the calendar value (in local time) to the desired Java object type. switch (jdbcType.category) { - case BINARY: { + case BINARY: + case SQL_VARIANT: { switch (ssType) { case DATE: { // Per JDBC spec, the time part of java.sql.Date values is initialized to midnight diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 3945a2096..0bba07774 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -390,5 +390,6 @@ protected Object[][] getContents() { {"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."}, {"R_invalidStringValue", "SQL_VARIANT does not support string values more than 8000 length."}, {"R_invalidValueForTVPWithSQLVariant", "Inserting null value with column type sql_variant in TVP is not supported."}, + {"R_invalidDataTypeSupportForSQLVariant", "Unexpected TDS type ' '{0}' ' in SQL_VARIANT."}, }; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java b/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java index 5030c22c9..cdd89f1e8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/dtv.java @@ -4238,7 +4238,6 @@ else if (TDSType.NVARCHAR == baseType) MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidProbbytes")); throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null); } - jdbcType = JDBCType.CHAR; // The reason we use char is to return nanoseconds if (internalVariant.isBaseTypeTimeValue()) { jdbcType = JDBCType.TIMESTAMP; } @@ -4290,10 +4289,12 @@ else if (TDSType.BIGVARBINARY == baseType) convertedValue = tdsReader.readGUID(expectedValueLength, jdbcType, streamGetterArgs.streamType); break; - // Unknown SSType should have already been rejected by TypeInfo.setFromTDS() - default: - assert false : "Unexpected TDSType in Sql-Variant " + baseType; - break; + // Unsupported TdsType should throw error message + default: { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidDataTypeSupportForSQLVariant")); + throw new SQLServerException(form.format(new Object[] {baseType}), null, 0, null); + } + } return convertedValue; } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java index 2f2c4b9b7..2c4a41980 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BulkCopyWithSqlVariantTest.java @@ -617,7 +617,7 @@ public void bulkCopyTestTime() throws SQLException { rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + destTableName); rs.next(); - assertEquals("" + rs.getObject(1).toString(), "12:26:27.15"); // TODO + assertEquals("" + rs.getObject(1).toString(), "12:26:27"); } /** diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java index bf14063a2..3ae649f18 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java @@ -131,7 +131,7 @@ public void readTime() throws SQLException { createAndPopulateTable("time(3)", value); rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + tableName); rs.next(); - assertEquals("" + rs.getObject(1).toString(), "12:26:27.123"); // TODO + assertEquals("" + rs.getObject(1).toString(), "12:26:27"); } /** @@ -640,7 +640,7 @@ public void callableStatementOutputDateTest() throws SQLException { @Test public void callableStatementOutputTimeTest() throws SQLException { String value = "12:26:27.123345"; - String returnValue = "12:26:27.123"; + String returnValue = "12:26:27"; Utils.dropTableIfExists(tableName, stmt); stmt.executeUpdate("create table " + tableName + " (col1 sql_variant)"); stmt.executeUpdate("INSERT into " + tableName + " values (CAST ('" + value + "' AS " + "time(3)" + "))"); @@ -652,7 +652,7 @@ public void callableStatementOutputTimeTest() throws SQLException { CallableStatement cs = con.prepareCall(" {call " + inputProc + " (?) }"); cs.registerOutParameter(1, microsoft.sql.Types.SQL_VARIANT, 3); cs.execute(); - assertEquals(cs.getString(1), String.valueOf(returnValue)); + assertEquals(String.valueOf(returnValue), ""+cs.getObject(1)); if (null != cs) { cs.close(); } From 5a55172951564228fc6f88732d07c288b3accf47 Mon Sep 17 00:00:00 2001 From: Afsaneh Rafighi Date: Mon, 28 Aug 2017 14:17:02 -0700 Subject: [PATCH 2/3] added test for the fix. --- .../datatypes/SQLVariantResultSetTest.java | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java index 3ae649f18..411debce6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SQLVariantResultSetTest.java @@ -9,6 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.math.BigDecimal; @@ -131,7 +132,7 @@ public void readTime() throws SQLException { createAndPopulateTable("time(3)", value); rs = (SQLServerResultSet) stmt.executeQuery("SELECT * FROM " + tableName); rs.next(); - assertEquals("" + rs.getObject(1).toString(), "12:26:27"); + assertEquals("" + rs.getObject(1).toString(), "12:26:27"); } /** @@ -652,7 +653,7 @@ public void callableStatementOutputTimeTest() throws SQLException { CallableStatement cs = con.prepareCall(" {call " + inputProc + " (?) }"); cs.registerOutParameter(1, microsoft.sql.Types.SQL_VARIANT, 3); cs.execute(); - assertEquals(String.valueOf(returnValue), ""+cs.getObject(1)); + assertEquals(String.valueOf(returnValue), "" + cs.getObject(1)); if (null != cs) { cs.close(); } @@ -804,6 +805,42 @@ public void readSeveralRows() throws SQLException { } + /** + * Tests unsupported type + * + * @throws SQLException + */ + @Test + public void testUnsupportedDatatype() throws SQLException { + rs = (SQLServerResultSet) stmt.executeQuery("select cast(cast('2017-08-16 17:31:09.995 +07:00' as datetimeoffset) as sql_variant)"); + rs.next(); + try { + rs.getObject(1); + fail("Should have thrown unssuported tds type exception"); + } + catch (Exception e) { + assertTrue(e.getMessage().equalsIgnoreCase("Unexpected TDS type DATETIMEOFFSETN in SQL_VARIANT.")); + } + if (null != rs) { + rs.close(); + } + } + + /** + * Tests that the returning class of base type time in sql_variant is correct. + * + * @throws SQLException + * + */ + @Test + public void testTimeClassAsSqlVariant() throws SQLException { + rs = (SQLServerResultSet) stmt.executeQuery("select cast(cast('17:31:09.995' as time(3)) as sql_variant)"); + rs.next(); + Object object = rs.getObject(1); + assertEquals(object.getClass(), java.sql.Time.class); + ; + } + private boolean parseByte(byte[] expectedData, byte[] retrieved) { assertTrue(Arrays.equals(expectedData, Arrays.copyOf(retrieved, expectedData.length)), " unexpected BINARY value, expected"); From d1d2ccbff313de49c9f8eedf6755d8be765f8c18 Mon Sep 17 00:00:00 2001 From: Afsaneh Rafighi Date: Mon, 28 Aug 2017 21:15:10 -0700 Subject: [PATCH 3/3] fix indentation of SQLServerResource.java --- .../microsoft/sqlserver/jdbc/SQLServerResource.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index fb257c337..ac1ee201e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -387,12 +387,12 @@ protected Object[][] getContents() { {"R_jaasConfigurationNamePropertyDescription", "Login configuration file for Kerberos authentication."}, {"R_AKVKeyNotFound", "Key not found: {0}"}, {"R_SQLVariantSupport", "SQL_VARIANT datatype is not supported in pre-SQL 2008 version."}, - {"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."}, - {"R_invalidStringValue", "SQL_VARIANT does not support string values more than 8000 length."}, - {"R_invalidValueForTVPWithSQLVariant", "Inserting null value with column type sql_variant in TVP is not supported."}, - {"R_invalidDataTypeSupportForSQLVariant", "Unexpected TDS type ' '{0}' ' in SQL_VARIANT."}, - {"R_sslProtocolPropertyDescription", "SSL protocol label from TLS, TLSv1, TLSv1.1 & TLSv1.2. The default is TLS."}, - {"R_invalidSSLProtocol", "SSL Protocol {0} label is not valid. Only TLS, TLSv1, TLSv1.1 & TLSv1.2 are supported."}, + {"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."}, + {"R_invalidStringValue", "SQL_VARIANT does not support string values more than 8000 length."}, + {"R_invalidValueForTVPWithSQLVariant", "Inserting null value with column type sql_variant in TVP is not supported."}, + {"R_invalidDataTypeSupportForSQLVariant", "Unexpected TDS type ' '{0}' ' in SQL_VARIANT."}, + {"R_sslProtocolPropertyDescription", "SSL protocol label from TLS, TLSv1, TLSv1.1 & TLSv1.2. The default is TLS."}, + {"R_invalidSSLProtocol", "SSL Protocol {0} label is not valid. Only TLS, TLSv1, TLSv1.1 & TLSv1.2 are supported."}, }; } \ No newline at end of file