diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java index dafffa974..bc6ae6f3a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java @@ -1740,7 +1740,6 @@ private void getDestinationMetadata() throws SQLServerException { } if (null == destColumnMetadata || destColumnMetadata.isEmpty()) { - if (connection.getEnableBulkCopyCache()) { DESTINATION_COL_METADATA_LOCK.lock(); destColumnMetadata = BULK_COPY_OPERATION_CACHE.get(key); @@ -1748,6 +1747,17 @@ private void getDestinationMetadata() throws SQLServerException { if (null == destColumnMetadata || destColumnMetadata.isEmpty()) { try { setDestinationColumnMetadata(escapedDestinationTableName); + + // We are caching the following metadata about the table: + // 1. collation_name + // 2. is_computed + // 3. encryption_type + // + // Using this caching method, 'enableBulkCopyCache', may have unintended consequences if the + // table changes somehow between inserts. For example, if the collation_name changes, the + // driver will not be aware of this and the inserted data will likely be corrupted. In such + // scenario, we can't detect this without making an additional metadata query, which would + // defeat the purpose of caching. BULK_COPY_OPERATION_CACHE.put(key, destColumnMetadata); } finally { DESTINATION_COL_METADATA_LOCK.unlock(); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchExecutionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchExecutionTest.java index 12f91b24e..c9b422cf9 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchExecutionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/statement/BatchExecutionTest.java @@ -161,8 +161,9 @@ public void testSqlServerBulkCopyCachingConnectionLevel() throws Exception { stmt.execute(createSqlTable1); stmt.execute(createSqlTable2); - // Calling getSuperClass() because SQLServerConnection is the parent - Field bulkcopyMetadataCacheField = con.getClass().getSuperclass().getDeclaredField("BULK_COPY_OPERATION_CACHE"); + Field bulkcopyMetadataCacheField = TestUtils.getJVMVersion() > 8 ? + con.getClass().getSuperclass().getDeclaredField("BULK_COPY_OPERATION_CACHE") : + con.getClass().getDeclaredField("BULK_COPY_OPERATION_CACHE"); bulkcopyMetadataCacheField.setAccessible(true); Object bulkcopyCache = bulkcopyMetadataCacheField.get(con);