From bfa575d4ebde3bfa2496a9d62e065940699995ef Mon Sep 17 00:00:00 2001 From: Peter Bae Date: Wed, 16 Sep 2020 14:47:53 -0700 Subject: [PATCH] Fix | Fix bulkcopy failing when inserting non-unicode multibyte String (#1421) Fix bulkcopy failing when inserting non-unicode multibyte String --- .../sqlserver/jdbc/SQLServerBulkCopy.java | 11 +++--- .../jdbc/bulkCopy/BulkCopyRowSetTest.java | 36 ++++++++++++++++++- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java index ec2d0dbbed..53f6c27c05 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java @@ -2308,15 +2308,16 @@ else if (null != sourceCryptoMeta) { tdsWriter.writeShort((short) bytes.length); tdsWriter.writeBytes(bytes); } else { - tdsWriter.writeShort((short) (colValueStr.length())); // converting string into destination collation using Charset - SQLCollation destCollation = destColumnMetadata.get(destColOrdinal).collation; - if (null != destCollation) { - tdsWriter.writeBytes(colValueStr.getBytes( - destColumnMetadata.get(destColOrdinal).collation.getCharset())); + if (null != destCollation) { + byte[] value = colValueStr.getBytes( + destColumnMetadata.get(destColOrdinal).collation.getCharset()); + tdsWriter.writeShort((short) value.length); + tdsWriter.writeBytes(value); } else { + tdsWriter.writeShort((short) (colValueStr.length())); tdsWriter.writeBytes(colValueStr.getBytes()); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyRowSetTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyRowSetTest.java index c461b13c8c..6d3519e9bd 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyRowSetTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyRowSetTest.java @@ -31,13 +31,15 @@ @RunWith(JUnitPlatform.class) -@Tag(Constants.xAzureSQLDW) public class BulkCopyRowSetTest extends AbstractTest { private static String tableName = AbstractSQLGenerator .escapeIdentifier(RandomUtil.getIdentifier("BulkCopyFloatTest")); + private static String tableName2 = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("BulkCopyFloatTest2")); @Test + @Tag(Constants.xAzureSQLDW) public void testBulkCopyFloatRowSet() throws SQLException { try (Connection con = getConnection(); Statement stmt = connection.createStatement()) { RowSetFactory rsf = RowSetProvider.newFactory(); @@ -71,11 +73,42 @@ public void testBulkCopyFloatRowSet() throws SQLException { } } + @Test + public void testBulkCopyJapaneseCollation() throws SQLException { + try (Connection con = getConnection(); Statement stmt = connection.createStatement(); + SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(con);) { + RowSetFactory rsf = RowSetProvider.newFactory(); + CachedRowSet crs = rsf.createCachedRowSet(); + RowSetMetaData rsmd = new RowSetMetaDataImpl(); + String unicodeData = "ああ"; + rsmd.setColumnCount(1); + rsmd.setColumnName(1, "c1"); + rsmd.setColumnType(1, java.sql.Types.VARCHAR); + rsmd.setTableName(1, tableName2); + + crs.setMetaData(rsmd); + crs.moveToInsertRow(); + crs.updateString("c1", unicodeData); + crs.insertRow(); + crs.moveToCurrentRow(); + + bulkCopy.setDestinationTableName(tableName2); + bulkCopy.writeToServer(crs); + + try (ResultSet rs = stmt.executeQuery("select * from " + tableName2)) { + rs.next(); + assertEquals(unicodeData, (String) rs.getString(1)); + } + } + } + @BeforeAll public static void testSetup() throws TestAbortedException, Exception { try (Statement stmt = connection.createStatement()) { String sql1 = "create table " + tableName + " (c1 float, c2 real)"; stmt.execute(sql1); + String sql2 = "create table " + tableName2 + " (c1 varchar(10) COLLATE Japanese_CS_AS_KS_WS NOT NULL)"; + stmt.execute(sql2); } } @@ -83,6 +116,7 @@ public static void testSetup() throws TestAbortedException, Exception { public static void terminateVariation() throws SQLException { try (Statement stmt = connection.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); + TestUtils.dropTableIfExists(tableName2, stmt); } } }