From 7e66b078ee095a564518f53d1206e4cef2d8b49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BA=91=E9=87=91YunjinXu?= Date: Tue, 21 Jan 2025 10:17:51 +0800 Subject: [PATCH 1/4] test: add tests for column case sensitivity in batch execution - Add test case for matching column case in batch execution - Add test case for mismatched column case in batch execution, expected SQLServerException --- .../unit/statement/BatchExecutionTest.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) 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 ba3f6e70c..11f74dac6 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 @@ -568,6 +568,55 @@ public void testBatchStatementCancellation() throws Exception { } } + @Test + public void testExecuteBatchColumnCaseMatching() throws Exception { + String varcharTable1 = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("varchartable1")); + // Insert Timestamp using prepared statement when useBulkCopyForBatchInsert=true + try (Connection con = DriverManager.getConnection(connectionString + + ";useBulkCopyForBatchInsert=true;sendTemporalDataTypesAsStringForBulkCopy=false;")) { + try (Statement statement = con.createStatement()) { + TestUtils.dropTableIfExists(varcharTable1, statement); + String createSql = "CREATE TABLE" + varcharTable1 + " (c1 varchar(10))"; + statement.execute(createSql); + } + try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + varcharTable1 + "(c1) VALUES(?)")) { + preparedStatement.setObject(1, "value1"); + preparedStatement.addBatch(); + preparedStatement.setObject(1, "value2"); + preparedStatement.addBatch(); + preparedStatement.executeBatch(); + } + } + } + + @Test + public void testExecuteBatchColumnCaseMismatch() throws Exception { + String varcharTable1 = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("varchartable1")); + // Insert Timestamp using prepared statement when useBulkCopyForBatchInsert=true + try (Connection con = DriverManager.getConnection(connectionString + + ";useBulkCopyForBatchInsert=true;sendTemporalDataTypesAsStringForBulkCopy=false;")) { + try (Statement statement = con.createStatement()) { + TestUtils.dropTableIfExists(varcharTable1, statement); + String createSql = "CREATE TABLE" + varcharTable1 + " (c1 varchar(10))"; + statement.execute(createSql); + } + // upper case C1 + try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + varcharTable1 + "(C1) VALUES(?)")) { + preparedStatement.setObject(1, "value1"); + preparedStatement.addBatch(); + preparedStatement.setObject(1, "value2"); + preparedStatement.addBatch(); + try { + preparedStatement.executeBatch(); + fail("Should have failed"); + } catch (Exception ex) { + assertInstanceOf(SQLServerException.class, ex); + assertEquals("Unable to retrieve column metadata.", ex.getMessage()); + } + } + } + } + /** * Get a PreparedStatement object and call the addBatch() method with 3 SQL statements and call the executeBatch() * method and it should return array of Integer values of length 3 From 902ac88f0b78dc052507bae22c925566751fd7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BA=91=E9=87=91YunjinXu?= Date: Tue, 21 Jan 2025 10:22:29 +0800 Subject: [PATCH 2/4] fix(batch): improve column metadata handling for batch execution - Update column index search to be case-insensitive in SQLServerPreparedStatement - Remove failing test case in BatchExecutionTest that was checking for specific exception --- .../sqlserver/jdbc/SQLServerPreparedStatement.java | 9 ++++++++- .../jdbc/unit/statement/BatchExecutionTest.java | 8 +------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 244cfb696..0e454226a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -2210,7 +2210,14 @@ public int[] executeBatch() throws SQLServerException, BatchUpdateException, SQL jdbctype = ti.getSSType().getJDBCType().getIntValue(); } if (null != bcOperationColumnList && !bcOperationColumnList.isEmpty()) { - int columnIndex = bcOperationColumnList.indexOf(c.getColumnName()); + // find index ignore case + int columnIndex = -1; + for (int opi = 0; opi < bcOperationColumnList.size(); opi++) { + if (bcOperationColumnList.get(opi).equalsIgnoreCase(c.getColumnName())) { + columnIndex = opi; + } + } + if (columnIndex > -1) { columnMappings.put(columnIndex + 1, i); batchRecord.addColumnMetadata(columnIndex + 1, c.getColumnName(), jdbctype, 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 11f74dac6..e258e97fb 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 @@ -606,13 +606,7 @@ public void testExecuteBatchColumnCaseMismatch() throws Exception { preparedStatement.addBatch(); preparedStatement.setObject(1, "value2"); preparedStatement.addBatch(); - try { - preparedStatement.executeBatch(); - fail("Should have failed"); - } catch (Exception ex) { - assertInstanceOf(SQLServerException.class, ex); - assertEquals("Unable to retrieve column metadata.", ex.getMessage()); - } + preparedStatement.executeBatch(); } } } From 2bbb7c7f2b445cb30f461db3818f7483ccc4d60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BA=91=E9=87=91YunjinXu?= Date: Thu, 23 Jan 2025 13:09:44 +0800 Subject: [PATCH 3/4] test(BatchExecutionTest): Add cleanup for caseSensitiveTable in the finally block --- .../jdbc/unit/statement/BatchExecutionTest.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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 e258e97fb..05f4b132d 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 @@ -72,6 +72,8 @@ public class BatchExecutionTest extends AbstractTest { .escapeIdentifier(RandomUtil.getIdentifier("timestamptable1")); private static String timestampTable2 = AbstractSQLGenerator .escapeIdentifier(RandomUtil.getIdentifier("timestamptable2")); + private static String caseSensitiveTable = AbstractSQLGenerator + .escapeIdentifier(RandomUtil.getIdentifier("caseSensitiveTable")); /** * This tests the updateCount when the error query does cause a SQL state HY008. @@ -570,16 +572,15 @@ public void testBatchStatementCancellation() throws Exception { @Test public void testExecuteBatchColumnCaseMatching() throws Exception { - String varcharTable1 = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("varchartable1")); // Insert Timestamp using prepared statement when useBulkCopyForBatchInsert=true try (Connection con = DriverManager.getConnection(connectionString + ";useBulkCopyForBatchInsert=true;sendTemporalDataTypesAsStringForBulkCopy=false;")) { try (Statement statement = con.createStatement()) { - TestUtils.dropTableIfExists(varcharTable1, statement); - String createSql = "CREATE TABLE" + varcharTable1 + " (c1 varchar(10))"; + TestUtils.dropTableIfExists(caseSensitiveTable, statement); + String createSql = "CREATE TABLE" + caseSensitiveTable + " (c1 varchar(10))"; statement.execute(createSql); } - try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + varcharTable1 + "(c1) VALUES(?)")) { + try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + caseSensitiveTable + "(c1) VALUES(?)")) { preparedStatement.setObject(1, "value1"); preparedStatement.addBatch(); preparedStatement.setObject(1, "value2"); @@ -591,17 +592,16 @@ public void testExecuteBatchColumnCaseMatching() throws Exception { @Test public void testExecuteBatchColumnCaseMismatch() throws Exception { - String varcharTable1 = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("varchartable1")); // Insert Timestamp using prepared statement when useBulkCopyForBatchInsert=true try (Connection con = DriverManager.getConnection(connectionString + ";useBulkCopyForBatchInsert=true;sendTemporalDataTypesAsStringForBulkCopy=false;")) { try (Statement statement = con.createStatement()) { - TestUtils.dropTableIfExists(varcharTable1, statement); - String createSql = "CREATE TABLE" + varcharTable1 + " (c1 varchar(10))"; + TestUtils.dropTableIfExists(caseSensitiveTable, statement); + String createSql = "CREATE TABLE" + caseSensitiveTable + " (c1 varchar(10))"; statement.execute(createSql); } // upper case C1 - try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + varcharTable1 + "(C1) VALUES(?)")) { + try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + caseSensitiveTable + "(C1) VALUES(?)")) { preparedStatement.setObject(1, "value1"); preparedStatement.addBatch(); preparedStatement.setObject(1, "value2"); @@ -882,6 +882,7 @@ private static void dropTable() throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(ctstable4), stmt); TestUtils.dropTableIfExists(timestampTable1, stmt); TestUtils.dropTableIfExists(timestampTable2, stmt); + TestUtils.dropTableIfExists(caseSensitiveTable, stmt); } } From 00272a5cca35c9559e0b83dfbce3b275d811c50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BA=91=E9=87=91YunjinXu?= Date: Fri, 24 Jan 2025 20:37:20 +0800 Subject: [PATCH 4/4] test: remove unused test case for column case matching --- .../unit/statement/BatchExecutionTest.java | 20 ------------------- 1 file changed, 20 deletions(-) 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 05f4b132d..39e69c525 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 @@ -570,26 +570,6 @@ public void testBatchStatementCancellation() throws Exception { } } - @Test - public void testExecuteBatchColumnCaseMatching() throws Exception { - // Insert Timestamp using prepared statement when useBulkCopyForBatchInsert=true - try (Connection con = DriverManager.getConnection(connectionString - + ";useBulkCopyForBatchInsert=true;sendTemporalDataTypesAsStringForBulkCopy=false;")) { - try (Statement statement = con.createStatement()) { - TestUtils.dropTableIfExists(caseSensitiveTable, statement); - String createSql = "CREATE TABLE" + caseSensitiveTable + " (c1 varchar(10))"; - statement.execute(createSql); - } - try (PreparedStatement preparedStatement = con.prepareStatement("INSERT INTO " + caseSensitiveTable + "(c1) VALUES(?)")) { - preparedStatement.setObject(1, "value1"); - preparedStatement.addBatch(); - preparedStatement.setObject(1, "value2"); - preparedStatement.addBatch(); - preparedStatement.executeBatch(); - } - } - } - @Test public void testExecuteBatchColumnCaseMismatch() throws Exception { // Insert Timestamp using prepared statement when useBulkCopyForBatchInsert=true