From eb3df3a2b273467cbfbdba909a15f206f64a70dd Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 13 Nov 2018 11:18:12 -0800 Subject: [PATCH 01/33] ported tests from VSO and added tests to increase code coverage --- .../microsoft/sqlserver/jdbc/bvt/BvtTest.java | 69 +++++++ .../jdbc/callablestatement/CallableMixed.java | 116 +++++++++++ .../jdbc/unit/serial/DTOSerialT.java | 184 ++++++++++++++++++ 3 files changed, 369 insertions(+) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java index 0d5f768d4..64401859e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java @@ -10,6 +10,7 @@ import java.math.BigDecimal; import java.sql.DatabaseMetaData; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -27,6 +28,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import com.microsoft.sqlserver.jdbc.SQLServerResultSet; import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.testframework.DBPreparedStatement; import com.microsoft.sqlserver.testframework.DBResultSet; @@ -418,6 +420,73 @@ public void testResultSetSelectMethod() throws SQLException { } } + /** + * Call resultset methods to run thru some code paths + * + * @throws SQLException + */ + @Test + public void testResultSetMethods() throws SQLException { + try (DBConnection conn = new DBConnection(connectionString); + DBStatement stmt = conn.createStatement(DBResultSetTypes.TYPE_SCROLL_SENSITIVE_CONCUR_UPDATABLE); + DBResultSet rs = stmt.selectAll(table1)) { + + ((ResultSet) rs.product()).clearWarnings(); + + assert (((ResultSet) rs.product()).getType() == ResultSet.TYPE_SCROLL_SENSITIVE); + + // check cursor + ((ResultSet) rs.product()).first(); + assert (((ResultSet) rs.product()).isFirst()); + + ((ResultSet) rs.product()).relative(1); + assert (!((ResultSet) rs.product()).isFirst()); + + ((ResultSet) rs.product()).last(); + assert (((ResultSet) rs.product()).isLast()); + + ((ResultSet) rs.product()).beforeFirst(); + assert (!((ResultSet) rs.product()).isLast()); + + ((ResultSet) rs.product()).afterLast(); + assert (((ResultSet) rs.product()).isAfterLast()); + assert (!((ResultSet) rs.product()).isLast()); + + ((ResultSet) rs.product()).absolute(1); + assert (((ResultSet) rs.product()).getRow() == 1); + + ((ResultSet) rs.product()).moveToInsertRow(); + assert (((ResultSet) rs.product()).getRow() == 0); + + ((ResultSet) rs.product()).moveToCurrentRow(); + assert (((ResultSet) rs.product()).getRow() == 1); + assert (!((ResultSet) rs.product()).rowInserted()); + assert (!((ResultSet) rs.product()).rowUpdated()); + + // check concurrency method + assert (((ResultSet) rs.product()).getConcurrency() == ResultSet.CONCUR_UPDATABLE); + + // check fetch direction + ((ResultSet) rs.product()).setFetchDirection(ResultSet.FETCH_FORWARD); + assert (((ResultSet) rs.product()).getFetchDirection() == ResultSet.FETCH_FORWARD); + + // check fetch size + ((ResultSet) rs.product()).setFetchSize(1); + assert (((ResultSet) rs.product()).getFetchSize() == 1); + + // test delete row + while (rs.next()) { + ((ResultSet) rs.product()).moveToCurrentRow(); + if (((ResultSet) rs.product()).getRow() == 1) { + ((ResultSet) rs.product()).deleteRow(); + assert (((ResultSet) rs.product()).rowDeleted()); + } + } + } catch (Exception e) { + fail(e.toString()); + } + } + /** * drops tables * diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java new file mode 100644 index 000000000..bdaa3f770 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java @@ -0,0 +1,116 @@ +package com.microsoft.sqlserver.jdbc.callablestatement; + +import java.sql.*; + +import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.jdbc.SQLServerDriver; +import com.microsoft.sqlserver.jdbc.TestUtils; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; +import static org.junit.jupiter.api.Assertions.fail; + + +@RunWith(JUnitPlatform.class) +public class CallableMixed { + + @Test + public void datatypestest() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); + String tableName = RandomUtil.getIdentifier("TFOO3"); + String procName = RandomUtil.getIdentifier("SPFOO3"); + + try (Connection conn = DriverManager.getConnection(connectionString)) { + try (Statement stmt = conn.createStatement()) { + try { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + stmt.executeUpdate(" DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + } catch (Exception e) {} + + String createSQL = "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + + "(c1_int int primary key, col2 int)"; + stmt.executeUpdate(createSQL); + + stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 1)"); + } + + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + + " (@p2_int int, @p2_int_out int OUTPUT, @p4_smallint smallint, @p4_smallint_out smallint OUTPUT) AS begin transaction SELECT * FROM " + + AbstractSQLGenerator.escapeIdentifier(tableName) + + " ; SELECT @p2_int_out=@p2_int, @p4_smallint_out=@p4_smallint commit transaction RETURN -2147483648"); + } + + try (CallableStatement cstmt = conn.prepareCall( + "{ ? = CALL " + AbstractSQLGenerator.escapeIdentifier(procName) + " (?, ?, ?, ?) }")) { + cstmt.registerOutParameter((int) 1, (int) 4); + cstmt.setObject((int) 2, Integer.valueOf("31"), (int) 4); + cstmt.registerOutParameter((int) 3, (int) 4); + cstmt.registerOutParameter((int) 5, java.sql.Types.BINARY); // Test OUT param + // re-registration + // (Defect 60921) + cstmt.registerOutParameter((int) 5, (int) 5); + cstmt.setObject((int) 4, Short.valueOf("-5372"), (int) 5); + + // get results and a value + ResultSet rs = cstmt.executeQuery(); + rs.next(); + + if (rs.getInt(1) != 0) { + fail("Received data not equal to setdata"); + + } + + if (cstmt.getInt((int) 5) != -5372) { + fail("Received data not equal to setdata"); + + } + // do nothing and reexecute + rs = cstmt.executeQuery(); + // get the param without getting the resultset + rs = cstmt.executeQuery(); + if (cstmt.getInt((int) 1) != -2147483648) { + fail("Received data not equal to setdata"); + + } + + if (cstmt.getInt((int) 1) != -2147483648) { + fail("Received data not equal to setdata"); + + } + + rs = cstmt.executeQuery(); + rs.next(); + + if (rs.getInt(1) != 0) { + fail("Received data not equal to setdata"); + + } + + if (cstmt.getInt((int) 1) != -2147483648) { + fail("Received data not equal to setdata"); + + } + + if (cstmt.getInt((int) 5) != -5372) { + fail("Received data not equal to setdata"); + + } + + rs = cstmt.executeQuery(); + } + } finally { + try (Connection conn = DriverManager.getConnection(connectionString); + Statement stmt = conn.createStatement()) { + TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + } catch (SQLException e) { + fail(e.toString()); + } + + } + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java new file mode 100644 index 000000000..d6bcc4439 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java @@ -0,0 +1,184 @@ +package com.microsoft.sqlserver.jdbc.unit.serial; + +import java.sql.*; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import junit.framework.*; +import javax.sql.*; + +import com.microsoft.sqlserver.jdbc.*; +import microsoft.sql.*; + +import java.io.*; + +import static org.junit.jupiter.api.Assertions.fail; + + +@RunWith(JUnitPlatform.class) +public class DTOSerialT { + private static final String dateString = "2007-05-08 12:35:29.1234567 +12:15"; + + // public static void testDSerial(String connString) throws Exception + @Test + public void testDSerial() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); + + try (Connection conn = DriverManager.getConnection(connectionString); + Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + + // create a DTO + ResultSet rs = stmt.executeQuery( + "SELECT CAST('" + dateString + "' AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' "); + rs.next(); + verifyCorrectSerialization(((SQLServerResultSet) rs).getDateTimeOffset(1)); + verifyMessedSerialization(); + } + } + + public void testESerial() throws Exception { + String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); + + try (Connection conn = DriverManager.getConnection(connectionString); + Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + + // raise an error. + SQLServerException currException = null; + + try { + stmt.executeUpdate("RAISERROR ('foo', 13,1) WITH LOG"); + } catch (SQLServerException x) { + currException = x; + } + // store the info + String errInfo = currException.toString(); + String sqlState = currException.getSQLState(); + int errCode = currException.getErrorCode(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + // serialize the exception; + out.writeObject(currException); + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); + SQLServerException ex = (SQLServerException) in.readObject(); + String newErrInfo = ex.toString(); + + if (!errInfo.equals(newErrInfo)) { + fail("Errors are different."); + } + if (sqlState != ex.getSQLState()) { + fail("Errors are different."); + } + if (errCode != ex.getErrorCode()) { + fail("Errors are different."); + } + } + } + + // Positive test case, this should succeed + private static void verifyCorrectSerialization(DateTimeOffset dto) throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos); + // serialize the DateTimeOffset; + out.writeObject(dto); + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); + DateTimeOffset dtn = (DateTimeOffset) in.readObject(); + verifyDTOEqual(dto, dtn); + // Make sure that you can send rehydrated to server + verifyCorrectSend(dtn); + } + + // this is to make sure that the rehydrated date can be sent to server correctly + private static void verifyCorrectSend(DateTimeOffset dtN) throws Exception { + String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); + + // create a DTO + try (Connection conn = DriverManager.getConnection(connectionString); + + SQLServerPreparedStatement ps = (SQLServerPreparedStatement) conn + .prepareStatement("SELECT CAST(? AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' ")) { + ps.setDateTimeOffset(1, dtN); + ResultSet rs = ps.executeQuery(); + rs.next(); + verifyDTOEqual(dtN, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + } + } + + /* + * I have created two files with wrong nano value (-1) and wrong offset (15*60) by "editing" couple of generated + * serialized files I have checked them in here so they can be used verify the error handling. Note the code to + * generate this is checked in as a text file in the same dir. DateTimeOffset.java.txt + */ + // Negative test cases. + private static void verifyMessedSerialization() throws Exception { + // these values are from the wrongnanos.dat wrongoffset.dat files checked in with the code + // the values represent the serialized DTO class with invalid values. + byte wrongnanos[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, + 108, 46, 68, 97, 116, 101, 84, 105, 109, 101, 79, 102, 102, 115, 101, 116, 36, 83, 101, 114, 105, 97, + 108, 105, 122, 97, 116, 105, 111, 110, 80, 114, 111, 120, 121, 9, 57, 90, 0, -49, -42, -72, 50, 2, 0, 3, + 73, 0, 13, 109, 105, 110, 117, 116, 101, 115, 79, 102, 102, 115, 101, 116, 73, 0, 5, 110, 97, 110, 111, + 115, 74, 0, 9, 117, 116, 99, 77, 105, 108, 108, 105, 115, 120, 112, 0, 0, 3, 12, -1, -1, -1, -1, 0, 0, + 0, 0, 0, 0, 0, 1}; + byte wrongoffset[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, + 108, 46, 68, 97, 116, 101, 84, 105, 109, 101, 79, 102, 102, 115, 101, 116, 36, 83, 101, 114, 105, 97, + 108, 105, 122, 97, 116, 105, 111, 110, 80, 114, 111, 120, 121, 9, 57, 90, 0, -49, -42, -72, 50, 2, 0, 3, + 73, 0, 13, 109, 105, 110, 117, 116, 101, 115, 79, 102, 102, 115, 101, 116, 73, 0, 5, 110, 97, 110, 111, + 115, 74, 0, 9, 117, 116, 99, 77, 105, 108, 108, 105, 115, 120, 112, 0, 0, 3, -124, 0, 0, 1, 44, 0, 0, 0, + 0, 0, 0, 0, 1}; + // These two serialized forms throw the exception illegalargument + boolean exThrown = false; + try { + verifyMessedSerializationHelper(wrongnanos); + } catch (IllegalArgumentException e) { + exThrown = true; + } + + if (!exThrown) { + fail("wrongnanos serialized form succeeded."); + } + + exThrown = false; + try { + verifyMessedSerializationHelper(wrongoffset); + } catch (IllegalArgumentException e) { + exThrown = true; + } + + if (!exThrown) { + fail("wrongnanos serialized form succeeded."); + } + } + + private static void verifyMessedSerializationHelper(byte[] svalue) throws Exception { + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(svalue)); + DateTimeOffset dtn = (DateTimeOffset) in.readObject(); + } + + // This function is used to make sure the hydrated is equal to original string and the initial DTO + private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrated) throws Exception { + // check string + String info = initial.toString(); + String newInfo = hydrated.toString(); + // check timestamp + java.sql.Timestamp originalTS = initial.getTimestamp(); + java.sql.Timestamp hydratedTS = hydrated.getTimestamp(); + // and offset + int originalOffset = initial.getMinutesOffset(); + int hydratedOffset = hydrated.getMinutesOffset(); + + if (!info.equals(newInfo)) { + fail("Strings are different."); + } + if (!info.equals(dateString)) { + fail("Strings are different from original."); + } + if (!initial.equals(hydrated)) { + fail("Equality test fails."); + } + if (!originalTS.equals(hydratedTS)) { + fail("Equality test fails from original."); + } + } +} From c31b1f34bc131ef693252889871ce038338a4d13 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 14 Nov 2018 12:20:09 -0800 Subject: [PATCH 02/33] moved resultset tests to resultset --- .../microsoft/sqlserver/jdbc/bvt/BvtTest.java | 68 ----------- .../jdbc/resultset/ResultSetTest.java | 107 ++++++++++++++++++ 2 files changed, 107 insertions(+), 68 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java index 64401859e..0988a861b 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java @@ -10,7 +10,6 @@ import java.math.BigDecimal; import java.sql.DatabaseMetaData; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -420,73 +419,6 @@ public void testResultSetSelectMethod() throws SQLException { } } - /** - * Call resultset methods to run thru some code paths - * - * @throws SQLException - */ - @Test - public void testResultSetMethods() throws SQLException { - try (DBConnection conn = new DBConnection(connectionString); - DBStatement stmt = conn.createStatement(DBResultSetTypes.TYPE_SCROLL_SENSITIVE_CONCUR_UPDATABLE); - DBResultSet rs = stmt.selectAll(table1)) { - - ((ResultSet) rs.product()).clearWarnings(); - - assert (((ResultSet) rs.product()).getType() == ResultSet.TYPE_SCROLL_SENSITIVE); - - // check cursor - ((ResultSet) rs.product()).first(); - assert (((ResultSet) rs.product()).isFirst()); - - ((ResultSet) rs.product()).relative(1); - assert (!((ResultSet) rs.product()).isFirst()); - - ((ResultSet) rs.product()).last(); - assert (((ResultSet) rs.product()).isLast()); - - ((ResultSet) rs.product()).beforeFirst(); - assert (!((ResultSet) rs.product()).isLast()); - - ((ResultSet) rs.product()).afterLast(); - assert (((ResultSet) rs.product()).isAfterLast()); - assert (!((ResultSet) rs.product()).isLast()); - - ((ResultSet) rs.product()).absolute(1); - assert (((ResultSet) rs.product()).getRow() == 1); - - ((ResultSet) rs.product()).moveToInsertRow(); - assert (((ResultSet) rs.product()).getRow() == 0); - - ((ResultSet) rs.product()).moveToCurrentRow(); - assert (((ResultSet) rs.product()).getRow() == 1); - assert (!((ResultSet) rs.product()).rowInserted()); - assert (!((ResultSet) rs.product()).rowUpdated()); - - // check concurrency method - assert (((ResultSet) rs.product()).getConcurrency() == ResultSet.CONCUR_UPDATABLE); - - // check fetch direction - ((ResultSet) rs.product()).setFetchDirection(ResultSet.FETCH_FORWARD); - assert (((ResultSet) rs.product()).getFetchDirection() == ResultSet.FETCH_FORWARD); - - // check fetch size - ((ResultSet) rs.product()).setFetchSize(1); - assert (((ResultSet) rs.product()).getFetchSize() == 1); - - // test delete row - while (rs.next()) { - ((ResultSet) rs.product()).moveToCurrentRow(); - if (((ResultSet) rs.product()).getRow() == 1) { - ((ResultSet) rs.product()).deleteRow(); - assert (((ResultSet) rs.product()).rowDeleted()); - } - } - } catch (Exception e) { - fail(e.toString()); - } - } - /** * drops tables * diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java index 574a928df..6144e4e28 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java @@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.math.BigDecimal; import java.sql.Blob; @@ -33,9 +34,14 @@ import com.microsoft.sqlserver.jdbc.ISQLServerResultSet; import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.jdbc.SQLServerResultSet; import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.DBConnection; +import com.microsoft.sqlserver.testframework.DBResultSet; +import com.microsoft.sqlserver.testframework.DBResultSetTypes; +import com.microsoft.sqlserver.testframework.DBStatement; @RunWith(JUnitPlatform.class) @@ -329,4 +335,105 @@ public void testGetterOnNull() throws SQLException { assertEquals(null, rs.getTime(1)); } } + + @Test + public void testHoldability() throws SQLException { + int[] holdabilityOptions = {ResultSet.HOLD_CURSORS_OVER_COMMIT, ResultSet.CLOSE_CURSORS_AT_COMMIT}; + + try (Connection con = DriverManager.getConnection(connectionString); Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("select null")) { + + int connHold = con.getHoldability(); + assertEquals(stmt.getResultSetHoldability(), connHold); + assertEquals(rs.getHoldability(), connHold); + + for (int i = 0; i < holdabilityOptions.length; i++) { + + if ((connHold = con.getHoldability()) != holdabilityOptions[i]) { + con.setHoldability(holdabilityOptions[i]); + assertEquals(con.getHoldability(), holdabilityOptions[i]); + } + } + } + } + + /** + * Call resultset methods to run thru some code paths + * + * @throws SQLException + */ + @Test + public void testResultSetMethods() throws SQLException { + try (Connection con = DriverManager.getConnection(connectionString); Statement stmt = con + .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + + stmt.executeUpdate( + "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 int primary key)"); + stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0)"); + stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(1)"); + stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(2)"); + + try (ResultSet rs = stmt + .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + + rs.clearWarnings(); + + assert (rs.getType() == ResultSet.TYPE_SCROLL_SENSITIVE); + + // check cursor + rs.first(); + assert (rs.isFirst()); + + rs.relative(1); + assert (!rs.isFirst()); + + rs.last(); + assert (rs.isLast()); + + rs.beforeFirst(); + assert (rs.isBeforeFirst()); + + rs.afterLast(); + assert (rs.isAfterLast()); + assert (!rs.isLast()); + + rs.absolute(1); + assert (rs.getRow() == 1); + + rs.moveToInsertRow(); + assert (rs.getRow() == 0); + rs.moveToCurrentRow(); + assert (rs.getRow() == 1); + + // no inserts or updates + assert (!rs.rowInserted()); + assert (!rs.rowUpdated()); + + // check concurrency method + assert (rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE); + + // check fetch direction + rs.setFetchDirection(ResultSet.FETCH_FORWARD); + assert (rs.getFetchDirection() == ResultSet.FETCH_FORWARD); + + // check fetch size + rs.setFetchSize(1); + assert (rs.getFetchSize() == 1); + + rs.refreshRow(); + + // test delete row + do { + rs.moveToCurrentRow(); + rs.deleteRow(); + assert (rs.rowDeleted()); + } while (rs.next()); + + } catch (Exception e) { + fail(e.toString()); + } finally { + stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } + } + } } From 145ee721e7cf42d2d70452985164f409f956c434 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 14 Nov 2018 12:21:29 -0800 Subject: [PATCH 03/33] removed unused import --- src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java index 0988a861b..0d5f768d4 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bvt/BvtTest.java @@ -27,7 +27,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import com.microsoft.sqlserver.jdbc.SQLServerResultSet; import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.testframework.DBPreparedStatement; import com.microsoft.sqlserver.testframework.DBResultSet; From fd123b29106dbadb61bd544835c1070f6a858075 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 15 Nov 2018 16:55:33 -0800 Subject: [PATCH 04/33] added tests to increase code coverage --- .../sqlserver/jdbc/TestResource.java | 3 +- .../microsoft/sqlserver/jdbc/TestUtils.java | 34 + ...lableMixed.java => CallableMixedTest.java} | 2 +- .../jdbc/datatypes/KatmaiDataTypesTest.java | 1752 +++++++++++++++++ .../jdbc/resultset/ResultSetTest.java | 62 +- .../{DTOSerialT.java => DTOSerialTest.java} | 3 +- .../jdbc/unit/statement/StatementTest.java | 10 +- 7 files changed, 1844 insertions(+), 22 deletions(-) rename src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/{CallableMixed.java => CallableMixedTest.java} (96%) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java rename src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/{DTOSerialT.java => DTOSerialTest.java} (97%) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java index 8b2ca84b4..d300f9e34 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java @@ -153,6 +153,7 @@ protected Object[][] getContents() { {"R_expectedValue", "Expected value: "}, {"R_expectedValueAtIndex", "Expected value at index: "}, {"R_switchFailed", "Switch case is not matched with data"}, {"R_resultsetNotInstance", "Result set is not instance of SQLServerResultSet"}, - + {"R_resultsetNotInstance", "Result set is not instance of SQLServerResultSet"}, + {"R_noJRESupport", "No JRE support for {0}"}, }; } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index bb7d317d4..a580def64 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -66,6 +66,8 @@ public class TestUtils { public static final String SERVER_TYPE_SQL_AZURE = "SQLAzure"; // private static SqlType types = null; private static ArrayList types = null; + private final static int ENGINE_EDITION_FOR_SQL_AZURE = 5; + private final static int ENGINE_EDITION_FOR_SQL_AZURE_DW = 6; /** * Returns serverType @@ -623,6 +625,8 @@ public static Object roundSmallDateTimeValue(Object value) { * @return boolean */ public static boolean serverSupportsDataClassification(Statement stmt) { + + try { stmt.execute("SELECT * FROM SYS.SENSITIVITY_CLASSIFICATIONS"); } catch (SQLException e) { @@ -666,4 +670,34 @@ public static boolean supportJDBC43(Connection con) throws SQLException { public static String escapeSingleQuotes(String name) { return name.replace("'", "''"); } + + /** + * Returns if connected to SQL Azure + * @param con + * connection to server + * @return boolean + * @throws SQLException + */ + public static boolean isSqlAzure(Connection con) throws SQLException { + try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { + rs.next(); + int engineEdition = rs.getInt(1); + return (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE || engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); + } + } + + /** + * Returns if connected to SQL Azure DW + * @param con + * connection to server + * @return boolean + * @throws SQLException + */ + public static boolean isSqlAzureDW(Connection con) throws SQLException { + try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { + rs.next(); + int engineEdition = rs.getInt(1); + return (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); + } + } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java similarity index 96% rename from src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java rename to src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index bdaa3f770..91b661504 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixed.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -14,7 +14,7 @@ @RunWith(JUnitPlatform.class) -public class CallableMixed { +public class CallableMixedTest { @Test public void datatypestest() throws Exception { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java new file mode 100644 index 000000000..5c15b55a5 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -0,0 +1,1752 @@ +package com.microsoft.sqlserver.jdbc.datatypes; + +import java.sql.*; +import java.text.MessageFormat; + +import com.microsoft.sqlserver.jdbc.*; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; + +import java.math.*; +import java.util.*; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.junit.Assert.fail; + +import microsoft.sql.DateTimeOffset; + + +/* + * This test suite tests all kinds of temporal data types for Katmai or later versions. It has tests for + * date/time/datetime2/datetimeoffset data types. Also includes tests for new data type mappings in JDBC 4.1. + */ +@RunWith(JUnitPlatform.class) +public class KatmaiDataTypesTest extends AbstractTest { + + final static String tableName = RandomUtil.getIdentifier("KatmaiDataTypesTable"); + final static String procName = RandomUtil.getIdentifier("KatmaiDataTypesTableProc"); + + /* + * public void testSparse() throws Exception { + * assumeTrue(!isSqlAzure(DriverManager.getConnection(connectionString)), TestResource.getResource("R_skipAzure")); + * try (Connection connection = DriverManager.getConnection(connectionString) { + * SparseTest.runTest(connectionString); } } public void testJDBC41BigInteger() throws Exception { if + * (fxConnection.isServerSqlAzureDW()) { + * CTestLog.Skip("this test is skipped because it cannot be meaningfully tested on SQL Azure DW."); } + * BigIntegerTest.runTest(connectionString); } + */ + + enum SQLType { + date("yyyy-mm-dd", 0, java.sql.Types.DATE, "java.sql.Date"), + + time("hh:mm:ss", 7, java.sql.Types.TIME, "java.sql.Time"), + + datetime("yyyy-mm-dd hh:mm:ss", 3, java.sql.Types.TIMESTAMP, "java.sql.Timestamp"), + + datetime2("yyyy-mm-dd hh:mm:ss", 7, java.sql.Types.TIMESTAMP, "java.sql.Timestamp"), + + datetimeoffset("yyyy-mm-dd hh:mm:ss +hh:mm", 7, microsoft.sql.Types.DATETIMEOFFSET, "microsoft.sql.DateTimeOffset"); + + final int basePrecision; + final int maxPrecision; + final int maxFractionalSecondsDigits; + final int jdbcType; + final String className; + + SQLType(String format, int maxFractionalSecondsDigits, int jdbcType, String className) { + assert maxFractionalSecondsDigits >= 0; + + this.basePrecision = format.length(); + this.maxFractionalSecondsDigits = maxFractionalSecondsDigits; + this.maxPrecision = basePrecision + + ((maxFractionalSecondsDigits > 0) ? (1 + maxFractionalSecondsDigits) : 0); + this.jdbcType = jdbcType; + this.className = className; + } + }; + + abstract static class SQLValue { + private final SQLType sqlType; + private final String stringValue; + + final String getString() { + return stringValue; + } + + private final String sqlTypeExpression; + private final int precision; + private final int scale; + + SQLValue(SQLType sqlType, String stringValue) { + this.sqlType = sqlType; + this.stringValue = stringValue; + this.sqlTypeExpression = sqlType.toString(); + this.precision = sqlType.maxPrecision; + this.scale = sqlType.maxFractionalSecondsDigits; + } + + SQLValue(SQLType sqlType, String stringValue, int fractionalSecondsDigits) { + this.sqlType = sqlType; + this.stringValue = stringValue; + this.sqlTypeExpression = sqlType.toString() + "(" + fractionalSecondsDigits + ")"; + this.precision = sqlType.basePrecision + (1 + fractionalSecondsDigits); + this.scale = fractionalSecondsDigits; + } + + private String sqlCastExpression() { + return "CAST('" + stringValue + "' AS " + sqlTypeExpression + ")"; + } + + void verifyResultSetMetaData(Connection conn) throws Exception { + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT TOP 0 " + sqlCastExpression()); + + try { + ResultSetMetaData metadata = rs.getMetaData(); + + assertEquals(metadata.getColumnType(1), sqlType.jdbcType, "getColumnType() of " + sqlCastExpression()); + assertEquals(metadata.getColumnTypeName(1), sqlType.toString(), + "getColumnTypeName() of " + sqlCastExpression()); + assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + + // Display size of temporal types is the precision per JDBC spec + assertEquals(metadata.getColumnDisplaySize(1), precision, + "getColumnDisplaySize() of " + sqlCastExpression()); + // Scale is interpreted as number of fractional seconds precision + assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); + assertEquals(metadata.getColumnClassName(1), sqlType.className, + "getColumnClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed + assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + + // Katmai temporal types are searchable (i.e. usable in a WHERE clause) + assertEquals(metadata.isSearchable(1), true, "isSearchable() of " + sqlCastExpression()); + } finally { + rs.close(); + stmt.close(); + } + } + + void verifyParameterMetaData(Connection conn) throws Exception { + + final String procName = RandomUtil.getIdentifier("testParameterMetaData"); + // final String procName = "[" + driver.createuniqueidentifer("testParameterMetaData") + "]"; + + Statement stmt = null; + PreparedStatement pstmt = null; + + try { + stmt = conn.createStatement(); + + // Create the stored proc + stmt.executeUpdate("CREATE PROCEDURE " + procName + " @arg " + sqlTypeExpression + " AS SELECT @arg"); + + pstmt = conn.prepareStatement("{call " + procName + "(?)}"); + ParameterMetaData metadata = pstmt.getParameterMetaData(); + + assertEquals(metadata.getParameterType(1), sqlType.jdbcType, + "getParameterType() of " + sqlCastExpression()); + assertEquals(metadata.getParameterTypeName(1), sqlType.toString(), + "getParameterTypeName() of " + sqlCastExpression()); + assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + + // Scale is interpreted as number of fractional seconds precision + assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); + assertEquals(metadata.getParameterClassName(1), sqlType.className, + "getParameterClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed + assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + } finally { + if (null != pstmt) + pstmt.close(); + + if (null != stmt) { + stmt.executeUpdate("DROP PROCEDURE " + procName); + stmt.close(); + } + } + } + + abstract void verifyRSGetters(ResultSet rs) throws Exception; + + void verifyRSGetters(Connection conn) throws Exception { + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery( + "SELECT " + sqlCastExpression() + ", CAST(" + sqlCastExpression() + " AS VARCHAR(60))"); + rs.next(); + verifyRSGetters(rs); + rs.close(); + stmt.close(); + } + + abstract void verifyRSUpdaters(ResultSet rs) throws Exception; + + void verifyRSUpdaters(Connection conn) throws Exception { + + assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + + Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + try { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (SQLException e) {} + stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " + + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); + + try { + stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" + + sqlCastExpression() + ")"); + + ResultSet rs = stmt.executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)); + rs.next(); + verifyRSUpdaters(rs); + rs.close(); + } finally { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } + + stmt.close(); + } + + /* + * For testing the setObject and setNull methods in PreparedStatement, use the verifySetter* methods. These + * methods prepare a single statement and execute it for all different data types by calling the appropriate + * 'setObject' methods for each data type and/or type conversion. + */ + abstract void verifySetters(PreparedStatement ps) throws Exception; + + abstract void verifySettersUtilDate(PreparedStatement ps) throws Exception; + + abstract void verifySettersCalendar(PreparedStatement ps) throws Exception; + + void verifySetters(Connection conn) throws Exception { + assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + + Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + try { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (SQLException e) {} + stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " + + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); + + PreparedStatement ps = conn.prepareStatement( + "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (?) SELECT * FROM " + + AbstractSQLGenerator.escapeIdentifier(tableName), + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + try { + verifySetters(ps); + // Verify setObject function for the new mapping in JDBC41 (java.util.Date to TIMESTAMP) + stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + + verifySettersUtilDate(ps); + // Verify setObject function for the new mapping in JDBC41 (java.util.Calendar to TIMESTAMP) + stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + verifySettersCalendar(ps); + } finally { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } + + ps.close(); + stmt.close(); + } + + abstract void verifyCSGetters(CallableStatement cs) throws Exception; + + void verifyCSGetters(Connection conn) throws Exception { + Statement stmt = conn.createStatement(); + try { + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + } catch (SQLException e) {} + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @argIn " + + sqlTypeExpression + "," + " @argOut " + sqlTypeExpression + " OUTPUT" + " AS " + + " SET @argOut=@argIn"); + + CallableStatement cs = conn + .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}"); + try { + verifyCSGetters(cs); + } finally { + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + } + + cs.close(); + stmt.close(); + } + } + + static final class DateValue extends SQLValue { + private final java.sql.Date expected; + + DateValue(String stringValue) { + super(SQLType.date, stringValue); + this.expected = java.sql.Date.valueOf(stringValue); + } + + private java.sql.Timestamp expectedTimestampMillisPrecision() { + return new java.sql.Timestamp(expected.getTime()); + } + + private java.util.Date expectedUtilDate() { + return (java.util.Date) expected; + } + + private java.util.Calendar expectedCalendar() { + Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.setTimeInMillis(expected.getTime()); + return cal; + } + + void verifyRSGetters(ResultSet rs) throws Exception { + + assertEquals(rs.getDate(1), expected, "getDate mismatch"); + + assertEquals(rs.getTimestamp(1), new java.sql.Timestamp(expected.getTime()), "getTimestamp mismatch"); + + assertEquals(rs.getString(1), expected.toString(), "getString mismatch"); + + rs.close(); + } + + void verifyRSUpdaters(ResultSet rs) throws Exception { + rs.updateDate(1, expected); + rs.updateRow(); + + assertEquals(rs.getDate(1), expected, "updateDate mismatch"); + } + + void verifySetters(PreparedStatement ps) throws Exception { + ps.setDate(1, expected); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + + assertEquals(rs.getDate(1), expected, "setDate mismatch"); + } + + void verifySettersUtilDate(PreparedStatement ps) throws Exception { + int currentRow = 0; + ps.setObject(1, expectedUtilDate()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + assertEquals(rs.getDate(1), expected, "getDate mismatch"); + assertEquals((java.util.Date) rs.getObject(1), expectedUtilDate(), "getObject mismatch"); + + // Test the additional conversions introduced in JDBC41 for types setters + // Test datetime2 column with target type TIMESTAMP + ps.setObject(1, expectedUtilDate(), java.sql.Types.DATE); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getDate(1), expected, "getDate mismatch"); + + ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + + // Test the setNull() methods for different data type conversions + ps.setNull(1, java.sql.Types.DATE); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + + ps.setNull(1, java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + } + + void verifySettersCalendar(PreparedStatement ps) throws Exception { + int currentRow = 0; + ps.setObject(1, expectedCalendar()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + assertEquals(rs.getDate(1), expected, "getDate mismatch"); + // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, java.sql.Date + // or java.util.Date can be cast to a calendar + + // Test the additional conversions introduced in JDBC41 for types setters + // Test datetime2 column with target type TIMESTAMP + ps.setObject(1, expectedCalendar(), java.sql.Types.DATE); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getDate(1), expected, "getDate mismatch"); + + ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + } + + void verifyCSGetters(CallableStatement cs) throws Exception { + cs.setDate(1, expected); + cs.registerOutParameter(2, java.sql.Types.DATE); + cs.execute(); + assertEquals(cs.getDate(2), expected, "getDate mismatch"); + assertEquals(cs.getObject(2), expected, "getObject mismatch"); + } + } + + static final class TimeValue extends SQLValue { + private int hour; + private int minute; + private int second; + private int nanos; + private TimeZone tz; + + TimeValue(String stringValue) { + super(SQLType.time, stringValue); + initExpected(stringValue, TimeZone.getDefault()); + } + + TimeValue(String stringValue, int fractionalSecondsDigits) { + super(SQLType.time, stringValue, fractionalSecondsDigits); + initExpected(stringValue, TimeZone.getDefault()); + } + + private void initExpected(String stringValue, TimeZone tz) { + // "hh:mm:ss[.nnnnnnn]" + this.hour = Integer.valueOf(stringValue.substring(0, 2)); + this.minute = Integer.valueOf(stringValue.substring(3, 5)); + this.second = Integer.valueOf(stringValue.substring(6, 8)); + + this.nanos = (8 == stringValue.indexOf('.')) ? (new BigDecimal(stringValue.substring(8))) + .scaleByPowerOfTen(9).intValue() : 0; + + this.tz = tz; + } + + private java.sql.Timestamp expectedTimestamp() { + Calendar cal = Calendar.getInstance(tz); + cal.clear(); + cal.set(1900, Calendar.JANUARY, 1, hour, minute, second); + + java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis()); + timestamp.setNanos(nanos); + + return timestamp; + } + + private java.sql.Time expectedTime() { + Calendar cal = Calendar.getInstance(tz); + cal.clear(); + cal.set(1970, Calendar.JANUARY, 1, hour, minute, second); + + cal.set(Calendar.MILLISECOND, (nanos + 500000) / 1000000); + + return new java.sql.Time(cal.getTimeInMillis()); + } + + private java.sql.Timestamp expectedTimestampMillisPrecision() { + Calendar cal = Calendar.getInstance(tz); + cal.clear(); + cal.set(1900, Calendar.JANUARY, 1, hour, minute, second); + cal.set(Calendar.MILLISECOND, (nanos + 500000) / 1000000); + + java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis()); + + return timestamp; + } + + private java.util.Date expectedUtilDate() { + Calendar cal = Calendar.getInstance(tz); + cal.clear(); + cal.set(1970, Calendar.JANUARY, 1, hour, minute, second); + + cal.set(Calendar.MILLISECOND, (nanos + 500000) / 1000000); + java.util.Date udate = new java.util.Date(cal.getTimeInMillis()); + return udate; + + } + + private java.util.Calendar expectedCalendar() { + Calendar cal = Calendar.getInstance(tz); + cal.clear(); + cal.set(1970, Calendar.JANUARY, 1, hour, minute, second); + + cal.set(Calendar.MILLISECOND, (nanos + 500000) / 1000000); + return cal; + } + + void verifyRSGetters(ResultSet rs) throws Exception { + assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); + + assertEquals(rs.getTimestamp(1), expectedTimestamp(), "getTimestamp mismatch"); + + assertEquals(rs.getString(1), this.getString(), "getString mismatch"); + } + + void verifyRSUpdaters(ResultSet rs) throws Exception { + rs.updateTime(1, expectedTime()); + rs.updateRow(); + + assertEquals(rs.getTime(1), expectedTime(), "updateTime mismatch"); + } + + void verifySetters(PreparedStatement ps) throws Exception { + ps.setTime(1, expectedTime()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + + assertEquals(rs.getTime(1), expectedTime(), "setTime mismatch"); + } + + void verifySettersUtilDate(PreparedStatement ps) throws Exception { + int currentRow = 0; + ps.setObject(1, expectedUtilDate()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + assertEquals((java.util.Date) rs.getObject(1), expectedUtilDate(), "getObject mismatch"); + + // Test the additional conversions introduced in JDBC41 for types setters + // Test datetime2 column with target type TIMESTAMP + ps.setObject(1, expectedUtilDate(), java.sql.Types.TIME); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); + + ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + + // Test the setNull() methods for different data type conversions + ps.setNull(1, java.sql.Types.TIME); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + + ps.setNull(1, java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + + } + + void verifySettersCalendar(PreparedStatement ps) throws Exception { + int currentRow = 0; + ps.setObject(1, expectedCalendar()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); + + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, java.sql.Date + // or java.util.Date can be cast to a calendar + + // Test the additional conversions introduced in JDBC41 for types setters + // Test datetime2 column with target type TIMESTAMP + ps.setObject(1, expectedCalendar(), java.sql.Types.TIME); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); + + ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + } + + void verifyCSGetters(CallableStatement cs) throws Exception { + cs.setTime(1, expectedTime()); + cs.registerOutParameter(2, java.sql.Types.TIME); + cs.execute(); + assertEquals(cs.getTime(2), expectedTime(), "getTime mismatch"); + assertEquals(cs.getObject(2), expectedTime(), "getObject mismatch"); + } + } + + static final class DateTime2Value extends SQLValue { + private String stringValue; + private long utcMillis; + private int nanos; + private TimeZone tz; + + DateTime2Value(String stringValue) { + super(SQLType.datetime2, stringValue); + initExpected(stringValue, TimeZone.getDefault()); + } + + DateTime2Value(String stringValue, int fractionalSecondsDigits) { + super(SQLType.datetime2, stringValue, fractionalSecondsDigits); + initExpected(stringValue, TimeZone.getDefault()); + } + + DateTime2Value(String stringValue, String timeZone) { + super(SQLType.datetime2, stringValue); + initExpected(stringValue, TimeZone.getTimeZone(timeZone)); + } + + DateTime2Value(String stringValue, int fractionalSecondsDigits, String timeZone) { + super(SQLType.datetime2, stringValue, fractionalSecondsDigits); + initExpected(stringValue, TimeZone.getTimeZone(timeZone)); + } + + private void initExpected(String timestampString, TimeZone tz) { + // "yyyy-MM-dd hh:mm:ss[.nnnnnnn]" + int year = Integer.valueOf(timestampString.substring(0, 4)); + int month = Integer.valueOf(timestampString.substring(5, 7)); + int day = Integer.valueOf(timestampString.substring(8, 10)); + int hour = Integer.valueOf(timestampString.substring(11, 13)); + int minute = Integer.valueOf(timestampString.substring(14, 16)); + int second = Integer.valueOf(timestampString.substring(17, 19)); + + int nanos = (19 == timestampString.indexOf('.')) ? (new BigDecimal(timestampString.substring(19))) + .scaleByPowerOfTen(9).intValue() : 0; + + Calendar cal = Calendar.getInstance(tz); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, day); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.set(Calendar.MILLISECOND, nanos / 1000000); + + this.stringValue = timestampString; + this.utcMillis = cal.getTimeInMillis(); + this.nanos = nanos; + this.tz = tz; + } + + private java.sql.Date expectedDate() { + Calendar cal = Calendar.getInstance(tz); + cal.setTimeInMillis(utcMillis); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return new java.sql.Date(cal.getTimeInMillis()); + } + + private java.sql.Time expectedTime() { + Calendar cal = Calendar.getInstance(tz); + cal.setTimeInMillis(utcMillis); + if (nanos % 1000000 >= 500000) + cal.add(Calendar.MILLISECOND, 1); + cal.set(Calendar.YEAR, 1970); + cal.set(Calendar.MONTH, Calendar.JANUARY); + cal.set(Calendar.DAY_OF_MONTH, 1); + return new java.sql.Time(cal.getTimeInMillis()); + } + + private java.sql.Timestamp expectedTimestamp() { + Timestamp timestamp = new java.sql.Timestamp(utcMillis); + timestamp.setNanos(nanos); + return timestamp; + } + + private java.sql.Timestamp expectedTimestampMillisPrecision() { + Timestamp timestamp = new java.sql.Timestamp(utcMillis); + // Cannot set the nanos to 0, as per doc " the fractional seconds are stored in the nanos field of the + // Timestamp object." + // timestamp.setNanos(0); + return timestamp; + } + + private java.util.Date expectedUtilDate() { + return new java.util.Date(utcMillis); + } + + private java.util.Calendar expectedCalendar() { + Calendar cal = Calendar.getInstance(tz); + cal.setTimeInMillis(utcMillis); + return cal; + } + + void verifyRSGetters(ResultSet rs) throws Exception { + assertEquals(rs.getDate(1, Calendar.getInstance(tz)), expectedDate(), "getDate mismatch"); + + assertEquals(rs.getTime(1, Calendar.getInstance(tz)), expectedTime(), "getTime mismatch"); + + assertEquals(rs.getTimestamp(1, Calendar.getInstance(tz)), expectedTimestamp(), "getTimestamp mismatch"); + + assertEquals(rs.getString(1), stringValue, "getString mismatch"); + } + + void verifyRSUpdaters(ResultSet rs) throws Exception { + // Unlike PreparedStatement.setTimestamp(), there is no ResultSet.updateTimestamp() + // that takes a Calendar argument for passing in the time zone. ResultSet.updateTimestamp() + // always uses the VM default time zone. So we have to temporarily change it while doing + // the update. + TimeZone tzDefault = TimeZone.getDefault(); + try { + TimeZone.setDefault(tz); + + // Update the timestamp value with this value's time zone (set as the VM default above) + rs.updateTimestamp(1, expectedTimestamp()); + rs.updateRow(); + + // Verify the update (this value's time zone is still the default) + assertEquals(rs.getTimestamp(1), expectedTimestamp(), "updateTimestamp mismatch (default time zone)"); + } finally { + // Restore the original default time zone + TimeZone.setDefault(tzDefault); + } + + // Verify the update (after restoring the default time zone) using the getTimestamp + // variant that takes a time zone argument (as a Calendar) + assertEquals(rs.getTimestamp(1, Calendar.getInstance(tz)), expectedTimestamp(), + "updateTimestamp mismatch (explicit time zone)"); + } + + void verifySetters(PreparedStatement ps) throws Exception { + // Verify PreparedStatement.setTimestamp with default time zone first. + // Temporarily change the VM default time zone as in the ResultSet verifier. + TimeZone tzDefault = TimeZone.getDefault(); + try { + TimeZone.setDefault(tz); + + ps.setTimestamp(1, expectedTimestamp()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + + assertEquals(rs.getTimestamp(1), expectedTimestamp(), "setTimestamp mismatch (default time zone)"); + } finally { + TimeZone.setDefault(tzDefault); + } + + // Verify PreparedStatement.setTimestamp(..., Calendar) as well (don't change the VM default) + ps.setTimestamp(1, expectedTimestamp(), Calendar.getInstance(tz)); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + + assertEquals(rs.getTimestamp(1, Calendar.getInstance(tz)), expectedTimestamp(), "setTimestamp mismatch"); + } + + void verifySettersUtilDate(PreparedStatement ps) throws Exception { + int currentRow = 0; + ps.setObject(1, expectedUtilDate()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + assertEquals((java.util.Date) rs.getObject(1), expectedUtilDate(), "getObject mismatch"); + + // Test the additional conversions introduced in JDBC41 for types setters + // Test datetime2 column with target type TIMESTAMP + ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + + // Test the setNull() methods for different data type conversions + ps.setNull(1, java.sql.Types.TIME); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + + ps.setNull(1, java.sql.Types.DATE); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + + ps.setNull(1, java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(rs.wasNull(), true, "getTimestamp mismatch"); + } + + void verifySettersCalendar(PreparedStatement ps) throws Exception { + int currentRow = 0; + ps.setObject(1, expectedCalendar()); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, java.sql.Date + // or java.util.Date can be cast to a calendar + + // Test the additional conversions introduced in JDBC41 for types setters + // Test datetime2 column with target type TIMESTAMP + ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); + ps.execute(); + ps.getMoreResults(); + rs = ps.getResultSet(); + // Go to the next row + rs.next(); + rs.relative(++currentRow); + assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); + } + + void verifyCSGetters(CallableStatement cs) throws Exception { + cs.setTimestamp(1, expectedTimestamp(), Calendar.getInstance(tz)); + cs.registerOutParameter(2, java.sql.Types.TIMESTAMP); + cs.execute(); + + // Verify typed getter (with time zone argument) + assertEquals(cs.getTimestamp(2, Calendar.getInstance(tz)), expectedTimestamp(), "getTimestamp mismatch"); + + // Verify getObject (no provision for time zone argument - need to push/pop the default) + TimeZone tzDefault = TimeZone.getDefault(); + try { + TimeZone.setDefault(tz); + + assertEquals(cs.getObject(2), expectedTimestamp(), "getObject mismatch"); + } finally { + TimeZone.setDefault(tzDefault); + } + } + } + + static final class DateTimeOffsetValue extends SQLValue { + private final DateTimeOffset dto; + + DateTimeOffset get() { + return dto; + } + + private final DateTimeOffset initExpected(String stringValue, int fractionalSecondsDigits) { + int lastColon = stringValue.lastIndexOf(':'); + + String offsetString = stringValue.substring(lastColon - 3); + int minutesOffset = 60 * Integer.valueOf(offsetString.substring(1, 3)) + + Integer.valueOf(offsetString.substring(4, 6)); + + if (offsetString.startsWith("-")) + minutesOffset = -minutesOffset; + + String timestampString = stringValue.substring(0, lastColon - 4); + int year = Integer.valueOf(timestampString.substring(0, 4)); + int month = Integer.valueOf(timestampString.substring(5, 7)); + int day = Integer.valueOf(timestampString.substring(8, 10)); + int hour = Integer.valueOf(timestampString.substring(11, 13)); + int minute = Integer.valueOf(timestampString.substring(14, 16)); + int second = Integer.valueOf(timestampString.substring(17, 19)); + + int nanos = (19 == timestampString.indexOf('.')) ? (new BigDecimal(timestampString.substring(19))) + .scaleByPowerOfTen(9).intValue() : 0; + + Calendar cal = Calendar.getInstance(Locale.US); + cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * minutesOffset); + cal.set(Calendar.DST_OFFSET, 0); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, day); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + + java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis()); + timestamp.setNanos(nanos); + + return DateTimeOffset.valueOf(timestamp, minutesOffset); + } + + DateTimeOffsetValue(String stringValue) { + super(SQLType.datetimeoffset, stringValue); + dto = initExpected(stringValue, -1); + } + + DateTimeOffsetValue(String stringValue, int fractionalSecondsDigits) { + super(SQLType.datetimeoffset, stringValue); + dto = initExpected(stringValue, fractionalSecondsDigits); + } + + private java.sql.Date expectedDate() { + Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); + cal.setTimeInMillis(dto.getTimestamp().getTime()); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return new java.sql.Date(cal.getTimeInMillis()); + } + + private java.sql.Time expectedTime() { + Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); + cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); + cal.setTimeInMillis(dto.getTimestamp().getTime()); + if (dto.getTimestamp().getNanos() % 1000000 >= 500000) + cal.add(Calendar.MILLISECOND, 1); + cal.set(Calendar.YEAR, 1970); + cal.set(Calendar.MONTH, Calendar.JANUARY); + cal.set(Calendar.DAY_OF_MONTH, 1); + return new java.sql.Time(cal.getTimeInMillis()); + } + + private java.sql.Timestamp expectedTimestamp() { + Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); + cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); + cal.setTimeInMillis(dto.getTimestamp().getTime()); + if (dto.getTimestamp().getNanos() % 1000000 >= 500000) + cal.add(Calendar.MILLISECOND, 1); + return new java.sql.Timestamp(cal.getTimeInMillis()); + } + + private java.util.Date expectedUtilDate() { + Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); + cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); + cal.setTimeInMillis(dto.getTimestamp().getTime()); + if (dto.getTimestamp().getNanos() % 1000000 >= 500000) + cal.add(Calendar.MILLISECOND, 1); + return new java.util.Date(cal.getTimeInMillis()); + } + + private java.util.Calendar expectedCalendar() { + Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); + cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); + cal.setTimeInMillis(dto.getTimestamp().getTime()); + if (dto.getTimestamp().getNanos() % 1000000 >= 500000) + cal.add(Calendar.MILLISECOND, 1); + return cal; + } + + void verifyRSGetters(ResultSet rs) throws Exception { + assertEquals(rs.getDate(1), expectedDate(), "getDate mismatch"); + + assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); + + assertEquals(rs.getTimestamp(1), dto.getTimestamp(), "getTimestamp mismatch"); + + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1), dto, "getDateTimeOffset mismatch"); + + assertEquals(rs.getString(1), this.getString(), "getString mismatch"); + } + + void verifyRSUpdaters(ResultSet rs) throws Exception { + ((SQLServerResultSet) rs).updateDateTimeOffset(1, dto); + rs.updateRow(); + + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1), dto, "updateDateTimeOffset mismatch"); + } + + void verifySetters(PreparedStatement ps) throws Exception { + ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); + ps.execute(); + ps.getMoreResults(); + ResultSet rs = ps.getResultSet(); + rs.next(); + + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1), dto, "setDateTimeOffset mismatch"); + } + + void verifySettersUtilDate(PreparedStatement ps) throws Exception { + /* + * Cannot test by setObject(...,java.util.Date) with the back end data type as datetimeoffset because by + * design anything but datetimeoffset is normalized to UTC time zone in the source code (in sendTemporal + * function in dtv.java) setObject(...,java.sql.Date) and setObject(...,java.utl.date) gets same exception + */ + } + + void verifySettersCalendar(PreparedStatement ps) throws Exception { + /* + * Cannot test by setObject(...,java.util.Date) with the back end data type as datetimeoffset because by + * design anything but datetimeoffset is normalized to UTC time zone in the source code (in sendTemporal + * function in dtv.java) + */ + } + + void verifyCSGetters(CallableStatement cs) throws Exception { + ((SQLServerCallableStatement) cs).setDateTimeOffset(1, dto); + cs.registerOutParameter(2, microsoft.sql.Types.DATETIMEOFFSET); + cs.execute(); + assertEquals(((SQLServerCallableStatement) cs).getDateTimeOffset(2), dto, "getDateTimeOffset mismatch"); + + assertEquals(cs.getObject(2), dto, "getObject mismatch"); + } + } + + enum TestValue { + POST_GREGORIAN_DATETIME2(new DateTime2Value("1582-10-25 15:07:09.0810000")), + + PRE_GREGORIAN_DTO_VALUE(new DateTimeOffsetValue("1414-01-05 00:00:00.0000000 -08:00")), + + PRE_GREGORIAN_DATETIME2_VALUE(new DateTime2Value("1414-01-05 00:00:00.0000000")), + + ANOTHER_TEST(new DateTimeOffsetValue("3431-04-13 15:23:32.7954829 -05:32")), + + BOA_VISTA(new DateTime2Value("6854-01-27 04:39:54.86772", 5, "America/Boa_Vista")), + + NEGATIVE_OFFSET(new DateTimeOffsetValue("3431-04-13 21:42:14.7954829 -05:32")), + + SOMETIME(new TimeValue("11:58:31.456789", 6)), + + THE_LAST_MILLISECOND_WITH_TIME_ZONE(new DateTimeOffsetValue("9999-12-31 23:59:59.9999999 +14:00")), + + COMMON_ERA_FIRST_DAY(new DateValue("0001-01-01")), + + PRE_CUTOVER(new DateValue("1582-10-04")), + + // Dates in the Gregorian cutover date range appear as 10 days later than what they should. + // This behavior is consistent with other JDBC drivers, such as IBM's: + // http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db2.doc.java/com.ibm.db2.luw.apdv.java.doc/doc/r0053436.htm + CUTOVER_START(new DateValue("1582-10-05")), + + CUTOVER_END(new DateValue("1582-10-14")), + + POST_CUTOVER(new DateValue("1582-10-15")), + + // Last "slow path" date + POST_CUTOVER_PLUS_1(new DateValue("1582-10-16")), + + // First "fast path" date + POST_CUTOVER_PLUS_2(new DateValue("1582-10-17")), + + // VSTS 403522 + // Post-cutover date requiring preservation of "wall calendar" date + // in computing Calendar.DAY_OF_YEAR. + POST_CUTOVER_NOVEMBER(new DateTime2Value("1582-11-15 15:07:09.0810000")), + + A_RECENT_DATE(new DateValue("2009-10-20")), + + A_FRACTION_OF_A_SECOND_PAST_MIDNIGHT(new TimeValue("00:00:00.007", 3)), + + TIME_7(new TimeValue("11:58:31.9999999", 7)), + + DATETIME2_4(new DateTime2Value("2009-10-20 11:58:31.1234", 4)), + + DATETIMEOFFSET(new DateTimeOffsetValue("2009-10-20 11:58:31.1230000 +07:00")); + + final SQLValue sqlValue; + + TestValue(SQLValue sqlValue) { + this.sqlValue = sqlValue; + } + }; + + public void testResultSetGetters() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString); + + for (TestValue value : TestValue.values()) + value.sqlValue.verifyRSGetters(conn); + + conn.close(); + } + + public void testResultSetUpdaters() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString); + + for (TestValue value : TestValue.values()) + value.sqlValue.verifyRSUpdaters(conn); + + conn.close(); + } + + public void testSetters() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDateTime=true"); + + for (TestValue value : TestValue.values()) + value.sqlValue.verifySetters(conn); + + conn.close(); + } + + public void testCallableStatementGetters() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString); + + for (TestValue value : TestValue.values()) + value.sqlValue.verifyCSGetters(conn); + + conn.close(); + } + + public void testResultSetMetaData() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString); + + for (TestValue value : TestValue.values()) + value.sqlValue.verifyResultSetMetaData(conn); + + conn.close(); + } + + public void testParameterMetaData() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString); + + for (TestValue value : TestValue.values()) + value.sqlValue.verifyParameterMetaData(conn); + + conn.close(); + } + + /** + * VSTS 411537 - CS.setObject(timestamp, TIME)/registerOutParam(TIME) on time backend type seems to ignore + * sendTimeAsDatetime knob. + */ + public void testSendTimestampAsTimeAsDatetime() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + Statement stmt = conn.createStatement(); + try { + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + } catch (SQLException e) {} + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @argIn time(7), " + + " @argOut time(7) OUTPUT " + " AS " + " SET @argOut=@argIn"); + + CallableStatement cs = conn.prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}"); + + // Set up a timestamp with a time component that is the last millisecond of the day... + java.sql.Timestamp ts = java.sql.Timestamp.valueOf("2010-02-15 23:59:59.999"); + + // ... and send that timestamp to the server using the TIME SQL type rather than TIMESTAMP. + // If the driver is doing the right thing, it strips the date portion and, because + // sendTimeAsDatetime=true, rounds the resulting time value to midnight because it should + // be sending a DATETIME which has only 1/300s accuracy. + cs.setObject(1, ts, java.sql.Types.TIME); + cs.registerOutParameter(2, java.sql.Types.TIME); + cs.execute(); + + // Fetch the OUT parameter and verify that we have a date-normalized TIME of midnight + java.sql.Time timeOut = cs.getTime(2); + java.sql.Timestamp tsOut = new java.sql.Timestamp(timeOut.getTime()); + assertEquals(tsOut.toString(), "1970-01-01 00:00:00.0", "CS.getTime() - Wrong OUT value"); + + cs.close(); + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + stmt.close(); + conn.close(); + } + + // 507919 - Sending Timestamp to the server via an updater does not result in the same behavior as a setter wrt + // double-rounding of fractional seconds + public void testDoubleRounding() throws Exception { + try (Connection conn = DriverManager.getConnection(connectionString)) { + + // create a table with a datetimeoffset column and insert a value in it + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + + String sql; + try (Statement stmt = conn.createStatement()) { + // SQL Azure requires each table to have a clustered index, so change col1 to the primary key + sql = "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1 int primary key, col2 datetimeoffset(6))"; + stmt.executeUpdate(sql); + sql = "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " VALUES(1, '2010-04-29 10:51:12.123456 +00:00')"; + stmt.executeUpdate(sql); + + } + + try (Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { + + DateTimeOffset dto; + DateTimeOffset actualDto; + + // create select query and update the datetimeoffset + String query = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName); + + try (ResultSet rs = stmt.executeQuery(query)) { + rs.next(); + + // when double-rounding to scale of 6, nanos should be 832909 + java.sql.Timestamp ts = java.sql.Timestamp.valueOf("3432-12-21 15:22:58.832908453"); + dto = DateTimeOffset.valueOf(ts, 0); + + // ts value that goes to driver is 3432-12-21 15:22:58.832908453 + rs.updateTimestamp(2, ts); + rs.updateRow(); // update row + } + + // get the datetime offset from server + sql = "SELECT col2 FROM " + AbstractSQLGenerator.escapeIdentifier(tableName); + try (ResultSet rs = stmt.executeQuery(sql)) { + rs.next(); + Object value = rs.getObject(1); + // 3432-12-21 15:22:58.832909 + actualDto = (DateTimeOffset) value; + } + + // compare after doing a cast on the server to datetimeoffset(6) + sql = "SELECT CAST('" + dto.getTimestamp().toString() + "' as datetimeoffset(6))"; + try (ResultSet rs = stmt.executeQuery(sql)) { + rs.next(); + // 3432-12-21 23:22:58.832909 +00:00 + DateTimeOffset expectedDto = (DateTimeOffset) rs.getObject(1); + assertEquals(actualDto, expectedDto, + "Actual dto: " + actualDto.toString() + ";Expected dto: " + expectedDto.toString()); + } + } finally { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (SQLException e) { + fail(TestResource.getResource("R_createDropTableFailed") + e.toString()); + } + } + } + } + + /** + * Tests "fail fast" SQLException path when a Japanese imperial calendar is used with values representing the first + * year of an imperial era. + * + * See for more details: http://java.sun.com/javase/6/docs/technotes/guides/intl/calendar.doc.html + */ + public void testWithJapaneseImperialCalendar() throws Exception { + // From http://java.sun.com/javase/6/docs/api/java/util/Locale.html : + // "Note: When you ask for a resource for a particular locale, + // you get back the best available match, not necessarily precisely what you asked for. + // For more information, look at ResourceBundle." + // + // Japanese Imperial locale does not exist with some VMs. In these VMs, Locale.US is + // substituted as "best available match". + Locale japaneseImperialLocale = new Locale("ja", "JP", "JP"); + Calendar japaneseImperialCalendar = Calendar.getInstance(japaneseImperialLocale); + + MessageFormat cal = new MessageFormat(TestResource.getResource("R_noJRESupport")); + assumeTrue(GregorianCalendar.class.isInstance(japaneseImperialCalendar), + cal.format(japaneseImperialLocale.toString())); + + Locale defaultLocale = Locale.getDefault(); + Locale.setDefault(japaneseImperialLocale); + try { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + ResultSet rs; + + // Get Gregorian date using Japanese imperial calendar + rs = conn.createStatement().executeQuery("SELECT CAST('0821-01-04' AS DATE)"); + rs.next(); + java.sql.Date date = rs.getDate(1, japaneseImperialCalendar); + assertEquals(date.toString(), "0821-01-04", "Get pre-Meiji"); + rs.close(); + + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))"); + java.sql.Timestamp ts; + + // Set second day of first year of Taisho era (1912 Gregorian) + // Note: Taisho era began July 30, 1912 Gregorian; second day of that year was July 31. + japaneseImperialCalendar.clear(); + japaneseImperialCalendar.set(Calendar.ERA, 2); // Taisho -> ERA 2 + japaneseImperialCalendar.set(Calendar.YEAR, 1); + japaneseImperialCalendar.set(Calendar.DAY_OF_YEAR, 2); + ts = new java.sql.Timestamp(japaneseImperialCalendar.getTimeInMillis()); + ps.setTimestamp(1, ts, japaneseImperialCalendar); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "1912-07-31 00:00:00.0000000", "Set Taisho 1"); + rs.close(); + + // Set second year of Showa era (1927 Gregorian) + japaneseImperialCalendar.clear(); + japaneseImperialCalendar.set(Calendar.ERA, 3); // Showa -> ERA 3 + japaneseImperialCalendar.set(Calendar.YEAR, 2); + japaneseImperialCalendar.set(Calendar.MONTH, Calendar.FEBRUARY); + japaneseImperialCalendar.set(Calendar.DATE, 15); + japaneseImperialCalendar.set(Calendar.HOUR_OF_DAY, 8); + japaneseImperialCalendar.set(Calendar.MINUTE, 49); + japaneseImperialCalendar.set(Calendar.SECOND, 3); + japaneseImperialCalendar.set(Calendar.MILLISECOND, 87); + ts = new java.sql.Timestamp(japaneseImperialCalendar.getTimeInMillis()); + ps.setTimestamp(1, ts, japaneseImperialCalendar); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "1927-02-15 08:49:03.0870000", "Set Showa 2"); + rs.close(); + + ps.close(); + conn.close(); + } finally { + Locale.setDefault(defaultLocale); + } + } + + enum StringFormatTestValue { + TIME_ZEROS_FILL("02:34:56.1", "TIME(3)"), + + TIME_NO_FRACTIONAL_SECONDS_WITH_SCALE("02:34:56", "TIME(3)"), + + TIME_ROUNDED_WITH_SCALE("02:34:56.777", "TIME(2)"), + + TIME_WITH_ZERO_SCALE("02:34:56", "TIME(0)"), + + DATETIME2_ZEROS_FILL("2010-03-10 02:34:56.1", "DATETIME2(3)"), + + DATETIME2_NO_FRACTIONAL_SECONDS_WITH_SCALE("2010-03-10 02:34:56", "DATETIME2(3)"), + + DATETIME2_ROUNDED_WITH_SCALE("2010-03-10 02:34:56.777", "DATETIME2(2)"), + + DATETIME2_WITH_ZERO_SCALE("2010-03-10 02:34:56", "DATETIME2(0)"), + + DATETIMEOFFSET_ZEROS_FILL("2010-03-10 02:34:56.1 -08:00", "DATETIMEOFFSET(3)"), + + DATETIMEOFFSET_NO_FRACTIONAL_SECONDS_WITH_SCALE("2010-03-10 02:34:56 -08:00", "DATETIMEOFFSET(3)"), + + DATETIMEOFFSET_ROUNDED_WITH_SCALE("2010-03-10 02:34:56.777 -08:00", "DATETIMEOFFSET(2)"), + + DATETIMEOFFSET_WITH_ZERO_SCALE("2010-03-10 02:34:56 -08:00", "DATETIMEOFFSET(0)"); + + final String sqlLiteral; + final String sqlType; + + StringFormatTestValue(String sqlLiteral, String sqlType) { + this.sqlLiteral = sqlLiteral; + this.sqlType = sqlType; + } + } + + @Test + public void testGetString() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString); + Statement stmt = conn.createStatement(); + + for (StringFormatTestValue testValue : EnumSet.allOf(StringFormatTestValue.class)) { + String query = "SELECT " + "CAST('" + testValue.sqlLiteral + "' AS " + testValue.sqlType + "), " + + "CAST(CAST('" + testValue.sqlLiteral + "' AS " + testValue.sqlType + ") AS VARCHAR)"; + + ResultSet rs = stmt.executeQuery(query); + rs.next(); + assertEquals(rs.getString(1), rs.getString(2), "Test failed for " + testValue); + rs.close(); + } + + stmt.close(); + conn.close(); + } + + @Test + public void testWithThaiLocale() throws Exception { + Locale locale = Locale.getDefault(); + Locale.setDefault(new Locale("th", "TH")); + try { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + + ResultSet rs; + + // Test setter conversions + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))"); + + // Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, month + // is from 0-11. + java.sql.Timestamp ts = new java.sql.Timestamp(2009 - 1900, 10, 17, 15, 23, 32, 0); + + // Test PreparedStatement with Timestamp + // Value sent as DATETIME2; result should have 7 digits of subsecond precision) + ps.setTimestamp(1, ts); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "2009-11-17 15:23:32.0000000", "Timestamp mismatch"); + rs.close(); + + // Test PreparedStatement with Time + // Value sent as DATETIME w/Unix Epoch as base date when sendTimeAsDatetime=true + java.sql.Time time = new java.sql.Time(ts.getTime()); + ps.setTime(1, time); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "Jan 1 1970 3:23PM", "Time mismatch"); + rs.close(); + + // Test PreparedStatement with Date + java.sql.Date date = new java.sql.Date(ts.getTime()); + ps.setDate(1, date); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "2009-11-17", "Date mismatch"); + rs.close(); + + // Test PreparedStatement with Date (using Buddhist calendar) + date = new java.sql.Date(ts.getTime()); + ps.setDate(1, date, Calendar.getInstance()); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "2009-11-17", "Date mismatch (w/calendar)"); + rs.close(); + + // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) + // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. + DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance()); + ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "2009-11-17 15:23:32.0000000 -08:00", "DateTimeOffset mismatch"); + rs.close(); + + ps.close(); + conn.close(); + } finally { + Locale.setDefault(locale); + } + } + + // DCR 393826 - DCR Need base date compatibility for Time to DATETIMEx conversions with 2.0 driver + @Test + public void testBaseDate() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + // Test Java base date (1/1/1970) + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIME)"); + ps.setTime(1, java.sql.Time.valueOf("12:34:56")); + ResultSet rs = ps.executeQuery(); + rs.next(); + Timestamp ts = rs.getTimestamp(1); + assertEquals(ts.toString(), "1970-01-01 12:34:56.0", "Expected Java base date"); + rs.close(); + ps.close(); + conn.close(); + + // Test SQL Server base date (1/1/1900) + conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=false"); + ps = conn.prepareStatement("SELECT CAST(? AS DATETIME)"); + ps.setTime(1, java.sql.Time.valueOf("12:34:56")); + rs = ps.executeQuery(); + rs.next(); + ts = rs.getTimestamp(1); + assertEquals(ts.toString(), "1900-01-01 12:34:56.0", "Expected SQL Server base date"); + rs.close(); + ps.close(); + conn.close(); + } + + // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset (+00:00) + @Test + public void testTimestampToDateTimeOffset() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + Connection conn = DriverManager.getConnection(connectionString); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIMEOFFSET)"); + ps.setTimestamp(1, java.sql.Timestamp.valueOf("2010-01-06 12:34:56")); + ResultSet rs = ps.executeQuery(); + rs.next(); + DateTimeOffset dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); + assertEquals(dto.toString(), "2010-01-06 12:34:56 +00:00", "Wrong value"); + rs.close(); + ps.close(); + conn.close(); + } + + // VSTS 400431 - PS.setObject() on a datetime2 with values on or after 0700-02-29 have a value one day ahead stored + // in the server + @Test + public void testJulianLeapYear() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + // PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR)"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATE)"); + ResultSet rs; + + // Julian date from string + java.sql.Date julianDate = java.sql.Date.valueOf("0700-03-01"); + ps.setDate(1, julianDate); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "0700-03-01", "Wrong date returned"); + rs.close(); + + ps.close(); + conn.close(); + } + + @Test + public void testGetTimeRounding() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + Statement stmt = conn.createStatement(); + ResultSet rs; + + // Test getTime() rounding from TIME(6) SQL type + rs = stmt.executeQuery("SELECT CAST('12:34:56.999500' AS TIME)"); + rs.next(); + assertEquals(rs.getTime(1).toString(), "12:34:57", "Rounding from TIME(6) failed"); + rs.close(); + + // Test getTime() rounding from character data + rs = stmt.executeQuery("SELECT '12:34:56.999500'"); + rs.next(); + assertEquals(rs.getTime(1).toString(), "12:34:57", "Rounding from character data failed"); + rs.close(); + + stmt.close(); + conn.close(); + } + + @Test + public void testGregorianCutoverDateTime2() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR)"); + ResultSet rs; + Timestamp ts; + + // Test setting value during the Gregorian cutover via Timestamp constructed from String + ts = java.sql.Timestamp.valueOf("1582-10-24 15:07:09.081"); + ps.setTimestamp(1, ts); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "1582-10-24 15:07:09.0810000", "Wrong value"); + rs.close(); + + // Test setting value during the Gregorian cutover via Timestamp constructed from Calendar + Calendar cal = Calendar.getInstance(); + cal.set(1582, Calendar.NOVEMBER, 1, 15, 7, 9); + cal.set(Calendar.MILLISECOND, 81); + ts = new java.sql.Timestamp(cal.getTimeInMillis()); + ps.setTimestamp(1, ts); + rs = ps.executeQuery(); + rs.next(); + assertEquals(rs.getString(1), "1582-11-01 15:07:09.0810000", "Wrong value"); + rs.close(); + + ps.close(); + conn.close(); + } + + // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset (+00:00) + // + // In this case, verify that SELECT with a WHERE clause doesn't fail due to mapping the Timestamp value to a + // SQL Server type that does not compare equal. For example, a DATETIMEOFFSET and DATETIME only compare equal + // if the DATETIMEOFFSET offset is 0 (UTC). + @Test + public void testTimestampToDateTime() throws Exception { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + Connection conn = DriverManager.getConnection(connectionString); + PreparedStatement ps = conn.prepareStatement("SELECT 1 WHERE ?=CAST('2009-12-17 17:00:29' AS DATETIME)"); + ps.setTimestamp(1, java.sql.Timestamp.valueOf("2009-12-17 17:00:29")); + ResultSet rs = ps.executeQuery(); + assertEquals(rs.next(), true, "Timestamp to DATETIME comparison failed for equal values"); + rs.close(); + ps.close(); + conn.close(); + } + + // testUpdateMisc + // + // Haphazard collection of bugs that popped up during unit testing (i.e. regression tests) + @Test + public void testUpdateMisc() throws Exception { + + // + ""[" + driver.createuniqueidentifer("testUpdateMisc") + "]"; + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + SQLServerConnection conn = (SQLServerConnection) DriverManager + .getConnection(connectionString + ";sendTimeAsDatetime=true"); + + assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + + Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + try { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (SQLException e) {} + stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1 datetimeoffset(2)," + " col2 datetime," + " col3 time(5)," + " col4 datetime2(5)," + + " col5 smalldatetime," + " col6 time(2)," + " col7 int identity(1,1) primary key)"); + stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" + + " '2010-01-12 09:00:23.17 -08:00'," + " '2010-01-12 10:20:23'," + " '10:20:23'," + + " '2010-01-12 10:20:23'," + " '2010-01-12 11:45:17'," + " '10:20:23')"); + + try { + DateTimeOffset dto; + + ResultSet rs = stmt.executeQuery( + "SELECT *, CAST(col1 AS VARCHAR) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)); + rs.next(); + + // Update datetimeoffset(2) from pre-Gregorian Date + rs.updateDate(1, java.sql.Date.valueOf("0814-02-18")); + rs.updateRow(); + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), "0814-02-18 00:00:00 +00:00", + "Update of datetimeoffset(2) from pre-Gregorian Date"); + + // Update datetimeoffset(2) from "last" Time + rs.updateTime(1, new java.sql.Time(Timestamp.valueOf("1970-01-01 23:59:59.998").getTime())); + rs.updateRow(); + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), "1970-01-02 00:00:00 +00:00", + "Update datetimeoffset(2) from last Time"); + + // Update datetimeoffset(2) from the "last" Timestamp + rs.updateTimestamp(1, java.sql.Timestamp.valueOf("9999-12-31 23:59:59.998")); + rs.updateRow(); + dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); + assertEquals(dto.toString(), "9999-12-31 23:59:59.99 +00:00", + "Update datetimeoffset(2) from last Timestamp"); + + // Attempt to update datetimeoffset(2) from the first out of range value + // Verify that an exception is thrown and that the statement/connection is still usable after + try { + java.sql.Timestamp tsInvalid = java.sql.Timestamp.valueOf("9999-12-31 23:59:59.999999999"); + tsInvalid = new java.sql.Timestamp(tsInvalid.getTime() + 1); + rs.updateTimestamp(1, tsInvalid); + rs.updateRow(); + assertEquals(false, true, "Update succeeded with out of range value"); + } catch (SQLServerException e) { + assertEquals(e.getSQLState(), "22008", // data exception - datetime field overflow (ISO/IEC + // 9075-2:1999) + "Wrong exception received"); + } + + // Update time(5) from Timestamp with nanos more precise than 100ns + Timestamp ts = java.sql.Timestamp.valueOf("2010-01-12 11:05:23"); + ts.setNanos(987659999); + rs.updateTimestamp(3, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 11:05:23.98766", + "Update time(5) from Timestamp with sub-100ns nanos"); + + // Update time(5) from Timestamp to max value in a day. The value should not be rounded + ts = java.sql.Timestamp.valueOf("2010-01-12 23:59:59"); + ts.setNanos(999999999); + Time time = new java.sql.Time(ts.getTime()); + rs.updateTimestamp(3, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.99999", + "Update time(5) from Timestamp to max value in a day"); + + // Update time(2) from Time to max value in a day. The value should not be rounded + rs.updateTime(6, time); + rs.updateRow(); + assertEquals(new java.sql.Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is + // necessary to see fractional + // secs + "1970-01-01 23:59:59.99", "Update time(2) from Time to max value in a day"); + + // Update time(5) from Timestamp to max value in a second. The value should be rounded + ts = java.sql.Timestamp.valueOf("2010-01-12 23:59:58"); + ts.setNanos(999999999); + time = new java.sql.Time(ts.getTime()); + rs.updateTimestamp(3, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.0", + "Update time(5) from Timestamp to max value in a second"); + + // Update time(2) from Time to max value in a second. The value should be rounded + rs.updateTime(6, time); + rs.updateRow(); + assertEquals(new java.sql.Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is + // necessary to see fractional + // secs + "1970-01-01 23:59:59.0", "Update time(2) from Time to max value in a second"); + + // Update datetime w/expected rounding of nanos to DATETIME's 1/300second resolution + ts = java.sql.Timestamp.valueOf("6289-04-22 05:13:57.6745106"); + rs.updateTimestamp(2, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(2).toString(), "6289-04-22 05:13:57.677", + "Update datetime from Timestamp with sub-1/3second nanos"); + + // Update datetime with rounding-induced overflow from Time + // (should roll date part to 1/2/1970) + ts = java.sql.Timestamp.valueOf("2010-01-18 23:59:59.999"); + rs.updateTime(2, new java.sql.Time(ts.getTime())); + rs.updateRow(); + assertEquals(rs.getTimestamp(2).toString(), "1970-01-02 00:00:00.0", + "Update datetime from Time near next day"); + + rs.close(); + } finally { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + stmt.close(); + conn.close(); + } + } + +} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java index 6144e4e28..d7625a514 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java @@ -356,7 +356,7 @@ public void testHoldability() throws SQLException { } } } - + /** * Call resultset methods to run thru some code paths * @@ -364,14 +364,17 @@ public void testHoldability() throws SQLException { */ @Test public void testResultSetMethods() throws SQLException { - try (Connection con = DriverManager.getConnection(connectionString); Statement stmt = con - .createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + try (Connection con = DriverManager.getConnection(connectionString); + Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + stmt.executeUpdate("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1 int primary key, col2 varchar(255))"); + stmt.executeUpdate( + "insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, " + " 'one')"); stmt.executeUpdate( - "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 int primary key)"); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0)"); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(1)"); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(2)"); + "insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(1, " + "'two')"); + stmt.executeUpdate( + "insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(2, " + "'three')"); try (ResultSet rs = stmt .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(tableName))) { @@ -383,13 +386,13 @@ public void testResultSetMethods() throws SQLException { // check cursor rs.first(); assert (rs.isFirst()); - + rs.relative(1); assert (!rs.isFirst()); rs.last(); assert (rs.isLast()); - + rs.beforeFirst(); assert (rs.isBeforeFirst()); @@ -402,9 +405,38 @@ public void testResultSetMethods() throws SQLException { rs.moveToInsertRow(); assert (rs.getRow() == 0); + + // insert and update + rs.updateInt(1, 4); + rs.updateString(2, "four"); + rs.insertRow(); + + rs.updateObject(1, 5); + rs.updateObject(2, new String("five")); + rs.insertRow(); + + rs.updateObject("col1", 6); + rs.updateObject("col2", new String("six")); + rs.insertRow(); + + rs.updateObject(1, 7, 0); + rs.updateObject("col2", new String("seven"), 0); + rs.insertRow(); + + // valid column names + assert (rs.findColumn("col1") == 1); + assert (rs.findColumn("col2") == 2); + + // invalid column name + try { + rs.findColumn("col3"); + } catch (SQLException e) { + assertTrue(e.getMessage().contains("column name col3 is not valid")); + } + rs.moveToCurrentRow(); assert (rs.getRow() == 1); - + // no inserts or updates assert (!rs.rowInserted()); assert (!rs.rowUpdated()); @@ -422,11 +454,15 @@ public void testResultSetMethods() throws SQLException { rs.refreshRow(); - // test delete row + rs.previous(); + assert (!rs.rowDeleted()); + rs.next(); + + // delete row do { rs.moveToCurrentRow(); - rs.deleteRow(); - assert (rs.rowDeleted()); + rs.deleteRow(); + assert (rs.rowDeleted()); } while (rs.next()); } catch (Exception e) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java similarity index 97% rename from src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java rename to src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index d6bcc4439..d71a12d32 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialT.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -7,7 +7,6 @@ import org.junit.runner.RunWith; import junit.framework.*; -import javax.sql.*; import com.microsoft.sqlserver.jdbc.*; import microsoft.sql.*; @@ -18,7 +17,7 @@ @RunWith(JUnitPlatform.class) -public class DTOSerialT { +public class DTOSerialTest { private static final String dateString = "2007-05-08 12:35:29.1234567 +12:15"; // public static void testDSerial(String connString) throws Exception diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java index b43dd312e..ac9d27dfd 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/StatementTest.java @@ -1111,11 +1111,11 @@ public void testJdbc41CallableStatementMethods() throws Exception { + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}")) { cstmt.registerOutParameter(1, java.sql.Types.VARCHAR); cstmt.registerOutParameter(2, java.sql.Types.INTEGER); - cstmt.registerOutParameter(3, java.sql.Types.FLOAT); - cstmt.registerOutParameter(4, java.sql.Types.DECIMAL); + cstmt.registerOutParameter("col3Value", java.sql.Types.FLOAT); + cstmt.registerOutParameter(4, java.sql.Types.DECIMAL, 2); cstmt.registerOutParameter(5, microsoft.sql.Types.GUID); cstmt.registerOutParameter(6, java.sql.Types.SQLXML); - cstmt.registerOutParameter(7, java.sql.Types.VARBINARY); + cstmt.registerOutParameter("col7Value", java.sql.Types.VARBINARY, 10); cstmt.registerOutParameter(8, java.sql.Types.CLOB); cstmt.registerOutParameter(9, java.sql.Types.NCLOB); cstmt.registerOutParameter(10, java.sql.Types.VARBINARY); @@ -1123,8 +1123,8 @@ public void testJdbc41CallableStatementMethods() throws Exception { cstmt.registerOutParameter(12, java.sql.Types.TIME); cstmt.registerOutParameter(13, java.sql.Types.TIMESTAMP); cstmt.registerOutParameter(14, java.sql.Types.TIMESTAMP_WITH_TIMEZONE); - cstmt.registerOutParameter(15, java.sql.Types.DECIMAL); - cstmt.registerOutParameter(16, java.sql.Types.DECIMAL); + cstmt.registerOutParameter(15, java.sql.Types.DECIMAL, "DECIMAL"); + cstmt.registerOutParameter("col16Value", java.sql.Types.DECIMAL, "DECIMAL"); cstmt.execute(); assertEquals("hello", cstmt.getObject(1, String.class)); From 3275750d8a225ad5da9c5a1c14a7d5c8f18525a4 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 16 Nov 2018 16:38:42 -0800 Subject: [PATCH 05/33] fixed issue with timezone --- .../sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 5c15b55a5..48e7e6e2e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -1461,10 +1461,11 @@ public void testWithThaiLocale() throws Exception { // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance()); + DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance(TimeZone.getDefault())); ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); rs = ps.executeQuery(); rs.next(); + assertEquals(rs.getString(1), "2009-11-17 15:23:32.0000000 -08:00", "DateTimeOffset mismatch"); rs.close(); From 45eeef5235147f001bb87cde5b10cf3bc0d1b1db Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 16 Nov 2018 17:53:49 -0800 Subject: [PATCH 06/33] fixed issue with timezone --- .../jdbc/datatypes/KatmaiDataTypesTest.java | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 48e7e6e2e..f1b762924 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -30,16 +30,6 @@ public class KatmaiDataTypesTest extends AbstractTest { final static String tableName = RandomUtil.getIdentifier("KatmaiDataTypesTable"); final static String procName = RandomUtil.getIdentifier("KatmaiDataTypesTableProc"); - /* - * public void testSparse() throws Exception { - * assumeTrue(!isSqlAzure(DriverManager.getConnection(connectionString)), TestResource.getResource("R_skipAzure")); - * try (Connection connection = DriverManager.getConnection(connectionString) { - * SparseTest.runTest(connectionString); } } public void testJDBC41BigInteger() throws Exception { if - * (fxConnection.isServerSqlAzureDW()) { - * CTestLog.Skip("this test is skipped because it cannot be meaningfully tested on SQL Azure DW."); } - * BigIntegerTest.runTest(connectionString); } - */ - enum SQLType { date("yyyy-mm-dd", 0, java.sql.Types.DATE, "java.sql.Date"), @@ -133,9 +123,6 @@ void verifyResultSetMetaData(Connection conn) throws Exception { void verifyParameterMetaData(Connection conn) throws Exception { - final String procName = RandomUtil.getIdentifier("testParameterMetaData"); - // final String procName = "[" + driver.createuniqueidentifer("testParameterMetaData") + "]"; - Statement stmt = null; PreparedStatement pstmt = null; @@ -143,9 +130,9 @@ void verifyParameterMetaData(Connection conn) throws Exception { stmt = conn.createStatement(); // Create the stored proc - stmt.executeUpdate("CREATE PROCEDURE " + procName + " @arg " + sqlTypeExpression + " AS SELECT @arg"); + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @arg " + sqlTypeExpression + " AS SELECT @arg"); - pstmt = conn.prepareStatement("{call " + procName + "(?)}"); + pstmt = conn.prepareStatement("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?)}"); ParameterMetaData metadata = pstmt.getParameterMetaData(); assertEquals(metadata.getParameterType(1), sqlType.jdbcType, @@ -165,7 +152,7 @@ void verifyParameterMetaData(Connection conn) throws Exception { pstmt.close(); if (null != stmt) { - stmt.executeUpdate("DROP PROCEDURE " + procName); + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); stmt.close(); } } @@ -187,7 +174,7 @@ void verifyRSGetters(Connection conn) throws Exception { void verifyRSUpdaters(Connection conn) throws Exception { - assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); try { @@ -223,7 +210,7 @@ void verifyRSUpdaters(Connection conn) throws Exception { abstract void verifySettersCalendar(PreparedStatement ps) throws Exception; void verifySetters(Connection conn) throws Exception { - assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); try { @@ -1218,7 +1205,7 @@ public void testDoubleRounding() throws Exception { // create a table with a datetimeoffset column and insert a value in it Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); String sql; try (Statement stmt = conn.createStatement()) { @@ -1461,7 +1448,8 @@ public void testWithThaiLocale() throws Exception { // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance(TimeZone.getDefault())); + DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); + ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); rs = ps.executeQuery(); rs.next(); @@ -1632,7 +1620,7 @@ public void testUpdateMisc() throws Exception { SQLServerConnection conn = (SQLServerConnection) DriverManager .getConnection(connectionString + ";sendTimeAsDatetime=true"); - assumeTrue(TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); try { From c5f4a9d415ffeb6e83ca5695ab1d5408dfe4ec38 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 19 Nov 2018 13:26:09 -0800 Subject: [PATCH 07/33] modified testWithThaiLocale to use current time --- .../jdbc/datatypes/KatmaiDataTypesTest.java | 126 +++++++++--------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index f1b762924..5dca35f08 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -9,6 +9,8 @@ import java.math.*; import java.util.*; +import java.sql.Date; +import java.sql.Timestamp; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -31,7 +33,7 @@ public class KatmaiDataTypesTest extends AbstractTest { final static String procName = RandomUtil.getIdentifier("KatmaiDataTypesTableProc"); enum SQLType { - date("yyyy-mm-dd", 0, java.sql.Types.DATE, "java.sql.Date"), + date("yyyy-mm-dd", 0, java.sql.Types.DATE, "Date"), time("hh:mm:ss", 7, java.sql.Types.TIME, "java.sql.Time"), @@ -265,15 +267,15 @@ void verifyCSGetters(Connection conn) throws Exception { } static final class DateValue extends SQLValue { - private final java.sql.Date expected; + private final Date expected; DateValue(String stringValue) { super(SQLType.date, stringValue); - this.expected = java.sql.Date.valueOf(stringValue); + this.expected = Date.valueOf(stringValue); } - private java.sql.Timestamp expectedTimestampMillisPrecision() { - return new java.sql.Timestamp(expected.getTime()); + private Timestamp expectedTimestampMillisPrecision() { + return new Timestamp(expected.getTime()); } private java.util.Date expectedUtilDate() { @@ -291,7 +293,7 @@ void verifyRSGetters(ResultSet rs) throws Exception { assertEquals(rs.getDate(1), expected, "getDate mismatch"); - assertEquals(rs.getTimestamp(1), new java.sql.Timestamp(expected.getTime()), "getTimestamp mismatch"); + assertEquals(rs.getTimestamp(1), new Timestamp(expected.getTime()), "getTimestamp mismatch"); assertEquals(rs.getString(1), expected.toString(), "getString mismatch"); @@ -379,7 +381,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); assertEquals(rs.getDate(1), expected, "getDate mismatch"); - // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, java.sql.Date + // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date // or java.util.Date can be cast to a calendar // Test the additional conversions introduced in JDBC41 for types setters @@ -443,12 +445,12 @@ private void initExpected(String stringValue, TimeZone tz) { this.tz = tz; } - private java.sql.Timestamp expectedTimestamp() { + private Timestamp expectedTimestamp() { Calendar cal = Calendar.getInstance(tz); cal.clear(); cal.set(1900, Calendar.JANUARY, 1, hour, minute, second); - java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis()); + Timestamp timestamp = new Timestamp(cal.getTimeInMillis()); timestamp.setNanos(nanos); return timestamp; @@ -464,13 +466,13 @@ private java.sql.Time expectedTime() { return new java.sql.Time(cal.getTimeInMillis()); } - private java.sql.Timestamp expectedTimestampMillisPrecision() { + private Timestamp expectedTimestampMillisPrecision() { Calendar cal = Calendar.getInstance(tz); cal.clear(); cal.set(1900, Calendar.JANUARY, 1, hour, minute, second); cal.set(Calendar.MILLISECOND, (nanos + 500000) / 1000000); - java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis()); + Timestamp timestamp = new Timestamp(cal.getTimeInMillis()); return timestamp; } @@ -588,7 +590,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { assertEquals(rs.getTime(1), expectedTime(), "getTime mismatch"); assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); - // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, java.sql.Date + // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date // or java.util.Date can be cast to a calendar // Test the additional conversions introduced in JDBC41 for types setters @@ -676,14 +678,14 @@ private void initExpected(String timestampString, TimeZone tz) { this.tz = tz; } - private java.sql.Date expectedDate() { + private Date expectedDate() { Calendar cal = Calendar.getInstance(tz); cal.setTimeInMillis(utcMillis); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - return new java.sql.Date(cal.getTimeInMillis()); + return new Date(cal.getTimeInMillis()); } private java.sql.Time expectedTime() { @@ -697,14 +699,14 @@ private java.sql.Time expectedTime() { return new java.sql.Time(cal.getTimeInMillis()); } - private java.sql.Timestamp expectedTimestamp() { - Timestamp timestamp = new java.sql.Timestamp(utcMillis); + private Timestamp expectedTimestamp() { + Timestamp timestamp = new Timestamp(utcMillis); timestamp.setNanos(nanos); return timestamp; } - private java.sql.Timestamp expectedTimestampMillisPrecision() { - Timestamp timestamp = new java.sql.Timestamp(utcMillis); + private Timestamp expectedTimestampMillisPrecision() { + Timestamp timestamp = new Timestamp(utcMillis); // Cannot set the nanos to 0, as per doc " the fractional seconds are stored in the nanos field of the // Timestamp object." // timestamp.setNanos(0); @@ -849,7 +851,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision(), "getTimestamp mismatch"); - // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, java.sql.Date + // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date // or java.util.Date can be cast to a calendar // Test the additional conversions introduced in JDBC41 for types setters @@ -922,7 +924,7 @@ private final DateTimeOffset initExpected(String stringValue, int fractionalSeco cal.set(Calendar.MINUTE, minute); cal.set(Calendar.SECOND, second); - java.sql.Timestamp timestamp = new java.sql.Timestamp(cal.getTimeInMillis()); + Timestamp timestamp = new Timestamp(cal.getTimeInMillis()); timestamp.setNanos(nanos); return DateTimeOffset.valueOf(timestamp, minutesOffset); @@ -938,14 +940,14 @@ private final DateTimeOffset initExpected(String stringValue, int fractionalSeco dto = initExpected(stringValue, fractionalSecondsDigits); } - private java.sql.Date expectedDate() { + private Date expectedDate() { Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); cal.setTimeInMillis(dto.getTimestamp().getTime()); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - return new java.sql.Date(cal.getTimeInMillis()); + return new Date(cal.getTimeInMillis()); } private java.sql.Time expectedTime() { @@ -960,13 +962,13 @@ private java.sql.Time expectedTime() { return new java.sql.Time(cal.getTimeInMillis()); } - private java.sql.Timestamp expectedTimestamp() { + private Timestamp expectedTimestamp() { Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); cal.setTimeInMillis(dto.getTimestamp().getTime()); if (dto.getTimestamp().getNanos() % 1000000 >= 500000) cal.add(Calendar.MILLISECOND, 1); - return new java.sql.Timestamp(cal.getTimeInMillis()); + return new Timestamp(cal.getTimeInMillis()); } private java.util.Date expectedUtilDate() { @@ -1020,7 +1022,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { /* * Cannot test by setObject(...,java.util.Date) with the back end data type as datetimeoffset because by * design anything but datetimeoffset is normalized to UTC time zone in the source code (in sendTemporal - * function in dtv.java) setObject(...,java.sql.Date) and setObject(...,java.utl.date) gets same exception + * function in dtv.java) setObject(...,Date) and setObject(...,java.utl.date) gets same exception */ } @@ -1177,7 +1179,7 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { CallableStatement cs = conn.prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}"); // Set up a timestamp with a time component that is the last millisecond of the day... - java.sql.Timestamp ts = java.sql.Timestamp.valueOf("2010-02-15 23:59:59.999"); + Timestamp ts = Timestamp.valueOf("2010-02-15 23:59:59.999"); // ... and send that timestamp to the server using the TIME SQL type rather than TIMESTAMP. // If the driver is doing the right thing, it strips the date portion and, because @@ -1189,7 +1191,7 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { // Fetch the OUT parameter and verify that we have a date-normalized TIME of midnight java.sql.Time timeOut = cs.getTime(2); - java.sql.Timestamp tsOut = new java.sql.Timestamp(timeOut.getTime()); + Timestamp tsOut = new Timestamp(timeOut.getTime()); assertEquals(tsOut.toString(), "1970-01-01 00:00:00.0", "CS.getTime() - Wrong OUT value"); cs.close(); @@ -1231,7 +1233,7 @@ public void testDoubleRounding() throws Exception { rs.next(); // when double-rounding to scale of 6, nanos should be 832909 - java.sql.Timestamp ts = java.sql.Timestamp.valueOf("3432-12-21 15:22:58.832908453"); + Timestamp ts = Timestamp.valueOf("3432-12-21 15:22:58.832908453"); dto = DateTimeOffset.valueOf(ts, 0); // ts value that goes to driver is 3432-12-21 15:22:58.832908453 @@ -1298,12 +1300,12 @@ public void testWithJapaneseImperialCalendar() throws Exception { // Get Gregorian date using Japanese imperial calendar rs = conn.createStatement().executeQuery("SELECT CAST('0821-01-04' AS DATE)"); rs.next(); - java.sql.Date date = rs.getDate(1, japaneseImperialCalendar); + Date date = rs.getDate(1, japaneseImperialCalendar); assertEquals(date.toString(), "0821-01-04", "Get pre-Meiji"); rs.close(); PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))"); - java.sql.Timestamp ts; + Timestamp ts; // Set second day of first year of Taisho era (1912 Gregorian) // Note: Taisho era began July 30, 1912 Gregorian; second day of that year was July 31. @@ -1311,7 +1313,7 @@ public void testWithJapaneseImperialCalendar() throws Exception { japaneseImperialCalendar.set(Calendar.ERA, 2); // Taisho -> ERA 2 japaneseImperialCalendar.set(Calendar.YEAR, 1); japaneseImperialCalendar.set(Calendar.DAY_OF_YEAR, 2); - ts = new java.sql.Timestamp(japaneseImperialCalendar.getTimeInMillis()); + ts = new Timestamp(japaneseImperialCalendar.getTimeInMillis()); ps.setTimestamp(1, ts, japaneseImperialCalendar); rs = ps.executeQuery(); rs.next(); @@ -1328,7 +1330,7 @@ public void testWithJapaneseImperialCalendar() throws Exception { japaneseImperialCalendar.set(Calendar.MINUTE, 49); japaneseImperialCalendar.set(Calendar.SECOND, 3); japaneseImperialCalendar.set(Calendar.MILLISECOND, 87); - ts = new java.sql.Timestamp(japaneseImperialCalendar.getTimeInMillis()); + ts = new Timestamp(japaneseImperialCalendar.getTimeInMillis()); ps.setTimestamp(1, ts, japaneseImperialCalendar); rs = ps.executeQuery(); rs.next(); @@ -1398,6 +1400,11 @@ public void testGetString() throws Exception { @Test public void testWithThaiLocale() throws Exception { + java.text.SimpleDateFormat tsFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000"); + java.text.SimpleDateFormat timeFormat = new java.text.SimpleDateFormat("K:mmaa"); + java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd"); + java.text.SimpleDateFormat dtoFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000 XXX"); + Locale locale = Locale.getDefault(); Locale.setDefault(new Locale("th", "TH")); try { @@ -1411,50 +1418,49 @@ public void testWithThaiLocale() throws Exception { // Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, month // is from 0-11. - java.sql.Timestamp ts = new java.sql.Timestamp(2009 - 1900, 10, 17, 15, 23, 32, 0); + Timestamp ts = new Timestamp(System.currentTimeMillis()); // Test PreparedStatement with Timestamp // Value sent as DATETIME2; result should have 7 digits of subsecond precision) ps.setTimestamp(1, ts); rs = ps.executeQuery(); rs.next(); - assertEquals(rs.getString(1), "2009-11-17 15:23:32.0000000", "Timestamp mismatch"); + assertEquals(rs.getString(1), tsFormat.format(ts), "Timestamp mismatch"); + rs.close(); // Test PreparedStatement with Time // Value sent as DATETIME w/Unix Epoch as base date when sendTimeAsDatetime=true - java.sql.Time time = new java.sql.Time(ts.getTime()); + java.sql.Time time = new java.sql.Time(ts.getTime()); ps.setTime(1, time); rs = ps.executeQuery(); rs.next(); - assertEquals(rs.getString(1), "Jan 1 1970 3:23PM", "Time mismatch"); + assertEquals(rs.getString(1), "Jan 1 1970 " + timeFormat.format(ts.getTime()), "Time mismatch"); rs.close(); // Test PreparedStatement with Date - java.sql.Date date = new java.sql.Date(ts.getTime()); + Date date = new Date(ts.getTime()); ps.setDate(1, date); rs = ps.executeQuery(); rs.next(); - assertEquals(rs.getString(1), "2009-11-17", "Date mismatch"); + assertEquals(rs.getString(1), dateFormat.format(ts), "Date mismatch"); rs.close(); // Test PreparedStatement with Date (using Buddhist calendar) - date = new java.sql.Date(ts.getTime()); + date = new Date(ts.getTime()); ps.setDate(1, date, Calendar.getInstance()); rs = ps.executeQuery(); rs.next(); - assertEquals(rs.getString(1), "2009-11-17", "Date mismatch (w/calendar)"); + assertEquals(rs.getString(1), dateFormat.format(ts), "Date mismatch (w/calendar)"); rs.close(); // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); - + DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance()); ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); rs = ps.executeQuery(); rs.next(); - - assertEquals(rs.getString(1), "2009-11-17 15:23:32.0000000 -08:00", "DateTimeOffset mismatch"); + assertEquals(rs.getString(1), dtoFormat.format(ts), "DateTimeOffset mismatch"); rs.close(); ps.close(); @@ -1501,7 +1507,7 @@ public void testTimestampToDateTimeOffset() throws Exception { Connection conn = DriverManager.getConnection(connectionString); PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIMEOFFSET)"); - ps.setTimestamp(1, java.sql.Timestamp.valueOf("2010-01-06 12:34:56")); + ps.setTimestamp(1, Timestamp.valueOf("2010-01-06 12:34:56")); ResultSet rs = ps.executeQuery(); rs.next(); DateTimeOffset dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); @@ -1522,7 +1528,7 @@ public void testJulianLeapYear() throws Exception { ResultSet rs; // Julian date from string - java.sql.Date julianDate = java.sql.Date.valueOf("0700-03-01"); + Date julianDate = Date.valueOf("0700-03-01"); ps.setDate(1, julianDate); rs = ps.executeQuery(); rs.next(); @@ -1567,7 +1573,7 @@ public void testGregorianCutoverDateTime2() throws Exception { Timestamp ts; // Test setting value during the Gregorian cutover via Timestamp constructed from String - ts = java.sql.Timestamp.valueOf("1582-10-24 15:07:09.081"); + ts = Timestamp.valueOf("1582-10-24 15:07:09.081"); ps.setTimestamp(1, ts); rs = ps.executeQuery(); rs.next(); @@ -1578,7 +1584,7 @@ public void testGregorianCutoverDateTime2() throws Exception { Calendar cal = Calendar.getInstance(); cal.set(1582, Calendar.NOVEMBER, 1, 15, 7, 9); cal.set(Calendar.MILLISECOND, 81); - ts = new java.sql.Timestamp(cal.getTimeInMillis()); + ts = new Timestamp(cal.getTimeInMillis()); ps.setTimestamp(1, ts); rs = ps.executeQuery(); rs.next(); @@ -1600,7 +1606,7 @@ public void testTimestampToDateTime() throws Exception { Connection conn = DriverManager.getConnection(connectionString); PreparedStatement ps = conn.prepareStatement("SELECT 1 WHERE ?=CAST('2009-12-17 17:00:29' AS DATETIME)"); - ps.setTimestamp(1, java.sql.Timestamp.valueOf("2009-12-17 17:00:29")); + ps.setTimestamp(1, Timestamp.valueOf("2009-12-17 17:00:29")); ResultSet rs = ps.executeQuery(); assertEquals(rs.next(), true, "Timestamp to DATETIME comparison failed for equal values"); rs.close(); @@ -1641,7 +1647,7 @@ public void testUpdateMisc() throws Exception { rs.next(); // Update datetimeoffset(2) from pre-Gregorian Date - rs.updateDate(1, java.sql.Date.valueOf("0814-02-18")); + rs.updateDate(1, Date.valueOf("0814-02-18")); rs.updateRow(); assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), "0814-02-18 00:00:00 +00:00", "Update of datetimeoffset(2) from pre-Gregorian Date"); @@ -1653,7 +1659,7 @@ public void testUpdateMisc() throws Exception { "Update datetimeoffset(2) from last Time"); // Update datetimeoffset(2) from the "last" Timestamp - rs.updateTimestamp(1, java.sql.Timestamp.valueOf("9999-12-31 23:59:59.998")); + rs.updateTimestamp(1, Timestamp.valueOf("9999-12-31 23:59:59.998")); rs.updateRow(); dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); assertEquals(dto.toString(), "9999-12-31 23:59:59.99 +00:00", @@ -1662,8 +1668,8 @@ public void testUpdateMisc() throws Exception { // Attempt to update datetimeoffset(2) from the first out of range value // Verify that an exception is thrown and that the statement/connection is still usable after try { - java.sql.Timestamp tsInvalid = java.sql.Timestamp.valueOf("9999-12-31 23:59:59.999999999"); - tsInvalid = new java.sql.Timestamp(tsInvalid.getTime() + 1); + Timestamp tsInvalid = Timestamp.valueOf("9999-12-31 23:59:59.999999999"); + tsInvalid = new Timestamp(tsInvalid.getTime() + 1); rs.updateTimestamp(1, tsInvalid); rs.updateRow(); assertEquals(false, true, "Update succeeded with out of range value"); @@ -1674,7 +1680,7 @@ public void testUpdateMisc() throws Exception { } // Update time(5) from Timestamp with nanos more precise than 100ns - Timestamp ts = java.sql.Timestamp.valueOf("2010-01-12 11:05:23"); + Timestamp ts = Timestamp.valueOf("2010-01-12 11:05:23"); ts.setNanos(987659999); rs.updateTimestamp(3, ts); rs.updateRow(); @@ -1682,7 +1688,7 @@ public void testUpdateMisc() throws Exception { "Update time(5) from Timestamp with sub-100ns nanos"); // Update time(5) from Timestamp to max value in a day. The value should not be rounded - ts = java.sql.Timestamp.valueOf("2010-01-12 23:59:59"); + ts = Timestamp.valueOf("2010-01-12 23:59:59"); ts.setNanos(999999999); Time time = new java.sql.Time(ts.getTime()); rs.updateTimestamp(3, ts); @@ -1693,13 +1699,13 @@ public void testUpdateMisc() throws Exception { // Update time(2) from Time to max value in a day. The value should not be rounded rs.updateTime(6, time); rs.updateRow(); - assertEquals(new java.sql.Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is + assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is // necessary to see fractional // secs "1970-01-01 23:59:59.99", "Update time(2) from Time to max value in a day"); // Update time(5) from Timestamp to max value in a second. The value should be rounded - ts = java.sql.Timestamp.valueOf("2010-01-12 23:59:58"); + ts = Timestamp.valueOf("2010-01-12 23:59:58"); ts.setNanos(999999999); time = new java.sql.Time(ts.getTime()); rs.updateTimestamp(3, ts); @@ -1710,13 +1716,13 @@ public void testUpdateMisc() throws Exception { // Update time(2) from Time to max value in a second. The value should be rounded rs.updateTime(6, time); rs.updateRow(); - assertEquals(new java.sql.Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is + assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is // necessary to see fractional // secs "1970-01-01 23:59:59.0", "Update time(2) from Time to max value in a second"); // Update datetime w/expected rounding of nanos to DATETIME's 1/300second resolution - ts = java.sql.Timestamp.valueOf("6289-04-22 05:13:57.6745106"); + ts = Timestamp.valueOf("6289-04-22 05:13:57.6745106"); rs.updateTimestamp(2, ts); rs.updateRow(); assertEquals(rs.getTimestamp(2).toString(), "6289-04-22 05:13:57.677", @@ -1724,7 +1730,7 @@ public void testUpdateMisc() throws Exception { // Update datetime with rounding-induced overflow from Time // (should roll date part to 1/2/1970) - ts = java.sql.Timestamp.valueOf("2010-01-18 23:59:59.999"); + ts = Timestamp.valueOf("2010-01-18 23:59:59.999"); rs.updateTime(2, new java.sql.Time(ts.getTime())); rs.updateRow(); assertEquals(rs.getTimestamp(2).toString(), "1970-01-02 00:00:00.0", From d93e0fe7beb97c7adea8b71d1c0fcf31d0cd86bf Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 19 Nov 2018 13:47:47 -0800 Subject: [PATCH 08/33] fixed issue with timezone --- .../sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 5dca35f08..ad44458bb 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -1456,7 +1456,8 @@ public void testWithThaiLocale() throws Exception { // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance()); + DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); + ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); rs = ps.executeQuery(); rs.next(); From 27702d335a4195b5d4d5d352ff22dfa3ce424852 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 19 Nov 2018 15:35:45 -0800 Subject: [PATCH 09/33] fixed issue with timezone --- .../sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index ad44458bb..9823b0679 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -1403,8 +1403,7 @@ public void testWithThaiLocale() throws Exception { java.text.SimpleDateFormat tsFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000"); java.text.SimpleDateFormat timeFormat = new java.text.SimpleDateFormat("K:mmaa"); java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd"); - java.text.SimpleDateFormat dtoFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000 XXX"); - + Locale locale = Locale.getDefault(); Locale.setDefault(new Locale("th", "TH")); try { @@ -1456,12 +1455,13 @@ public void testWithThaiLocale() throws Exception { // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); - + DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance()); ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); rs = ps.executeQuery(); rs.next(); - assertEquals(rs.getString(1), dtoFormat.format(ts), "DateTimeOffset mismatch"); + + // local time zone may not be same as server time zone + assertEquals(rs.getString(1).substring(0, 27), tsFormat.format(ts), "DateTimeOffset mismatch"); rs.close(); ps.close(); From a48c8107b6c1fec6f355918b7e97293c35683cd5 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 19 Nov 2018 18:22:37 -0800 Subject: [PATCH 10/33] fixed issue with timezone --- .../jdbc/datatypes/KatmaiDataTypesTest.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 9823b0679..e505ed8fa 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -132,7 +132,8 @@ void verifyParameterMetaData(Connection conn) throws Exception { stmt = conn.createStatement(); // Create the stored proc - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @arg " + sqlTypeExpression + " AS SELECT @arg"); + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @arg " + + sqlTypeExpression + " AS SELECT @arg"); pstmt = conn.prepareStatement("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?)}"); ParameterMetaData metadata = pstmt.getParameterMetaData(); @@ -1403,9 +1404,11 @@ public void testWithThaiLocale() throws Exception { java.text.SimpleDateFormat tsFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000"); java.text.SimpleDateFormat timeFormat = new java.text.SimpleDateFormat("K:mmaa"); java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd"); + java.text.SimpleDateFormat dtoFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000 XXX"); Locale locale = Locale.getDefault(); Locale.setDefault(new Locale("th", "TH")); + try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); @@ -1414,27 +1417,30 @@ public void testWithThaiLocale() throws Exception { // Test setter conversions PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))"); - + // Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, month // is from 0-11. Timestamp ts = new Timestamp(System.currentTimeMillis()); - + // Test PreparedStatement with Timestamp // Value sent as DATETIME2; result should have 7 digits of subsecond precision) ps.setTimestamp(1, ts); rs = ps.executeQuery(); rs.next(); assertEquals(rs.getString(1), tsFormat.format(ts), "Timestamp mismatch"); - rs.close(); // Test PreparedStatement with Time // Value sent as DATETIME w/Unix Epoch as base date when sendTimeAsDatetime=true - java.sql.Time time = new java.sql.Time(ts.getTime()); + Time time = new Time(ts.getTime()); ps.setTime(1, time); rs = ps.executeQuery(); rs.next(); - assertEquals(rs.getString(1), "Jan 1 1970 " + timeFormat.format(ts.getTime()), "Time mismatch"); + + // compare these separately since there may be an extra space between the 2 + assertEquals(rs.getString(1).substring(0, 11), "Jan 1 1970", "Time mismatch"); + assertEquals(rs.getString(1).substring(rs.getString(1).length() - 7).trim(), + timeFormat.format(ts.getTime()), "Time mismatch"); rs.close(); // Test PreparedStatement with Date @@ -1455,13 +1461,15 @@ public void testWithThaiLocale() throws Exception { // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, Calendar.getInstance()); + DateTimeOffset dto = DateTimeOffset.valueOf(ts, + Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); + ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); rs = ps.executeQuery(); rs.next(); - - // local time zone may not be same as server time zone - assertEquals(rs.getString(1).substring(0, 27), tsFormat.format(ts), "DateTimeOffset mismatch"); + + dtoFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + assertEquals(rs.getString(1), dtoFormat.format(ts), "DateTimeOffset mismatch"); rs.close(); ps.close(); @@ -1701,8 +1709,8 @@ public void testUpdateMisc() throws Exception { rs.updateTime(6, time); rs.updateRow(); assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is - // necessary to see fractional - // secs + // necessary to see fractional + // secs "1970-01-01 23:59:59.99", "Update time(2) from Time to max value in a day"); // Update time(5) from Timestamp to max value in a second. The value should be rounded @@ -1718,8 +1726,8 @@ public void testUpdateMisc() throws Exception { rs.updateTime(6, time); rs.updateRow(); assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is - // necessary to see fractional - // secs + // necessary to see fractional + // secs "1970-01-01 23:59:59.0", "Update time(2) from Time to max value in a second"); // Update datetime w/expected rounding of nanos to DATETIME's 1/300second resolution From 9c697cf400513b71b49c3d2aac9878367d8ac06d Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 19 Nov 2018 22:47:21 -0800 Subject: [PATCH 11/33] added SparseTest and BigIntegerTest and cleaned up with try-with-resources --- .../jdbc/datatypes/BigIntegerTest.java | 243 +++++ .../jdbc/datatypes/KatmaiDataTypesTest.java | 966 ++++++++---------- .../sqlserver/jdbc/datatypes/SparseTest.java | 61 ++ 3 files changed, 751 insertions(+), 519 deletions(-) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java new file mode 100644 index 000000000..a42657245 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java @@ -0,0 +1,243 @@ +package com.microsoft.sqlserver.jdbc.datatypes; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; + +/* + * This test is for testing the setObject methods for the new data type mappings in JDBC 4.1 for java.math.BigInteger + */ +@RunWith(JUnitPlatform.class) +public class BigIntegerTest extends AbstractTest { + + enum TestType { + SETOBJECT_WITHTYPE, // This is to test conversions in Table B-5 + SETOBJECT_WITHOUTTYPE, // This is to test conversions in Table B-4 + SETNULL // This is to test setNull method + }; + + final static String tableName = RandomUtil.getIdentifier("BigIntegerTestTable"); + + @Test + public void testJDBC41BigInteger() throws Exception { + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { + + // Create the test table + try { + stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (Exception e) {} + + String query = "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1 varchar(100), col2 bigint, col3 real, col4 float, " + + "col5 numeric(38,0), col6 int, col7 smallint, col8 char(100), col9 varchar(max), " + + "id int IDENTITY primary key)"; + stmt.executeUpdate(query); + + try (PreparedStatement pstmt = conn + .prepareStatement("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM " + + AbstractSQLGenerator.escapeIdentifier(tableName) + " where id = ?")) { + + // test that the driver converts the BigInteger values greater than LONG.MAX_VALUE and lesser than + // LONG.MIN_VALUE correctly + // A random value that is bigger than LONG.MAX_VALUE + BigInteger bigIntPos = new BigInteger("922337203685477580776767676"); + // A random value that is smaller than LONG.MIN_VALUE + BigInteger bigIntNeg = new BigInteger("-922337203685477580776767676"); + + // Test the setObject method for different types of BigInteger values. Since BigInteger is mapped to + // JDBC + // BIGINT, the max and min limits for + int row = 1; + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MAX_VALUE), + row++, pstmt, TestType.SETOBJECT_WITHTYPE); + + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MIN_VALUE), + row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(10), row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(-10), row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.ZERO, row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntPos, row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntNeg, row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + + // Test setObject method with SQL TYPE parameter + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MAX_VALUE), + row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MIN_VALUE), + row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(1000), row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(-1000), row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.ZERO, row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntPos, row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntNeg, row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + + // Test setNull + testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntNeg, row++, pstmt, + TestType.SETNULL); + + try { + stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (Exception e) {} + } + } + } + + static void testSetObject(String tableName, BigInteger obj, int id, PreparedStatement pstmt, + TestType testType) throws SQLException { + if (TestType.SETOBJECT_WITHTYPE == testType) { + callSetObjectWithType(obj, pstmt); + } else if (TestType.SETOBJECT_WITHOUTTYPE == testType) { + callSetObjectWithoutType(obj, pstmt); + } else if (TestType.SETNULL == testType) { + callSetNull(obj, pstmt); + } else + assertEquals(true, false, "Invalid test type"); + + // The id column + pstmt.setObject(10, id); + + pstmt.execute(); + pstmt.getMoreResults(); + try (ResultSet rs = pstmt.getResultSet()) { + rs.next(); + + if (TestType.SETNULL == testType) { + for (int i = 1; 9 >= i; ++i) { + // Get the data first before calling rs.wasNull() + rs.getString(i); + assertEquals(rs.wasNull(), true, "setNull mismatch"); + } + return; + } + + if ((0 > obj.compareTo(BigInteger.valueOf(Long.MIN_VALUE))) + || (0 < obj.compareTo(BigInteger.valueOf(Long.MAX_VALUE)))) { + // For the BigInteger values greater/less than Long limits test only the long data type. + // This test is here just to make sure the driver does not do anything wired when the value is + // bigger/smaller than JDBC BIGINT + assertEquals(rs.getString(1), Long.valueOf(obj.longValue()).toString(), + "getString(greater/less than Long limits) mismatch"); + assertEquals(rs.getLong(2), obj.longValue(), "getLong(greater/less than Long limits) mismatch"); + // As CHAR is fixed length, rs.getString() returns a string of the size allocated in the database. + // Need to trim it for comparison. + assertEquals(rs.getString(8).trim(), Long.valueOf(obj.longValue()).toString(), + "getString(greater/less than Long limits (char)) mismatch"); + + assertEquals(rs.getString(9), Long.valueOf(obj.longValue()).toString(), + "getString(greater/less than Long limits (varchar(max)))) mismatch"); + } else { + assertEquals(rs.getString(1), obj.toString(), "getString mismatch"); + assertEquals(rs.getLong(2), obj.longValue(), "getLong mismatch"); + assertEquals(rs.getFloat(3), obj.floatValue(), "getFloat mismatch"); + assertEquals(rs.getDouble(4), obj.doubleValue(), "getDouble(float) mismatch"); + assertEquals(rs.getDouble(5), obj.doubleValue(), "getDouble(numeric) mismatch"); + if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { + assertEquals(rs.getInt(6), Integer.MAX_VALUE, "getInt(numeric) mismatch"); + } else if (obj.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) <= 0) { + assertEquals(rs.getInt(6), Integer.MIN_VALUE, "getInt(numeric) mismatch"); + } else { + assertEquals(rs.getInt(6), obj.intValue(), "getInt(numeric) mismatch"); + } + if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { + assertEquals(rs.getShort(7), Short.MAX_VALUE, "getShort(numeric) mismatch"); + } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { + assertEquals(rs.getShort(7), Short.MIN_VALUE, "getShort(numeric) mismatch"); + } else { + assertEquals(rs.getShort(7), obj.shortValue(), "getShort(numeric) mismatch"); + } + + assertEquals(rs.getString(8).trim(), obj.toString(), "getString(char) mismatch"); + assertEquals(rs.getString(9), obj.toString(), "getString(varchar(max)) mismatch"); + } + } + } + + static void callSetObjectWithType(BigInteger obj, PreparedStatement pstmt) throws SQLException { + pstmt.setObject(1, obj, java.sql.Types.VARCHAR); + pstmt.setObject(2, obj, java.sql.Types.BIGINT); + pstmt.setObject(3, obj, java.sql.Types.FLOAT); + pstmt.setObject(4, obj, java.sql.Types.DOUBLE); + pstmt.setObject(5, obj, java.sql.Types.NUMERIC); + // Use Integer/Short limits instead of Long limits for the int/smallint column + if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { + pstmt.setObject(6, BigInteger.valueOf(Integer.MAX_VALUE), java.sql.Types.INTEGER); + } else if (obj.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) <= 0) { + pstmt.setObject(6, BigInteger.valueOf(Integer.MIN_VALUE), java.sql.Types.INTEGER); + } else { + pstmt.setObject(6, obj, java.sql.Types.INTEGER); + } + if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { + pstmt.setObject(7, BigInteger.valueOf(Short.MAX_VALUE), java.sql.Types.SMALLINT); + } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { + pstmt.setObject(7, BigInteger.valueOf(Short.MIN_VALUE), java.sql.Types.SMALLINT); + } else { + pstmt.setObject(7, obj, java.sql.Types.SMALLINT); + } + pstmt.setObject(8, obj, java.sql.Types.CHAR); + pstmt.setObject(9, obj, java.sql.Types.LONGVARCHAR); + } + + static void callSetObjectWithoutType(BigInteger obj, PreparedStatement pstmt) throws SQLException { + // Cannot send a long value to a column of type int/smallint (even if the long value is small enough to fit in + // those types) + pstmt.setObject(1, obj); + pstmt.setObject(2, obj); + pstmt.setObject(3, obj); + pstmt.setObject(4, obj); + pstmt.setObject(5, obj); + // Use Integer/Short limits instead of Long limits for the int/smallint column + if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { + pstmt.setObject(6, BigInteger.valueOf(Integer.MAX_VALUE)); + } else if (obj.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) <= 0) { + pstmt.setObject(6, BigInteger.valueOf(Integer.MIN_VALUE)); + } else { + pstmt.setObject(6, obj); + } + if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { + pstmt.setObject(7, BigInteger.valueOf(Short.MAX_VALUE)); + } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { + pstmt.setObject(7, BigInteger.valueOf(Short.MIN_VALUE)); + } else { + pstmt.setObject(7, obj); + } + + pstmt.setObject(8, obj); + pstmt.setObject(9, obj); + } + + static void callSetNull(BigInteger obj, PreparedStatement pstmt) throws SQLException { + pstmt.setNull(1, java.sql.Types.VARCHAR); + pstmt.setNull(2, java.sql.Types.BIGINT); + pstmt.setNull(3, java.sql.Types.FLOAT); + pstmt.setNull(4, java.sql.Types.DOUBLE); + pstmt.setNull(5, java.sql.Types.NUMERIC); + pstmt.setNull(6, java.sql.Types.INTEGER); + pstmt.setNull(7, java.sql.Types.SMALLINT); + pstmt.setNull(8, java.sql.Types.CHAR); + pstmt.setNull(9, java.sql.Types.LONGVARCHAR); + } +} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index e505ed8fa..c8d3ff469 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -10,7 +10,6 @@ import java.math.*; import java.util.*; import java.sql.Date; -import java.sql.Timestamp; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -94,69 +93,62 @@ private String sqlCastExpression() { } void verifyResultSetMetaData(Connection conn) throws Exception { - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT TOP 0 " + sqlCastExpression()); - - try { - ResultSetMetaData metadata = rs.getMetaData(); - - assertEquals(metadata.getColumnType(1), sqlType.jdbcType, "getColumnType() of " + sqlCastExpression()); - assertEquals(metadata.getColumnTypeName(1), sqlType.toString(), - "getColumnTypeName() of " + sqlCastExpression()); - assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); - - // Display size of temporal types is the precision per JDBC spec - assertEquals(metadata.getColumnDisplaySize(1), precision, - "getColumnDisplaySize() of " + sqlCastExpression()); - // Scale is interpreted as number of fractional seconds precision - assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); - assertEquals(metadata.getColumnClassName(1), sqlType.className, - "getColumnClassName() of " + sqlCastExpression()); - // Katmai temporal types are not signed - assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); - - // Katmai temporal types are searchable (i.e. usable in a WHERE clause) - assertEquals(metadata.isSearchable(1), true, "isSearchable() of " + sqlCastExpression()); - } finally { - rs.close(); - stmt.close(); + try (Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT TOP 0 " + sqlCastExpression())) { + + try { + ResultSetMetaData metadata = rs.getMetaData(); + + assertEquals(metadata.getColumnType(1), sqlType.jdbcType, + "getColumnType() of " + sqlCastExpression()); + assertEquals(metadata.getColumnTypeName(1), sqlType.toString(), + "getColumnTypeName() of " + sqlCastExpression()); + assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + + // Display size of temporal types is the precision per JDBC spec + assertEquals(metadata.getColumnDisplaySize(1), precision, + "getColumnDisplaySize() of " + sqlCastExpression()); + // Scale is interpreted as number of fractional seconds precision + assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); + assertEquals(metadata.getColumnClassName(1), sqlType.className, + "getColumnClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed + assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + + // Katmai temporal types are searchable (i.e. usable in a WHERE clause) + assertEquals(metadata.isSearchable(1), true, "isSearchable() of " + sqlCastExpression()); + + } finally {} } } void verifyParameterMetaData(Connection conn) throws Exception { - Statement stmt = null; - PreparedStatement pstmt = null; - - try { - stmt = conn.createStatement(); - + try (Statement stmt = conn.createStatement()) { // Create the stored proc stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @arg " + sqlTypeExpression + " AS SELECT @arg"); - pstmt = conn.prepareStatement("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?)}"); - ParameterMetaData metadata = pstmt.getParameterMetaData(); - - assertEquals(metadata.getParameterType(1), sqlType.jdbcType, - "getParameterType() of " + sqlCastExpression()); - assertEquals(metadata.getParameterTypeName(1), sqlType.toString(), - "getParameterTypeName() of " + sqlCastExpression()); - assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); - - // Scale is interpreted as number of fractional seconds precision - assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); - assertEquals(metadata.getParameterClassName(1), sqlType.className, - "getParameterClassName() of " + sqlCastExpression()); - // Katmai temporal types are not signed - assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + try (PreparedStatement pstmt = conn + .prepareStatement("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?)}")) { + ParameterMetaData metadata = pstmt.getParameterMetaData(); + + assertEquals(metadata.getParameterType(1), sqlType.jdbcType, + "getParameterType() of " + sqlCastExpression()); + assertEquals(metadata.getParameterTypeName(1), sqlType.toString(), + "getParameterTypeName() of " + sqlCastExpression()); + assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + + // Scale is interpreted as number of fractional seconds precision + assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); + assertEquals(metadata.getParameterClassName(1), sqlType.className, + "getParameterClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed + assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + } } finally { - if (null != pstmt) - pstmt.close(); - - if (null != stmt) { + try (Statement stmt = conn.createStatement()) { stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - stmt.close(); } } } @@ -164,13 +156,11 @@ void verifyParameterMetaData(Connection conn) throws Exception { abstract void verifyRSGetters(ResultSet rs) throws Exception; void verifyRSGetters(Connection conn) throws Exception { - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery( - "SELECT " + sqlCastExpression() + ", CAST(" + sqlCastExpression() + " AS VARCHAR(60))"); - rs.next(); - verifyRSGetters(rs); - rs.close(); - stmt.close(); + try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( + "SELECT " + sqlCastExpression() + ", CAST(" + sqlCastExpression() + " AS VARCHAR(60))")) { + rs.next(); + verifyRSGetters(rs); + } } abstract void verifyRSUpdaters(ResultSet rs) throws Exception; @@ -179,26 +169,24 @@ void verifyRSUpdaters(Connection conn) throws Exception { assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); - Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - try { + try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (SQLException e) {} - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " - + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); - try { + stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " + + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); + stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" + sqlCastExpression() + ")"); - ResultSet rs = stmt.executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)); - rs.next(); - verifyRSUpdaters(rs); - rs.close(); - } finally { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + try (ResultSet rs = stmt + .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + rs.next(); + verifyRSUpdaters(rs); + } finally { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } } - - stmt.close(); } /* @@ -215,55 +203,45 @@ void verifyRSUpdaters(Connection conn) throws Exception { void verifySetters(Connection conn) throws Exception { assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); - Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - try { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (SQLException e) {} - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " - + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); - - PreparedStatement ps = conn.prepareStatement( - "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (?) SELECT * FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName), - ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - try { - verifySetters(ps); - // Verify setObject function for the new mapping in JDBC41 (java.util.Date to TIMESTAMP) - stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - - verifySettersUtilDate(ps); - // Verify setObject function for the new mapping in JDBC41 (java.util.Calendar to TIMESTAMP) - stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - verifySettersCalendar(ps); - } finally { + try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " + + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); + + try (PreparedStatement ps = conn.prepareStatement( + "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (?) SELECT * FROM " + + AbstractSQLGenerator.escapeIdentifier(tableName), + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { + verifySetters(ps); + // Verify setObject function for the new mapping in JDBC41 (java.util.Date to TIMESTAMP) + stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + + verifySettersUtilDate(ps); + // Verify setObject function for the new mapping in JDBC41 (java.util.Calendar to TIMESTAMP) + stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + verifySettersCalendar(ps); + } finally { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } } - - ps.close(); - stmt.close(); } abstract void verifyCSGetters(CallableStatement cs) throws Exception; void verifyCSGetters(Connection conn) throws Exception { - Statement stmt = conn.createStatement(); - try { - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - } catch (SQLException e) {} - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @argIn " - + sqlTypeExpression + "," + " @argOut " + sqlTypeExpression + " OUTPUT" + " AS " - + " SET @argOut=@argIn"); - - CallableStatement cs = conn - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}"); - try { - verifyCSGetters(cs); - } finally { + try (Statement stmt = conn.createStatement()) { stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @argIn " + + sqlTypeExpression + "," + " @argOut " + sqlTypeExpression + " OUTPUT" + " AS " + + " SET @argOut=@argIn"); + + try (CallableStatement cs = conn + .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}")) { + verifyCSGetters(cs); + } finally { + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + } } - - cs.close(); - stmt.close(); } } @@ -1104,63 +1082,50 @@ enum TestValue { }; public void testResultSetGetters() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString); - - for (TestValue value : TestValue.values()) - value.sqlValue.verifyRSGetters(conn); + try (Connection conn = DriverManager.getConnection(connectionString)) { - conn.close(); + for (TestValue value : TestValue.values()) + value.sqlValue.verifyRSGetters(conn); + } } public void testResultSetUpdaters() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString); - - for (TestValue value : TestValue.values()) - value.sqlValue.verifyRSUpdaters(conn); + try (Connection conn = DriverManager.getConnection(connectionString)) { + for (TestValue value : TestValue.values()) - conn.close(); + value.sqlValue.verifyRSUpdaters(conn); + } } public void testSetters() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDateTime=true"); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDateTime=true")) { - for (TestValue value : TestValue.values()) - value.sqlValue.verifySetters(conn); - - conn.close(); + for (TestValue value : TestValue.values()) + value.sqlValue.verifySetters(conn); + } } public void testCallableStatementGetters() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString); - - for (TestValue value : TestValue.values()) - value.sqlValue.verifyCSGetters(conn); - - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString)) { + for (TestValue value : TestValue.values()) + value.sqlValue.verifyCSGetters(conn); + } } public void testResultSetMetaData() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString); - - for (TestValue value : TestValue.values()) - value.sqlValue.verifyResultSetMetaData(conn); + try (Connection conn = DriverManager.getConnection(connectionString)) { - conn.close(); + for (TestValue value : TestValue.values()) + value.sqlValue.verifyResultSetMetaData(conn); + } } public void testParameterMetaData() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString); - - for (TestValue value : TestValue.values()) - value.sqlValue.verifyParameterMetaData(conn); + try (Connection conn = DriverManager.getConnection(connectionString)) { - conn.close(); + for (TestValue value : TestValue.values()) + value.sqlValue.verifyParameterMetaData(conn); + } ; } /** @@ -1168,37 +1133,40 @@ public void testParameterMetaData() throws Exception { * sendTimeAsDatetime knob. */ public void testSendTimestampAsTimeAsDatetime() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - Statement stmt = conn.createStatement(); - try { - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - } catch (SQLException e) {} - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @argIn time(7), " - + " @argOut time(7) OUTPUT " + " AS " + " SET @argOut=@argIn"); - - CallableStatement cs = conn.prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}"); - - // Set up a timestamp with a time component that is the last millisecond of the day... - Timestamp ts = Timestamp.valueOf("2010-02-15 23:59:59.999"); - - // ... and send that timestamp to the server using the TIME SQL type rather than TIMESTAMP. - // If the driver is doing the right thing, it strips the date portion and, because - // sendTimeAsDatetime=true, rounds the resulting time value to midnight because it should - // be sending a DATETIME which has only 1/300s accuracy. - cs.setObject(1, ts, java.sql.Types.TIME); - cs.registerOutParameter(2, java.sql.Types.TIME); - cs.execute(); - - // Fetch the OUT parameter and verify that we have a date-normalized TIME of midnight - java.sql.Time timeOut = cs.getTime(2); - Timestamp tsOut = new Timestamp(timeOut.getTime()); - assertEquals(tsOut.toString(), "1970-01-01 00:00:00.0", "CS.getTime() - Wrong OUT value"); - - cs.close(); - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - stmt.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true")) { + try (Statement stmt = conn.createStatement()) { + + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + + stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + + " @argIn time(7), " + " @argOut time(7) OUTPUT " + " AS " + " SET @argOut=@argIn"); + + try (CallableStatement cs = conn + .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}")) { + + // Set up a timestamp with a time component that is the last millisecond of the day... + Timestamp ts = Timestamp.valueOf("2010-02-15 23:59:59.999"); + + // ... and send that timestamp to the server using the TIME SQL type rather than TIMESTAMP. + // If the driver is doing the right thing, it strips the date portion and, because + // sendTimeAsDatetime=true, rounds the resulting time value to midnight because it should + // be sending a DATETIME which has only 1/300s accuracy. + cs.setObject(1, ts, java.sql.Types.TIME); + cs.registerOutParameter(2, java.sql.Types.TIME); + cs.execute(); + + // Fetch the OUT parameter and verify that we have a date-normalized TIME of midnight + java.sql.Time timeOut = cs.getTime(2); + Timestamp tsOut = new Timestamp(timeOut.getTime()); + assertEquals(tsOut.toString(), "1970-01-01 00:00:00.0", "CS.getTime() - Wrong OUT value"); + + } + } finally { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + } + } + } } // 507919 - Sending Timestamp to the server via an updater does not result in the same behavior as a setter wrt @@ -1207,7 +1175,6 @@ public void testDoubleRounding() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString)) { // create a table with a datetimeoffset column and insert a value in it - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); String sql; @@ -1293,53 +1260,49 @@ public void testWithJapaneseImperialCalendar() throws Exception { Locale defaultLocale = Locale.getDefault(); Locale.setDefault(japaneseImperialLocale); - try { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - ResultSet rs; - - // Get Gregorian date using Japanese imperial calendar - rs = conn.createStatement().executeQuery("SELECT CAST('0821-01-04' AS DATE)"); - rs.next(); - Date date = rs.getDate(1, japaneseImperialCalendar); - assertEquals(date.toString(), "0821-01-04", "Get pre-Meiji"); - rs.close(); - PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))"); - Timestamp ts; + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true")) { - // Set second day of first year of Taisho era (1912 Gregorian) - // Note: Taisho era began July 30, 1912 Gregorian; second day of that year was July 31. - japaneseImperialCalendar.clear(); - japaneseImperialCalendar.set(Calendar.ERA, 2); // Taisho -> ERA 2 - japaneseImperialCalendar.set(Calendar.YEAR, 1); - japaneseImperialCalendar.set(Calendar.DAY_OF_YEAR, 2); - ts = new Timestamp(japaneseImperialCalendar.getTimeInMillis()); - ps.setTimestamp(1, ts, japaneseImperialCalendar); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), "1912-07-31 00:00:00.0000000", "Set Taisho 1"); - rs.close(); + // Get Gregorian date using Japanese imperial calendar + try (ResultSet rs = conn.createStatement().executeQuery("SELECT CAST('0821-01-04' AS DATE)")) { + rs.next(); + Date date = rs.getDate(1, japaneseImperialCalendar); + assertEquals(date.toString(), "0821-01-04", "Get pre-Meiji"); + } - // Set second year of Showa era (1927 Gregorian) - japaneseImperialCalendar.clear(); - japaneseImperialCalendar.set(Calendar.ERA, 3); // Showa -> ERA 3 - japaneseImperialCalendar.set(Calendar.YEAR, 2); - japaneseImperialCalendar.set(Calendar.MONTH, Calendar.FEBRUARY); - japaneseImperialCalendar.set(Calendar.DATE, 15); - japaneseImperialCalendar.set(Calendar.HOUR_OF_DAY, 8); - japaneseImperialCalendar.set(Calendar.MINUTE, 49); - japaneseImperialCalendar.set(Calendar.SECOND, 3); - japaneseImperialCalendar.set(Calendar.MILLISECOND, 87); - ts = new Timestamp(japaneseImperialCalendar.getTimeInMillis()); - ps.setTimestamp(1, ts, japaneseImperialCalendar); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), "1927-02-15 08:49:03.0870000", "Set Showa 2"); - rs.close(); + try (PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))")) { + Timestamp ts; + + // Set second day of first year of Taisho era (1912 Gregorian) + // Note: Taisho era began July 30, 1912 Gregorian; second day of that year was July 31. + japaneseImperialCalendar.clear(); + japaneseImperialCalendar.set(Calendar.ERA, 2); // Taisho -> ERA 2 + japaneseImperialCalendar.set(Calendar.YEAR, 1); + japaneseImperialCalendar.set(Calendar.DAY_OF_YEAR, 2); + ts = new Timestamp(japaneseImperialCalendar.getTimeInMillis()); + ps.setTimestamp(1, ts, japaneseImperialCalendar); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), "1912-07-31 00:00:00.0000000", "Set Taisho 1"); + } - ps.close(); - conn.close(); + // Set second year of Showa era (1927 Gregorian) + japaneseImperialCalendar.clear(); + japaneseImperialCalendar.set(Calendar.ERA, 3); // Showa -> ERA 3 + japaneseImperialCalendar.set(Calendar.YEAR, 2); + japaneseImperialCalendar.set(Calendar.MONTH, Calendar.FEBRUARY); + japaneseImperialCalendar.set(Calendar.DATE, 15); + japaneseImperialCalendar.set(Calendar.HOUR_OF_DAY, 8); + japaneseImperialCalendar.set(Calendar.MINUTE, 49); + japaneseImperialCalendar.set(Calendar.SECOND, 3); + japaneseImperialCalendar.set(Calendar.MILLISECOND, 87); + ts = new Timestamp(japaneseImperialCalendar.getTimeInMillis()); + ps.setTimestamp(1, ts, japaneseImperialCalendar); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), "1927-02-15 08:49:03.0870000", "Set Showa 2"); + } + } } finally { Locale.setDefault(defaultLocale); } @@ -1381,22 +1344,18 @@ enum StringFormatTestValue { @Test public void testGetString() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString); - Statement stmt = conn.createStatement(); + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - for (StringFormatTestValue testValue : EnumSet.allOf(StringFormatTestValue.class)) { - String query = "SELECT " + "CAST('" + testValue.sqlLiteral + "' AS " + testValue.sqlType + "), " - + "CAST(CAST('" + testValue.sqlLiteral + "' AS " + testValue.sqlType + ") AS VARCHAR)"; + for (StringFormatTestValue testValue : EnumSet.allOf(StringFormatTestValue.class)) { + String query = "SELECT " + "CAST('" + testValue.sqlLiteral + "' AS " + testValue.sqlType + "), " + + "CAST(CAST('" + testValue.sqlLiteral + "' AS " + testValue.sqlType + ") AS VARCHAR)"; - ResultSet rs = stmt.executeQuery(query); - rs.next(); - assertEquals(rs.getString(1), rs.getString(2), "Test failed for " + testValue); - rs.close(); + try (ResultSet rs = stmt.executeQuery(query)) { + rs.next(); + assertEquals(rs.getString(1), rs.getString(2), "Test failed for " + testValue); + } + } } - - stmt.close(); - conn.close(); } @Test @@ -1409,71 +1368,65 @@ public void testWithThaiLocale() throws Exception { Locale locale = Locale.getDefault(); Locale.setDefault(new Locale("th", "TH")); - try { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - - ResultSet rs; - + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true")) { // Test setter conversions - PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))"); - - // Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, month - // is from 0-11. - Timestamp ts = new Timestamp(System.currentTimeMillis()); + try (PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))")) { - // Test PreparedStatement with Timestamp - // Value sent as DATETIME2; result should have 7 digits of subsecond precision) - ps.setTimestamp(1, ts); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), tsFormat.format(ts), "Timestamp mismatch"); - rs.close(); + // Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, + // month + // is from 0-11. + Timestamp ts = new Timestamp(System.currentTimeMillis()); - // Test PreparedStatement with Time - // Value sent as DATETIME w/Unix Epoch as base date when sendTimeAsDatetime=true - Time time = new Time(ts.getTime()); - ps.setTime(1, time); - rs = ps.executeQuery(); - rs.next(); + // Test PreparedStatement with Timestamp + // Value sent as DATETIME2; result should have 7 digits of subsecond precision) + ps.setTimestamp(1, ts); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), tsFormat.format(ts), "Timestamp mismatch"); + } - // compare these separately since there may be an extra space between the 2 - assertEquals(rs.getString(1).substring(0, 11), "Jan 1 1970", "Time mismatch"); - assertEquals(rs.getString(1).substring(rs.getString(1).length() - 7).trim(), - timeFormat.format(ts.getTime()), "Time mismatch"); - rs.close(); + // Test PreparedStatement with Time + // Value sent as DATETIME w/Unix Epoch as base date when sendTimeAsDatetime=true + Time time = new Time(ts.getTime()); + ps.setTime(1, time); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); - // Test PreparedStatement with Date - Date date = new Date(ts.getTime()); - ps.setDate(1, date); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), dateFormat.format(ts), "Date mismatch"); - rs.close(); + // compare these separately since there may be an extra space between the 2 + assertEquals(rs.getString(1).substring(0, 11), "Jan 1 1970", "Time mismatch"); + assertEquals(rs.getString(1).substring(rs.getString(1).length() - 7).trim(), + timeFormat.format(ts.getTime()), "Time mismatch"); + } - // Test PreparedStatement with Date (using Buddhist calendar) - date = new Date(ts.getTime()); - ps.setDate(1, date, Calendar.getInstance()); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), dateFormat.format(ts), "Date mismatch (w/calendar)"); - rs.close(); + // Test PreparedStatement with Date + Date date = new Date(ts.getTime()); + ps.setDate(1, date); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), dateFormat.format(ts), "Date mismatch"); + } - // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) - // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. - DateTimeOffset dto = DateTimeOffset.valueOf(ts, - Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); + // Test PreparedStatement with Date (using Buddhist calendar) + date = new Date(ts.getTime()); + ps.setDate(1, date, Calendar.getInstance()); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), dateFormat.format(ts), "Date mismatch (w/calendar)"); + } - ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); - rs = ps.executeQuery(); - rs.next(); + // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) + // Note: Expected value does not reflect Buddhist year, even though a Buddhist calendar is used. + DateTimeOffset dto = DateTimeOffset.valueOf(ts, + Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); - dtoFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - assertEquals(rs.getString(1), dtoFormat.format(ts), "DateTimeOffset mismatch"); - rs.close(); + ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); - ps.close(); - conn.close(); + dtoFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); + assertEquals(rs.getString(1), dtoFormat.format(ts), "DateTimeOffset mismatch"); + } + } } finally { Locale.setDefault(locale); } @@ -1482,145 +1435,127 @@ public void testWithThaiLocale() throws Exception { // DCR 393826 - DCR Need base date compatibility for Time to DATETIMEx conversions with 2.0 driver @Test public void testBaseDate() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + Timestamp ts; // Test Java base date (1/1/1970) - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIME)"); - ps.setTime(1, java.sql.Time.valueOf("12:34:56")); - ResultSet rs = ps.executeQuery(); - rs.next(); - Timestamp ts = rs.getTimestamp(1); - assertEquals(ts.toString(), "1970-01-01 12:34:56.0", "Expected Java base date"); - rs.close(); - ps.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIME)")) { + ps.setTime(1, java.sql.Time.valueOf("12:34:56")); + + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + ts = rs.getTimestamp(1); + assertEquals(ts.toString(), "1970-01-01 12:34:56.0", "Expected Java base date"); + } + } // Test SQL Server base date (1/1/1900) - conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=false"); - ps = conn.prepareStatement("SELECT CAST(? AS DATETIME)"); - ps.setTime(1, java.sql.Time.valueOf("12:34:56")); - rs = ps.executeQuery(); - rs.next(); - ts = rs.getTimestamp(1); - assertEquals(ts.toString(), "1900-01-01 12:34:56.0", "Expected SQL Server base date"); - rs.close(); - ps.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=false"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIME)")) { + ps.setTime(1, java.sql.Time.valueOf("12:34:56")); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + ts = rs.getTimestamp(1); + assertEquals(ts.toString(), "1900-01-01 12:34:56.0", "Expected SQL Server base date"); + } + } } - // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset (+00:00) + // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset + // (+00:00) @Test public void testTimestampToDateTimeOffset() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - - Connection conn = DriverManager.getConnection(connectionString); - PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIMEOFFSET)"); - ps.setTimestamp(1, Timestamp.valueOf("2010-01-06 12:34:56")); - ResultSet rs = ps.executeQuery(); - rs.next(); - DateTimeOffset dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); - assertEquals(dto.toString(), "2010-01-06 12:34:56 +00:00", "Wrong value"); - rs.close(); - ps.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATETIMEOFFSET)")) { + ps.setTimestamp(1, Timestamp.valueOf("2010-01-06 12:34:56")); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + DateTimeOffset dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); + assertEquals(dto.toString(), "2010-01-06 12:34:56 +00:00", "Wrong value"); + } + } } - // VSTS 400431 - PS.setObject() on a datetime2 with values on or after 0700-02-29 have a value one day ahead stored + // VSTS 400431 - PS.setObject() on a datetime2 with values on or after 0700-02-29 have a value one day ahead + // stored // in the server @Test public void testJulianLeapYear() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - // PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR)"); - PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATE)"); - ResultSet rs; - - // Julian date from string - Date julianDate = Date.valueOf("0700-03-01"); - ps.setDate(1, julianDate); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), "0700-03-01", "Wrong date returned"); - rs.close(); - - ps.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + // PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR)"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS DATE)")) { + + // Julian date from string + Date julianDate = Date.valueOf("0700-03-01"); + ps.setDate(1, julianDate); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), "0700-03-01", "Wrong date returned"); + } + } } @Test public void testGetTimeRounding() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - Statement stmt = conn.createStatement(); - ResultSet rs; - - // Test getTime() rounding from TIME(6) SQL type - rs = stmt.executeQuery("SELECT CAST('12:34:56.999500' AS TIME)"); - rs.next(); - assertEquals(rs.getTime(1).toString(), "12:34:57", "Rounding from TIME(6) failed"); - rs.close(); - - // Test getTime() rounding from character data - rs = stmt.executeQuery("SELECT '12:34:56.999500'"); - rs.next(); - assertEquals(rs.getTime(1).toString(), "12:34:57", "Rounding from character data failed"); - rs.close(); - - stmt.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + Statement stmt = conn.createStatement()) { + + // Test getTime() rounding from TIME(6) SQL type + try (ResultSet rs = stmt.executeQuery("SELECT CAST('12:34:56.999500' AS TIME)")) { + rs.next(); + assertEquals(rs.getTime(1).toString(), "12:34:57", "Rounding from TIME(6) failed"); + } + + // Test getTime() rounding from character data + try (ResultSet rs = stmt.executeQuery("SELECT '12:34:56.999500'")) { + rs.next(); + assertEquals(rs.getTime(1).toString(), "12:34:57", "Rounding from character data failed"); + } + } } @Test public void testGregorianCutoverDateTime2() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); + PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR)")) { + Timestamp ts; - Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); - PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR)"); - ResultSet rs; - Timestamp ts; + // Test setting value during the Gregorian cutover via Timestamp constructed from String + ts = Timestamp.valueOf("1582-10-24 15:07:09.081"); + ps.setTimestamp(1, ts); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), "1582-10-24 15:07:09.0810000", "Wrong value"); + } - // Test setting value during the Gregorian cutover via Timestamp constructed from String - ts = Timestamp.valueOf("1582-10-24 15:07:09.081"); - ps.setTimestamp(1, ts); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), "1582-10-24 15:07:09.0810000", "Wrong value"); - rs.close(); - - // Test setting value during the Gregorian cutover via Timestamp constructed from Calendar - Calendar cal = Calendar.getInstance(); - cal.set(1582, Calendar.NOVEMBER, 1, 15, 7, 9); - cal.set(Calendar.MILLISECOND, 81); - ts = new Timestamp(cal.getTimeInMillis()); - ps.setTimestamp(1, ts); - rs = ps.executeQuery(); - rs.next(); - assertEquals(rs.getString(1), "1582-11-01 15:07:09.0810000", "Wrong value"); - rs.close(); - - ps.close(); - conn.close(); + // Test setting value during the Gregorian cutover via Timestamp constructed from Calendar + Calendar cal = Calendar.getInstance(); + cal.set(1582, Calendar.NOVEMBER, 1, 15, 7, 9); + cal.set(Calendar.MILLISECOND, 81); + ts = new Timestamp(cal.getTimeInMillis()); + ps.setTimestamp(1, ts); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getString(1), "1582-11-01 15:07:09.0810000", "Wrong value"); + } + } } - // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset (+00:00) + // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset + // (+00:00) // // In this case, verify that SELECT with a WHERE clause doesn't fail due to mapping the Timestamp value to a // SQL Server type that does not compare equal. For example, a DATETIMEOFFSET and DATETIME only compare equal // if the DATETIMEOFFSET offset is 0 (UTC). @Test public void testTimestampToDateTime() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - - Connection conn = DriverManager.getConnection(connectionString); - PreparedStatement ps = conn.prepareStatement("SELECT 1 WHERE ?=CAST('2009-12-17 17:00:29' AS DATETIME)"); - ps.setTimestamp(1, Timestamp.valueOf("2009-12-17 17:00:29")); - ResultSet rs = ps.executeQuery(); - assertEquals(rs.next(), true, "Timestamp to DATETIME comparison failed for equal values"); - rs.close(); - ps.close(); - conn.close(); + try (Connection conn = DriverManager.getConnection(connectionString); PreparedStatement ps = conn + .prepareStatement("SELECT 1 WHERE ?=CAST('2009-12-17 17:00:29' AS DATETIME)")) { + ps.setTimestamp(1, Timestamp.valueOf("2009-12-17 17:00:29")); + try (ResultSet rs = ps.executeQuery()) { + assertEquals(rs.next(), true, "Timestamp to DATETIME comparison failed for equal values"); + } + } } // testUpdateMisc @@ -1628,129 +1563,122 @@ public void testTimestampToDateTime() throws Exception { // Haphazard collection of bugs that popped up during unit testing (i.e. regression tests) @Test public void testUpdateMisc() throws Exception { + try (SQLServerConnection conn = (SQLServerConnection) DriverManager + .getConnection(connectionString + ";sendTimeAsDatetime=true")) { - // + ""[" + driver.createuniqueidentifer("testUpdateMisc") + "]"; - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - - SQLServerConnection conn = (SQLServerConnection) DriverManager - .getConnection(connectionString + ";sendTimeAsDatetime=true"); - - assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); - - Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - try { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (SQLException e) {} - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 datetimeoffset(2)," + " col2 datetime," + " col3 time(5)," + " col4 datetime2(5)," - + " col5 smalldatetime," + " col6 time(2)," + " col7 int identity(1,1) primary key)"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" - + " '2010-01-12 09:00:23.17 -08:00'," + " '2010-01-12 10:20:23'," + " '10:20:23'," - + " '2010-01-12 10:20:23'," + " '2010-01-12 11:45:17'," + " '10:20:23')"); - - try { - DateTimeOffset dto; + assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); - ResultSet rs = stmt.executeQuery( - "SELECT *, CAST(col1 AS VARCHAR) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName)); - rs.next(); + try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { + try { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (SQLException e) {} - // Update datetimeoffset(2) from pre-Gregorian Date - rs.updateDate(1, Date.valueOf("0814-02-18")); - rs.updateRow(); - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), "0814-02-18 00:00:00 +00:00", - "Update of datetimeoffset(2) from pre-Gregorian Date"); - - // Update datetimeoffset(2) from "last" Time - rs.updateTime(1, new java.sql.Time(Timestamp.valueOf("1970-01-01 23:59:59.998").getTime())); - rs.updateRow(); - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), "1970-01-02 00:00:00 +00:00", - "Update datetimeoffset(2) from last Time"); + stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1 datetimeoffset(2)," + " col2 datetime," + " col3 time(5)," + " col4 datetime2(5)," + + " col5 smalldatetime," + " col6 time(2)," + " col7 int identity(1,1) primary key)"); + stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" + + " '2010-01-12 09:00:23.17 -08:00'," + " '2010-01-12 10:20:23'," + " '10:20:23'," + + " '2010-01-12 10:20:23'," + " '2010-01-12 11:45:17'," + " '10:20:23')"); + DateTimeOffset dto; - // Update datetimeoffset(2) from the "last" Timestamp - rs.updateTimestamp(1, Timestamp.valueOf("9999-12-31 23:59:59.998")); - rs.updateRow(); - dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); - assertEquals(dto.toString(), "9999-12-31 23:59:59.99 +00:00", - "Update datetimeoffset(2) from last Timestamp"); + try (ResultSet rs = stmt.executeQuery( + "SELECT *, CAST(col1 AS VARCHAR) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + rs.next(); - // Attempt to update datetimeoffset(2) from the first out of range value - // Verify that an exception is thrown and that the statement/connection is still usable after - try { - Timestamp tsInvalid = Timestamp.valueOf("9999-12-31 23:59:59.999999999"); - tsInvalid = new Timestamp(tsInvalid.getTime() + 1); - rs.updateTimestamp(1, tsInvalid); - rs.updateRow(); - assertEquals(false, true, "Update succeeded with out of range value"); - } catch (SQLServerException e) { - assertEquals(e.getSQLState(), "22008", // data exception - datetime field overflow (ISO/IEC - // 9075-2:1999) - "Wrong exception received"); + // Update datetimeoffset(2) from pre-Gregorian Date + rs.updateDate(1, Date.valueOf("0814-02-18")); + rs.updateRow(); + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), + "0814-02-18 00:00:00 +00:00", "Update of datetimeoffset(2) from pre-Gregorian Date"); + + // Update datetimeoffset(2) from "last" Time + rs.updateTime(1, new java.sql.Time(Timestamp.valueOf("1970-01-01 23:59:59.998").getTime())); + rs.updateRow(); + assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), + "1970-01-02 00:00:00 +00:00", "Update datetimeoffset(2) from last Time"); + + // Update datetimeoffset(2) from the "last" Timestamp + rs.updateTimestamp(1, Timestamp.valueOf("9999-12-31 23:59:59.998")); + rs.updateRow(); + dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); + assertEquals(dto.toString(), "9999-12-31 23:59:59.99 +00:00", + "Update datetimeoffset(2) from last Timestamp"); + + // Attempt to update datetimeoffset(2) from the first out of range value + // Verify that an exception is thrown and that the statement/connection is still usable after + try { + Timestamp tsInvalid = Timestamp.valueOf("9999-12-31 23:59:59.999999999"); + tsInvalid = new Timestamp(tsInvalid.getTime() + 1); + rs.updateTimestamp(1, tsInvalid); + rs.updateRow(); + assertEquals(false, true, "Update succeeded with out of range value"); + } catch (SQLServerException e) { + assertEquals(e.getSQLState(), "22008", // data exception - datetime field overflow (ISO/IEC + // 9075-2:1999) + "Wrong exception received"); + } + + // Update time(5) from Timestamp with nanos more precise than 100ns + Timestamp ts = Timestamp.valueOf("2010-01-12 11:05:23"); + ts.setNanos(987659999); + rs.updateTimestamp(3, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 11:05:23.98766", + "Update time(5) from Timestamp with sub-100ns nanos"); + + // Update time(5) from Timestamp to max value in a day. The value should not be rounded + ts = Timestamp.valueOf("2010-01-12 23:59:59"); + ts.setNanos(999999999); + Time time = new java.sql.Time(ts.getTime()); + rs.updateTimestamp(3, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.99999", + "Update time(5) from Timestamp to max value in a day"); + + // Update time(2) from Time to max value in a day. The value should not be rounded + rs.updateTime(6, time); + rs.updateRow(); + assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is + // necessary to see fractional + // secs + "1970-01-01 23:59:59.99", "Update time(2) from Time to max value in a day"); + + // Update time(5) from Timestamp to max value in a second. The value should be rounded + ts = Timestamp.valueOf("2010-01-12 23:59:58"); + ts.setNanos(999999999); + time = new java.sql.Time(ts.getTime()); + rs.updateTimestamp(3, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.0", + "Update time(5) from Timestamp to max value in a second"); + + // Update time(2) from Time to max value in a second. The value should be rounded + rs.updateTime(6, time); + rs.updateRow(); + assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is + // necessary to see fractional + // secs + "1970-01-01 23:59:59.0", "Update time(2) from Time to max value in a second"); + + // Update datetime w/expected rounding of nanos to DATETIME's 1/300second resolution + ts = Timestamp.valueOf("6289-04-22 05:13:57.6745106"); + rs.updateTimestamp(2, ts); + rs.updateRow(); + assertEquals(rs.getTimestamp(2).toString(), "6289-04-22 05:13:57.677", + "Update datetime from Timestamp with sub-1/3second nanos"); + + // Update datetime with rounding-induced overflow from Time + // (should roll date part to 1/2/1970) + ts = Timestamp.valueOf("2010-01-18 23:59:59.999"); + rs.updateTime(2, new java.sql.Time(ts.getTime())); + rs.updateRow(); + assertEquals(rs.getTimestamp(2).toString(), "1970-01-02 00:00:00.0", + "Update datetime from Time near next day"); + + } finally { + stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } } - - // Update time(5) from Timestamp with nanos more precise than 100ns - Timestamp ts = Timestamp.valueOf("2010-01-12 11:05:23"); - ts.setNanos(987659999); - rs.updateTimestamp(3, ts); - rs.updateRow(); - assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 11:05:23.98766", - "Update time(5) from Timestamp with sub-100ns nanos"); - - // Update time(5) from Timestamp to max value in a day. The value should not be rounded - ts = Timestamp.valueOf("2010-01-12 23:59:59"); - ts.setNanos(999999999); - Time time = new java.sql.Time(ts.getTime()); - rs.updateTimestamp(3, ts); - rs.updateRow(); - assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.99999", - "Update time(5) from Timestamp to max value in a day"); - - // Update time(2) from Time to max value in a day. The value should not be rounded - rs.updateTime(6, time); - rs.updateRow(); - assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is - // necessary to see fractional - // secs - "1970-01-01 23:59:59.99", "Update time(2) from Time to max value in a day"); - - // Update time(5) from Timestamp to max value in a second. The value should be rounded - ts = Timestamp.valueOf("2010-01-12 23:59:58"); - ts.setNanos(999999999); - time = new java.sql.Time(ts.getTime()); - rs.updateTimestamp(3, ts); - rs.updateRow(); - assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.0", - "Update time(5) from Timestamp to max value in a second"); - - // Update time(2) from Time to max value in a second. The value should be rounded - rs.updateTime(6, time); - rs.updateRow(); - assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), // conversion to timestamp is - // necessary to see fractional - // secs - "1970-01-01 23:59:59.0", "Update time(2) from Time to max value in a second"); - - // Update datetime w/expected rounding of nanos to DATETIME's 1/300second resolution - ts = Timestamp.valueOf("6289-04-22 05:13:57.6745106"); - rs.updateTimestamp(2, ts); - rs.updateRow(); - assertEquals(rs.getTimestamp(2).toString(), "6289-04-22 05:13:57.677", - "Update datetime from Timestamp with sub-1/3second nanos"); - - // Update datetime with rounding-induced overflow from Time - // (should roll date part to 1/2/1970) - ts = Timestamp.valueOf("2010-01-18 23:59:59.999"); - rs.updateTime(2, new java.sql.Time(ts.getTime())); - rs.updateRow(); - assertEquals(rs.getTimestamp(2).toString(), "1970-01-02 00:00:00.0", - "Update datetime from Time near next day"); - - rs.close(); - } finally { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - stmt.close(); - conn.close(); } } - } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java new file mode 100644 index 000000000..c06dd667b --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java @@ -0,0 +1,61 @@ +package com.microsoft.sqlserver.jdbc.datatypes; + +import java.sql.*; +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.junit.Assert.fail; + +import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.jdbc.TestResource; +import com.microsoft.sqlserver.jdbc.TestUtils; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; + +@RunWith(JUnitPlatform.class) +public class SparseTest extends AbstractTest +{ + final static String tableName = RandomUtil.getIdentifier("SparseTestTable"); + + @Test + public void testSparse() throws Exception { + try (Connection conn = DriverManager.getConnection(connectionString)) { + assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + try (Statement stmt = conn.createStatement()) { + + // Create the test table + try { + stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (Exception e) {} + + StringBuilder bd = new StringBuilder(); + bd.append("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1 int, col2 varbinary(max)"); + for (int i = 3; i <= 1024; i++) { + bd.append(", col" + i + " varchar(20) SPARSE NULL"); + } + bd.append(")"); + String query = bd.toString(); + + stmt.executeUpdate(query); + + stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + + " (col1, col2, col1023)values(1, 0x45, 'yo')"); + + try (ResultSet rs = stmt + .executeQuery("Select * from " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + rs.next(); + assertEquals(rs.getString("col1023"), "yo", "Wrong value returned"); + } + } finally { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + } catch (Exception e) { + fail(TestResource.getResource("R_createDropTableFailed") + e.toString()); + } + } + } + } +} From 83b6ddc718d3fc6912dd1a80ec267a552f859147 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 22 Nov 2018 17:30:55 -0800 Subject: [PATCH 12/33] review changes --- .../microsoft/sqlserver/jdbc/TestResource.java | 1 - .../callablestatement/CallableMixedTest.java | 17 ++--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java index d300f9e34..e4c538a30 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java @@ -153,7 +153,6 @@ protected Object[][] getContents() { {"R_expectedValue", "Expected value: "}, {"R_expectedValueAtIndex", "Expected value at index: "}, {"R_switchFailed", "Switch case is not matched with data"}, {"R_resultsetNotInstance", "Result set is not instance of SQLServerResultSet"}, - {"R_resultsetNotInstance", "Result set is not instance of SQLServerResultSet"}, {"R_noJRESupport", "No JRE support for {0}"}, }; } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index 91b661504..790e14011 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -25,19 +25,14 @@ public void datatypestest() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { - try { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - stmt.executeUpdate(" DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - } catch (Exception e) {} + TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); String createSQL = "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + "(c1_int int primary key, col2 int)"; stmt.executeUpdate(createSQL); stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 1)"); - } - try (Statement stmt = conn.createStatement()) { stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " (@p2_int int, @p2_int_out int OUTPUT, @p4_smallint smallint, @p4_smallint_out smallint OUTPUT) AS begin transaction SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) @@ -61,25 +56,22 @@ public void datatypestest() throws Exception { if (rs.getInt(1) != 0) { fail("Received data not equal to setdata"); - } if (cstmt.getInt((int) 5) != -5372) { fail("Received data not equal to setdata"); - } + // do nothing and reexecute rs = cstmt.executeQuery(); // get the param without getting the resultset rs = cstmt.executeQuery(); if (cstmt.getInt((int) 1) != -2147483648) { fail("Received data not equal to setdata"); - } if (cstmt.getInt((int) 1) != -2147483648) { fail("Received data not equal to setdata"); - } rs = cstmt.executeQuery(); @@ -87,17 +79,14 @@ public void datatypestest() throws Exception { if (rs.getInt(1) != 0) { fail("Received data not equal to setdata"); - } if (cstmt.getInt((int) 1) != -2147483648) { fail("Received data not equal to setdata"); - } if (cstmt.getInt((int) 5) != -5372) { fail("Received data not equal to setdata"); - } rs = cstmt.executeQuery(); @@ -109,8 +98,6 @@ public void datatypestest() throws Exception { } catch (SQLException e) { fail(e.toString()); } - } } - } From b3c5ac5c9800a07f0ea97214972865ca9286bad7 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 23 Nov 2018 15:34:29 -0800 Subject: [PATCH 13/33] review comments --- .../microsoft/sqlserver/jdbc/TestUtils.java | 2 - .../jdbc/resultset/ResultSetTest.java | 6 -- .../jdbc/unit/serial/DTOSerialTest.java | 2 - .../jdbc/unit/serial/DateTimeOffset.java.txt | 87 +++++++++++++++++++ 4 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index a580def64..0322a1011 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -625,8 +625,6 @@ public static Object roundSmallDateTimeValue(Object value) { * @return boolean */ public static boolean serverSupportsDataClassification(Statement stmt) { - - try { stmt.execute("SELECT * FROM SYS.SENSITIVITY_CLASSIFICATIONS"); } catch (SQLException e) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java index d7625a514..2e8764e9f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java @@ -34,15 +34,9 @@ import com.microsoft.sqlserver.jdbc.ISQLServerResultSet; import com.microsoft.sqlserver.jdbc.RandomUtil; -import com.microsoft.sqlserver.jdbc.SQLServerResultSet; import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; -import com.microsoft.sqlserver.testframework.DBConnection; -import com.microsoft.sqlserver.testframework.DBResultSet; -import com.microsoft.sqlserver.testframework.DBResultSetTypes; -import com.microsoft.sqlserver.testframework.DBStatement; - @RunWith(JUnitPlatform.class) public class ResultSetTest extends AbstractTest { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index d71a12d32..3b0c951ad 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -6,8 +6,6 @@ import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import junit.framework.*; - import com.microsoft.sqlserver.jdbc.*; import microsoft.sql.*; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt new file mode 100644 index 000000000..524864044 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt @@ -0,0 +1,87 @@ +package microsoft.sql; + +import java.io.File; +import java.io.FileOutputStream; + +/* Copyright Microsoft All rights reserved. */ +/* + * Dummy class to create serialized values that should not be accepted by the standard + * class. + */ + + +/** + * !DUMMY CLASS! + * + * + */ +public final class DateTimeOffset extends Object implements java.io.Serializable +{ + private static final long serialVersionUID = 541973748553014280L; + + public final long utcMillis; + public final int nanos; + public final int minutesOffset; + + public DateTimeOffset(long utcMillis, int nanos, int minutesOffset) + { + this.utcMillis = utcMillis; + this.nanos = nanos; + this.minutesOffset = minutesOffset; + } + public static class SerializationProxy implements java.io.Serializable + { + private final long utcMillis; + private final int nanos; + private final int minutesOffset; + + SerializationProxy(DateTimeOffset dateTimeOffset) + { + this.utcMillis = dateTimeOffset.utcMillis; + this.nanos = dateTimeOffset.nanos; + this.minutesOffset = dateTimeOffset.minutesOffset; + } + + private static final long serialVersionUID = 664661379547314226L; + + } + + private Object writeReplace() + { + return new SerializationProxy(this); + } + + public static void createBadNanos()throws Exception + { + File simple = new File("d:\\temp\\wrongnanos.dat"); + // -1 should not be accepted + DateTimeOffset dtm = new DateTimeOffset(1, -1, 13*60); + createBadSerializedForm(simple, dtm); + } + public static void createBadOffset()throws Exception + { + File simple = new File("d:\\temp\\wrongoffset.dat"); + // 15 hours offset not valid + DateTimeOffset dtm = new DateTimeOffset(1, 300, 15*60); + createBadSerializedForm(simple, dtm); + } + static void createBadSerializedForm(File simple, DateTimeOffset dtm) throws Exception + { + FileOutputStream so = new java.io.FileOutputStream(simple); + java.io.ObjectOutput s = new java.io.ObjectOutputStream(so); + s.writeObject(dtm); + s.flush(); + s.close(); + } + + private void readObject(java.io.ObjectInputStream stream) throws java.io.InvalidObjectException + { + // For added security/robustness, the only way to rehydrate a serialized DateTimeOffset + // is to use a SerializationProxy. Direct use of readObject() is not supported. + // + // Note that the reason provided for the InvalidObjectException is deliberately less + // than specific. Anyone trying to "hack" this class doesn't need to know why we + // didn't let them... + throw new java.io.InvalidObjectException(""); + } +} From 8f71ce674e93962596025e4d60043641c0fc8151 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 23 Nov 2018 15:37:31 -0800 Subject: [PATCH 14/33] more review updates --- .../sqlserver/jdbc/unit/serial/DTOSerialTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 3b0c951ad..5f294f35d 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -7,6 +7,8 @@ import org.junit.runner.RunWith; import com.microsoft.sqlserver.jdbc.*; +import com.microsoft.sqlserver.testframework.AbstractTest; + import microsoft.sql.*; import java.io.*; @@ -15,15 +17,12 @@ @RunWith(JUnitPlatform.class) -public class DTOSerialTest { +public class DTOSerialTest extends AbstractTest { private static final String dateString = "2007-05-08 12:35:29.1234567 +12:15"; // public static void testDSerial(String connString) throws Exception @Test public void testDSerial() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { From c46db9fc08b57b643d0f4a60d179753834d3a7e5 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Sun, 25 Nov 2018 21:35:43 -0800 Subject: [PATCH 15/33] review updates --- .../microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java | 1 - .../sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 5f294f35d..c0c9025b1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -92,7 +92,6 @@ private static void verifyCorrectSend(DateTimeOffset dtN) throws Exception { // create a DTO try (Connection conn = DriverManager.getConnection(connectionString); - SQLServerPreparedStatement ps = (SQLServerPreparedStatement) conn .prepareStatement("SELECT CAST(? AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' ")) { ps.setDateTimeOffset(1, dtN); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt index 524864044..3db7773de 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt @@ -78,10 +78,6 @@ public final class DateTimeOffset extends Object implements java.io.Serializable { // For added security/robustness, the only way to rehydrate a serialized DateTimeOffset // is to use a SerializationProxy. Direct use of readObject() is not supported. - // - // Note that the reason provided for the InvalidObjectException is deliberately less - // than specific. Anyone trying to "hack" this class doesn't need to know why we - // didn't let them... throw new java.io.InvalidObjectException(""); } } From 3a0703d1404f422e76d78fa89e9d03b0a2e402af Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 26 Nov 2018 12:17:05 -0800 Subject: [PATCH 16/33] removed dummy file --- .../jdbc/unit/serial/DTOSerialTest.java | 25 +++--- .../jdbc/unit/serial/DateTimeOffset.java.txt | 83 ------------------- 2 files changed, 11 insertions(+), 97 deletions(-) delete mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index c0c9025b1..0b4126e99 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -65,10 +65,10 @@ public void testESerial() throws Exception { fail("Errors are different."); } if (sqlState != ex.getSQLState()) { - fail("Errors are different."); + fail("Sql states are different."); } if (errCode != ex.getErrorCode()) { - fail("Errors are different."); + fail("Error codes are different."); } } } @@ -101,31 +101,28 @@ private static void verifyCorrectSend(DateTimeOffset dtN) throws Exception { } } - /* - * I have created two files with wrong nano value (-1) and wrong offset (15*60) by "editing" couple of generated - * serialized files I have checked them in here so they can be used verify the error handling. Note the code to - * generate this is checked in as a text file in the same dir. DateTimeOffset.java.txt - */ // Negative test cases. private static void verifyMessedSerialization() throws Exception { - // these values are from the wrongnanos.dat wrongoffset.dat files checked in with the code - // the values represent the serialized DTO class with invalid values. - byte wrongnanos[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, + // serialized DTO class with wrong nano values (-1) + byte wrongNanos[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, 108, 46, 68, 97, 116, 101, 84, 105, 109, 101, 79, 102, 102, 115, 101, 116, 36, 83, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 80, 114, 111, 120, 121, 9, 57, 90, 0, -49, -42, -72, 50, 2, 0, 3, 73, 0, 13, 109, 105, 110, 117, 116, 101, 115, 79, 102, 102, 115, 101, 116, 73, 0, 5, 110, 97, 110, 111, 115, 74, 0, 9, 117, 116, 99, 77, 105, 108, 108, 105, 115, 120, 112, 0, 0, 3, 12, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 1}; - byte wrongoffset[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, + + // serialized DTO class with wrong offset (15*60) + byte wrongOffset[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, 108, 46, 68, 97, 116, 101, 84, 105, 109, 101, 79, 102, 102, 115, 101, 116, 36, 83, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 80, 114, 111, 120, 121, 9, 57, 90, 0, -49, -42, -72, 50, 2, 0, 3, 73, 0, 13, 109, 105, 110, 117, 116, 101, 115, 79, 102, 102, 115, 101, 116, 73, 0, 5, 110, 97, 110, 111, 115, 74, 0, 9, 117, 116, 99, 77, 105, 108, 108, 105, 115, 120, 112, 0, 0, 3, -124, 0, 0, 1, 44, 0, 0, 0, 0, 0, 0, 0, 1}; - // These two serialized forms throw the exception illegalargument + + // These two serialized forms throw the exception IllegalArgumentException boolean exThrown = false; try { - verifyMessedSerializationHelper(wrongnanos); + verifyMessedSerializationHelper(wrongNanos); } catch (IllegalArgumentException e) { exThrown = true; } @@ -136,7 +133,7 @@ private static void verifyMessedSerialization() throws Exception { exThrown = false; try { - verifyMessedSerializationHelper(wrongoffset); + verifyMessedSerializationHelper(wrongOffset); } catch (IllegalArgumentException e) { exThrown = true; } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt deleted file mode 100644 index 3db7773de..000000000 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DateTimeOffset.java.txt +++ /dev/null @@ -1,83 +0,0 @@ -package microsoft.sql; - -import java.io.File; -import java.io.FileOutputStream; - -/* Copyright Microsoft All rights reserved. */ -/* - * Dummy class to create serialized values that should not be accepted by the standard - * class. - */ - - -/** - * !DUMMY CLASS! - * - * - */ -public final class DateTimeOffset extends Object implements java.io.Serializable -{ - private static final long serialVersionUID = 541973748553014280L; - - public final long utcMillis; - public final int nanos; - public final int minutesOffset; - - public DateTimeOffset(long utcMillis, int nanos, int minutesOffset) - { - this.utcMillis = utcMillis; - this.nanos = nanos; - this.minutesOffset = minutesOffset; - } - public static class SerializationProxy implements java.io.Serializable - { - private final long utcMillis; - private final int nanos; - private final int minutesOffset; - - SerializationProxy(DateTimeOffset dateTimeOffset) - { - this.utcMillis = dateTimeOffset.utcMillis; - this.nanos = dateTimeOffset.nanos; - this.minutesOffset = dateTimeOffset.minutesOffset; - } - - private static final long serialVersionUID = 664661379547314226L; - - } - - private Object writeReplace() - { - return new SerializationProxy(this); - } - - public static void createBadNanos()throws Exception - { - File simple = new File("d:\\temp\\wrongnanos.dat"); - // -1 should not be accepted - DateTimeOffset dtm = new DateTimeOffset(1, -1, 13*60); - createBadSerializedForm(simple, dtm); - } - public static void createBadOffset()throws Exception - { - File simple = new File("d:\\temp\\wrongoffset.dat"); - // 15 hours offset not valid - DateTimeOffset dtm = new DateTimeOffset(1, 300, 15*60); - createBadSerializedForm(simple, dtm); - } - static void createBadSerializedForm(File simple, DateTimeOffset dtm) throws Exception - { - FileOutputStream so = new java.io.FileOutputStream(simple); - java.io.ObjectOutput s = new java.io.ObjectOutputStream(so); - s.writeObject(dtm); - s.flush(); - s.close(); - } - - private void readObject(java.io.ObjectInputStream stream) throws java.io.InvalidObjectException - { - // For added security/robustness, the only way to rehydrate a serialized DateTimeOffset - // is to use a SerializationProxy. Direct use of readObject() is not supported. - throw new java.io.InvalidObjectException(""); - } -} From d5071146c9d9563b6c8493c048cb01ade2d1c224 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 26 Nov 2018 18:03:52 -0800 Subject: [PATCH 17/33] review udpates --- .../microsoft/sqlserver/jdbc/TestUtils.java | 9 ++ .../callablestatement/CallableMixedTest.java | 18 ++- .../jdbc/datatypes/BigIntegerTest.java | 61 ++++----- .../jdbc/datatypes/KatmaiDataTypesTest.java | 123 ++++++++---------- .../sqlserver/jdbc/datatypes/SparseTest.java | 22 ++-- 5 files changed, 106 insertions(+), 127 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index 0322a1011..bc3ee69d7 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -64,11 +64,16 @@ public class TestUtils { // 'SQL' represents SQL Server, while 'SQLAzure' represents SQL Azure. public static final String SERVER_TYPE_SQL_SERVER = "SQL"; public static final String SERVER_TYPE_SQL_AZURE = "SQLAzure"; + // private static SqlType types = null; private static ArrayList types = null; private final static int ENGINE_EDITION_FOR_SQL_AZURE = 5; private final static int ENGINE_EDITION_FOR_SQL_AZURE_DW = 6; + // whether we determined if the target server is SQL Azure + private static boolean _determinedSqlAzureOrSqlServer = false; + private static boolean _isSqlAzure = false; + /** * Returns serverType * @@ -677,6 +682,10 @@ public static String escapeSingleQuotes(String name) { * @throws SQLException */ public static boolean isSqlAzure(Connection con) throws SQLException { + if (_determinedSqlAzureOrSqlServer) { + return _isSqlAzure; + } + try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { rs.next(); int engineEdition = rs.getInt(1); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index 790e14011..933fba413 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -3,9 +3,9 @@ import java.sql.*; import com.microsoft.sqlserver.jdbc.RandomUtil; -import com.microsoft.sqlserver.jdbc.SQLServerDriver; import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -14,28 +14,26 @@ @RunWith(JUnitPlatform.class) -public class CallableMixedTest { +public class CallableMixedTest extends AbstractTest { @Test public void datatypestest() throws Exception { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); String tableName = RandomUtil.getIdentifier("TFOO3"); + String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); String procName = RandomUtil.getIdentifier("SPFOO3"); try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(escapedTableName, stmt); - String createSQL = "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) - + "(c1_int int primary key, col2 int)"; + String createSQL = "create table " + escapedTableName + "(c1_int int primary key, col2 int)"; stmt.executeUpdate(createSQL); - stmt.executeUpdate("Insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) + " values(0, 1)"); + stmt.executeUpdate("Insert into " + escapedTableName + " values(0, 1)"); stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " (@p2_int int, @p2_int_out int OUTPUT, @p4_smallint smallint, @p4_smallint_out smallint OUTPUT) AS begin transaction SELECT * FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName) + + escapedTableName + " ; SELECT @p2_int_out=@p2_int, @p4_smallint_out=@p4_smallint commit transaction RETURN -2147483648"); } @@ -94,7 +92,7 @@ public void datatypestest() throws Exception { } finally { try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); + TestUtils.dropTableIfExists(escapedTableName, stmt); } catch (SQLException e) { fail(e.toString()); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java index a42657245..670515ec0 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java @@ -15,9 +15,11 @@ import java.math.BigInteger; import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; + /* * This test is for testing the setObject methods for the new data type mappings in JDBC 4.1 for java.math.BigInteger */ @@ -31,26 +33,23 @@ enum TestType { }; final static String tableName = RandomUtil.getIdentifier("BigIntegerTestTable"); + final static String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); @Test public void testJDBC41BigInteger() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { // Create the test table - try { - stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (Exception e) {} + TestUtils.dropTableIfExists(escapedTableName, stmt); - String query = "create table " + AbstractSQLGenerator.escapeIdentifier(tableName) + String query = "create table " + escapedTableName + " (col1 varchar(100), col2 bigint, col3 real, col4 float, " + "col5 numeric(38,0), col6 int, col7 smallint, col8 char(100), col9 varchar(max), " + "id int IDENTITY primary key)"; stmt.executeUpdate(query); - try (PreparedStatement pstmt = conn - .prepareStatement("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName) + " where id = ?")) { + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + escapedTableName + + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM " + escapedTableName + " where id = ?")) { // test that the driver converts the BigInteger values greater than LONG.MAX_VALUE and lesser than // LONG.MIN_VALUE correctly @@ -63,45 +62,33 @@ public void testJDBC41BigInteger() throws Exception { // JDBC // BIGINT, the max and min limits for int row = 1; - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MAX_VALUE), - row++, pstmt, TestType.SETOBJECT_WITHTYPE); - - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MIN_VALUE), - row++, pstmt, TestType.SETOBJECT_WITHTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(10), row++, pstmt, - TestType.SETOBJECT_WITHTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(-10), row++, pstmt, - TestType.SETOBJECT_WITHTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.ZERO, row++, pstmt, + testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, TestType.SETOBJECT_WITHTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntPos, row++, pstmt, - TestType.SETOBJECT_WITHTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntNeg, row++, pstmt, + + testSetObject(escapedTableName, BigInteger.valueOf(Long.MIN_VALUE), row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(10), row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(-10), row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, BigInteger.ZERO, row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, bigIntPos, row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETOBJECT_WITHTYPE); // Test setObject method with SQL TYPE parameter - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MAX_VALUE), - row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(Long.MIN_VALUE), - row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(1000), row++, pstmt, - TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.valueOf(-1000), row++, pstmt, - TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), BigInteger.ZERO, row++, pstmt, + testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntPos, row++, pstmt, + testSetObject(escapedTableName, BigInteger.valueOf(Long.MIN_VALUE), row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntNeg, row++, pstmt, + testSetObject(escapedTableName, BigInteger.valueOf(1000), row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(-1000), row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, BigInteger.ZERO, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, bigIntPos, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); // Test setNull - testSetObject(AbstractSQLGenerator.escapeIdentifier(tableName), bigIntNeg, row++, pstmt, - TestType.SETNULL); + testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETNULL); - try { - stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (Exception e) {} + TestUtils.dropTableIfExists(escapedTableName, stmt); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index c8d3ff469..fee805fd4 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -29,7 +29,10 @@ public class KatmaiDataTypesTest extends AbstractTest { final static String tableName = RandomUtil.getIdentifier("KatmaiDataTypesTable"); + final static String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); + final static String procName = RandomUtil.getIdentifier("KatmaiDataTypesTableProc"); + final static String escapedProcName = AbstractSQLGenerator.escapeIdentifier(procName); enum SQLType { date("yyyy-mm-dd", 0, java.sql.Types.DATE, "Date"), @@ -88,6 +91,17 @@ final String getString() { this.scale = fractionalSecondsDigits; } + /** + * For testing the setObject and setNull methods in PreparedStatement, use the verifySetter* methods. These + * methods prepare a single statement and execute it for all different data types by calling the appropriate + * 'setObject' methods for each data type and/or type conversion. + */ + abstract void verifySetters(PreparedStatement ps) throws Exception; + + abstract void verifySettersUtilDate(PreparedStatement ps) throws Exception; + + abstract void verifySettersCalendar(PreparedStatement ps) throws Exception; + private String sqlCastExpression() { return "CAST('" + stringValue + "' AS " + sqlTypeExpression + ")"; } @@ -126,11 +140,10 @@ void verifyParameterMetaData(Connection conn) throws Exception { try (Statement stmt = conn.createStatement()) { // Create the stored proc - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @arg " - + sqlTypeExpression + " AS SELECT @arg"); + stmt.executeUpdate( + "CREATE PROCEDURE " + escapedProcName + " @arg " + sqlTypeExpression + " AS SELECT @arg"); - try (PreparedStatement pstmt = conn - .prepareStatement("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?)}")) { + try (PreparedStatement pstmt = conn.prepareStatement("{call " + escapedProcName + "(?)}")) { ParameterMetaData metadata = pstmt.getParameterMetaData(); assertEquals(metadata.getParameterType(1), sqlType.jdbcType, @@ -148,7 +161,7 @@ void verifyParameterMetaData(Connection conn) throws Exception { } } finally { try (Statement stmt = conn.createStatement()) { - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); } } } @@ -171,57 +184,43 @@ void verifyRSUpdaters(Connection conn) throws Exception { try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(escapedTableName, stmt); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " - + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); + stmt.executeUpdate("CREATE TABLE " + escapedTableName + " (col1 " + sqlTypeExpression + + ", col2 int identity(1,1) primary key)"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" - + sqlCastExpression() + ")"); + stmt.executeUpdate("INSERT INTO " + escapedTableName + " VALUES (" + sqlCastExpression() + ")"); - try (ResultSet rs = stmt - .executeQuery("SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + escapedTableName)) { rs.next(); verifyRSUpdaters(rs); } finally { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(escapedTableName, stmt); } } } - /* - * For testing the setObject and setNull methods in PreparedStatement, use the verifySetter* methods. These - * methods prepare a single statement and execute it for all different data types by calling the appropriate - * 'setObject' methods for each data type and/or type conversion. - */ - abstract void verifySetters(PreparedStatement ps) throws Exception; - - abstract void verifySettersUtilDate(PreparedStatement ps) throws Exception; - - abstract void verifySettersCalendar(PreparedStatement ps) throws Exception; - void verifySetters(Connection conn) throws Exception { assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (col1 " - + sqlTypeExpression + ", col2 int identity(1,1) primary key)"); + TestUtils.dropTableIfExists(escapedTableName, stmt); + stmt.executeUpdate("CREATE TABLE " + escapedTableName + " (col1 " + sqlTypeExpression + + ", col2 int identity(1,1) primary key)"); try (PreparedStatement ps = conn.prepareStatement( - "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (?) SELECT * FROM " - + AbstractSQLGenerator.escapeIdentifier(tableName), + "INSERT INTO " + escapedTableName + " VALUES (?) SELECT * FROM " + escapedTableName, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { verifySetters(ps); // Verify setObject function for the new mapping in JDBC41 (java.util.Date to TIMESTAMP) - stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + stmt.executeUpdate("TRUNCATE TABLE " + escapedTableName); verifySettersUtilDate(ps); // Verify setObject function for the new mapping in JDBC41 (java.util.Calendar to TIMESTAMP) - stmt.executeUpdate("TRUNCATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + stmt.executeUpdate("TRUNCATE TABLE " + escapedTableName); verifySettersCalendar(ps); } finally { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(escapedTableName, stmt); } } } @@ -230,16 +229,14 @@ void verifySetters(Connection conn) throws Exception { void verifyCSGetters(Connection conn) throws Exception { try (Statement stmt = conn.createStatement()) { - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + " @argIn " - + sqlTypeExpression + "," + " @argOut " + sqlTypeExpression + " OUTPUT" + " AS " - + " SET @argOut=@argIn"); + TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + stmt.executeUpdate("CREATE PROCEDURE " + escapedProcName + " @argIn " + sqlTypeExpression + "," + + " @argOut " + sqlTypeExpression + " OUTPUT" + " AS " + " SET @argOut=@argIn"); - try (CallableStatement cs = conn - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}")) { + try (CallableStatement cs = conn.prepareCall("{call " + escapedProcName + "(?,?)}")) { verifyCSGetters(cs); } finally { - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); } } } @@ -1135,14 +1132,11 @@ public void testParameterMetaData() throws Exception { public void testSendTimestampAsTimeAsDatetime() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true")) { try (Statement stmt = conn.createStatement()) { + TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + stmt.executeUpdate("CREATE PROCEDURE " + escapedProcName + " @argIn time(7), " + + " @argOut time(7) OUTPUT " + " AS " + " SET @argOut=@argIn"); - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); - - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) - + " @argIn time(7), " + " @argOut time(7) OUTPUT " + " AS " + " SET @argOut=@argIn"); - - try (CallableStatement cs = conn - .prepareCall("{call " + AbstractSQLGenerator.escapeIdentifier(procName) + "(?,?)}")) { + try (CallableStatement cs = conn.prepareCall("{call " + escapedProcName + "(?,?)}")) { // Set up a timestamp with a time component that is the last millisecond of the day... Timestamp ts = Timestamp.valueOf("2010-02-15 23:59:59.999"); @@ -1163,7 +1157,7 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { } } finally { try (Statement stmt = conn.createStatement()) { - stmt.executeUpdate("DROP PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName)); + TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); } } } @@ -1180,11 +1174,9 @@ public void testDoubleRounding() throws Exception { String sql; try (Statement stmt = conn.createStatement()) { // SQL Azure requires each table to have a clustered index, so change col1 to the primary key - sql = "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 int primary key, col2 datetimeoffset(6))"; + sql = "CREATE TABLE " + escapedTableName + " (col1 int primary key, col2 datetimeoffset(6))"; stmt.executeUpdate(sql); - sql = "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " VALUES(1, '2010-04-29 10:51:12.123456 +00:00')"; + sql = "INSERT INTO " + escapedTableName + " VALUES(1, '2010-04-29 10:51:12.123456 +00:00')"; stmt.executeUpdate(sql); } @@ -1195,7 +1187,7 @@ public void testDoubleRounding() throws Exception { DateTimeOffset actualDto; // create select query and update the datetimeoffset - String query = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName); + String query = "SELECT * FROM " + escapedTableName; try (ResultSet rs = stmt.executeQuery(query)) { rs.next(); @@ -1210,7 +1202,7 @@ public void testDoubleRounding() throws Exception { } // get the datetime offset from server - sql = "SELECT col2 FROM " + AbstractSQLGenerator.escapeIdentifier(tableName); + sql = "SELECT col2 FROM " + escapedTableName; try (ResultSet rs = stmt.executeQuery(sql)) { rs.next(); Object value = rs.getObject(1); @@ -1229,7 +1221,7 @@ public void testDoubleRounding() throws Exception { } } finally { try (Statement stmt = conn.createStatement()) { - stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(escapedTableName, stmt); } catch (SQLException e) { fail(TestResource.getResource("R_createDropTableFailed") + e.toString()); } @@ -1569,20 +1561,17 @@ public void testUpdateMisc() throws Exception { assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { - try { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (SQLException e) {} - - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 datetimeoffset(2)," + " col2 datetime," + " col3 time(5)," + " col4 datetime2(5)," - + " col5 smalldatetime," + " col6 time(2)," + " col7 int identity(1,1) primary key)"); - stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " VALUES (" - + " '2010-01-12 09:00:23.17 -08:00'," + " '2010-01-12 10:20:23'," + " '10:20:23'," - + " '2010-01-12 10:20:23'," + " '2010-01-12 11:45:17'," + " '10:20:23')"); + TestUtils.dropTableIfExists(escapedTableName, stmt); + + stmt.executeUpdate("CREATE TABLE " + escapedTableName + " (col1 datetimeoffset(2)," + " col2 datetime," + + " col3 time(5)," + " col4 datetime2(5)," + " col5 smalldatetime," + " col6 time(2)," + + " col7 int identity(1,1) primary key)"); + stmt.executeUpdate("INSERT INTO " + escapedTableName + " VALUES (" + " '2010-01-12 09:00:23.17 -08:00'," + + " '2010-01-12 10:20:23'," + " '10:20:23'," + " '2010-01-12 10:20:23'," + + " '2010-01-12 11:45:17'," + " '10:20:23')"); DateTimeOffset dto; - try (ResultSet rs = stmt.executeQuery( - "SELECT *, CAST(col1 AS VARCHAR) FROM " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("SELECT *, CAST(col1 AS VARCHAR) FROM " + escapedTableName)) { rs.next(); // Update datetimeoffset(2) from pre-Gregorian Date @@ -1676,7 +1665,7 @@ public void testUpdateMisc() throws Exception { "Update datetime from Time near next day"); } finally { - stmt.executeUpdate("DROP TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(escapedTableName, stmt); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java index c06dd667b..40f4573d1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java @@ -1,6 +1,6 @@ package com.microsoft.sqlserver.jdbc.datatypes; -import java.sql.*; +import java.sql.*; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; @@ -14,10 +14,11 @@ import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; + @RunWith(JUnitPlatform.class) -public class SparseTest extends AbstractTest -{ +public class SparseTest extends AbstractTest { final static String tableName = RandomUtil.getIdentifier("SparseTestTable"); + final static String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); @Test public void testSparse() throws Exception { @@ -26,13 +27,10 @@ public void testSparse() throws Exception { try (Statement stmt = conn.createStatement()) { // Create the test table - try { - stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); - } catch (Exception e) {} + TestUtils.dropTableIfExists(escapedTableName, stmt); StringBuilder bd = new StringBuilder(); - bd.append("create table " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1 int, col2 varbinary(max)"); + bd.append("create table " + escapedTableName + " (col1 int, col2 varbinary(max)"); for (int i = 3; i <= 1024; i++) { bd.append(", col" + i + " varchar(20) SPARSE NULL"); } @@ -41,17 +39,15 @@ public void testSparse() throws Exception { stmt.executeUpdate(query); - stmt.executeUpdate("insert into " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (col1, col2, col1023)values(1, 0x45, 'yo')"); + stmt.executeUpdate("insert into " + escapedTableName + " (col1, col2, col1023)values(1, 0x45, 'yo')"); - try (ResultSet rs = stmt - .executeQuery("Select * from " + AbstractSQLGenerator.escapeIdentifier(tableName))) { + try (ResultSet rs = stmt.executeQuery("Select * from " + escapedTableName)) { rs.next(); assertEquals(rs.getString("col1023"), "yo", "Wrong value returned"); } } finally { try (Statement stmt = conn.createStatement()) { - stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(escapedTableName, stmt); } catch (Exception e) { fail(TestResource.getResource("R_createDropTableFailed") + e.toString()); } From 2994200b1f2e7c2233b0dfe76eb3cfa70d5a6a48 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 27 Nov 2018 13:06:09 -0800 Subject: [PATCH 18/33] more cleanup --- .../bulkCopy/BulkCopyColumnMappingTest.java | 59 +++++------------ .../callablestatement/CallableMixedTest.java | 65 ++++++++++--------- .../jdbc/datatypes/KatmaiDataTypesTest.java | 22 +++---- 3 files changed, 60 insertions(+), 86 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java index 0da47193c..9452d5dd6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java @@ -9,6 +9,7 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Statement; import java.text.MessageFormat; import java.util.concurrent.ThreadLocalRandom; @@ -21,6 +22,7 @@ import com.microsoft.sqlserver.jdbc.ComparisonUtil; import com.microsoft.sqlserver.jdbc.TestResource; +import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.DBConnection; import com.microsoft.sqlserver.testframework.DBResultSet; import com.microsoft.sqlserver.testframework.DBStatement; @@ -55,7 +57,7 @@ public static void closeConnection() throws SQLException { @Test @DisplayName("BulkCopy:test no explicit column mapping") - public void testNoExplicitCM() { + public void testNoExplicitCM() throws SQLException { DBTable destTable = null; try { // create dest table @@ -67,16 +69,13 @@ public void testNoExplicitCM() { bulkWrapper.setUsingConnection((0 == ThreadLocalRandom.current().nextInt(2)) ? true : false); BulkCopyTestUtil.performBulkCopy(bulkWrapper, sourceTable, destTable); } finally { - if (null != destTable) { - // drop dest table - stmt.dropTable(destTable); - } + TestUtils.dropTableIfExists(destTable.getEscapedTableName(), (Statement) stmt.product()); } } @Test @DisplayName("BulkCopy:test explicit column mapping") - public void testExplicitCM() { + public void testExplicitCM() throws SQLException { DBTable destTable = null; try { // create dest table @@ -109,16 +108,13 @@ public void testExplicitCM() { } BulkCopyTestUtil.performBulkCopy(bulkWrapper, sourceTable, destTable); } finally { - // drop dest table - if (null != destTable) { - stmt.dropTable(destTable); - } + TestUtils.dropTableIfExists(destTable.getEscapedTableName(), (Statement) stmt.product()); } } @Test @DisplayName("BulkCopy:test unicode column mapping") - public void testUnicodeCM() { + public void testUnicodeCM() throws SQLException { DBTable sourceTableUnicode = null; DBTable destTableUnicode = null; try { @@ -157,18 +153,14 @@ public void testUnicodeCM() { } BulkCopyTestUtil.performBulkCopy(bulkWrapper, sourceTableUnicode, destTableUnicode); } finally { - if (null != sourceTableUnicode) { - dropTable(sourceTableUnicode.getEscapedTableName()); - } - if (null != destTableUnicode) { - dropTable(destTableUnicode.getEscapedTableName()); - } + TestUtils.dropTableIfExists(sourceTableUnicode.getEscapedTableName(), (Statement) stmt.product()); + TestUtils.dropTableIfExists(destTableUnicode.getEscapedTableName(), (Statement) stmt.product()); } } @Test @DisplayName("BulkCopy:test repetitive column mapping") - public void testRepetitiveCM() { + public void testRepetitiveCM() throws SQLException { DBTable sourceTable1 = null; DBTable destTable = null; try { @@ -224,18 +216,14 @@ public void testRepetitiveCM() { fail(form.format(msgArgs) + "\n" + destTable.getTableName() + "\n" + e.getMessage()); } } finally { - if (null != sourceTable1) { - dropTable(sourceTable1.getEscapedTableName()); - } - if (null != destTable) { - dropTable(destTable.getEscapedTableName()); - } + TestUtils.dropTableIfExists(sourceTable1.getEscapedTableName(), (Statement) stmt.product()); + TestUtils.dropTableIfExists(destTable.getEscapedTableName(), (Statement) stmt.product()); } } @Test @DisplayName("BulkCopy:test implicit mismatched column mapping") - public void testImplicitMismatchCM() { + public void testImplicitMismatchCM() throws SQLException { DBTable destTable = null; try { // create non unicode dest table with different schema from source table @@ -268,15 +256,13 @@ public void testImplicitMismatchCM() { } BulkCopyTestUtil.performBulkCopy(bulkWrapper, sourceTable, destTable, true, true); } finally { - if (null != destTable) { - stmt.dropTable(destTable); - } + TestUtils.dropTableIfExists(destTable.getEscapedTableName(), (Statement) stmt.product()); } } @Test @DisplayName("BulkCopy:test invalid column mapping") - public void testInvalidCM() { + public void testInvalidCM() throws SQLException { DBTable destTable = null; try { // create dest table @@ -359,9 +345,7 @@ public void testInvalidCM() { bulkWrapper.setColumnMapping(Integer.MIN_VALUE, Integer.MAX_VALUE); BulkCopyTestUtil.performBulkCopy(bulkWrapper, sourceTable, destTable, true, true); } finally { - if (null != destTable) { - stmt.dropTable(destTable); - } + TestUtils.dropTableIfExists(destTable.getEscapedTableName(), (Statement) stmt.product()); } } @@ -405,15 +389,4 @@ private void validateValuesRepetitiveCM(DBConnection con, DBTable sourceTable, } } } - - private void dropTable(String tableName) { - - String dropSQL = "DROP TABLE [dbo]." + tableName; - try { - stmt.execute(dropSQL); - } catch (SQLException e) { - fail(tableName + " " + TestResource.getResource("R_tableNotDropped") + "\n" + e.getMessage()); - } - } - } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index 933fba413..a8dbbeaef 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -21,6 +21,7 @@ public void datatypestest() throws Exception { String tableName = RandomUtil.getIdentifier("TFOO3"); String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); String procName = RandomUtil.getIdentifier("SPFOO3"); + String escapedProcName = AbstractSQLGenerator.escapeIdentifier(procName); try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { @@ -31,63 +32,63 @@ public void datatypestest() throws Exception { stmt.executeUpdate("Insert into " + escapedTableName + " values(0, 1)"); - stmt.executeUpdate("CREATE PROCEDURE " + AbstractSQLGenerator.escapeIdentifier(procName) + stmt.executeUpdate("CREATE PROCEDURE " + escapedProcName + " (@p2_int int, @p2_int_out int OUTPUT, @p4_smallint smallint, @p4_smallint_out smallint OUTPUT) AS begin transaction SELECT * FROM " + escapedTableName + " ; SELECT @p2_int_out=@p2_int, @p4_smallint_out=@p4_smallint commit transaction RETURN -2147483648"); } - try (CallableStatement cstmt = conn.prepareCall( - "{ ? = CALL " + AbstractSQLGenerator.escapeIdentifier(procName) + " (?, ?, ?, ?) }")) { + try (CallableStatement cstmt = conn.prepareCall("{ ? = CALL " + escapedProcName + " (?, ?, ?, ?) }")) { cstmt.registerOutParameter((int) 1, (int) 4); cstmt.setObject((int) 2, Integer.valueOf("31"), (int) 4); cstmt.registerOutParameter((int) 3, (int) 4); - cstmt.registerOutParameter((int) 5, java.sql.Types.BINARY); // Test OUT param - // re-registration - // (Defect 60921) + + // Test OUT param re-registration + cstmt.registerOutParameter((int) 5, java.sql.Types.BINARY); + cstmt.registerOutParameter((int) 5, (int) 5); cstmt.setObject((int) 4, Short.valueOf("-5372"), (int) 5); // get results and a value - ResultSet rs = cstmt.executeQuery(); - rs.next(); + try (ResultSet rs = cstmt.executeQuery()) { + rs.next(); - if (rs.getInt(1) != 0) { - fail("Received data not equal to setdata"); - } + if (rs.getInt(1) != 0) { + fail("Received data not equal to setdata"); + } - if (cstmt.getInt((int) 5) != -5372) { - fail("Received data not equal to setdata"); + if (cstmt.getInt((int) 5) != -5372) { + fail("Received data not equal to setdata"); + } } // do nothing and reexecute - rs = cstmt.executeQuery(); - // get the param without getting the resultset - rs = cstmt.executeQuery(); - if (cstmt.getInt((int) 1) != -2147483648) { - fail("Received data not equal to setdata"); - } + try (ResultSet rs = cstmt.executeQuery()) {} - if (cstmt.getInt((int) 1) != -2147483648) { - fail("Received data not equal to setdata"); + // get the param without getting the resultset + try (ResultSet rs = cstmt.executeQuery()) { + if (cstmt.getInt((int) 1) != -2147483648) { + fail("Received data not equal to setdata"); + } } - rs = cstmt.executeQuery(); - rs.next(); + try (ResultSet rs = cstmt.executeQuery()) { + rs.next(); - if (rs.getInt(1) != 0) { - fail("Received data not equal to setdata"); - } + if (rs.getInt(1) != 0) { + fail("Received data not equal to setdata"); + } - if (cstmt.getInt((int) 1) != -2147483648) { - fail("Received data not equal to setdata"); - } + if (cstmt.getInt((int) 1) != -2147483648) { + fail("Received data not equal to setdata"); + } - if (cstmt.getInt((int) 5) != -5372) { - fail("Received data not equal to setdata"); + if (cstmt.getInt((int) 5) != -5372) { + fail("Received data not equal to setdata"); + } } - rs = cstmt.executeQuery(); + try (ResultSet rs = cstmt.executeQuery()) {} } } finally { try (Connection conn = DriverManager.getConnection(connectionString); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index fee805fd4..17002976f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -102,6 +102,12 @@ final String getString() { abstract void verifySettersCalendar(PreparedStatement ps) throws Exception; + abstract void verifyRSGetters(ResultSet rs) throws Exception; + + abstract void verifyRSUpdaters(ResultSet rs) throws Exception; + + abstract void verifyCSGetters(CallableStatement cs) throws Exception; + private String sqlCastExpression() { return "CAST('" + stringValue + "' AS " + sqlTypeExpression + ")"; } @@ -161,13 +167,11 @@ void verifyParameterMetaData(Connection conn) throws Exception { } } finally { try (Statement stmt = conn.createStatement()) { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + TestUtils.dropProcedureIfExists(escapedProcName, stmt); } } } - abstract void verifyRSGetters(ResultSet rs) throws Exception; - void verifyRSGetters(Connection conn) throws Exception { try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT " + sqlCastExpression() + ", CAST(" + sqlCastExpression() + " AS VARCHAR(60))")) { @@ -176,8 +180,6 @@ void verifyRSGetters(Connection conn) throws Exception { } } - abstract void verifyRSUpdaters(ResultSet rs) throws Exception; - void verifyRSUpdaters(Connection conn) throws Exception { assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); @@ -225,18 +227,16 @@ void verifySetters(Connection conn) throws Exception { } } - abstract void verifyCSGetters(CallableStatement cs) throws Exception; - void verifyCSGetters(Connection conn) throws Exception { try (Statement stmt = conn.createStatement()) { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + TestUtils.dropProcedureIfExists(escapedProcName, stmt); stmt.executeUpdate("CREATE PROCEDURE " + escapedProcName + " @argIn " + sqlTypeExpression + "," + " @argOut " + sqlTypeExpression + " OUTPUT" + " AS " + " SET @argOut=@argIn"); try (CallableStatement cs = conn.prepareCall("{call " + escapedProcName + "(?,?)}")) { verifyCSGetters(cs); } finally { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + TestUtils.dropProcedureIfExists(escapedProcName, stmt); } } } @@ -1132,7 +1132,7 @@ public void testParameterMetaData() throws Exception { public void testSendTimestampAsTimeAsDatetime() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true")) { try (Statement stmt = conn.createStatement()) { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + TestUtils.dropProcedureIfExists(escapedProcName, stmt); stmt.executeUpdate("CREATE PROCEDURE " + escapedProcName + " @argIn time(7), " + " @argOut time(7) OUTPUT " + " AS " + " SET @argOut=@argIn"); @@ -1157,7 +1157,7 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { } } finally { try (Statement stmt = conn.createStatement()) { - TestUtils.dropProcedureIfExists(AbstractSQLGenerator.escapeIdentifier(escapedProcName), stmt); + TestUtils.dropProcedureIfExists(escapedProcName, stmt); } } } From e3512f92dae320244044127750e73954781417a8 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 28 Nov 2018 13:07:25 -0800 Subject: [PATCH 19/33] updated isSqlAzure --- .../java/com/microsoft/sqlserver/jdbc/TestUtils.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index bc3ee69d7..1cfd22168 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -70,9 +70,10 @@ public class TestUtils { private final static int ENGINE_EDITION_FOR_SQL_AZURE = 5; private final static int ENGINE_EDITION_FOR_SQL_AZURE_DW = 6; - // whether we determined if the target server is SQL Azure + // whether we determined if the target server is SQL Azure or DW private static boolean _determinedSqlAzureOrSqlServer = false; private static boolean _isSqlAzure = false; + private static boolean _isSqlAzureDW = false; /** * Returns serverType @@ -689,6 +690,8 @@ public static boolean isSqlAzure(Connection con) throws SQLException { try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { rs.next(); int engineEdition = rs.getInt(1); + _determinedSqlAzureOrSqlServer = true; + _isSqlAzure = true; return (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE || engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); } } @@ -701,9 +704,15 @@ public static boolean isSqlAzure(Connection con) throws SQLException { * @throws SQLException */ public static boolean isSqlAzureDW(Connection con) throws SQLException { + if (_determinedSqlAzureOrSqlServer) { + return _isSqlAzureDW; + } + try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { rs.next(); int engineEdition = rs.getInt(1); + _determinedSqlAzureOrSqlServer = true; + _isSqlAzureDW = true; return (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); } } From 5217270f6542a91a707143176e534688b09dafac Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 12 Dec 2018 23:11:42 -0800 Subject: [PATCH 20/33] review updates --- .../callablestatement/CallableMixedTest.java | 19 ++++++++++----- .../sqlserver/jdbc/datatypes/SparseTest.java | 15 ++++++++---- .../jdbc/resultset/ResultSetTest.java | 8 +++++-- .../jdbc/unit/serial/DTOSerialTest.java | 23 +++++++++++++------ 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index a8dbbeaef..f7e857545 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -1,16 +1,23 @@ package com.microsoft.sqlserver.jdbc.callablestatement; -import java.sql.*; -import com.microsoft.sqlserver.jdbc.RandomUtil; -import com.microsoft.sqlserver.jdbc.TestUtils; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; -import com.microsoft.sqlserver.testframework.AbstractTest; +import static org.junit.jupiter.api.Assertions.fail; + +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import static org.junit.jupiter.api.Assertions.fail; + +import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.jdbc.TestUtils; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; @RunWith(JUnitPlatform.class) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java index 40f4573d1..e63901d14 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java @@ -1,12 +1,17 @@ package com.microsoft.sqlserver.jdbc.datatypes; -import java.sql.*; +import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.junit.Assert.fail; import com.microsoft.sqlserver.jdbc.RandomUtil; import com.microsoft.sqlserver.jdbc.TestResource; @@ -44,6 +49,8 @@ public void testSparse() throws Exception { try (ResultSet rs = stmt.executeQuery("Select * from " + escapedTableName)) { rs.next(); assertEquals(rs.getString("col1023"), "yo", "Wrong value returned"); + assertEquals(rs.getInt("col1"), 1, "Wrong value returned"); + assertEquals(rs.getBytes("col2")[0], 0x45, "Wrong value returned"); } } finally { try (Statement stmt = conn.createStatement()) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java index 2e8764e9f..e163cba63 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java @@ -330,8 +330,13 @@ public void testGetterOnNull() throws SQLException { } } + /** + * Tests getters and setters for holdability. + * + * @throws SQLException + */ @Test - public void testHoldability() throws SQLException { + public void testGetSetHoldability() throws SQLException { int[] holdabilityOptions = {ResultSet.HOLD_CURSORS_OVER_COMMIT, ResultSet.CLOSE_CURSORS_AT_COMMIT}; try (Connection con = DriverManager.getConnection(connectionString); Statement stmt = con.createStatement(); @@ -342,7 +347,6 @@ public void testHoldability() throws SQLException { assertEquals(rs.getHoldability(), connHold); for (int i = 0; i < holdabilityOptions.length; i++) { - if ((connHold = con.getHoldability()) != holdabilityOptions[i]) { con.setHoldability(holdabilityOptions[i]); assertEquals(con.getHoldability(), holdabilityOptions[i]); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 0b4126e99..f448025a3 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -1,19 +1,28 @@ package com.microsoft.sqlserver.jdbc.unit.serial; -import java.sql.*; + +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import com.microsoft.sqlserver.jdbc.*; +import com.microsoft.sqlserver.jdbc.SQLServerException; +import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; +import com.microsoft.sqlserver.jdbc.SQLServerResultSet; +import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractTest; -import microsoft.sql.*; - -import java.io.*; - -import static org.junit.jupiter.api.Assertions.fail; +import microsoft.sql.DateTimeOffset; @RunWith(JUnitPlatform.class) From 79ac177cefeda917c477df735a658f4a1cc50bb9 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 12 Dec 2018 23:51:15 -0800 Subject: [PATCH 21/33] more review updates --- .../sqlserver/jdbc/unit/serial/DTOSerialTest.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index f448025a3..24b99cba4 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -1,6 +1,5 @@ package com.microsoft.sqlserver.jdbc.unit.serial; - import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; @@ -11,6 +10,8 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; +import java.text.SimpleDateFormat; +import java.util.Date; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -27,11 +28,12 @@ @RunWith(JUnitPlatform.class) public class DTOSerialTest extends AbstractTest { - private static final String dateString = "2007-05-08 12:35:29.1234567 +12:15"; + private static final String dateString = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX").format(new Date()); // public static void testDSerial(String connString) throws Exception @Test public void testDSerial() throws Exception { + System.out.println("datString=" + dateString); try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { @@ -137,7 +139,7 @@ private static void verifyMessedSerialization() throws Exception { } if (!exThrown) { - fail("wrongnanos serialized form succeeded."); + fail("serialized form with wrong nano values unexpectedly succeeded"); } exThrown = false; @@ -148,7 +150,7 @@ private static void verifyMessedSerialization() throws Exception { } if (!exThrown) { - fail("wrongnanos serialized form succeeded."); + fail("serialized form with wrong offset unexpectedly succeeded"); } } From ada91ae8bf298285a56f5cc8d042005925224009 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 13 Dec 2018 00:04:53 -0800 Subject: [PATCH 22/33] fixed imports --- .../jdbc/datatypes/KatmaiDataTypesTest.java | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 17002976f..2d4dd173e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -1,22 +1,44 @@ package com.microsoft.sqlserver.jdbc.datatypes; -import java.sql.*; -import java.text.MessageFormat; - -import com.microsoft.sqlserver.jdbc.*; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; -import com.microsoft.sqlserver.testframework.AbstractTest; +import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assumptions.assumeTrue; -import java.math.*; -import java.util.*; +import java.math.BigDecimal; +import java.sql.CallableStatement; +import java.sql.Connection; import java.sql.Date; +import java.sql.DriverManager; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.text.MessageFormat; +import java.util.Calendar; +import java.util.EnumSet; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.SimpleTimeZone; +import java.util.TimeZone; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.junit.Assert.fail; + +import com.microsoft.sqlserver.jdbc.RandomUtil; +import com.microsoft.sqlserver.jdbc.SQLServerCallableStatement; +import com.microsoft.sqlserver.jdbc.SQLServerConnection; +import com.microsoft.sqlserver.jdbc.SQLServerException; +import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; +import com.microsoft.sqlserver.jdbc.SQLServerResultSet; +import com.microsoft.sqlserver.jdbc.TestResource; +import com.microsoft.sqlserver.jdbc.TestUtils; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; import microsoft.sql.DateTimeOffset; From 36838a8c7c2111ef02221bb8d6783e8e12a3c20a Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 13 Dec 2018 11:54:26 -0800 Subject: [PATCH 23/33] updated failed error strings with more detail --- .../jdbc/unit/serial/DTOSerialTest.java | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 24b99cba4..889b119b6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -30,10 +30,8 @@ public class DTOSerialTest extends AbstractTest { private static final String dateString = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX").format(new Date()); - // public static void testDSerial(String connString) throws Exception @Test public void testDSerial() throws Exception { - System.out.println("datString=" + dateString); try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { @@ -46,9 +44,8 @@ public void testDSerial() throws Exception { } } + @Test public void testESerial() throws Exception { - String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { @@ -57,29 +54,31 @@ public void testESerial() throws Exception { try { stmt.executeUpdate("RAISERROR ('foo', 13,1) WITH LOG"); + } catch (SQLServerException x) { currException = x; } + // store the info - String errInfo = currException.toString(); - String sqlState = currException.getSQLState(); - int errCode = currException.getErrorCode(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); + // serialize the exception; out.writeObject(currException); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); SQLServerException ex = (SQLServerException) in.readObject(); - String newErrInfo = ex.toString(); - if (!errInfo.equals(newErrInfo)) { - fail("Errors are different."); + if (!currException.toString().equals(ex.toString())) { + fail("Error strings are different. Expected: " + currException.toString() + " Received: " + + ex.toString()); } - if (sqlState != ex.getSQLState()) { - fail("Sql states are different."); + if (!currException.getSQLState().equals(ex.getSQLState())) { + fail("Sql states are different. Expected: " + currException.getSQLState() + " Received: " + + ex.getSQLState()); } - if (errCode != ex.getErrorCode()) { - fail("Error codes are different."); + if (currException.getErrorCode() != ex.getErrorCode()) { + fail("Error codes are different. Expected: " + currException.getErrorCode() + " Received: " + + ex.getErrorCode()); } } } @@ -161,27 +160,31 @@ private static void verifyMessedSerializationHelper(byte[] svalue) throws Except // This function is used to make sure the hydrated is equal to original string and the initial DTO private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrated) throws Exception { - // check string - String info = initial.toString(); - String newInfo = hydrated.toString(); - // check timestamp + String initialStr = initial.toString(); + String hydratedStr = hydrated.toString(); + java.sql.Timestamp originalTS = initial.getTimestamp(); java.sql.Timestamp hydratedTS = hydrated.getTimestamp(); + // and offset - int originalOffset = initial.getMinutesOffset(); + int initiallOffset = initial.getMinutesOffset(); int hydratedOffset = hydrated.getMinutesOffset(); - if (!info.equals(newInfo)) { - fail("Strings are different."); + if (!initialStr.equals(hydratedStr)) { + fail("Hydrated string is different. Expected: " + initialStr + " Received: " + hydratedStr); } - if (!info.equals(dateString)) { - fail("Strings are different from original."); + if (!initialStr.equals(dateString)) { + fail("String is different from original datestring. Expected: " + dateString + " Received: " + initialStr); } if (!initial.equals(hydrated)) { - fail("Equality test fails."); + fail("Hydrated datetimeoffset is different. Expected: " + initial + " Received: " + hydrated); } if (!originalTS.equals(hydratedTS)) { - fail("Equality test fails from original."); + fail("Hydrated timestamp is different. Expected: " + initial.getTimestamp() + " Received: " + + hydrated.getTimestamp()); + } + if (initiallOffset != hydratedOffset) { + fail("Hydrated offset is different. Expected: " + initiallOffset + " Received: " + hydratedOffset); } } } From a196be9464c06983671141a5af9e8d2a3fd2d608 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 13 Dec 2018 12:48:41 -0800 Subject: [PATCH 24/33] added locale to time format --- .../microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 889b119b6..b6254bb9e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -12,6 +12,7 @@ import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -28,7 +29,8 @@ @RunWith(JUnitPlatform.class) public class DTOSerialTest extends AbstractTest { - private static final String dateString = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX").format(new Date()); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX", Locale.US); + private static final String dateString = sdf.format(new Date()); @Test public void testDSerial() throws Exception { @@ -87,11 +89,13 @@ public void testESerial() throws Exception { private static void verifyCorrectSerialization(DateTimeOffset dto) throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); + // serialize the DateTimeOffset; out.writeObject(dto); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); DateTimeOffset dtn = (DateTimeOffset) in.readObject(); verifyDTOEqual(dto, dtn); + // Make sure that you can send rehydrated to server verifyCorrectSend(dtn); } From c7df1ed99ec8877c1ea5c320cc71f40501542a4e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 13 Dec 2018 15:42:39 -0800 Subject: [PATCH 25/33] format date for comparision --- .../sqlserver/jdbc/unit/serial/DTOSerialTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index b6254bb9e..93056885f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -29,7 +29,7 @@ @RunWith(JUnitPlatform.class) public class DTOSerialTest extends AbstractTest { - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX", Locale.US); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSS XXX", Locale.US); private static final String dateString = sdf.format(new Date()); @Test @@ -177,8 +177,10 @@ private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrat if (!initialStr.equals(hydratedStr)) { fail("Hydrated string is different. Expected: " + initialStr + " Received: " + hydratedStr); } - if (!initialStr.equals(dateString)) { - fail("String is different from original datestring. Expected: " + dateString + " Received: " + initialStr); + + String formattedDate = sdf.format(sdf.parse(initialStr)); + if (!formattedDate.equals(dateString)) { + fail("String is different from original datestring. Expected: " + dateString + " Received: " + formattedDate); } if (!initial.equals(hydrated)) { fail("Hydrated datetimeoffset is different. Expected: " + initial + " Received: " + hydrated); From dbcc0a3031059f64b57d6778eb401d7d3d3668a4 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 13 Dec 2018 17:33:19 -0800 Subject: [PATCH 26/33] 1 more timezone fix --- .../sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java | 2 +- .../sqlserver/jdbc/unit/serial/DTOSerialTest.java | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 2d4dd173e..957701481 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -1375,7 +1375,7 @@ public void testGetString() throws Exception { @Test public void testWithThaiLocale() throws Exception { java.text.SimpleDateFormat tsFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000"); - java.text.SimpleDateFormat timeFormat = new java.text.SimpleDateFormat("K:mmaa"); + java.text.SimpleDateFormat timeFormat = new java.text.SimpleDateFormat("h:mmaa"); java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd"); java.text.SimpleDateFormat dtoFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS0000 XXX"); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 93056885f..9b6ea5519 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -12,7 +12,7 @@ import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.Locale; +import java.util.TimeZone; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -29,11 +29,14 @@ @RunWith(JUnitPlatform.class) public class DTOSerialTest extends AbstractTest { - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSS XXX", Locale.US); - private static final String dateString = sdf.format(new Date()); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX"); + private static String dateString; @Test public void testDSerial() throws Exception { + sdf.setTimeZone(TimeZone.getTimeZone("Z")); + dateString = sdf.format(new Date()); + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { From bcc87326e8b92658060e8fe88010a18dc77ec092 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 17 Dec 2018 12:47:16 -0800 Subject: [PATCH 27/33] cleanup leaded stream resources --- .../callablestatement/CallableMixedTest.java | 3 - .../jdbc/resultset/ResultSetTest.java | 3 +- .../jdbc/unit/serial/DTOSerialTest.java | 91 ++++++++++--------- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index f7e857545..df3c8188d 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -1,6 +1,5 @@ package com.microsoft.sqlserver.jdbc.callablestatement; - import static org.junit.jupiter.api.Assertions.fail; import java.sql.CallableStatement; @@ -94,8 +93,6 @@ public void datatypestest() throws Exception { fail("Received data not equal to setdata"); } } - - try (ResultSet rs = cstmt.executeQuery()) {} } } finally { try (Connection conn = DriverManager.getConnection(connectionString); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java index e163cba63..ffc3e9a84 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java @@ -38,6 +38,7 @@ import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; + @RunWith(JUnitPlatform.class) public class ResultSetTest extends AbstractTest { private static final String tableName = RandomUtil.getIdentifier("StatementParam"); @@ -466,7 +467,7 @@ public void testResultSetMethods() throws SQLException { } catch (Exception e) { fail(e.toString()); } finally { - stmt.executeUpdate("drop table " + AbstractSQLGenerator.escapeIdentifier(tableName)); + TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableName), stmt); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 9b6ea5519..e8a4c7973 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -21,7 +21,6 @@ import com.microsoft.sqlserver.jdbc.SQLServerException; import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; import com.microsoft.sqlserver.jdbc.SQLServerResultSet; -import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractTest; import microsoft.sql.DateTimeOffset; @@ -41,11 +40,12 @@ public void testDSerial() throws Exception { Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { // create a DTO - ResultSet rs = stmt.executeQuery( - "SELECT CAST('" + dateString + "' AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' "); - rs.next(); - verifyCorrectSerialization(((SQLServerResultSet) rs).getDateTimeOffset(1)); - verifyMessedSerialization(); + try (ResultSet rs = stmt.executeQuery( + "SELECT CAST('" + dateString + "' AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' ")) { + rs.next(); + verifyCorrectSerialization(((SQLServerResultSet) rs).getDateTimeOffset(1)); + verifyMessedSerialization(); + } } } @@ -65,56 +65,59 @@ public void testESerial() throws Exception { } // store the info - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(bos); - - // serialize the exception; - out.writeObject(currException); - ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); - SQLServerException ex = (SQLServerException) in.readObject(); - - if (!currException.toString().equals(ex.toString())) { - fail("Error strings are different. Expected: " + currException.toString() + " Received: " - + ex.toString()); - } - if (!currException.getSQLState().equals(ex.getSQLState())) { - fail("Sql states are different. Expected: " + currException.getSQLState() + " Received: " - + ex.getSQLState()); - } - if (currException.getErrorCode() != ex.getErrorCode()) { - fail("Error codes are different. Expected: " + currException.getErrorCode() + " Received: " - + ex.getErrorCode()); + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos)) { + + // serialize the exception; + out.writeObject(currException); + try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) { + SQLServerException ex = (SQLServerException) in.readObject(); + + if (!currException.toString().equals(ex.toString())) { + fail("Error strings are different. Expected: " + currException.toString() + " Received: " + + ex.toString()); + } + if (!currException.getSQLState().equals(ex.getSQLState())) { + fail("Sql states are different. Expected: " + currException.getSQLState() + " Received: " + + ex.getSQLState()); + } + if (currException.getErrorCode() != ex.getErrorCode()) { + fail("Error codes are different. Expected: " + currException.getErrorCode() + " Received: " + + ex.getErrorCode()); + } + } } } } // Positive test case, this should succeed private static void verifyCorrectSerialization(DateTimeOffset dto) throws Exception { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(bos); + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bos)) { - // serialize the DateTimeOffset; - out.writeObject(dto); - ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); - DateTimeOffset dtn = (DateTimeOffset) in.readObject(); - verifyDTOEqual(dto, dtn); + // serialize the DateTimeOffset; + out.writeObject(dto); + try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) { + DateTimeOffset dtn = (DateTimeOffset) in.readObject(); + verifyDTOEqual(dto, dtn); - // Make sure that you can send rehydrated to server - verifyCorrectSend(dtn); + // Make sure that you can send rehydrated to server + verifyCorrectSend(dtn); + } + } } // this is to make sure that the rehydrated date can be sent to server correctly private static void verifyCorrectSend(DateTimeOffset dtN) throws Exception { - String connectionString = TestUtils.getConfiguredProperty("mssql_jdbc_test_connection_properties"); - // create a DTO try (Connection conn = DriverManager.getConnection(connectionString); SQLServerPreparedStatement ps = (SQLServerPreparedStatement) conn .prepareStatement("SELECT CAST(? AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' ")) { ps.setDateTimeOffset(1, dtN); - ResultSet rs = ps.executeQuery(); - rs.next(); - verifyDTOEqual(dtN, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + verifyDTOEqual(dtN, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + } } } @@ -161,8 +164,9 @@ private static void verifyMessedSerialization() throws Exception { } private static void verifyMessedSerializationHelper(byte[] svalue) throws Exception { - ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(svalue)); - DateTimeOffset dtn = (DateTimeOffset) in.readObject(); + try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(svalue))) { + DateTimeOffset dtn = (DateTimeOffset) in.readObject(); + } } // This function is used to make sure the hydrated is equal to original string and the initial DTO @@ -180,10 +184,11 @@ private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrat if (!initialStr.equals(hydratedStr)) { fail("Hydrated string is different. Expected: " + initialStr + " Received: " + hydratedStr); } - + String formattedDate = sdf.format(sdf.parse(initialStr)); if (!formattedDate.equals(dateString)) { - fail("String is different from original datestring. Expected: " + dateString + " Received: " + formattedDate); + fail("String is different from original datestring. Expected: " + dateString + " Received: " + + formattedDate); } if (!initial.equals(hydrated)) { fail("Hydrated datetimeoffset is different. Expected: " + initial + " Received: " + hydrated); From fe01b416b28f381553da903fd142c76b308fd546 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 17 Dec 2018 17:55:13 -0800 Subject: [PATCH 28/33] manually merged with #903 changes for now --- .../bulkCopy/BulkCopyColumnMappingTest.java | 1 + .../jdbc/unit/serial/DTOSerialTest.java | 12 +++-- .../sqlserver/testframework/AbstractTest.java | 46 ++++++++++++++++++- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java index 824d6a36f..bbc538e07 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyColumnMappingTest.java @@ -23,6 +23,7 @@ import com.microsoft.sqlserver.jdbc.ComparisonUtil; import com.microsoft.sqlserver.jdbc.TestResource; +import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.DBConnection; import com.microsoft.sqlserver.testframework.DBResultSet; import com.microsoft.sqlserver.testframework.DBStatement; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index e8a4c7973..6e1e8155c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -28,7 +28,7 @@ @RunWith(JUnitPlatform.class) public class DTOSerialTest extends AbstractTest { - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSSS XXX"); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS XXX"); private static String dateString; @Test @@ -91,6 +91,7 @@ public void testESerial() throws Exception { } // Positive test case, this should succeed + @Test private static void verifyCorrectSerialization(DateTimeOffset dto) throws Exception { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos)) { @@ -108,20 +109,22 @@ private static void verifyCorrectSerialization(DateTimeOffset dto) throws Except } // this is to make sure that the rehydrated date can be sent to server correctly - private static void verifyCorrectSend(DateTimeOffset dtN) throws Exception { + @Test + private static void verifyCorrectSend(DateTimeOffset dtn) throws Exception { // create a DTO try (Connection conn = DriverManager.getConnection(connectionString); SQLServerPreparedStatement ps = (SQLServerPreparedStatement) conn .prepareStatement("SELECT CAST(? AS datetimeoffset(7)) AS" + " 'datetimeoffset IS08601' ")) { - ps.setDateTimeOffset(1, dtN); + ps.setDateTimeOffset(1, dtn); try (ResultSet rs = ps.executeQuery()) { rs.next(); - verifyDTOEqual(dtN, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + verifyDTOEqual(dtn, ((SQLServerResultSet) rs).getDateTimeOffset(1)); } } } // Negative test cases. + @Test private static void verifyMessedSerialization() throws Exception { // serialized DTO class with wrong nano values (-1) byte wrongNanos[] = {-84, -19, 0, 5, 115, 114, 0, 47, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 115, 113, @@ -165,6 +168,7 @@ private static void verifyMessedSerialization() throws Exception { private static void verifyMessedSerializationHelper(byte[] svalue) throws Exception { try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(svalue))) { + //this will throw error for negative tests DateTimeOffset dtn = (DateTimeOffset) in.readObject(); } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java index 0e58d3151..0d2e6f37c 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java @@ -6,6 +6,9 @@ package com.microsoft.sqlserver.testframework; import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; import java.util.Properties; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; @@ -52,6 +55,12 @@ public abstract class AbstractTest { protected static Properties info = new Properties(); + private final static int ENGINE_EDITION_FOR_SQL_AZURE = 5; + private final static int ENGINE_EDITION_FOR_SQL_AZURE_DW = 6; + private static boolean _determinedSqlAzureOrSqlServer = false; + private static boolean _isSqlAzure = false; + private static boolean _isSqlAzureDW = false; + /** * This will take care of all initialization before running the Test Suite. * @@ -83,6 +92,7 @@ public static void setup() throws Exception { try { Assertions.assertNotNull(connectionString, "Connection String should not be null"); connection = PrepUtil.getConnection(connectionString, info); + isSqlAzureOrAzureDW(connection); } catch (Exception e) { throw e; } @@ -164,13 +174,45 @@ public static void invokeLogging() { handler.setLevel(Level.FINEST); Logger.getLogger("").addHandler(handler); } - // By default, Loggers also send their output to their parent logger.   + // By default, Loggers also send their output to their parent logger. // Typically the root Logger is configured with a set of Handlers that essentially act as default handlers - // for all loggers.  + // for all loggers. Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc"); logger.setLevel(Level.FINEST); } catch (Exception e) { System.err.println("Some how could not invoke logging: " + e.getMessage()); } } + + public static boolean isSqlAzure() { + return _isSqlAzure; + } + + public static boolean isSqlAzureDW() { + return _isSqlAzureDW; + } + + /** + * Determines the server's type. + * + * @param con + * connection to server + * @return void + * @throws SQLException + */ + private static void isSqlAzureOrAzureDW(Connection con) throws SQLException { + if (_determinedSqlAzureOrSqlServer) { + return; + } + + try (Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { + rs.next(); + int engineEdition = rs.getInt(1); + _isSqlAzure = (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE + || engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); + _isSqlAzureDW = (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); + _determinedSqlAzureOrSqlServer = true; + } + } } From 238b66f0c5b2799e5aa2aa4c0faebd93b0f36ad4 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 18 Dec 2018 14:01:19 -0800 Subject: [PATCH 29/33] more cleanup on assertEqual checks --- .../callablestatement/CallableMixedTest.java | 14 +++++++------- .../sqlserver/jdbc/datatypes/SparseTest.java | 6 +++--- .../jdbc/unit/serial/DTOSerialTest.java | 18 +++++++++--------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index 38e31b714..4d3e255a1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -1,6 +1,6 @@ package com.microsoft.sqlserver.jdbc.callablestatement; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.sql.CallableStatement; @@ -60,9 +60,9 @@ public void datatypestest() throws Exception { try (ResultSet rs = cstmt.executeQuery()) { rs.next(); - assertTrue(rs.getInt(1) == 0); + assertEquals(rs.getInt(1), 0); - assertTrue(cstmt.getInt((int) 5) == -5372); + assertEquals(cstmt.getInt((int) 5), -5372); } // do nothing and reexecute @@ -70,17 +70,17 @@ public void datatypestest() throws Exception { // get the param without getting the resultset try (ResultSet rs = cstmt.executeQuery()) { - assertTrue(cstmt.getInt((int) 1) == -2147483648); + assertEquals(cstmt.getInt((int) 1), -2147483648); } try (ResultSet rs = cstmt.executeQuery()) { rs.next(); - assertTrue(rs.getInt(1) == 0); + assertEquals(rs.getInt(1), 0); - assertTrue(cstmt.getInt((int) 1) == -2147483648); + assertEquals(cstmt.getInt((int) 1), -2147483648); - assertTrue(cstmt.getInt((int) 5) == -5372); + assertEquals(cstmt.getInt((int) 5), -5372); } } } finally { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java index e63901d14..b41163787 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java @@ -48,9 +48,9 @@ public void testSparse() throws Exception { try (ResultSet rs = stmt.executeQuery("Select * from " + escapedTableName)) { rs.next(); - assertEquals(rs.getString("col1023"), "yo", "Wrong value returned"); - assertEquals(rs.getInt("col1"), 1, "Wrong value returned"); - assertEquals(rs.getBytes("col2")[0], 0x45, "Wrong value returned"); + assertEquals(rs.getString("col1023"), "yo"); + assertEquals(rs.getInt("col1"), 1); + assertEquals(rs.getBytes("col2")[0], 0x45); } } finally { try (Statement stmt = conn.createStatement()) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index 4acd7ec83..a7e05c371 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -1,6 +1,6 @@ package com.microsoft.sqlserver.jdbc.unit.serial; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; @@ -75,9 +75,9 @@ public void testESerial() throws Exception { try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) { SQLServerException ex = (SQLServerException) in.readObject(); - assertTrue(currException.toString().equals(ex.toString())); - assertTrue(currException.getSQLState().equals(ex.getSQLState())); - assertTrue(currException.getErrorCode() == ex.getErrorCode()); + assertEquals(currException.toString(), ex.toString()); + assertEquals(currException.getSQLState(), ex.getSQLState()); + assertEquals(currException.getErrorCode(), ex.getErrorCode()); } } } @@ -179,19 +179,19 @@ private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrat int hydratedOffset = hydrated.getMinutesOffset(); // check hydrated string - assertTrue(initialStr.equals(hydratedStr)); + assertEquals(initialStr, hydratedStr); // check formatted date string String formattedDate = sdf.format(sdf.parse(initialStr)); - assertTrue(formattedDate.equals(dateString)); + assertEquals(formattedDate, dateString); // check hydrated datetimeoffset - assertTrue(initial.equals(hydrated)); + assertEquals(initial, hydrated); // check hydrated timestamp - assertTrue(originalTS.equals(hydratedTS)); + assertEquals(originalTS, hydratedTS); // check hydrated offset - assertTrue(initiallOffset == hydratedOffset); + assertEquals(initiallOffset, hydratedOffset); } } From dc1a721607ed936140de87b03926c0aeed0393fc Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 18 Dec 2018 14:28:40 -0800 Subject: [PATCH 30/33] more cleanup on assertEqual checks --- .../microsoft/sqlserver/jdbc/TestUtils.java | 49 ------ .../jdbc/datatypes/BigIntegerTest.java | 150 +++++++++--------- .../jdbc/datatypes/KatmaiDataTypesTest.java | 8 +- .../sqlserver/jdbc/datatypes/SparseTest.java | 5 +- 4 files changed, 81 insertions(+), 131 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index 7b6840775..48b1f0d30 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -67,13 +67,6 @@ public class TestUtils { // private static SqlType types = null; private static ArrayList types = null; - private final static int ENGINE_EDITION_FOR_SQL_AZURE = 5; - private final static int ENGINE_EDITION_FOR_SQL_AZURE_DW = 6; - - // whether we determined if the target server is SQL Azure or DW - private static boolean _determinedSqlAzureOrSqlServer = false; - private static boolean _isSqlAzure = false; - private static boolean _isSqlAzureDW = false; /** * Returns serverType @@ -674,46 +667,4 @@ public static boolean supportJDBC43(Connection con) throws SQLException { public static String escapeSingleQuotes(String name) { return name.replace("'", "''"); } - - /** - * Returns if connected to SQL Azure - * @param con - * connection to server - * @return boolean - * @throws SQLException - */ - public static boolean isSqlAzure(Connection con) throws SQLException { - if (_determinedSqlAzureOrSqlServer) { - return _isSqlAzure; - } - - try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { - rs.next(); - int engineEdition = rs.getInt(1); - _determinedSqlAzureOrSqlServer = true; - _isSqlAzure = true; - return (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE || engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); - } - } - - /** - * Returns if connected to SQL Azure DW - * @param con - * connection to server - * @return boolean - * @throws SQLException - */ - public static boolean isSqlAzureDW(Connection con) throws SQLException { - if (_determinedSqlAzureOrSqlServer) { - return _isSqlAzureDW; - } - - try (ResultSet rs = con.createStatement().executeQuery("SELECT CAST(SERVERPROPERTY('EngineEdition') as INT)")) { - rs.next(); - int engineEdition = rs.getInt(1); - _determinedSqlAzureOrSqlServer = true; - _isSqlAzureDW = true; - return (engineEdition == ENGINE_EDITION_FOR_SQL_AZURE_DW); - } - } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java index 670515ec0..73b6cb073 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java @@ -1,5 +1,8 @@ package com.microsoft.sqlserver.jdbc.datatypes; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -10,9 +13,6 @@ import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.math.BigInteger; import com.microsoft.sqlserver.jdbc.RandomUtil; import com.microsoft.sqlserver.jdbc.TestUtils; @@ -37,58 +37,63 @@ enum TestType { @Test public void testJDBC41BigInteger() throws Exception { - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - - // Create the test table - TestUtils.dropTableIfExists(escapedTableName, stmt); - - String query = "create table " + escapedTableName - + " (col1 varchar(100), col2 bigint, col3 real, col4 float, " - + "col5 numeric(38,0), col6 int, col7 smallint, col8 char(100), col9 varchar(max), " - + "id int IDENTITY primary key)"; - stmt.executeUpdate(query); - - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + escapedTableName - + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM " + escapedTableName + " where id = ?")) { - - // test that the driver converts the BigInteger values greater than LONG.MAX_VALUE and lesser than - // LONG.MIN_VALUE correctly - // A random value that is bigger than LONG.MAX_VALUE - BigInteger bigIntPos = new BigInteger("922337203685477580776767676"); - // A random value that is smaller than LONG.MIN_VALUE - BigInteger bigIntNeg = new BigInteger("-922337203685477580776767676"); - - // Test the setObject method for different types of BigInteger values. Since BigInteger is mapped to - // JDBC - // BIGINT, the max and min limits for - int row = 1; - testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, - TestType.SETOBJECT_WITHTYPE); - - testSetObject(escapedTableName, BigInteger.valueOf(Long.MIN_VALUE), row++, pstmt, - TestType.SETOBJECT_WITHTYPE); - testSetObject(escapedTableName, BigInteger.valueOf(10), row++, pstmt, TestType.SETOBJECT_WITHTYPE); - testSetObject(escapedTableName, BigInteger.valueOf(-10), row++, pstmt, TestType.SETOBJECT_WITHTYPE); - testSetObject(escapedTableName, BigInteger.ZERO, row++, pstmt, TestType.SETOBJECT_WITHTYPE); - testSetObject(escapedTableName, bigIntPos, row++, pstmt, TestType.SETOBJECT_WITHTYPE); - testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETOBJECT_WITHTYPE); - - // Test setObject method with SQL TYPE parameter - testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, - TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(escapedTableName, BigInteger.valueOf(Long.MIN_VALUE), row++, pstmt, - TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(escapedTableName, BigInteger.valueOf(1000), row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(escapedTableName, BigInteger.valueOf(-1000), row++, pstmt, - TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(escapedTableName, BigInteger.ZERO, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(escapedTableName, bigIntPos, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); - - // Test setNull - testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETNULL); + try (Connection conn = DriverManager.getConnection(connectionString)) { + try (Statement stmt = conn.createStatement()) { + // Create the test table TestUtils.dropTableIfExists(escapedTableName, stmt); + + String query = "create table " + escapedTableName + + " (col1 varchar(100), col2 bigint, col3 real, col4 float, " + + "col5 numeric(38,0), col6 int, col7 smallint, col8 char(100), col9 varchar(max), " + + "id int IDENTITY primary key)"; + stmt.executeUpdate(query); + + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + escapedTableName + + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM " + escapedTableName + " where id = ?")) { + + // test that the driver converts the BigInteger values greater than LONG.MAX_VALUE and lesser than + // LONG.MIN_VALUE correctly + // A random value that is bigger than LONG.MAX_VALUE + BigInteger bigIntPos = new BigInteger("922337203685477580776767676"); + // A random value that is smaller than LONG.MIN_VALUE + BigInteger bigIntNeg = new BigInteger("-922337203685477580776767676"); + + // Test the setObject method for different types of BigInteger values. Since BigInteger is mapped to + // JDBC + // BIGINT, the max and min limits for + int row = 1; + testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + + testSetObject(escapedTableName, BigInteger.valueOf(Long.MIN_VALUE), row++, pstmt, + TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(10), row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(-10), row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, BigInteger.ZERO, row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, bigIntPos, row++, pstmt, TestType.SETOBJECT_WITHTYPE); + testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETOBJECT_WITHTYPE); + + // Test setObject method with SQL TYPE parameter + testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(Long.MIN_VALUE), row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(1000), row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, BigInteger.valueOf(-1000), row++, pstmt, + TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, BigInteger.ZERO, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, bigIntPos, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETOBJECT_WITHOUTTYPE); + + // Test setNull + testSetObject(escapedTableName, bigIntNeg, row++, pstmt, TestType.SETNULL); + } + } finally { + try (Statement stmt = conn.createStatement()) { + TestUtils.dropTableIfExists(escapedTableName, stmt); + } } } } @@ -102,7 +107,7 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat } else if (TestType.SETNULL == testType) { callSetNull(obj, pstmt); } else - assertEquals(true, false, "Invalid test type"); + return; // The id column pstmt.setObject(10, id); @@ -116,7 +121,7 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat for (int i = 1; 9 >= i; ++i) { // Get the data first before calling rs.wasNull() rs.getString(i); - assertEquals(rs.wasNull(), true, "setNull mismatch"); + assertEquals(rs.wasNull(), true); } return; } @@ -126,39 +131,36 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat // For the BigInteger values greater/less than Long limits test only the long data type. // This test is here just to make sure the driver does not do anything wired when the value is // bigger/smaller than JDBC BIGINT - assertEquals(rs.getString(1), Long.valueOf(obj.longValue()).toString(), - "getString(greater/less than Long limits) mismatch"); + assertEquals(rs.getString(1), Long.valueOf(obj.longValue()).toString()); assertEquals(rs.getLong(2), obj.longValue(), "getLong(greater/less than Long limits) mismatch"); // As CHAR is fixed length, rs.getString() returns a string of the size allocated in the database. // Need to trim it for comparison. - assertEquals(rs.getString(8).trim(), Long.valueOf(obj.longValue()).toString(), - "getString(greater/less than Long limits (char)) mismatch"); + assertEquals(rs.getString(8).trim(), Long.valueOf(obj.longValue()).toString()); - assertEquals(rs.getString(9), Long.valueOf(obj.longValue()).toString(), - "getString(greater/less than Long limits (varchar(max)))) mismatch"); + assertEquals(rs.getString(9), Long.valueOf(obj.longValue()).toString()); } else { - assertEquals(rs.getString(1), obj.toString(), "getString mismatch"); - assertEquals(rs.getLong(2), obj.longValue(), "getLong mismatch"); - assertEquals(rs.getFloat(3), obj.floatValue(), "getFloat mismatch"); - assertEquals(rs.getDouble(4), obj.doubleValue(), "getDouble(float) mismatch"); - assertEquals(rs.getDouble(5), obj.doubleValue(), "getDouble(numeric) mismatch"); + assertEquals(rs.getString(1), obj.toString()); + assertEquals(rs.getLong(2), obj.longValue()); + assertEquals(rs.getFloat(3), obj.floatValue()); + assertEquals(rs.getDouble(4), obj.doubleValue()); + assertEquals(rs.getDouble(5), obj.doubleValue()); if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { - assertEquals(rs.getInt(6), Integer.MAX_VALUE, "getInt(numeric) mismatch"); + assertEquals(rs.getInt(6), Integer.MAX_VALUE); } else if (obj.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) <= 0) { - assertEquals(rs.getInt(6), Integer.MIN_VALUE, "getInt(numeric) mismatch"); + assertEquals(rs.getInt(6), Integer.MIN_VALUE); } else { - assertEquals(rs.getInt(6), obj.intValue(), "getInt(numeric) mismatch"); + assertEquals(rs.getInt(6), obj.intValue()); } if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { - assertEquals(rs.getShort(7), Short.MAX_VALUE, "getShort(numeric) mismatch"); + assertEquals(rs.getShort(7), Short.MAX_VALUE); } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { - assertEquals(rs.getShort(7), Short.MIN_VALUE, "getShort(numeric) mismatch"); + assertEquals(rs.getShort(7), Short.MIN_VALUE); } else { - assertEquals(rs.getShort(7), obj.shortValue(), "getShort(numeric) mismatch"); + assertEquals(rs.getShort(7), obj.shortValue()); } - assertEquals(rs.getString(8).trim(), obj.toString(), "getString(char) mismatch"); - assertEquals(rs.getString(9), obj.toString(), "getString(varchar(max)) mismatch"); + assertEquals(rs.getString(8).trim(), obj.toString()); + assertEquals(rs.getString(9), obj.toString()); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 993be3b9e..2dcc707a7 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -202,7 +202,7 @@ void verifyRSGetters(Connection conn) throws Exception { } void verifyRSUpdaters(Connection conn) throws Exception { - assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!isSqlAzureDW(), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { @@ -223,7 +223,7 @@ void verifyRSUpdaters(Connection conn) throws Exception { } void verifySetters(Connection conn) throws Exception { - assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!isSqlAzureDW(), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { TestUtils.dropTableIfExists(escapedTableName, stmt); @@ -1180,7 +1180,7 @@ public void testDoubleRounding() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString)) { // create a table with a datetimeoffset column and insert a value in it - assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!isSqlAzureDW(), TestResource.getResource("R_skipAzure")); String sql; try (Statement stmt = conn.createStatement()) { @@ -1575,7 +1575,7 @@ public void testUpdateMisc() throws Exception { try (SQLServerConnection conn = (SQLServerConnection) DriverManager .getConnection(connectionString + ";sendTimeAsDatetime=true")) { - assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!isSqlAzureDW(), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { TestUtils.dropTableIfExists(escapedTableName, stmt); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java index b41163787..6c5103c4a 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java @@ -1,6 +1,5 @@ package com.microsoft.sqlserver.jdbc.datatypes; -import static org.junit.Assert.fail; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -28,7 +27,7 @@ public class SparseTest extends AbstractTest { @Test public void testSparse() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString)) { - assumeTrue(!TestUtils.isSqlAzureDW(conn), TestResource.getResource("R_skipAzure")); + assumeTrue(!isSqlAzureDW(), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement()) { // Create the test table @@ -55,8 +54,6 @@ public void testSparse() throws Exception { } finally { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(escapedTableName, stmt); - } catch (Exception e) { - fail(TestResource.getResource("R_createDropTableFailed") + e.toString()); } } } From 6eac22ce6c9929c2383ecdf30e9424a2bbb8e21f Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 18 Dec 2018 22:38:39 -0800 Subject: [PATCH 31/33] cosmetic changes from review --- .../callablestatement/CallableMixedTest.java | 5 -- .../jdbc/datatypes/BigIntegerTest.java | 50 ++++++++++++------- .../jdbc/datatypes/KatmaiDataTypesTest.java | 44 ++++++++-------- 3 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index 4d3e255a1..c8ab9c937 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -59,9 +59,7 @@ public void datatypestest() throws Exception { // get results and a value try (ResultSet rs = cstmt.executeQuery()) { rs.next(); - assertEquals(rs.getInt(1), 0); - assertEquals(cstmt.getInt((int) 5), -5372); } @@ -75,11 +73,8 @@ public void datatypestest() throws Exception { try (ResultSet rs = cstmt.executeQuery()) { rs.next(); - assertEquals(rs.getInt(1), 0); - assertEquals(cstmt.getInt((int) 1), -2147483648); - assertEquals(cstmt.getInt((int) 5), -5372); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java index 73b6cb073..ee02e1a7e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java @@ -21,22 +21,25 @@ /* - * This test is for testing the setObject methods for the new data type mappings in JDBC 4.1 for java.math.BigInteger + * This test is for testing the setObject methods for the data type mappings in JDBC for java.math.BigInteger */ @RunWith(JUnitPlatform.class) public class BigIntegerTest extends AbstractTest { enum TestType { - SETOBJECT_WITHTYPE, // This is to test conversions in Table B-5 - SETOBJECT_WITHOUTTYPE, // This is to test conversions in Table B-4 + SETOBJECT_WITHTYPE, // This is to test conversions with type + SETOBJECT_WITHOUTTYPE, // This is to test conversions without type SETNULL // This is to test setNull method }; final static String tableName = RandomUtil.getIdentifier("BigIntegerTestTable"); final static String escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); + /* + * Test BigInteger conversions + */ @Test - public void testJDBC41BigInteger() throws Exception { + public void testBigInteger() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { @@ -52,16 +55,16 @@ public void testJDBC41BigInteger() throws Exception { try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + escapedTableName + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?) SELECT * FROM " + escapedTableName + " where id = ?")) { - // test that the driver converts the BigInteger values greater than LONG.MAX_VALUE and lesser than - // LONG.MIN_VALUE correctly + /* + * test conversion of BigInteger values greater than LONG.MAX_VALUE and lesser than LONG.MIN_VALUE + */ + // A random value that is bigger than LONG.MAX_VALUE BigInteger bigIntPos = new BigInteger("922337203685477580776767676"); // A random value that is smaller than LONG.MIN_VALUE BigInteger bigIntNeg = new BigInteger("-922337203685477580776767676"); - // Test the setObject method for different types of BigInteger values. Since BigInteger is mapped to - // JDBC - // BIGINT, the max and min limits for + // Test the setObject method for different types of BigInteger values int row = 1; testSetObject(escapedTableName, BigInteger.valueOf(Long.MAX_VALUE), row++, pstmt, TestType.SETOBJECT_WITHTYPE); @@ -128,15 +131,18 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat if ((0 > obj.compareTo(BigInteger.valueOf(Long.MIN_VALUE))) || (0 < obj.compareTo(BigInteger.valueOf(Long.MAX_VALUE)))) { - // For the BigInteger values greater/less than Long limits test only the long data type. - // This test is here just to make sure the driver does not do anything wired when the value is - // bigger/smaller than JDBC BIGINT + /* + * For the BigInteger values greater/less than Long limits test only the long data type. This tests when + * the value is bigger/smaller than JDBC BIGINT + */ assertEquals(rs.getString(1), Long.valueOf(obj.longValue()).toString()); - assertEquals(rs.getLong(2), obj.longValue(), "getLong(greater/less than Long limits) mismatch"); - // As CHAR is fixed length, rs.getString() returns a string of the size allocated in the database. - // Need to trim it for comparison. - assertEquals(rs.getString(8).trim(), Long.valueOf(obj.longValue()).toString()); + assertEquals(rs.getLong(2), obj.longValue()); + /* + * As CHAR is fixed length, rs.getString() returns a string of the size allocated in the database. Need + * to trim it for comparison. + */ + assertEquals(rs.getString(8).trim(), Long.valueOf(obj.longValue()).toString()); assertEquals(rs.getString(9), Long.valueOf(obj.longValue()).toString()); } else { assertEquals(rs.getString(1), obj.toString()); @@ -144,6 +150,7 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat assertEquals(rs.getFloat(3), obj.floatValue()); assertEquals(rs.getDouble(4), obj.doubleValue()); assertEquals(rs.getDouble(5), obj.doubleValue()); + if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { assertEquals(rs.getInt(6), Integer.MAX_VALUE); } else if (obj.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) <= 0) { @@ -151,6 +158,7 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat } else { assertEquals(rs.getInt(6), obj.intValue()); } + if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { assertEquals(rs.getShort(7), Short.MAX_VALUE); } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { @@ -171,6 +179,7 @@ static void callSetObjectWithType(BigInteger obj, PreparedStatement pstmt) throw pstmt.setObject(3, obj, java.sql.Types.FLOAT); pstmt.setObject(4, obj, java.sql.Types.DOUBLE); pstmt.setObject(5, obj, java.sql.Types.NUMERIC); + // Use Integer/Short limits instead of Long limits for the int/smallint column if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { pstmt.setObject(6, BigInteger.valueOf(Integer.MAX_VALUE), java.sql.Types.INTEGER); @@ -179,6 +188,7 @@ static void callSetObjectWithType(BigInteger obj, PreparedStatement pstmt) throw } else { pstmt.setObject(6, obj, java.sql.Types.INTEGER); } + if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { pstmt.setObject(7, BigInteger.valueOf(Short.MAX_VALUE), java.sql.Types.SMALLINT); } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { @@ -191,13 +201,16 @@ static void callSetObjectWithType(BigInteger obj, PreparedStatement pstmt) throw } static void callSetObjectWithoutType(BigInteger obj, PreparedStatement pstmt) throws SQLException { - // Cannot send a long value to a column of type int/smallint (even if the long value is small enough to fit in - // those types) + /* + * Cannot send a long value to a column of type int/smallint (even if the long value is small enough to fit in + * those types) + */ pstmt.setObject(1, obj); pstmt.setObject(2, obj); pstmt.setObject(3, obj); pstmt.setObject(4, obj); pstmt.setObject(5, obj); + // Use Integer/Short limits instead of Long limits for the int/smallint column if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { pstmt.setObject(6, BigInteger.valueOf(Integer.MAX_VALUE)); @@ -206,6 +219,7 @@ static void callSetObjectWithoutType(BigInteger obj, PreparedStatement pstmt) th } else { pstmt.setObject(6, obj); } + if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { pstmt.setObject(7, BigInteger.valueOf(Short.MAX_VALUE)); } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 2dcc707a7..5b57ac571 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -45,7 +45,7 @@ /* * This test suite tests all kinds of temporal data types for Katmai or later versions. It has tests for - * date/time/datetime2/datetimeoffset data types. Also includes tests for new data type mappings in JDBC 4.1. + * date/time/datetime2/datetimeoffset data types. Also includes tests for data type mappings. */ @RunWith(JUnitPlatform.class) public class KatmaiDataTypesTest extends AbstractTest { @@ -138,29 +138,25 @@ void verifyResultSetMetaData(Connection conn) throws Exception { try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT TOP 0 " + sqlCastExpression())) { - try { - ResultSetMetaData metadata = rs.getMetaData(); - - assertEquals(metadata.getColumnType(1), sqlType.jdbcType, - "getColumnType() of " + sqlCastExpression()); - assertEquals(metadata.getColumnTypeName(1), sqlType.toString(), - "getColumnTypeName() of " + sqlCastExpression()); - assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); - - // Display size of temporal types is the precision per JDBC spec - assertEquals(metadata.getColumnDisplaySize(1), precision, - "getColumnDisplaySize() of " + sqlCastExpression()); - // Scale is interpreted as number of fractional seconds precision - assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); - assertEquals(metadata.getColumnClassName(1), sqlType.className, - "getColumnClassName() of " + sqlCastExpression()); - // Katmai temporal types are not signed - assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); - - // Katmai temporal types are searchable (i.e. usable in a WHERE clause) - assertEquals(metadata.isSearchable(1), true, "isSearchable() of " + sqlCastExpression()); - - } finally {} + ResultSetMetaData metadata = rs.getMetaData(); + + assertEquals(metadata.getColumnType(1), sqlType.jdbcType, "getColumnType() of " + sqlCastExpression()); + assertEquals(metadata.getColumnTypeName(1), sqlType.toString(), + "getColumnTypeName() of " + sqlCastExpression()); + assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + + // Display size of temporal types is the precision per JDBC spec + assertEquals(metadata.getColumnDisplaySize(1), precision, + "getColumnDisplaySize() of " + sqlCastExpression()); + // Scale is interpreted as number of fractional seconds precision + assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); + assertEquals(metadata.getColumnClassName(1), sqlType.className, + "getColumnClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed + assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + + // Katmai temporal types are searchable (i.e. usable in a WHERE clause) + assertEquals(metadata.isSearchable(1), true, "isSearchable() of " + sqlCastExpression()); } } From 72956ed72497d62d21f27046513544bd8a8bee8c Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 19 Dec 2018 00:42:22 -0800 Subject: [PATCH 32/33] updated all assertEquals params to proper expected, actual order --- .../callablestatement/CallableMixedTest.java | 12 +- .../jdbc/datatypes/BigIntegerTest.java | 36 +-- .../jdbc/datatypes/KatmaiDataTypesTest.java | 230 +++++++++--------- .../sqlserver/jdbc/datatypes/SparseTest.java | 6 +- .../jdbc/unit/serial/DTOSerialTest.java | 11 +- 5 files changed, 144 insertions(+), 151 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index c8ab9c937..697e345cc 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -59,8 +59,8 @@ public void datatypestest() throws Exception { // get results and a value try (ResultSet rs = cstmt.executeQuery()) { rs.next(); - assertEquals(rs.getInt(1), 0); - assertEquals(cstmt.getInt((int) 5), -5372); + assertEquals(0, rs.getInt(1)); + assertEquals(-5372, cstmt.getInt((int) 5)); } // do nothing and reexecute @@ -68,14 +68,14 @@ public void datatypestest() throws Exception { // get the param without getting the resultset try (ResultSet rs = cstmt.executeQuery()) { - assertEquals(cstmt.getInt((int) 1), -2147483648); + assertEquals(-2147483648, cstmt.getInt((int) 1)); } try (ResultSet rs = cstmt.executeQuery()) { rs.next(); - assertEquals(rs.getInt(1), 0); - assertEquals(cstmt.getInt((int) 1), -2147483648); - assertEquals(cstmt.getInt((int) 5), -5372); + assertEquals(0, rs.getInt(1)); + assertEquals(-2147483648, cstmt.getInt((int) 1)); + assertEquals(-5372, cstmt.getInt((int) 5)); } } } finally { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java index ee02e1a7e..4a63ec894 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/BigIntegerTest.java @@ -124,7 +124,7 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat for (int i = 1; 9 >= i; ++i) { // Get the data first before calling rs.wasNull() rs.getString(i); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); } return; } @@ -135,40 +135,40 @@ static void testSetObject(String tableName, BigInteger obj, int id, PreparedStat * For the BigInteger values greater/less than Long limits test only the long data type. This tests when * the value is bigger/smaller than JDBC BIGINT */ - assertEquals(rs.getString(1), Long.valueOf(obj.longValue()).toString()); - assertEquals(rs.getLong(2), obj.longValue()); + assertEquals(Long.valueOf(obj.longValue()).toString(), rs.getString(1)); + assertEquals(obj.longValue(), rs.getLong(2)); /* * As CHAR is fixed length, rs.getString() returns a string of the size allocated in the database. Need * to trim it for comparison. */ - assertEquals(rs.getString(8).trim(), Long.valueOf(obj.longValue()).toString()); - assertEquals(rs.getString(9), Long.valueOf(obj.longValue()).toString()); + assertEquals(Long.valueOf(obj.longValue()).toString(), rs.getString(8).trim()); + assertEquals(Long.valueOf(obj.longValue()).toString(), rs.getString(9)); } else { - assertEquals(rs.getString(1), obj.toString()); - assertEquals(rs.getLong(2), obj.longValue()); - assertEquals(rs.getFloat(3), obj.floatValue()); - assertEquals(rs.getDouble(4), obj.doubleValue()); - assertEquals(rs.getDouble(5), obj.doubleValue()); + assertEquals(obj.toString(), rs.getString(1)); + assertEquals(obj.longValue(), rs.getLong(2)); + assertEquals(obj.floatValue(), rs.getFloat(3)); + assertEquals(obj.doubleValue(), rs.getDouble(4)); + assertEquals(obj.doubleValue(), rs.getDouble(5)); if (obj.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 0) { - assertEquals(rs.getInt(6), Integer.MAX_VALUE); + assertEquals(Integer.MAX_VALUE, rs.getInt(6)); } else if (obj.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) <= 0) { - assertEquals(rs.getInt(6), Integer.MIN_VALUE); + assertEquals(Integer.MIN_VALUE, rs.getInt(6)); } else { - assertEquals(rs.getInt(6), obj.intValue()); + assertEquals(obj.intValue(), rs.getInt(6)); } if (obj.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) >= 0) { - assertEquals(rs.getShort(7), Short.MAX_VALUE); + assertEquals(Short.MAX_VALUE, rs.getShort(7)); } else if (obj.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) <= 0) { - assertEquals(rs.getShort(7), Short.MIN_VALUE); + assertEquals(Short.MIN_VALUE, rs.getShort(7)); } else { - assertEquals(rs.getShort(7), obj.shortValue()); + assertEquals(obj.shortValue(), rs.getShort(7)); } - assertEquals(rs.getString(8).trim(), obj.toString()); - assertEquals(rs.getString(9), obj.toString()); + assertEquals(obj.toString(), rs.getString(8).trim()); + assertEquals(obj.toString(), rs.getString(9)); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index 5b57ac571..e6f76a490 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -140,23 +140,25 @@ void verifyResultSetMetaData(Connection conn) throws Exception { ResultSetMetaData metadata = rs.getMetaData(); - assertEquals(metadata.getColumnType(1), sqlType.jdbcType, "getColumnType() of " + sqlCastExpression()); - assertEquals(metadata.getColumnTypeName(1), sqlType.toString(), + assertEquals(sqlType.jdbcType, metadata.getColumnType(1), "getColumnType() of " + sqlCastExpression()); + assertEquals(sqlType.toString(), metadata.getColumnTypeName(1), "getColumnTypeName() of " + sqlCastExpression()); - assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + assertEquals(precision, metadata.getPrecision(1), "getPrecision() of " + sqlCastExpression()); // Display size of temporal types is the precision per JDBC spec - assertEquals(metadata.getColumnDisplaySize(1), precision, + assertEquals(precision, metadata.getColumnDisplaySize(1), "getColumnDisplaySize() of " + sqlCastExpression()); + // Scale is interpreted as number of fractional seconds precision - assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); - assertEquals(metadata.getColumnClassName(1), sqlType.className, + assertEquals(scale, metadata.getScale(1), "getScale() of " + sqlCastExpression()); + assertEquals(sqlType.className, metadata.getColumnClassName(1), "getColumnClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed - assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + assertEquals(false, metadata.isSigned(1), "isSigned() of " + sqlCastExpression()); // Katmai temporal types are searchable (i.e. usable in a WHERE clause) - assertEquals(metadata.isSearchable(1), true, "isSearchable() of " + sqlCastExpression()); + assertEquals(true, metadata.isSearchable(1), "isSearchable() of " + sqlCastExpression()); } } @@ -169,18 +171,19 @@ void verifyParameterMetaData(Connection conn) throws Exception { try (PreparedStatement pstmt = conn.prepareStatement("{call " + escapedProcName + "(?)}")) { ParameterMetaData metadata = pstmt.getParameterMetaData(); - assertEquals(metadata.getParameterType(1), sqlType.jdbcType, + assertEquals(sqlType.jdbcType, metadata.getParameterType(1), "getParameterType() of " + sqlCastExpression()); - assertEquals(metadata.getParameterTypeName(1), sqlType.toString(), + assertEquals(sqlType.toString(), metadata.getParameterTypeName(1), "getParameterTypeName() of " + sqlCastExpression()); - assertEquals(metadata.getPrecision(1), precision, "getPrecision() of " + sqlCastExpression()); + assertEquals(precision, metadata.getPrecision(1), "getPrecision() of " + sqlCastExpression()); // Scale is interpreted as number of fractional seconds precision - assertEquals(metadata.getScale(1), scale, "getScale() of " + sqlCastExpression()); - assertEquals(metadata.getParameterClassName(1), sqlType.className, + assertEquals(scale, metadata.getScale(1), "getScale() of " + sqlCastExpression()); + assertEquals(sqlType.className, metadata.getParameterClassName(1), "getParameterClassName() of " + sqlCastExpression()); + // Katmai temporal types are not signed - assertEquals(metadata.isSigned(1), false, "isSigned() of " + sqlCastExpression()); + assertEquals(false, metadata.isSigned(1), "isSigned() of " + sqlCastExpression()); } } finally { try (Statement stmt = conn.createStatement()) { @@ -282,18 +285,16 @@ private java.util.Calendar expectedCalendar() { } void verifyRSGetters(ResultSet rs) throws Exception { - assertEquals(rs.getDate(1), expected); - - assertEquals(rs.getTimestamp(1), new Timestamp(expected.getTime())); - - assertEquals(rs.getString(1), expected.toString()); + assertEquals(expected, rs.getDate(1)); + assertEquals(new Timestamp(expected.getTime()), rs.getTimestamp(1)); + assertEquals(expected.toString(), rs.getString(1)); } void verifyRSUpdaters(ResultSet rs) throws Exception { rs.updateDate(1, expected); rs.updateRow(); - assertEquals(rs.getDate(1), expected); + assertEquals(expected, rs.getDate(1)); } void verifySetters(PreparedStatement ps) throws Exception { @@ -303,7 +304,7 @@ void verifySetters(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getDate(1), expected); + assertEquals(expected, rs.getDate(1)); } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -313,8 +314,8 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { ps.getMoreResults(); ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getDate(1), expected); - assertEquals((java.util.Date) rs.getObject(1), expectedUtilDate()); + assertEquals(expected, rs.getDate(1)); + assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP @@ -326,7 +327,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getDate(1), expected); + assertEquals(expected, rs.getDate(1)); ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); ps.execute(); @@ -336,7 +337,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); // Test the setNull() methods for different data type conversions ps.setNull(1, java.sql.Types.DATE); @@ -348,7 +349,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); ps.setNull(1, java.sql.Types.TIMESTAMP); ps.execute(); @@ -359,7 +360,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); } void verifySettersCalendar(PreparedStatement ps) throws Exception { @@ -369,7 +370,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ps.getMoreResults(); ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getDate(1), expected); + assertEquals(expected, rs.getDate(1)); // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date // or java.util.Date can be cast to a calendar @@ -383,7 +384,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getDate(1), expected); + assertEquals(expected, rs.getDate(1)); ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); ps.execute(); @@ -393,15 +394,15 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); } void verifyCSGetters(CallableStatement cs) throws Exception { cs.setDate(1, expected); cs.registerOutParameter(2, java.sql.Types.DATE); cs.execute(); - assertEquals(cs.getDate(2), expected); - assertEquals(cs.getObject(2), expected); + assertEquals(expected, cs.getDate(2)); + assertEquals(expected, cs.getObject(2)); } } @@ -487,18 +488,16 @@ private java.util.Calendar expectedCalendar() { } void verifyRSGetters(ResultSet rs) throws Exception { - assertEquals(rs.getTime(1), expectedTime()); - - assertEquals(rs.getTimestamp(1), expectedTimestamp()); - - assertEquals(rs.getString(1), this.getString()); + assertEquals(expectedTime(), rs.getTime(1)); + assertEquals(expectedTimestamp(), rs.getTimestamp(1)); + assertEquals(this.getString(), rs.getString(1)); } void verifyRSUpdaters(ResultSet rs) throws Exception { rs.updateTime(1, expectedTime()); rs.updateRow(); - assertEquals(rs.getTime(1), expectedTime()); + assertEquals(expectedTime(), rs.getTime(1)); } void verifySetters(PreparedStatement ps) throws Exception { @@ -508,7 +507,7 @@ void verifySetters(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTime(1), expectedTime()); + assertEquals(expectedTime(), rs.getTime(1)); } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -518,9 +517,9 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { ps.getMoreResults(); ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTime(1), expectedTime()); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); - assertEquals((java.util.Date) rs.getObject(1), expectedUtilDate()); + assertEquals(expectedTime(), rs.getTime(1)); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP @@ -532,7 +531,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getTime(1), expectedTime()); + assertEquals(expectedTime(), rs.getTime(1)); ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); ps.execute(); @@ -542,7 +541,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); // Test the setNull() methods for different data type conversions ps.setNull(1, java.sql.Types.TIME); @@ -554,7 +553,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); ps.setNull(1, java.sql.Types.TIMESTAMP); ps.execute(); @@ -565,7 +564,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); } @@ -576,7 +575,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ps.getMoreResults(); ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTime(1), expectedTime()); + assertEquals(expectedTime(), rs.getTime(1)); assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date @@ -592,7 +591,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getTime(1), expectedTime()); + assertEquals(expectedTime(), rs.getTime(1)); ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); ps.execute(); @@ -602,15 +601,15 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { rs.next(); // Go to the row just inserted rs.relative(++currentRow); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); } void verifyCSGetters(CallableStatement cs) throws Exception { cs.setTime(1, expectedTime()); cs.registerOutParameter(2, java.sql.Types.TIME); cs.execute(); - assertEquals(cs.getTime(2), expectedTime()); - assertEquals(cs.getObject(2), expectedTime()); + assertEquals(expectedTime(), cs.getTime(2)); + assertEquals(expectedTime(), cs.getObject(2)); } } @@ -713,13 +712,10 @@ private java.util.Calendar expectedCalendar() { } void verifyRSGetters(ResultSet rs) throws Exception { - assertEquals(rs.getDate(1, Calendar.getInstance(tz)), expectedDate()); - - assertEquals(rs.getTime(1, Calendar.getInstance(tz)), expectedTime()); - - assertEquals(rs.getTimestamp(1, Calendar.getInstance(tz)), expectedTimestamp()); - - assertEquals(rs.getString(1), stringValue); + assertEquals(expectedDate(), rs.getDate(1, Calendar.getInstance(tz))); + assertEquals(expectedTime(), rs.getTime(1, Calendar.getInstance(tz))); + assertEquals(expectedTimestamp(), rs.getTimestamp(1, Calendar.getInstance(tz))); + assertEquals(stringValue, rs.getString(1)); } void verifyRSUpdaters(ResultSet rs) throws Exception { @@ -736,7 +732,7 @@ void verifyRSUpdaters(ResultSet rs) throws Exception { rs.updateRow(); // Verify the update (this value's time zone is still the default) - assertEquals(rs.getTimestamp(1), expectedTimestamp()); + assertEquals(expectedTimestamp(), rs.getTimestamp(1)); } finally { // Restore the original default time zone TimeZone.setDefault(tzDefault); @@ -744,7 +740,7 @@ void verifyRSUpdaters(ResultSet rs) throws Exception { // Verify the update (after restoring the default time zone) using the getTimestamp // variant that takes a time zone argument (as a Calendar) - assertEquals(rs.getTimestamp(1, Calendar.getInstance(tz)), expectedTimestamp()); + assertEquals(expectedTimestamp(), rs.getTimestamp(1, Calendar.getInstance(tz))); } void verifySetters(PreparedStatement ps) throws Exception { @@ -760,7 +756,7 @@ void verifySetters(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTimestamp(1), expectedTimestamp()); + assertEquals(expectedTimestamp(), rs.getTimestamp(1)); } finally { TimeZone.setDefault(tzDefault); } @@ -772,7 +768,7 @@ void verifySetters(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTimestamp(1, Calendar.getInstance(tz)), expectedTimestamp()); + assertEquals(expectedTimestamp(), rs.getTimestamp(1, Calendar.getInstance(tz))); } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -782,8 +778,8 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { ps.getMoreResults(); ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); - assertEquals((java.util.Date) rs.getObject(1), expectedUtilDate()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP @@ -794,7 +790,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { // Go to the next row rs.next(); rs.relative(++currentRow); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); // Test the setNull() methods for different data type conversions ps.setNull(1, java.sql.Types.TIME); @@ -806,7 +802,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); ps.setNull(1, java.sql.Types.DATE); ps.execute(); @@ -817,7 +813,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); ps.setNull(1, java.sql.Types.TIMESTAMP); ps.execute(); @@ -828,7 +824,7 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { rs.relative(++currentRow); // Read the column, first before calling rs.wasNull() rs.getTimestamp(1); - assertEquals(rs.wasNull(), true); + assertEquals(true, rs.wasNull()); } void verifySettersCalendar(PreparedStatement ps) throws Exception { @@ -838,7 +834,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ps.getMoreResults(); ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date // or java.util.Date can be cast to a calendar @@ -851,7 +847,7 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { // Go to the next row rs.next(); rs.relative(++currentRow); - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); } void verifyCSGetters(CallableStatement cs) throws Exception { @@ -860,14 +856,14 @@ void verifyCSGetters(CallableStatement cs) throws Exception { cs.execute(); // Verify typed getter (with time zone argument) - assertEquals(cs.getTimestamp(2, Calendar.getInstance(tz)), expectedTimestamp()); + assertEquals(expectedTimestamp(), cs.getTimestamp(2, Calendar.getInstance(tz))); // Verify getObject (no provision for time zone argument - need to push/pop the default) TimeZone tzDefault = TimeZone.getDefault(); try { TimeZone.setDefault(tz); - assertEquals(cs.getObject(2), expectedTimestamp()); + assertEquals(expectedTimestamp(), cs.getObject(2)); } finally { TimeZone.setDefault(tzDefault); } @@ -978,22 +974,18 @@ private java.util.Calendar expectedCalendar() { } void verifyRSGetters(ResultSet rs) throws Exception { - assertEquals(rs.getDate(1), expectedDate()); - - assertEquals(rs.getTime(1), expectedTime()); - - assertEquals(rs.getTimestamp(1), dto.getTimestamp()); - - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1), dto); - - assertEquals(rs.getString(1), this.getString()); + assertEquals(expectedDate(), rs.getDate(1)); + assertEquals(expectedTime(), rs.getTime(1)); + assertEquals(dto.getTimestamp(), rs.getTimestamp(1)); + assertEquals(dto, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + assertEquals(this.getString(), rs.getString(1)); } void verifyRSUpdaters(ResultSet rs) throws Exception { ((SQLServerResultSet) rs).updateDateTimeOffset(1, dto); rs.updateRow(); - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1), dto); + assertEquals(dto, ((SQLServerResultSet) rs).getDateTimeOffset(1)); } void verifySetters(PreparedStatement ps) throws Exception { @@ -1003,7 +995,7 @@ void verifySetters(PreparedStatement ps) throws Exception { ResultSet rs = ps.getResultSet(); rs.next(); - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1), dto); + assertEquals(dto, ((SQLServerResultSet) rs).getDateTimeOffset(1)); } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -1026,9 +1018,9 @@ void verifyCSGetters(CallableStatement cs) throws Exception { ((SQLServerCallableStatement) cs).setDateTimeOffset(1, dto); cs.registerOutParameter(2, microsoft.sql.Types.DATETIMEOFFSET); cs.execute(); - assertEquals(((SQLServerCallableStatement) cs).getDateTimeOffset(2), dto); + assertEquals(dto, ((SQLServerCallableStatement) cs).getDateTimeOffset(2)); - assertEquals(cs.getObject(2), dto); + assertEquals(dto, cs.getObject(2)); } } @@ -1159,7 +1151,7 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { // Fetch the OUT parameter and verify that we have a date-normalized TIME of midnight java.sql.Time timeOut = cs.getTime(2); Timestamp tsOut = new Timestamp(timeOut.getTime()); - assertEquals(tsOut.toString(), "1970-01-01 00:00:00.0"); + assertEquals("1970-01-01 00:00:00.0", tsOut.toString()); } } finally { @@ -1222,7 +1214,7 @@ public void testDoubleRounding() throws Exception { rs.next(); // 3432-12-21 23:22:58.832909 +00:00 DateTimeOffset expectedDto = (DateTimeOffset) rs.getObject(1); - assertEquals(actualDto, expectedDto); + assertEquals(expectedDto, actualDto); } } finally { try (Statement stmt = conn.createStatement()) { @@ -1266,7 +1258,7 @@ public void testWithJapaneseImperialCalendar() throws Exception { Date date = rs.getDate(1, japaneseImperialCalendar); // check pre-Meiji - assertEquals(date.toString(), "0821-01-04"); + assertEquals("0821-01-04", date.toString()); } try (PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))")) { @@ -1283,7 +1275,7 @@ public void testWithJapaneseImperialCalendar() throws Exception { try (ResultSet rs = ps.executeQuery()) { rs.next(); // check Taisho 1 - assertEquals(rs.getString(1), "1912-07-31 00:00:00.0000000"); + assertEquals("1912-07-31 00:00:00.0000000", rs.getString(1)); } // Set second year of Showa era (1927 Gregorian) @@ -1301,7 +1293,7 @@ public void testWithJapaneseImperialCalendar() throws Exception { try (ResultSet rs = ps.executeQuery()) { rs.next(); // check Showa 2 - assertEquals(rs.getString(1), "1927-02-15 08:49:03.0870000"); + assertEquals("1927-02-15 08:49:03.0870000", rs.getString(1)); } } } finally { @@ -1383,7 +1375,7 @@ public void testWithThaiLocale() throws Exception { ps.setTimestamp(1, ts); try (ResultSet rs = ps.executeQuery()) { rs.next(); - assertEquals(rs.getString(1), tsFormat.format(ts)); + assertEquals(tsFormat.format(ts), rs.getString(1)); } // Test PreparedStatement with Time @@ -1394,9 +1386,9 @@ public void testWithThaiLocale() throws Exception { rs.next(); // compare these separately since there may be an extra space between the 2 - assertEquals(rs.getString(1).substring(0, 11), "Jan 1 1970"); - assertEquals(rs.getString(1).substring(rs.getString(1).length() - 7).trim(), - timeFormat.format(ts.getTime())); + assertEquals("Jan 1 1970", rs.getString(1).substring(0, 11)); + assertEquals(timeFormat.format(ts.getTime()), + rs.getString(1).substring(rs.getString(1).length() - 7).trim()); } // Test PreparedStatement with Date @@ -1404,7 +1396,7 @@ public void testWithThaiLocale() throws Exception { ps.setDate(1, date); try (ResultSet rs = ps.executeQuery()) { rs.next(); - assertEquals(rs.getString(1), dateFormat.format(ts)); + assertEquals(dateFormat.format(ts), rs.getString(1)); } // Test PreparedStatement with Date (using Buddhist calendar) @@ -1412,7 +1404,7 @@ public void testWithThaiLocale() throws Exception { ps.setDate(1, date, Calendar.getInstance()); try (ResultSet rs = ps.executeQuery()) { rs.next(); - assertEquals(rs.getString(1), dateFormat.format(ts)); + assertEquals(dateFormat.format(ts), rs.getString(1)); } // Test PreparedStatement with DateTimeOffset (using Buddhist calendar) @@ -1425,7 +1417,7 @@ public void testWithThaiLocale() throws Exception { rs.next(); dtoFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - assertEquals(rs.getString(1), dtoFormat.format(ts)); + assertEquals(dtoFormat.format(ts), rs.getString(1)); } } } finally { @@ -1447,7 +1439,7 @@ public void testBaseDate() throws Exception { rs.next(); ts = rs.getTimestamp(1); // java base date - assertEquals(ts.toString(), "1970-01-01 12:34:56.0"); + assertEquals("1970-01-01 12:34:56.0", ts.toString()); } } @@ -1460,7 +1452,7 @@ public void testBaseDate() throws Exception { rs.next(); ts = rs.getTimestamp(1); // SQL Server base date - assertEquals(ts.toString(), "1900-01-01 12:34:56.0"); + assertEquals("1900-01-01 12:34:56.0", ts.toString()); } } } @@ -1476,7 +1468,7 @@ public void testTimestampToDateTimeOffset() throws Exception { try (ResultSet rs = ps.executeQuery()) { rs.next(); DateTimeOffset dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); - assertEquals(dto.toString(), "2010-01-06 12:34:56 +00:00"); + assertEquals("2010-01-06 12:34:56 +00:00", dto.toString()); } } } @@ -1495,7 +1487,7 @@ public void testJulianLeapYear() throws Exception { ps.setDate(1, julianDate); try (ResultSet rs = ps.executeQuery()) { rs.next(); - assertEquals(rs.getString(1), "0700-03-01"); + assertEquals("0700-03-01", rs.getString(1)); } } } @@ -1508,13 +1500,13 @@ public void testGetTimeRounding() throws Exception { // Test getTime() rounding from TIME(6) SQL type try (ResultSet rs = stmt.executeQuery("SELECT CAST('12:34:56.999500' AS TIME)")) { rs.next(); - assertEquals(rs.getTime(1).toString(), "12:34:57"); + assertEquals("12:34:57", rs.getTime(1).toString()); } // Test getTime() rounding from character data try (ResultSet rs = stmt.executeQuery("SELECT '12:34:56.999500'")) { rs.next(); - assertEquals(rs.getTime(1).toString(), "12:34:57"); + assertEquals("12:34:57", rs.getTime(1).toString()); } } } @@ -1530,7 +1522,7 @@ public void testGregorianCutoverDateTime2() throws Exception { ps.setTimestamp(1, ts); try (ResultSet rs = ps.executeQuery()) { rs.next(); - assertEquals(rs.getString(1), "1582-10-24 15:07:09.0810000"); + assertEquals("1582-10-24 15:07:09.0810000", rs.getString(1)); } // Test setting value during the Gregorian cutover via Timestamp constructed from Calendar @@ -1541,7 +1533,7 @@ public void testGregorianCutoverDateTime2() throws Exception { ps.setTimestamp(1, ts); try (ResultSet rs = ps.executeQuery()) { rs.next(); - assertEquals(rs.getString(1), "1582-11-01 15:07:09.0810000"); + assertEquals("1582-11-01 15:07:09.0810000", rs.getString(1)); } } } @@ -1558,7 +1550,7 @@ public void testTimestampToDateTime() throws Exception { .prepareStatement("SELECT 1 WHERE ?=CAST('2009-12-17 17:00:29' AS DATETIME)")) { ps.setTimestamp(1, Timestamp.valueOf("2009-12-17 17:00:29")); try (ResultSet rs = ps.executeQuery()) { - assertEquals(rs.next(), true); + assertEquals(true, rs.next()); } } } @@ -1590,20 +1582,20 @@ public void testUpdateMisc() throws Exception { // Update datetimeoffset(2) from pre-Gregorian Date rs.updateDate(1, Date.valueOf("0814-02-18")); rs.updateRow(); - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), - "0814-02-18 00:00:00 +00:00"); + assertEquals("0814-02-18 00:00:00 +00:00", + ((SQLServerResultSet) rs).getDateTimeOffset(1).toString()); // Update datetimeoffset(2) from "last" Time rs.updateTime(1, new java.sql.Time(Timestamp.valueOf("1970-01-01 23:59:59.998").getTime())); rs.updateRow(); - assertEquals(((SQLServerResultSet) rs).getDateTimeOffset(1).toString(), - "1970-01-02 00:00:00 +00:00"); + assertEquals("1970-01-02 00:00:00 +00:00", + ((SQLServerResultSet) rs).getDateTimeOffset(1).toString()); // Update datetimeoffset(2) from the "last" Timestamp rs.updateTimestamp(1, Timestamp.valueOf("9999-12-31 23:59:59.998")); rs.updateRow(); dto = ((SQLServerResultSet) rs).getDateTimeOffset(1); - assertEquals(dto.toString(), "9999-12-31 23:59:59.99 +00:00"); + assertEquals("9999-12-31 23:59:59.99 +00:00", dto.toString()); // Attempt to update datetimeoffset(2) from the first out of range value // Verify that an exception is thrown and that the statement/connection is still usable after @@ -1616,7 +1608,7 @@ public void testUpdateMisc() throws Exception { exceptionThrown = false; } catch (SQLServerException e) { // data exception - datetime field overflow (ISO/IEC 9075-2:1999 - assertEquals(e.getSQLState(), "22008"); + assertEquals("22008", e.getSQLState()); } if (!exceptionThrown) { @@ -1628,7 +1620,7 @@ public void testUpdateMisc() throws Exception { ts.setNanos(987659999); rs.updateTimestamp(3, ts); rs.updateRow(); - assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 11:05:23.98766"); + assertEquals("1900-01-01 11:05:23.98766", rs.getTimestamp(3).toString()); // Update time(5) from Timestamp to max value in a day. The value should not be rounded ts = Timestamp.valueOf("2010-01-12 23:59:59"); @@ -1636,13 +1628,13 @@ public void testUpdateMisc() throws Exception { Time time = new java.sql.Time(ts.getTime()); rs.updateTimestamp(3, ts); rs.updateRow(); - assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.99999"); + assertEquals("1900-01-01 23:59:59.99999", rs.getTimestamp(3).toString()); // Update time(2) from Time to max value in a day. The value should not be rounded rs.updateTime(6, time); rs.updateRow(); // conversion to timestamp is necessary to see fractional secs - assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), "1970-01-01 23:59:59.99"); + assertEquals("1970-01-01 23:59:59.99", new Timestamp(rs.getTime(6).getTime()).toString()); // Update time(5) from Timestamp to max value in a second. The value should be rounded ts = Timestamp.valueOf("2010-01-12 23:59:58"); @@ -1650,26 +1642,26 @@ public void testUpdateMisc() throws Exception { time = new java.sql.Time(ts.getTime()); rs.updateTimestamp(3, ts); rs.updateRow(); - assertEquals(rs.getTimestamp(3).toString(), "1900-01-01 23:59:59.0"); + assertEquals("1900-01-01 23:59:59.0", rs.getTimestamp(3).toString()); // Update time(2) from Time to max value in a second. The value should be rounded rs.updateTime(6, time); rs.updateRow(); // conversion to timestamp is necessary to see fractional secs - assertEquals(new Timestamp(rs.getTime(6).getTime()).toString(), "1970-01-01 23:59:59.0"); + assertEquals("1970-01-01 23:59:59.0", new Timestamp(rs.getTime(6).getTime()).toString()); // Update datetime w/expected rounding of nanos to DATETIME's 1/300second resolution ts = Timestamp.valueOf("6289-04-22 05:13:57.6745106"); rs.updateTimestamp(2, ts); rs.updateRow(); - assertEquals(rs.getTimestamp(2).toString(), "6289-04-22 05:13:57.677"); + assertEquals("6289-04-22 05:13:57.677", rs.getTimestamp(2).toString()); // Update datetime with rounding-induced overflow from Time // (should roll date part to 1/2/1970) ts = Timestamp.valueOf("2010-01-18 23:59:59.999"); rs.updateTime(2, new java.sql.Time(ts.getTime())); rs.updateRow(); - assertEquals(rs.getTimestamp(2).toString(), "1970-01-02 00:00:00.0"); + assertEquals("1970-01-02 00:00:00.0", rs.getTimestamp(2).toString()); } finally { TestUtils.dropTableIfExists(escapedTableName, stmt); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java index 6c5103c4a..436e62089 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/SparseTest.java @@ -47,9 +47,9 @@ public void testSparse() throws Exception { try (ResultSet rs = stmt.executeQuery("Select * from " + escapedTableName)) { rs.next(); - assertEquals(rs.getString("col1023"), "yo"); - assertEquals(rs.getInt("col1"), 1); - assertEquals(rs.getBytes("col2")[0], 0x45); + assertEquals("yo", rs.getString("col1023")); + assertEquals(1, rs.getInt("col1")); + assertEquals(0x45, rs.getBytes("col2")[0]); } } finally { try (Statement stmt = conn.createStatement()) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index a7e05c371..f08ce00b2 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -30,7 +30,7 @@ @RunWith(JUnitPlatform.class) public class DTOSerialTest extends AbstractTest { - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS XXX"); + private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss XXX"); private static String dateString; @Test @@ -75,9 +75,9 @@ public void testESerial() throws Exception { try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) { SQLServerException ex = (SQLServerException) in.readObject(); - assertEquals(currException.toString(), ex.toString()); - assertEquals(currException.getSQLState(), ex.getSQLState()); - assertEquals(currException.getErrorCode(), ex.getErrorCode()); + assertEquals(ex.toString(), currException.toString()); + assertEquals(ex.getSQLState(), currException.getSQLState()); + assertEquals(ex.getErrorCode(), currException.getErrorCode()); } } } @@ -183,7 +183,8 @@ private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrat // check formatted date string String formattedDate = sdf.format(sdf.parse(initialStr)); - assertEquals(formattedDate, dateString); + + assertEquals(dateString, formattedDate); // check hydrated datetimeoffset assertEquals(initial, hydrated); From db38827ebfece40e855e6c6c8f0baae90fb528ae Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 20 Dec 2018 00:29:59 -0800 Subject: [PATCH 33/33] fixed comments and leaked resultsets --- .../callablestatement/CallableMixedTest.java | 4 - .../jdbc/datatypes/KatmaiDataTypesTest.java | 505 +++++++++--------- .../jdbc/resultset/ResultSetTest.java | 4 +- .../jdbc/unit/serial/DTOSerialTest.java | 2 +- 4 files changed, 245 insertions(+), 270 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java index 697e345cc..07890734c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/callablestatement/CallableMixedTest.java @@ -52,7 +52,6 @@ public void datatypestest() throws Exception { // Test OUT param re-registration cstmt.registerOutParameter((int) 5, java.sql.Types.BINARY); - cstmt.registerOutParameter((int) 5, (int) 5); cstmt.setObject((int) 4, Short.valueOf("-5372"), (int) 5); @@ -63,9 +62,6 @@ public void datatypestest() throws Exception { assertEquals(-5372, cstmt.getInt((int) 5)); } - // do nothing and reexecute - try (ResultSet rs = cstmt.executeQuery()) {} - // get the param without getting the resultset try (ResultSet rs = cstmt.executeQuery()) { assertEquals(-2147483648, cstmt.getInt((int) 1)); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java index e6f76a490..cd256d056 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/datatypes/KatmaiDataTypesTest.java @@ -113,7 +113,7 @@ final String getString() { this.scale = fractionalSecondsDigits; } - /** + /* * For testing the setObject and setNull methods in PreparedStatement, use the verifySetter* methods. These * methods prepare a single statement and execute it for all different data types by calling the appropriate * 'setObject' methods for each data type and/or type conversion. @@ -204,7 +204,6 @@ void verifyRSUpdaters(Connection conn) throws Exception { assumeTrue(!isSqlAzureDW(), TestResource.getResource("R_skipAzure")); try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { - TestUtils.dropTableIfExists(escapedTableName, stmt); stmt.executeUpdate("CREATE TABLE " + escapedTableName + " (col1 " + sqlTypeExpression @@ -233,11 +232,11 @@ void verifySetters(Connection conn) throws Exception { "INSERT INTO " + escapedTableName + " VALUES (?) SELECT * FROM " + escapedTableName, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { verifySetters(ps); - // Verify setObject function for the new mapping in JDBC41 (java.util.Date to TIMESTAMP) + // Verify setObject function for the mapping java.util.Date to TIMESTAMP stmt.executeUpdate("TRUNCATE TABLE " + escapedTableName); verifySettersUtilDate(ps); - // Verify setObject function for the new mapping in JDBC41 (java.util.Calendar to TIMESTAMP) + // Verify setObject function for the mapping java.util.Calendar to TIMESTAMP stmt.executeUpdate("TRUNCATE TABLE " + escapedTableName); verifySettersCalendar(ps); } finally { @@ -301,10 +300,10 @@ void verifySetters(PreparedStatement ps) throws Exception { ps.setDate(1, expected); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - - assertEquals(expected, rs.getDate(1)); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expected, rs.getDate(1)); + } } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -312,55 +311,59 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { ps.setObject(1, expectedUtilDate()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - assertEquals(expected, rs.getDate(1)); - assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expected, rs.getDate(1)); + assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); + } - // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP ps.setObject(1, expectedUtilDate(), java.sql.Types.DATE); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expected, rs.getDate(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expected, rs.getDate(1)); + } ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } // Test the setNull() methods for different data type conversions ps.setNull(1, java.sql.Types.DATE); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } ps.setNull(1, java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } } void verifySettersCalendar(PreparedStatement ps) throws Exception { @@ -368,33 +371,33 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ps.setObject(1, expectedCalendar()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - assertEquals(expected, rs.getDate(1)); - // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date - // or java.util.Date can be cast to a calendar + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expected, rs.getDate(1)); + } - // Test the additional conversions introduced in JDBC41 for types setters - // Test datetime2 column with target type TIMESTAMP + // test datetime2 column with target type TIMESTAMP ps.setObject(1, expectedCalendar(), java.sql.Types.DATE); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expected, rs.getDate(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expected, rs.getDate(1)); + } ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } } void verifyCSGetters(CallableStatement cs) throws Exception { @@ -463,7 +466,6 @@ private Timestamp expectedTimestampMillisPrecision() { cal.set(Calendar.MILLISECOND, (nanos + 500000) / 1000000); Timestamp timestamp = new Timestamp(cal.getTimeInMillis()); - return timestamp; } @@ -504,10 +506,10 @@ void verifySetters(PreparedStatement ps) throws Exception { ps.setTime(1, expectedTime()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - - assertEquals(expectedTime(), rs.getTime(1)); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expectedTime(), rs.getTime(1)); + } } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -515,57 +517,60 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { ps.setObject(1, expectedUtilDate()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - assertEquals(expectedTime(), rs.getTime(1)); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); - assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expectedTime(), rs.getTime(1)); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); + } - // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP ps.setObject(1, expectedUtilDate(), java.sql.Types.TIME); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expectedTime(), rs.getTime(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expectedTime(), rs.getTime(1)); + } ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } // Test the setNull() methods for different data type conversions ps.setNull(1, java.sql.Types.TIME); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } ps.setNull(1, java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); - + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } } void verifySettersCalendar(PreparedStatement ps) throws Exception { @@ -573,35 +578,34 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ps.setObject(1, expectedCalendar()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - assertEquals(expectedTime(), rs.getTime(1)); - - assertEquals(rs.getTimestamp(1), expectedTimestampMillisPrecision()); - // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date - // or java.util.Date can be cast to a calendar + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expectedTime(), rs.getTime(1)); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } - // Test the additional conversions introduced in JDBC41 for types setters - // Test datetime2 column with target type TIMESTAMP + // test datetime2 column with target type TIMESTAMP ps.setObject(1, expectedCalendar(), java.sql.Types.TIME); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expectedTime(), rs.getTime(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expectedTime(), rs.getTime(1)); + } ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the first row - rs.next(); - // Go to the row just inserted - rs.relative(++currentRow); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the first row + rs.next(); + // Go to the row just inserted + rs.relative(++currentRow); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } } void verifyCSGetters(CallableStatement cs) throws Exception { @@ -695,9 +699,6 @@ private Timestamp expectedTimestamp() { private Timestamp expectedTimestampMillisPrecision() { Timestamp timestamp = new Timestamp(utcMillis); - // Cannot set the nanos to 0, as per doc " the fractional seconds are stored in the nanos field of the - // Timestamp object." - // timestamp.setNanos(0); return timestamp; } @@ -719,12 +720,9 @@ void verifyRSGetters(ResultSet rs) throws Exception { } void verifyRSUpdaters(ResultSet rs) throws Exception { - // Unlike PreparedStatement.setTimestamp(), there is no ResultSet.updateTimestamp() - // that takes a Calendar argument for passing in the time zone. ResultSet.updateTimestamp() - // always uses the VM default time zone. So we have to temporarily change it while doing - // the update. TimeZone tzDefault = TimeZone.getDefault(); try { + // temporary change default time zone while doing the update TimeZone.setDefault(tz); // Update the timestamp value with this value's time zone (set as the VM default above) @@ -738,26 +736,29 @@ void verifyRSUpdaters(ResultSet rs) throws Exception { TimeZone.setDefault(tzDefault); } - // Verify the update (after restoring the default time zone) using the getTimestamp - // variant that takes a time zone argument (as a Calendar) + /* + * Verify the update (after restoring the default time zone) using the getTimestamp variant that takes a + * time zone argument (as a Calendar) + */ assertEquals(expectedTimestamp(), rs.getTimestamp(1, Calendar.getInstance(tz))); } void verifySetters(PreparedStatement ps) throws Exception { - // Verify PreparedStatement.setTimestamp with default time zone first. - // Temporarily change the VM default time zone as in the ResultSet verifier. TimeZone tzDefault = TimeZone.getDefault(); try { + // temporary change default time zone TimeZone.setDefault(tz); ps.setTimestamp(1, expectedTimestamp()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); - assertEquals(expectedTimestamp(), rs.getTimestamp(1)); + assertEquals(expectedTimestamp(), rs.getTimestamp(1)); + } } finally { + // Restore the original default time zone TimeZone.setDefault(tzDefault); } @@ -765,10 +766,10 @@ void verifySetters(PreparedStatement ps) throws Exception { ps.setTimestamp(1, expectedTimestamp(), Calendar.getInstance(tz)); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - - assertEquals(expectedTimestamp(), rs.getTimestamp(1, Calendar.getInstance(tz))); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expectedTimestamp(), rs.getTimestamp(1, Calendar.getInstance(tz))); + } } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -776,55 +777,59 @@ void verifySettersUtilDate(PreparedStatement ps) throws Exception { ps.setObject(1, expectedUtilDate()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); - assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + assertEquals(expectedUtilDate(), (java.util.Date) rs.getObject(1)); + } - // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP ps.setObject(1, expectedUtilDate(), java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } // Test the setNull() methods for different data type conversions ps.setNull(1, java.sql.Types.TIME); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } ps.setNull(1, java.sql.Types.DATE); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } ps.setNull(1, java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - // Read the column, first before calling rs.wasNull() - rs.getTimestamp(1); - assertEquals(true, rs.wasNull()); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + // Read the column, first before calling rs.wasNull() + rs.getTimestamp(1); + assertEquals(true, rs.wasNull()); + } } void verifySettersCalendar(PreparedStatement ps) throws Exception { @@ -832,22 +837,21 @@ void verifySettersCalendar(PreparedStatement ps) throws Exception { ps.setObject(1, expectedCalendar()); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); - // Cannot test rs.getObject for the Calendar object type, as none of Time, Timestamp, Date - // or java.util.Date can be cast to a calendar + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } - // Test the additional conversions introduced in JDBC41 for types setters // Test datetime2 column with target type TIMESTAMP ps.setObject(1, expectedCalendar(), java.sql.Types.TIMESTAMP); ps.execute(); ps.getMoreResults(); - rs = ps.getResultSet(); - // Go to the next row - rs.next(); - rs.relative(++currentRow); - assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + try (ResultSet rs = ps.getResultSet()) { + // Go to the next row + rs.next(); + rs.relative(++currentRow); + assertEquals(expectedTimestampMillisPrecision(), rs.getTimestamp(1)); + } } void verifyCSGetters(CallableStatement cs) throws Exception { @@ -946,33 +950,6 @@ private java.sql.Time expectedTime() { return new java.sql.Time(cal.getTimeInMillis()); } - private Timestamp expectedTimestamp() { - Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); - cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); - cal.setTimeInMillis(dto.getTimestamp().getTime()); - if (dto.getTimestamp().getNanos() % 1000000 >= 500000) - cal.add(Calendar.MILLISECOND, 1); - return new Timestamp(cal.getTimeInMillis()); - } - - private java.util.Date expectedUtilDate() { - Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); - cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); - cal.setTimeInMillis(dto.getTimestamp().getTime()); - if (dto.getTimestamp().getNanos() % 1000000 >= 500000) - cal.add(Calendar.MILLISECOND, 1); - return new java.util.Date(cal.getTimeInMillis()); - } - - private java.util.Calendar expectedCalendar() { - Calendar cal = Calendar.getInstance(new SimpleTimeZone(1000 * 60 * dto.getMinutesOffset(), ""), Locale.US); - cal.set(Calendar.ZONE_OFFSET, 1000 * 60 * dto.getMinutesOffset()); - cal.setTimeInMillis(dto.getTimestamp().getTime()); - if (dto.getTimestamp().getNanos() % 1000000 >= 500000) - cal.add(Calendar.MILLISECOND, 1); - return cal; - } - void verifyRSGetters(ResultSet rs) throws Exception { assertEquals(expectedDate(), rs.getDate(1)); assertEquals(expectedTime(), rs.getTime(1)); @@ -992,10 +969,10 @@ void verifySetters(PreparedStatement ps) throws Exception { ((SQLServerPreparedStatement) ps).setDateTimeOffset(1, dto); ps.execute(); ps.getMoreResults(); - ResultSet rs = ps.getResultSet(); - rs.next(); - - assertEquals(dto, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + try (ResultSet rs = ps.getResultSet()) { + rs.next(); + assertEquals(dto, ((SQLServerResultSet) rs).getDateTimeOffset(1)); + } } void verifySettersUtilDate(PreparedStatement ps) throws Exception { @@ -1019,7 +996,6 @@ void verifyCSGetters(CallableStatement cs) throws Exception { cs.registerOutParameter(2, microsoft.sql.Types.DATETIMEOFFSET); cs.execute(); assertEquals(dto, ((SQLServerCallableStatement) cs).getDateTimeOffset(2)); - assertEquals(dto, cs.getObject(2)); } } @@ -1045,9 +1021,10 @@ enum TestValue { PRE_CUTOVER(new DateValue("1582-10-04")), - // Dates in the Gregorian cutover date range appear as 10 days later than what they should. - // This behavior is consistent with other JDBC drivers, such as IBM's: - // http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db2.doc.java/com.ibm.db2.luw.apdv.java.doc/doc/r0053436.htm + /* + * Dates in the Gregorian cutover date range appear as 10 days later than what they should. This behavior is + * consistent with other JDBC drivers, such as IBM + */ CUTOVER_START(new DateValue("1582-10-05")), CUTOVER_END(new DateValue("1582-10-14")), @@ -1060,9 +1037,9 @@ enum TestValue { // First "fast path" date POST_CUTOVER_PLUS_2(new DateValue("1582-10-17")), - // VSTS 403522 - // Post-cutover date requiring preservation of "wall calendar" date - // in computing Calendar.DAY_OF_YEAR. + /* + * Post-cutover date requiring preservation of "wall calendar" date in computing Calendar.DAY_OF_YEAR + */ POST_CUTOVER_NOVEMBER(new DateTime2Value("1582-11-15 15:07:09.0810000")), A_RECENT_DATE(new DateValue("2009-10-20")), @@ -1124,9 +1101,8 @@ public void testParameterMetaData() throws Exception { } ; } - /** - * VSTS 411537 - CS.setObject(timestamp, TIME)/registerOutParam(TIME) on time backend type seems to ignore - * sendTimeAsDatetime knob. + /* + * test CS.setObject(timestamp, TIME)/registerOutParam(TIME) with sendTimeAsDatetime */ public void testSendTimestampAsTimeAsDatetime() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true")) { @@ -1137,13 +1113,14 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { try (CallableStatement cs = conn.prepareCall("{call " + escapedProcName + "(?,?)}")) { - // Set up a timestamp with a time component that is the last millisecond of the day... + // Set up a timestamp with a time component that is the last millisecond of the day Timestamp ts = Timestamp.valueOf("2010-02-15 23:59:59.999"); - // ... and send that timestamp to the server using the TIME SQL type rather than TIMESTAMP. - // If the driver is doing the right thing, it strips the date portion and, because - // sendTimeAsDatetime=true, rounds the resulting time value to midnight because it should - // be sending a DATETIME which has only 1/300s accuracy. + /* + * send the timestamp to the server using the TIME SQL type rather than TIMESTAMP. The driver will + * strip the date portion and, because sendTimeAsDatetime=true, round the resulting time value to + * midnight because it should be sending a DATETIME which has only 1/300s accuracy + */ cs.setObject(1, ts, java.sql.Types.TIME); cs.registerOutParameter(2, java.sql.Types.TIME); cs.execute(); @@ -1152,7 +1129,6 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { java.sql.Time timeOut = cs.getTime(2); Timestamp tsOut = new Timestamp(timeOut.getTime()); assertEquals("1970-01-01 00:00:00.0", tsOut.toString()); - } } finally { try (Statement stmt = conn.createStatement()) { @@ -1162,8 +1138,10 @@ public void testSendTimestampAsTimeAsDatetime() throws Exception { } } - // 507919 - Sending Timestamp to the server via an updater does not result in the same behavior as a setter wrt - // double-rounding of fractional seconds + /* + * test sending Timestamp to the server via an updater does not result in the same behavior as a setter wrt + * double-rounding of fractional seconds + */ public void testDoubleRounding() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString)) { @@ -1226,20 +1204,18 @@ public void testDoubleRounding() throws Exception { } } - /** + /* * Tests "fail fast" SQLException path when a Japanese imperial calendar is used with values representing the first - * year of an imperial era. - * - * See for more details: http://java.sun.com/javase/6/docs/technotes/guides/intl/calendar.doc.html + * year of an imperial era. See for more details: + * http://java.sun.com/javase/6/docs/technotes/guides/intl/calendar.doc.html */ public void testWithJapaneseImperialCalendar() throws Exception { - // From http://java.sun.com/javase/6/docs/api/java/util/Locale.html : - // "Note: When you ask for a resource for a particular locale, - // you get back the best available match, not necessarily precisely what you asked for. - // For more information, look at ResourceBundle." - // - // Japanese Imperial locale does not exist with some VMs. In these VMs, Locale.US is - // substituted as "best available match". + /* + * From http://java.sun.com/javase/6/docs/api/java/util/Locale.html : "Note: When you ask for a resource for a + * particular locale, you get back the best available match, not necessarily precisely what you asked for. For + * more information, look at ResourceBundle." Japanese Imperial locale does not exist with some VMs. In these + * VMs, Locale.US is substituted as "best available match". + */ Locale japaneseImperialLocale = new Locale("ja", "JP", "JP"); Calendar japaneseImperialCalendar = Calendar.getInstance(japaneseImperialLocale); @@ -1264,8 +1240,10 @@ public void testWithJapaneseImperialCalendar() throws Exception { try (PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))")) { Timestamp ts; - // Set second day of first year of Taisho era (1912 Gregorian) - // Note: Taisho era began July 30, 1912 Gregorian; second day of that year was July 31. + /* + * Set second day of first year of Taisho era (1912 Gregorian) Note: Taisho era began July 30, 1912 + * Gregorian; second day of that year was July 31. + */ japaneseImperialCalendar.clear(); japaneseImperialCalendar.set(Calendar.ERA, 2); // Taisho -> ERA 2 japaneseImperialCalendar.set(Calendar.YEAR, 1); @@ -1365,21 +1343,26 @@ public void testWithThaiLocale() throws Exception { // Test setter conversions try (PreparedStatement ps = conn.prepareStatement("SELECT CAST(? AS VARCHAR(40))")) { - // Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, - // month - // is from 0-11. + /* + * Need to use the following constructor for running against IBM JVM. Here, year should be year-1900, // + * month // is from 0-11. + */ Timestamp ts = new Timestamp(System.currentTimeMillis()); - // Test PreparedStatement with Timestamp - // Value sent as DATETIME2; result should have 7 digits of subsecond precision) + /* + * Test PreparedStatement with Timestamp Value sent as DATETIME2; result should have 7 digits of + * subsecond precision) + */ ps.setTimestamp(1, ts); try (ResultSet rs = ps.executeQuery()) { rs.next(); assertEquals(tsFormat.format(ts), rs.getString(1)); } - // Test PreparedStatement with Time - // Value sent as DATETIME w/Unix Epoch as base date when sendTimeAsDatetime=true + /* + * Test PreparedStatement with Time Value sent as DATETIME w/Unix Epoch as base date when + * sendTimeAsDatetime=true + */ Time time = new Time(ts.getTime()); ps.setTime(1, time); try (ResultSet rs = ps.executeQuery()) { @@ -1425,7 +1408,7 @@ public void testWithThaiLocale() throws Exception { } } - // DCR 393826 - DCR Need base date compatibility for Time to DATETIMEx conversions with 2.0 driver + // test base date compatibility for Time to DATETIMEx conversions @Test public void testBaseDate() throws Exception { Timestamp ts; @@ -1457,8 +1440,7 @@ public void testBaseDate() throws Exception { } } - // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset - // (+00:00) + // test setTimestamp to DATETIMEOFFSET yields a value in local time with UTC time zone offset (+00:00) @Test public void testTimestampToDateTimeOffset() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString); @@ -1473,9 +1455,10 @@ public void testTimestampToDateTimeOffset() throws Exception { } } - // VSTS 400431 - PS.setObject() on a datetime2 with values on or after 0700-02-29 have a value one day ahead - // stored - // in the server + /* + * test PS.setObject() on a datetime2 with values on or after 0700-02-29 have a value one day ahead stored in the + * server + */ @Test public void testJulianLeapYear() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString + ";sendTimeAsDatetime=true"); @@ -1538,12 +1521,12 @@ public void testGregorianCutoverDateTime2() throws Exception { } } - // VSTS 393831 - setTimestamp to DATETIMEOFFSET must yield a value in local time with UTC time zone offset - // (+00:00) - // - // In this case, verify that SELECT with a WHERE clause doesn't fail due to mapping the Timestamp value to a - // SQL Server type that does not compare equal. For example, a DATETIMEOFFSET and DATETIME only compare equal - // if the DATETIMEOFFSET offset is 0 (UTC). + /* + * setTimestamp to DATETIMEOFFSET yields a value in local time with UTC time zone offset (+00:00) In this case, + * verify that SELECT with a WHERE clause does not fail due to mapping the Timestamp value to a SQL Server type that + * does not compare equal. For example, a DATETIMEOFFSET and DATETIME only compare equal if the DATETIMEOFFSET + * offset is 0 (UTC). + */ @Test public void testTimestampToDateTime() throws Exception { try (Connection conn = DriverManager.getConnection(connectionString); PreparedStatement ps = conn @@ -1555,9 +1538,6 @@ public void testTimestampToDateTime() throws Exception { } } - // testUpdateMisc - // - // Haphazard collection of bugs that popped up during unit testing (i.e. regression tests) @Test public void testUpdateMisc() throws Exception { try (SQLServerConnection conn = (SQLServerConnection) DriverManager @@ -1656,8 +1636,7 @@ public void testUpdateMisc() throws Exception { rs.updateRow(); assertEquals("6289-04-22 05:13:57.677", rs.getTimestamp(2).toString()); - // Update datetime with rounding-induced overflow from Time - // (should roll date part to 1/2/1970) + // Update datetime with rounding-induced overflow from Time (should roll date part to 1/2/1970) ts = Timestamp.valueOf("2010-01-18 23:59:59.999"); rs.updateTime(2, new java.sql.Time(ts.getTime())); rs.updateRow(); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java index d8b9316b8..a76ee6580 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/resultset/ResultSetTest.java @@ -267,8 +267,8 @@ public void testGetObjectAsLocalDateTime() throws SQLException { final String testValueTime = "02:00:00.1234567"; final String testValueDateTime = testValueDate + "T" + testValueTime; - stmt.executeUpdate("CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) - + " (id INT, dt2 DATETIME2)"); + stmt.executeUpdate( + "CREATE TABLE " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (id INT, dt2 DATETIME2)"); stmt.executeUpdate("INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableName) + " (id, dt2) VALUES (1, '" + testValueDateTime + "')"); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java index f08ce00b2..3cf7fe82b 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/serial/DTOSerialTest.java @@ -166,7 +166,7 @@ private static void verifyMessedSerializationHelper(byte[] svalue) throws Except } } - // This function is used to make sure the hydrated is equal to original string and the initial DTO + // This is used to make sure the hydrated is equal to original string and the initial DTO private static void verifyDTOEqual(DateTimeOffset initial, DateTimeOffset hydrated) throws Exception { String initialStr = initial.toString(); String hydratedStr = hydrated.toString();