Skip to content

Commit

Permalink
Merge pull request #317 from v-xiangs/TVP-time-4-fix-RTW
Browse files Browse the repository at this point in the history
Tvp time 4 fix rtw
  • Loading branch information
xiangyushawn authored May 29, 2017
2 parents d2fd9c4 + f76d872 commit d8f677e
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 38 deletions.
9 changes: 8 additions & 1 deletion src/main/java/com/microsoft/sqlserver/jdbc/TVP.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,14 @@ Object[] getRowData() throws SQLServerException {
Object[] rowData = new Object[colCount];
for (int i = 0; i < colCount; i++) {
try {
rowData[i] = sourceResultSet.getObject(i + 1);
// for Time types, getting Timestamp instead of Time, because this value will be converted to String later on. If the value is a
// time object, the millisecond would be removed.
if (java.sql.Types.TIME == sourceResultSet.getMetaData().getColumnType(i + 1)) {
rowData[i] = sourceResultSet.getTimestamp(i + 1);
}
else {
rowData[i] = sourceResultSet.getObject(i + 1);
}
}
catch (SQLException e) {
throw new SQLServerException(SQLServerException.getErrString("R_unableRetrieveSourceData"), e);
Expand Down
138 changes: 101 additions & 37 deletions src/test/java/com/microsoft/sqlserver/jdbc/tvp/TVPIssuesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,32 @@ public class TVPIssuesTest extends AbstractTest {

static Connection connection = null;
static Statement stmt = null;
private static String tvpName = "TVPIssuesTest_TVP";
private static String procedureName = "TVPIssuesTest_SP";
private static String srcTable = "TVPIssuesTest_src";
private static String desTable = "TVPIssuesTest_dest";
private static String tvp_varcharMax = "TVPIssuesTest_varcharMax_TVP";
private static String spName_varcharMax = "TVPIssuesTest_varcharMax_SP";
private static String srcTable_varcharMax = "TVPIssuesTest_varcharMax_srcTable";
private static String desTable_varcharMax = "TVPIssuesTest_varcharMax_destTable";

private static String tvp_time_6 = "TVPIssuesTest_time_6_TVP";
private static String srcTable_time_6 = "TVPIssuesTest_time_6_srcTable";
private static String desTable_time_6 = "TVPIssuesTest_time_6_destTable";

private static String expectedTime6value = "15:39:27.616667";

@Test
public void tryTVP_RS_varcharMax_4001_Issue() throws Exception {

setup();

SQLServerStatement st = (SQLServerStatement) connection.createStatement();
ResultSet rs = st.executeQuery("select * from " + srcTable);
ResultSet rs = st.executeQuery("select * from " + srcTable_varcharMax);

SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement("INSERT INTO " + desTable + " select * from ? ;");
SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection
.prepareStatement("INSERT INTO " + desTable_varcharMax + " select * from ? ;");

pstmt.setStructured(1, tvpName, rs);
pstmt.setStructured(1, tvp_varcharMax, rs);
pstmt.execute();

testDestinationTable();
testCharDestTable();
}

/**
Expand All @@ -64,11 +71,11 @@ public void tryTVP_RS_varcharMax_4001_Issue() throws Exception {
@Test
public void testExceptionWithInvalidStoredProcedureName() throws Exception {
SQLServerStatement st = (SQLServerStatement) connection.createStatement();
ResultSet rs = st.executeQuery("select * from " + srcTable);
ResultSet rs = st.executeQuery("select * from " + srcTable_varcharMax);

dropProcedure();

final String sql = "{call " + procedureName + "(?)}";
final String sql = "{call " + spName_varcharMax + "(?)}";
SQLServerCallableStatement Cstmt = (SQLServerCallableStatement) connection.prepareCall(sql);
try {
Cstmt.setObject(1, rs);
Expand All @@ -84,8 +91,29 @@ public void testExceptionWithInvalidStoredProcedureName() throws Exception {
}
}

private void testDestinationTable() throws SQLException, IOException {
ResultSet rs = connection.createStatement().executeQuery("select * from " + desTable);
/**
* Fix an issue: If column is time(x) and TVP is used (with either ResultSet, Stored Procedure or SQLServerDataTable). The milliseconds or
* nanoseconds are not copied into the destination table.
*
* @throws Exception
*/
@Test
public void tryTVP_Precision_missed_issue_315() throws Exception {

setup();

ResultSet rs = stmt.executeQuery("select * from " + srcTable_time_6);

SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection
.prepareStatement("INSERT INTO " + desTable_time_6 + " select * from ? ;");
pstmt.setStructured(1, tvp_time_6, rs);
pstmt.execute();

testTime6DestTable();
}

private void testCharDestTable() throws SQLException, IOException {
ResultSet rs = connection.createStatement().executeQuery("select * from " + desTable_varcharMax);
while (rs.next()) {
assertEquals(rs.getString(1).length(), 4001, " The inserted length is truncated or not correct!");
}
Expand All @@ -94,19 +122,14 @@ private void testDestinationTable() throws SQLException, IOException {
}
}

private static void populateSourceTable() throws SQLException {
String sql = "insert into " + srcTable + " values (?)";

StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4001; i++) {
sb.append("a");
private void testTime6DestTable() throws SQLException, IOException {
ResultSet rs = connection.createStatement().executeQuery("select * from " + desTable_time_6);
while (rs.next()) {
assertEquals(rs.getString(1), expectedTime6value, " The time value is truncated or not correct!");
}
if (null != rs) {
rs.close();
}
String value = sb.toString();

SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(sql);

pstmt.setString(1, value);
pstmt.execute();
}

@BeforeAll
Expand All @@ -117,41 +140,82 @@ public static void beforeAll() throws SQLException {

dropProcedure();

stmt.executeUpdate("IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvpName + "') " + " drop type " + tvpName);
Utils.dropTableIfExists(srcTable, stmt);
Utils.dropTableIfExists(desTable, stmt);
stmt.executeUpdate(
"IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvp_varcharMax + "') " + " drop type " + tvp_varcharMax);
Utils.dropTableIfExists(srcTable_varcharMax, stmt);
Utils.dropTableIfExists(desTable_varcharMax, stmt);

stmt.executeUpdate(
"IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvp_time_6 + "') " + " drop type " + tvp_time_6);
Utils.dropTableIfExists(srcTable_time_6, stmt);
Utils.dropTableIfExists(desTable_time_6, stmt);

String sql = "create table " + srcTable + " (c1 varchar(max) null);";
String sql = "create table " + srcTable_varcharMax + " (c1 varchar(max) null);";
stmt.execute(sql);
sql = "create table " + desTable_varcharMax + " (c1 varchar(max) null);";
stmt.execute(sql);

sql = "create table " + desTable + " (c1 varchar(max) null);";
sql = "create table " + srcTable_time_6 + " (c1 time(6) null);";
stmt.execute(sql);
sql = "create table " + desTable_time_6 + " (c1 time(6) null);";
stmt.execute(sql);

String TVPCreateCmd = "CREATE TYPE " + tvpName + " as table (c1 varchar(max) null)";
String TVPCreateCmd = "CREATE TYPE " + tvp_varcharMax + " as table (c1 varchar(max) null)";
stmt.executeUpdate(TVPCreateCmd);

TVPCreateCmd = "CREATE TYPE " + tvp_time_6 + " as table (c1 time(6) null)";
stmt.executeUpdate(TVPCreateCmd);

createPreocedure();

populateSourceTable();
populateCharSrcTable();
populateTime6SrcTable();
}

private static void populateCharSrcTable() throws SQLException {
String sql = "insert into " + srcTable_varcharMax + " values (?)";

StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4001; i++) {
sb.append("a");
}
String value = sb.toString();

SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(sql);

pstmt.setString(1, value);
pstmt.execute();
}

private static void populateTime6SrcTable() throws SQLException {
String sql = "insert into " + srcTable_time_6 + " values ('2017-05-12 " + expectedTime6value + "')";
connection.createStatement().execute(sql);
}

private static void dropProcedure() throws SQLException {
Utils.dropProcedureIfExists(procedureName, stmt);
Utils.dropProcedureIfExists(spName_varcharMax, stmt);
}

private static void createPreocedure() throws SQLException {
String sql = "CREATE PROCEDURE " + procedureName + " @InputData " + tvpName + " READONLY " + " AS " + " BEGIN " + " INSERT INTO " + desTable
+ " SELECT * FROM @InputData" + " END";
String sql = "CREATE PROCEDURE " + spName_varcharMax + " @InputData " + tvp_varcharMax + " READONLY " + " AS " + " BEGIN " + " INSERT INTO "
+ desTable_varcharMax + " SELECT * FROM @InputData" + " END";

stmt.execute(sql);
}

@AfterAll
public static void terminateVariation() throws SQLException {
dropProcedure();
stmt.executeUpdate("IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvpName + "') " + " drop type " + tvpName);
Utils.dropTableIfExists(srcTable, stmt);
Utils.dropTableIfExists(desTable, stmt);
stmt.executeUpdate(
"IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvp_varcharMax + "') " + " drop type " + tvp_varcharMax);
Utils.dropTableIfExists(srcTable_varcharMax, stmt);
Utils.dropTableIfExists(desTable_varcharMax, stmt);

stmt.executeUpdate(
"IF EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = '" + tvp_time_6 + "') " + " drop type " + tvp_time_6);
Utils.dropTableIfExists(srcTable_time_6, stmt);
Utils.dropTableIfExists(desTable_time_6, stmt);

if (null != connection) {
connection.close();
}
Expand Down

0 comments on commit d8f677e

Please sign in to comment.