Skip to content

Commit 3fc45fc

Browse files
committed
Few more test combinations
1 parent 80d67c9 commit 3fc45fc

File tree

1 file changed

+182
-41
lines changed

1 file changed

+182
-41
lines changed

src/test/java/com/microsoft/sqlserver/jdbc/preparedStatement/BatchExecutionWithBulkCopyTest.java

Lines changed: 182 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
import java.util.Calendar;
3131
import java.util.Random;
3232
import java.util.UUID;
33+
import java.util.logging.Handler;
34+
import java.util.logging.LogRecord;
35+
import java.util.logging.Logger;
3336

3437
import org.junit.jupiter.api.AfterAll;
35-
import org.junit.jupiter.api.Assertions;
36-
import org.junit.jupiter.api.BeforeEach;
3738
import org.junit.jupiter.api.BeforeAll;
39+
import org.junit.jupiter.api.BeforeEach;
3840
import org.junit.jupiter.api.Tag;
3941
import org.junit.jupiter.api.Test;
4042
import org.junit.platform.runner.JUnitPlatform;
@@ -1408,51 +1410,28 @@ private void getCreateTableTemporalSQL(String tableName) throws SQLException {
14081410
}
14091411
}
14101412

1411-
/**
1412-
* Test insert-select fallback to normal execution for bulk copy API
1413-
*/
1414-
@Test
1415-
public void testInsertSelectFallbackToNormalExecution() throws Exception {
1416-
String tableNameSource = AbstractSQLGenerator.escapeIdentifier("SourceTable");
1417-
String tableNameDestination = AbstractSQLGenerator.escapeIdentifier("DestinationTable");
1418-
1419-
String connectStringUrl = connectionString
1420-
+ ";useBulkCopyForBatchInsert=true;sendStringParametersAsUnicode=false;";
1421-
1422-
try (Connection connection = PrepUtil.getConnection(connectStringUrl);
1423-
Statement stmt = connection.createStatement()) {
1413+
class FallbackWatcherLogHandler extends Handler implements AutoCloseable {
14241414

1425-
TestUtils.dropTableIfExists(tableNameSource, stmt);
1426-
String createSourceTableSQL = "CREATE TABLE " + tableNameSource + " (id INT, value VARCHAR(50))";
1427-
stmt.execute(createSourceTableSQL);
1415+
Logger stmtLogger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerStatement");
1416+
boolean gotFallbackMessage = false;
14281417

1429-
String insertSourceDataSQL = "INSERT INTO " + tableNameSource + " VALUES (1, 'TestValue1'), (2, 'TestValue2')";
1430-
stmt.execute(insertSourceDataSQL);
1431-
1432-
TestUtils.dropTableIfExists(tableNameDestination, stmt);
1433-
String createDestinationTableSQL = "CREATE TABLE " + tableNameDestination + " (id INT, value VARCHAR(50))";
1434-
stmt.execute(createDestinationTableSQL);
1435-
1436-
// Attempt unsupported INSERT-SELECT query for bulk copy api
1437-
String insertSelectSQL = "INSERT INTO " + tableNameDestination + " SELECT * FROM " + tableNameSource
1438-
+ " WHERE value = ?";
1418+
public FallbackWatcherLogHandler() {
1419+
stmtLogger.addHandler(this);
1420+
}
14391421

1440-
try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection
1441-
.prepareStatement(insertSelectSQL)) {
1442-
pstmt.setString(1, "TestValue1");
1443-
pstmt.addBatch();
1444-
pstmt.executeBatch(); // This should fall back to normal execution flow
1422+
@Override
1423+
public void publish(LogRecord record) {
1424+
if (record.getMessage().contains("Falling back to the original implementation for Batch Insert.")) {
1425+
gotFallbackMessage = true;
14451426
}
1427+
}
14461428

1447-
// Validate inserted data in destination table
1448-
String selectSQL = "SELECT * FROM " + tableNameDestination;
1449-
try (ResultSet rs = stmt.executeQuery(selectSQL)) {
1450-
assertTrue(rs.next(), "Expected at least one row in result set");
1451-
assertEquals(1, rs.getInt("id"));
1452-
assertEquals("TestValue1", rs.getString("value"));
1429+
@Override
1430+
public void flush() {}
14531431

1454-
Assertions.assertFalse(rs.next(), "No more rows expected");
1455-
}
1432+
@Override
1433+
public void close() throws SecurityException {
1434+
stmtLogger.removeHandler(this);
14561435
}
14571436
}
14581437

@@ -1469,6 +1448,7 @@ public void testBulkInsertStringAllCombinations() throws Exception {
14691448
for (boolean useBulkCopy : bulkCopyOptions) {
14701449
for (boolean sendUnicode : unicodeOptions) {
14711450
runBulkInsertStringTest(useBulkCopy, sendUnicode);
1451+
runBulkInsertStringTestForceFallback(useBulkCopy, sendUnicode);
14721452
}
14731453
}
14741454
}
@@ -1532,6 +1512,166 @@ public void runBulkInsertStringTest(boolean useBulkCopy, boolean sendUnicode) th
15321512
}
15331513
}
15341514

1515+
/**
1516+
* Test batch insert using an unsupported statement (falls back to batch mode) with accented and Unicode characters.
1517+
*/
1518+
public void runBulkInsertStringTestForceFallback(boolean useBulkCopy, boolean sendUnicode) throws Exception {
1519+
String insertSQL = "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(tableNameBulkString)
1520+
+ " (charCol, varcharCol, longvarcharCol, ncharCol1, nvarcharCol1, longnvarcharCol1, "
1521+
+ "ncharCol2, nvarcharCol2, longnvarcharCol2) VALUES ('Anaïs_Ni', ?, ?, ?, ?, ?, ?, ?, ?)";
1522+
1523+
String selectSQL = "SELECT charCol, varcharCol, longvarcharCol, ncharCol1, nvarcharCol1, "
1524+
+ "longnvarcharCol1, ncharCol2, nvarcharCol2, longnvarcharCol2 FROM "
1525+
+ AbstractSQLGenerator.escapeIdentifier(tableNameBulkString);
1526+
1527+
try (Connection connection = PrepUtil.getConnection(connectionString + ";useBulkCopyForBatchInsert="
1528+
+ useBulkCopy + ";sendStringParametersAsUnicode=" + sendUnicode + ";");
1529+
SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(insertSQL);
1530+
Statement stmt = (SQLServerStatement) connection.createStatement()) {
1531+
1532+
getCreateTableWithStringData();
1533+
1534+
String charValue = "Anaïs_Ni";
1535+
String varcharValue = "café";
1536+
String longVarcharValue = "Sørén Kierkégaard";
1537+
String ncharValue1 = "José Müll";
1538+
String nvarcharValue1 = "José Müller";
1539+
String longNvarcharValue1 = "François Saldaña";
1540+
String ncharValue2 = "Test1汉字😀";
1541+
String nvarcharValue2 = "汉字";
1542+
String longNvarcharValue2 = "日本語";
1543+
1544+
pstmt.setString(1, varcharValue);
1545+
pstmt.setString(2, longVarcharValue);
1546+
pstmt.setString(3, ncharValue1);
1547+
pstmt.setString(4, nvarcharValue1);
1548+
pstmt.setString(5, longNvarcharValue1);
1549+
pstmt.setNString(6, ncharValue2);
1550+
pstmt.setNString(7, nvarcharValue2);
1551+
pstmt.setNString(8, longNvarcharValue2);
1552+
pstmt.addBatch();
1553+
1554+
try (FallbackWatcherLogHandler handler = new FallbackWatcherLogHandler()) {
1555+
pstmt.executeBatch();
1556+
if (useBulkCopy) {
1557+
assertTrue(handler.gotFallbackMessage);
1558+
}
1559+
}
1560+
1561+
// Validate inserted data
1562+
try (ResultSet rs = stmt.executeQuery(selectSQL)) {
1563+
assertTrue(rs.next(), "Expected at least one row in result set");
1564+
assertEquals(charValue, rs.getString("charCol"));
1565+
assertEquals(varcharValue, rs.getString("varcharCol"));
1566+
assertEquals(longVarcharValue, rs.getString("longvarcharCol"));
1567+
assertEquals(ncharValue1, rs.getString("ncharCol1"));
1568+
assertEquals(nvarcharValue1, rs.getString("nvarcharCol1"));
1569+
assertEquals(longNvarcharValue1, rs.getString("longnvarcharCol1"));
1570+
assertEquals(ncharValue2, rs.getString("ncharCol2"));
1571+
assertEquals(nvarcharValue2, rs.getString("nvarcharCol2"));
1572+
assertEquals(longNvarcharValue2, rs.getString("longnvarcharCol2"));
1573+
assertFalse(rs.next());
1574+
}
1575+
}
1576+
}
1577+
1578+
@Test
1579+
public void testIssue2669Repro() throws Exception {
1580+
// Original repro
1581+
testIssue2669Variation(false, true);
1582+
// Variations
1583+
testIssue2669Variation(false, false);
1584+
testIssue2669Variation(true, true);
1585+
testIssue2669Variation(true, false);
1586+
1587+
// Test the same combos except falling back to batch insert
1588+
testIssue2669VariationForceFallback(false, true);
1589+
testIssue2669VariationForceFallback(false, false);
1590+
testIssue2669VariationForceFallback(true, true);
1591+
testIssue2669VariationForceFallback(true, false);
1592+
}
1593+
1594+
public void testIssue2669Variation(boolean sendStringsAsUnicode,
1595+
boolean useBulkCopyForBatchInsert) throws Exception {
1596+
String statesTable = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("states"));
1597+
try (Statement stmt = connection.createStatement()) {
1598+
TestUtils.dropTableIfExists(statesTable, stmt);
1599+
String createTableSQL = "CREATE TABLE " + statesTable + " (" + "StateCode nvarchar(50) NOT NULL " + ")";
1600+
1601+
stmt.execute(createTableSQL);
1602+
}
1603+
1604+
String insertSQL = "INSERT INTO " + statesTable + " (StateCode) VALUES (?)";
1605+
1606+
String selectSQL = "SELECT StateCode FROM " + statesTable;
1607+
1608+
try (Connection connection = PrepUtil.getConnection(connectionString + ";useBulkCopyForBatchInsert="
1609+
+ useBulkCopyForBatchInsert + ";sendStringParametersAsUnicode=" + sendStringsAsUnicode + ";");
1610+
SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(insertSQL);
1611+
Statement stmt = (SQLServerStatement) connection.createStatement()) {
1612+
1613+
pstmt.setString(1, "OH");
1614+
pstmt.addBatch();
1615+
pstmt.executeBatch();
1616+
1617+
// Validate inserted data
1618+
try (ResultSet rs = stmt.executeQuery(selectSQL)) {
1619+
assertTrue(rs.next(), "Expected at least one row in result set");
1620+
assertEquals("OH", rs.getString("StateCode"));
1621+
assertFalse(rs.next());
1622+
}
1623+
} finally {
1624+
try (Statement stmt = connection.createStatement()) {
1625+
TestUtils.dropTableIfExists(statesTable, stmt);
1626+
}
1627+
}
1628+
}
1629+
1630+
public void testIssue2669VariationForceFallback(boolean sendStringsAsUnicode,
1631+
boolean useBulkCopyForBatchInsert) throws SQLException {
1632+
String statesTable = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("states"));
1633+
try (Statement stmt = connection.createStatement()) {
1634+
TestUtils.dropTableIfExists(statesTable, stmt);
1635+
String createTableSQL = "CREATE TABLE " + statesTable
1636+
+ " (StateCode nvarchar(50), StateCode2 nvarchar(50) NOT NULL " + ")";
1637+
1638+
stmt.execute(createTableSQL);
1639+
}
1640+
1641+
// Use an INSERT that forces fall back to plain batch insert
1642+
String insertSQL = "INSERT INTO " + statesTable + " (StateCode, StateCode2) VALUES ('NA', ?)";
1643+
1644+
String selectSQL = "SELECT StateCode, StateCode2 FROM " + statesTable;
1645+
1646+
try (Connection connection = PrepUtil.getConnection(connectionString + ";useBulkCopyForBatchInsert="
1647+
+ useBulkCopyForBatchInsert + ";sendStringParametersAsUnicode=" + sendStringsAsUnicode + ";");
1648+
SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(insertSQL);
1649+
Statement stmt = (SQLServerStatement) connection.createStatement()) {
1650+
1651+
pstmt.setString(1, "OH");
1652+
pstmt.addBatch();
1653+
1654+
try (FallbackWatcherLogHandler handler = new FallbackWatcherLogHandler()) {
1655+
pstmt.executeBatch();
1656+
if (useBulkCopyForBatchInsert) {
1657+
assertTrue(handler.gotFallbackMessage);
1658+
}
1659+
}
1660+
1661+
// Validate inserted data
1662+
try (ResultSet rs = stmt.executeQuery(selectSQL)) {
1663+
assertTrue(rs.next(), "Expected at least one row in result set");
1664+
assertEquals("NA", rs.getString("StateCode"));
1665+
assertEquals("OH", rs.getString("StateCode2"));
1666+
assertFalse(rs.next());
1667+
}
1668+
} finally {
1669+
try (Statement stmt = connection.createStatement()) {
1670+
TestUtils.dropTableIfExists(statesTable, stmt);
1671+
}
1672+
}
1673+
}
1674+
15351675
private void getCreateTableWithStringData() throws SQLException {
15361676
try (Statement stmt = connection.createStatement()) {
15371677
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableNameBulkString), stmt);
@@ -1580,6 +1720,7 @@ public static void terminateVariation() throws SQLException {
15801720
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(doubleQuoteTableName), stmt);
15811721
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(schemaTableName), stmt);
15821722
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableNameBulkString), stmt);
1723+
TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(tableNameBulkComputedCols), stmt);
15831724
}
15841725
}
15851726
}

0 commit comments

Comments
 (0)