From b657159ff2d082c590bfff5e70f0faa90266bead Mon Sep 17 00:00:00 2001 From: machavan Date: Mon, 6 Jan 2025 16:45:30 +0530 Subject: [PATCH 1/6] Fixed issue with SQLServerBulkCopy from CSV for setEscapeColumnDelimitersCSV --- .../jdbc/SQLServerBulkCSVFileRecord.java | 4 +- .../jdbc/bulkCopy/BulkCopyCSVTest.java | 118 ++++++++++++++++++ ...nputDelimiterEscapeExtraLineWithBlanks.csv | 16 +++ ...TestInputDelimiterEscapeNoNewLineAtEnd.csv | 15 +++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv create mode 100644 src/test/resources/BulkCopyCSVTestInputDelimiterEscapeNoNewLineAtEnd.csv diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index 2db4339fa..1dd60edb9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -247,7 +247,9 @@ private String readLineEscapeDelimiters() throws SQLServerException { throw new SQLServerException(SQLServerException.getErrString("R_InvalidCSVQuotes"), null, 0, null); } if (c == -1) { // keep semantics of readLine() by returning a null when there is no more data - return null; + if (sb.toString().isBlank()) { + return null; + } } } catch (IOException e) { throw new SQLServerException(e.getMessage(), null, 0, e); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java index 2a8fdb0a0..3695233fe 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java @@ -66,6 +66,8 @@ public class BulkCopyCSVTest extends AbstractTest { static String inputFile = "BulkCopyCSVTestInput.csv"; static String inputFileNoColumnName = "BulkCopyCSVTestInputNoColumnName.csv"; static String inputFileDelimiterEscape = "BulkCopyCSVTestInputDelimiterEscape.csv"; + static String inputFileDelimiterEscapeNoNewLineAtEnd = "BulkCopyCSVTestInputDelimiterEscapeNoNewLineAtEnd.csv"; + static String inputFileDelimiterEscapeExtraLineWithBalnks = "BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv"; static String inputFileMultipleDoubleQuotes = "BulkCopyCSVTestInputMultipleDoubleQuotes.csv"; static String encoding = "UTF-8"; static String delimiter = ","; @@ -197,12 +199,128 @@ public void testEscapeColumnDelimitersCSV() throws Exception { assertEquals(expectedEscaped[i][3], rs.getString("c4")); i++; } + assertEquals(i, 12, "Expected to load 12 records, but loaded " + i + " records"); } TestUtils.dropTableIfExists(tableName, stmt); } } + @Test + @DisplayName("Test setEscapeColumnDelimitersCSVNoNewLineAtEnd") + public void testEscapeColumnDelimitersCSVNoNewLineAtEnd() throws Exception { + String tableName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("BulkEscape")); + String fileName = filePath + inputFileDelimiterEscapeNoNewLineAtEnd; + /* + * The list below is the copy of inputFileDelimiterEsc ape with quotes removed. + */ + String[][] expectedEscaped = new String[12][4]; + expectedEscaped[0] = new String[] {"test", " test\"", "no@split", " testNoQuote", ""}; + expectedEscaped[1] = new String[] {null, null, null, null, ""}; + expectedEscaped[2] = new String[] {"\"", "test\"test", "test@\" test", null, ""}; + expectedEscaped[3] = new String[] {"testNoQuote ", " testSpaceAround ", " testSpaceInside ", + " testSpaceQuote\" ", ""}; + expectedEscaped[4] = new String[] {null, null, null, " testSpaceInside ", ""}; + expectedEscaped[5] = new String[] {"1997", "Ford", "E350", "E63", ""}; + expectedEscaped[6] = new String[] {"1997", "Ford", "E350", "E63", ""}; + expectedEscaped[7] = new String[] {"1997", "Ford", "E350", "Super@ luxurious truck", ""}; + expectedEscaped[8] = new String[] {"1997", "Ford", "E350", "Super@ \"luxurious\" truck", ""}; + expectedEscaped[9] = new String[] {"1997", "Ford", "E350", "E63", ""}; + expectedEscaped[10] = new String[] {"1997", "Ford", "E350", " Super luxurious truck ", ""}; + expectedEscaped[11] = new String[] {"1997", "F\r\no\r\nr\r\nd", "E350", "\"Super\" \"luxurious\" \"truck\"", + ""}; + + try (Connection con = getConnection(); Statement stmt = con.createStatement(); + SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(con); + SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord(fileName, encoding, "@", + false)) { + bulkCopy.setDestinationTableName(tableName); + fileRecord.setEscapeColumnDelimitersCSV(true); + fileRecord.addColumnMetadata(1, null, java.sql.Types.INTEGER, 0, 0); + fileRecord.addColumnMetadata(2, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(3, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(4, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(5, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(6, null, java.sql.Types.VARCHAR, 50, 0); + stmt.executeUpdate("CREATE TABLE " + tableName + + " (id INT IDENTITY(1,1), c1 VARCHAR(50), c2 VARCHAR(50), c3 VARCHAR(50), c4 VARCHAR(50), c5 VARCHAR(50))"); + bulkCopy.writeToServer(fileRecord); + + int i = 0; + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id"); + BufferedReader br = new BufferedReader(new FileReader(fileName));) { + while (rs.next()) { + assertEquals(expectedEscaped[i][0], rs.getString("c1")); + assertEquals(expectedEscaped[i][1], rs.getString("c2")); + assertEquals(expectedEscaped[i][2], rs.getString("c3")); + assertEquals(expectedEscaped[i][3], rs.getString("c4")); + i++; + } + assertEquals(i, 12, "Expected to load 12 records, but loaded " + i + " records"); + } + + TestUtils.dropTableIfExists(tableName, stmt); + } + } + + @Test + @DisplayName("Test setEscapeColumnDelimitersCSVExtraLineWithBlanks") + public void testEscapeColumnDelimitersCSVExtraLineWithBlanks() throws Exception { + String tableName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("BulkEscape")); + String fileName = filePath + inputFileDelimiterEscapeExtraLineWithBalnks; + /* + * The list below is the copy of inputFileDelimiterEsc ape with quotes removed. + */ + String[][] expectedEscaped = new String[12][4]; + expectedEscaped[0] = new String[] {"test", " test\"", "no@split", " testNoQuote", ""}; + expectedEscaped[1] = new String[] {null, null, null, null, ""}; + expectedEscaped[2] = new String[] {"\"", "test\"test", "test@\" test", null, ""}; + expectedEscaped[3] = new String[] {"testNoQuote ", " testSpaceAround ", " testSpaceInside ", + " testSpaceQuote\" ", ""}; + expectedEscaped[4] = new String[] {null, null, null, " testSpaceInside ", ""}; + expectedEscaped[5] = new String[] {"1997", "Ford", "E350", "E63", ""}; + expectedEscaped[6] = new String[] {"1997", "Ford", "E350", "E63", ""}; + expectedEscaped[7] = new String[] {"1997", "Ford", "E350", "Super@ luxurious truck", ""}; + expectedEscaped[8] = new String[] {"1997", "Ford", "E350", "Super@ \"luxurious\" truck", ""}; + expectedEscaped[9] = new String[] {"1997", "Ford", "E350", "E63", ""}; + expectedEscaped[10] = new String[] {"1997", "Ford", "E350", " Super luxurious truck ", ""}; + expectedEscaped[11] = new String[] {"1997", "F\r\no\r\nr\r\nd", "E350", "\"Super\" \"luxurious\" \"truck\"", + ""}; + + try (Connection con = getConnection(); Statement stmt = con.createStatement(); + SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(con); + SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord(fileName, encoding, "@", + false)) { + bulkCopy.setDestinationTableName(tableName); + fileRecord.setEscapeColumnDelimitersCSV(true); + fileRecord.addColumnMetadata(1, null, java.sql.Types.INTEGER, 0, 0); + fileRecord.addColumnMetadata(2, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(3, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(4, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(5, null, java.sql.Types.VARCHAR, 50, 0); + fileRecord.addColumnMetadata(6, null, java.sql.Types.VARCHAR, 50, 0); + stmt.executeUpdate("CREATE TABLE " + tableName + + " (id INT IDENTITY(1,1), c1 VARCHAR(50), c2 VARCHAR(50), c3 VARCHAR(50), c4 VARCHAR(50), c5 VARCHAR(50))"); + bulkCopy.writeToServer(fileRecord); + + int i = 0; + try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id"); + BufferedReader br = new BufferedReader(new FileReader(fileName));) { + while (rs.next()) { + assertEquals(expectedEscaped[i][0], rs.getString("c1")); + assertEquals(expectedEscaped[i][1], rs.getString("c2")); + assertEquals(expectedEscaped[i][2], rs.getString("c3")); + assertEquals(expectedEscaped[i][3], rs.getString("c4")); + i++; + } + assertEquals(i, 12, "Expected to load 12 records, but loaded " + i + " records"); + } + + TestUtils.dropTableIfExists(tableName, stmt); + } + } + + /** * test simple csv file for bulkcopy, for GitHub issue 1391 Tests to ensure that the set returned by * getColumnOrdinals doesn't have to be ordered diff --git a/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv b/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv new file mode 100644 index 000000000..872cb3c70 --- /dev/null +++ b/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv @@ -0,0 +1,16 @@ +1@"test"@ " test"""@ "no@split" @ testNoQuote@ +2@""@ ""@ ""@ ""@ +3@""""@ "test""test"@ "test@"" test"@ ""@ +4@testNoQuote @ testSpaceAround @ " testSpaceInside "@ " testSpaceQuote"" "@ +5@""@ ""@ ""@ " testSpaceInside "@ +6@1997@Ford@E350@E63@ +7@"1997"@"Ford"@"E350"@"E63"@ +8@1997@Ford@E350@"Super@ luxurious truck"@ +9@1997@Ford@E350@"Super@ ""luxurious"" truck"@ +10@1997@ "Ford" @E350@ "E63"@ +11@1997@Ford@E350@" Super luxurious truck "@ +12@1997@"F +o +r +d"@"E350"@"""Super"" ""luxurious"" ""truck"""@ + \ No newline at end of file diff --git a/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeNoNewLineAtEnd.csv b/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeNoNewLineAtEnd.csv new file mode 100644 index 000000000..98ac9f114 --- /dev/null +++ b/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeNoNewLineAtEnd.csv @@ -0,0 +1,15 @@ +1@"test"@ " test"""@ "no@split" @ testNoQuote@ +2@""@ ""@ ""@ ""@ +3@""""@ "test""test"@ "test@"" test"@ ""@ +4@testNoQuote @ testSpaceAround @ " testSpaceInside "@ " testSpaceQuote"" "@ +5@""@ ""@ ""@ " testSpaceInside "@ +6@1997@Ford@E350@E63@ +7@"1997"@"Ford"@"E350"@"E63"@ +8@1997@Ford@E350@"Super@ luxurious truck"@ +9@1997@Ford@E350@"Super@ ""luxurious"" truck"@ +10@1997@ "Ford" @E350@ "E63"@ +11@1997@Ford@E350@" Super luxurious truck "@ +12@1997@"F +o +r +d"@"E350"@"""Super"" ""luxurious"" ""truck"""@ \ No newline at end of file From af2b730f55c518e87bbd509b6a7149293811f0cc Mon Sep 17 00:00:00 2001 From: machavan Date: Tue, 7 Jan 2025 10:14:34 +0530 Subject: [PATCH 2/6] Fixed scenario with last line having blank content --- .../jdbc/SQLServerBulkCSVFileRecord.java | 2 +- .../jdbc/bulkCopy/BulkCopyCSVTest.java | 59 ------------------- ...nputDelimiterEscapeExtraLineWithBlanks.csv | 16 ----- 3 files changed, 1 insertion(+), 76 deletions(-) delete mode 100644 src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index 1dd60edb9..86dcc7b3c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -247,7 +247,7 @@ private String readLineEscapeDelimiters() throws SQLServerException { throw new SQLServerException(SQLServerException.getErrString("R_InvalidCSVQuotes"), null, 0, null); } if (c == -1) { // keep semantics of readLine() by returning a null when there is no more data - if (sb.toString().isBlank()) { + if (sb.isEmpty()) { return null; } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java index 3695233fe..fe2a551bf 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java @@ -67,7 +67,6 @@ public class BulkCopyCSVTest extends AbstractTest { static String inputFileNoColumnName = "BulkCopyCSVTestInputNoColumnName.csv"; static String inputFileDelimiterEscape = "BulkCopyCSVTestInputDelimiterEscape.csv"; static String inputFileDelimiterEscapeNoNewLineAtEnd = "BulkCopyCSVTestInputDelimiterEscapeNoNewLineAtEnd.csv"; - static String inputFileDelimiterEscapeExtraLineWithBalnks = "BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv"; static String inputFileMultipleDoubleQuotes = "BulkCopyCSVTestInputMultipleDoubleQuotes.csv"; static String encoding = "UTF-8"; static String delimiter = ","; @@ -262,64 +261,6 @@ public void testEscapeColumnDelimitersCSVNoNewLineAtEnd() throws Exception { TestUtils.dropTableIfExists(tableName, stmt); } } - - @Test - @DisplayName("Test setEscapeColumnDelimitersCSVExtraLineWithBlanks") - public void testEscapeColumnDelimitersCSVExtraLineWithBlanks() throws Exception { - String tableName = AbstractSQLGenerator.escapeIdentifier(RandomUtil.getIdentifier("BulkEscape")); - String fileName = filePath + inputFileDelimiterEscapeExtraLineWithBalnks; - /* - * The list below is the copy of inputFileDelimiterEsc ape with quotes removed. - */ - String[][] expectedEscaped = new String[12][4]; - expectedEscaped[0] = new String[] {"test", " test\"", "no@split", " testNoQuote", ""}; - expectedEscaped[1] = new String[] {null, null, null, null, ""}; - expectedEscaped[2] = new String[] {"\"", "test\"test", "test@\" test", null, ""}; - expectedEscaped[3] = new String[] {"testNoQuote ", " testSpaceAround ", " testSpaceInside ", - " testSpaceQuote\" ", ""}; - expectedEscaped[4] = new String[] {null, null, null, " testSpaceInside ", ""}; - expectedEscaped[5] = new String[] {"1997", "Ford", "E350", "E63", ""}; - expectedEscaped[6] = new String[] {"1997", "Ford", "E350", "E63", ""}; - expectedEscaped[7] = new String[] {"1997", "Ford", "E350", "Super@ luxurious truck", ""}; - expectedEscaped[8] = new String[] {"1997", "Ford", "E350", "Super@ \"luxurious\" truck", ""}; - expectedEscaped[9] = new String[] {"1997", "Ford", "E350", "E63", ""}; - expectedEscaped[10] = new String[] {"1997", "Ford", "E350", " Super luxurious truck ", ""}; - expectedEscaped[11] = new String[] {"1997", "F\r\no\r\nr\r\nd", "E350", "\"Super\" \"luxurious\" \"truck\"", - ""}; - - try (Connection con = getConnection(); Statement stmt = con.createStatement(); - SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(con); - SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord(fileName, encoding, "@", - false)) { - bulkCopy.setDestinationTableName(tableName); - fileRecord.setEscapeColumnDelimitersCSV(true); - fileRecord.addColumnMetadata(1, null, java.sql.Types.INTEGER, 0, 0); - fileRecord.addColumnMetadata(2, null, java.sql.Types.VARCHAR, 50, 0); - fileRecord.addColumnMetadata(3, null, java.sql.Types.VARCHAR, 50, 0); - fileRecord.addColumnMetadata(4, null, java.sql.Types.VARCHAR, 50, 0); - fileRecord.addColumnMetadata(5, null, java.sql.Types.VARCHAR, 50, 0); - fileRecord.addColumnMetadata(6, null, java.sql.Types.VARCHAR, 50, 0); - stmt.executeUpdate("CREATE TABLE " + tableName - + " (id INT IDENTITY(1,1), c1 VARCHAR(50), c2 VARCHAR(50), c3 VARCHAR(50), c4 VARCHAR(50), c5 VARCHAR(50))"); - bulkCopy.writeToServer(fileRecord); - - int i = 0; - try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id"); - BufferedReader br = new BufferedReader(new FileReader(fileName));) { - while (rs.next()) { - assertEquals(expectedEscaped[i][0], rs.getString("c1")); - assertEquals(expectedEscaped[i][1], rs.getString("c2")); - assertEquals(expectedEscaped[i][2], rs.getString("c3")); - assertEquals(expectedEscaped[i][3], rs.getString("c4")); - i++; - } - assertEquals(i, 12, "Expected to load 12 records, but loaded " + i + " records"); - } - - TestUtils.dropTableIfExists(tableName, stmt); - } - } - /** * test simple csv file for bulkcopy, for GitHub issue 1391 Tests to ensure that the set returned by diff --git a/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv b/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv deleted file mode 100644 index 872cb3c70..000000000 --- a/src/test/resources/BulkCopyCSVTestInputDelimiterEscapeExtraLineWithBlanks.csv +++ /dev/null @@ -1,16 +0,0 @@ -1@"test"@ " test"""@ "no@split" @ testNoQuote@ -2@""@ ""@ ""@ ""@ -3@""""@ "test""test"@ "test@"" test"@ ""@ -4@testNoQuote @ testSpaceAround @ " testSpaceInside "@ " testSpaceQuote"" "@ -5@""@ ""@ ""@ " testSpaceInside "@ -6@1997@Ford@E350@E63@ -7@"1997"@"Ford"@"E350"@"E63"@ -8@1997@Ford@E350@"Super@ luxurious truck"@ -9@1997@Ford@E350@"Super@ ""luxurious"" truck"@ -10@1997@ "Ford" @E350@ "E63"@ -11@1997@Ford@E350@" Super luxurious truck "@ -12@1997@"F -o -r -d"@"E350"@"""Super"" ""luxurious"" ""truck"""@ - \ No newline at end of file From e567922460c6c368c2b59a3ca0a8d6ff96a13b15 Mon Sep 17 00:00:00 2001 From: machavan Date: Tue, 7 Jan 2025 14:41:44 +0530 Subject: [PATCH 3/6] Simplied if condition --- .../sqlserver/jdbc/SQLServerBulkCSVFileRecord.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index 86dcc7b3c..688a302f8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -246,10 +246,8 @@ private String readLineEscapeDelimiters() throws SQLServerException { if (c == -1 && quoteCount % 2 != 0) { // stream ended, but we are within quotes -- data problem throw new SQLServerException(SQLServerException.getErrString("R_InvalidCSVQuotes"), null, 0, null); } - if (c == -1) { // keep semantics of readLine() by returning a null when there is no more data - if (sb.isEmpty()) { - return null; - } + if ((c == -1) && sb.isEmpty()) { // keep semantics of readLine() by returning a null when there is no more data + return null; } } catch (IOException e) { throw new SQLServerException(e.getMessage(), null, 0, e); From 92cad20cda20692b985068f037893da77700455a Mon Sep 17 00:00:00 2001 From: machavan Date: Tue, 7 Jan 2025 14:54:39 +0530 Subject: [PATCH 4/6] Changed sb.isEmpty to sb.toString().isEmpty() --- .../microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index 688a302f8..7583aea1a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -246,7 +246,7 @@ private String readLineEscapeDelimiters() throws SQLServerException { if (c == -1 && quoteCount % 2 != 0) { // stream ended, but we are within quotes -- data problem throw new SQLServerException(SQLServerException.getErrString("R_InvalidCSVQuotes"), null, 0, null); } - if ((c == -1) && sb.isEmpty()) { // keep semantics of readLine() by returning a null when there is no more data + if ((c == -1) && sb.toString().isEmpty()) { // keep semantics of readLine() by returning a null when there is no more data return null; } } catch (IOException e) { From 6adfc61bef773999be900b969cb8aa53dbc6f41d Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 23 Jan 2025 11:13:19 +0530 Subject: [PATCH 5/6] Use length instead of toString --- .../microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java index 7583aea1a..1b21544f9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBulkCSVFileRecord.java @@ -246,7 +246,7 @@ private String readLineEscapeDelimiters() throws SQLServerException { if (c == -1 && quoteCount % 2 != 0) { // stream ended, but we are within quotes -- data problem throw new SQLServerException(SQLServerException.getErrString("R_InvalidCSVQuotes"), null, 0, null); } - if ((c == -1) && sb.toString().isEmpty()) { // keep semantics of readLine() by returning a null when there is no more data + if ((c == -1) && (sb.length() == 0)) { // keep semantics of readLine() by returning a null when there is no more data return null; } } catch (IOException e) { From 59cad8f06050c2e917751d13cc173c2354637ebf Mon Sep 17 00:00:00 2001 From: machavan Date: Thu, 23 Jan 2025 11:22:12 +0530 Subject: [PATCH 6/6] Added dropTable in finally block. --- .../microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java index fe2a551bf..057c5068c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/bulkCopy/BulkCopyCSVTest.java @@ -256,9 +256,9 @@ public void testEscapeColumnDelimitersCSVNoNewLineAtEnd() throws Exception { i++; } assertEquals(i, 12, "Expected to load 12 records, but loaded " + i + " records"); + } finally { + TestUtils.dropTableIfExists(tableName, stmt); } - - TestUtils.dropTableIfExists(tableName, stmt); } }