From bb254f2b5ba98b5e47c7be6f02edda2f3ef0e343 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Tue, 28 Aug 2018 17:08:03 -0700 Subject: [PATCH 01/25] filling clob if stream is not of type plpinputstream --- src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index b59fd9062..a0a08373c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -381,10 +381,10 @@ public String getSubString(long pos, int length) throws SQLException { */ public long length() throws SQLException { checkClosed(); - if (value == null && activeStreams.get(0) instanceof PLPInputStream) { return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength / 2; } + getStringFromStream(); return value.length(); } From 225c9851aa70b7bc1d1ee914a2995cc0ceb7d328 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Thu, 30 Aug 2018 13:36:13 -0700 Subject: [PATCH 02/25] fix for simpleinputstream --- .../microsoft/sqlserver/jdbc/PLPInputStream.java | 3 --- .../microsoft/sqlserver/jdbc/SQLServerClob.java | 15 ++++++++++++--- .../sqlserver/jdbc/SimpleInputStream.java | 6 +++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/PLPInputStream.java b/src/main/java/com/microsoft/sqlserver/jdbc/PLPInputStream.java index 0b4563e0b..8a502a370 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/PLPInputStream.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/PLPInputStream.java @@ -25,9 +25,6 @@ class PLPInputStream extends BaseInputStream { static final int PLP_TERMINATOR = 0x00000000; private final static byte[] EMPTY_PLP_BYTES = new byte[0]; - // Stated length of the PLP stream payload; -1 if unknown length. - int payloadLength; - private static final int PLP_EOS = -1; private int currentChunkRemain; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index a0a08373c..896211116 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -7,6 +7,7 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_16LE; +import static java.nio.charset.StandardCharsets.UTF_16; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -20,6 +21,7 @@ import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.charset.Charset; import java.sql.Clob; import java.sql.SQLException; import java.text.MessageFormat; @@ -301,7 +303,12 @@ public Reader getCharacterStream() throws SQLException { Reader getterStream = null; if (null == value && !activeStreams.isEmpty()) { InputStream inputStream = (InputStream) activeStreams.get(0); - getterStream = new BufferedReader(new InputStreamReader(inputStream, UTF_16LE)); + try { + inputStream.reset(); + } catch (IOException e) { + throw new SQLServerException(e.getMessage(), null, 0, e); + } + getterStream = new BufferedReader(new InputStreamReader(inputStream)); } else { getterStream = new StringReader(value); activeStreams.add(getterStream); @@ -383,9 +390,11 @@ public long length() throws SQLException { checkClosed(); if (value == null && activeStreams.get(0) instanceof PLPInputStream) { return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength / 2; + } else if (value == null && activeStreams.get(0) instanceof SimpleInputStream) { + return (long) ((SimpleInputStream) activeStreams.get(0)).payloadLength / 2; + } else { + return value.length(); } - getStringFromStream(); - return value.length(); } /** diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java b/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java index 2135858c1..fa22c96ca 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SimpleInputStream.java @@ -24,6 +24,9 @@ abstract class BaseInputStream extends InputStream { // Flag indicating whether the stream consumes and discards data as it reads it final boolean isStreaming; + + // Stated length of the payload + int payloadLength; /** Generate the logging ID */ private String parentLoggingInfo = ""; @@ -131,9 +134,6 @@ void resetHelper() throws IOException { final class SimpleInputStream extends BaseInputStream { - // Stated length of the payload - private final int payloadLength; - /** * Initializes the input stream. */ From 8f6d1974f63bcefa7b9cad9fb746d2e76d7f5649 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Tue, 4 Sep 2018 17:00:43 -0700 Subject: [PATCH 03/25] Added more streaming tests. Changed Clob to use different charset instead of always UTF-16LE --- .../sqlserver/jdbc/SQLServerClob.java | 20 +- .../sqlserver/jdbc/SQLServerNClob.java | 23 +- .../jdbc/unit/lobs/lobsStreamingTest.java | 250 ++++++++++++++++++ 3 files changed, 279 insertions(+), 14 deletions(-) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 896211116..5b61e62ae 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -6,8 +6,6 @@ package com.microsoft.sqlserver.jdbc; import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_16LE; -import static java.nio.charset.StandardCharsets.UTF_16; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -21,7 +19,6 @@ import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.io.Writer; -import java.nio.charset.Charset; import java.sql.Clob; import java.sql.SQLException; import java.text.MessageFormat; @@ -154,7 +151,7 @@ abstract class SQLServerClobBase extends SQLServerLob implements Serializable { // The value of the CLOB that this Clob object represents. // This value is never null unless/until the free() method is called. - private String value; + protected String value; private final SQLCollation sqlCollation; @@ -167,7 +164,7 @@ abstract class SQLServerClobBase extends SQLServerLob implements Serializable { * assumption that a Clob/NClob object is typically used either for input or output, and then only once. The array * size grows automatically if multiple streams are used. */ - private ArrayList activeStreams = new ArrayList<>(1); + protected ArrayList activeStreams = new ArrayList<>(1); transient SQLServerConnection con; @@ -262,7 +259,7 @@ public void free() throws SQLException { /** * Throws a SQLException if the LOB has been freed. */ - private void checkClosed() throws SQLServerException { + protected void checkClosed() throws SQLServerException { if (isClosed) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_isFreed")); SQLServerException.makeFromDriverError(con, null, form.format(new Object[] {getDisplayClassName()}), null, @@ -308,7 +305,7 @@ public Reader getCharacterStream() throws SQLException { } catch (IOException e) { throw new SQLServerException(e.getMessage(), null, 0, e); } - getterStream = new BufferedReader(new InputStreamReader(inputStream)); + getterStream = new BufferedReader(new InputStreamReader(inputStream, typeInfo.getCharset())); } else { getterStream = new StringReader(value); activeStreams.add(getterStream); @@ -388,13 +385,10 @@ public String getSubString(long pos, int length) throws SQLException { */ public long length() throws SQLException { checkClosed(); - if (value == null && activeStreams.get(0) instanceof PLPInputStream) { - return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength / 2; - } else if (value == null && activeStreams.get(0) instanceof SimpleInputStream) { - return (long) ((SimpleInputStream) activeStreams.get(0)).payloadLength / 2; - } else { - return value.length(); + if (value == null && activeStreams.get(0) instanceof BaseInputStream) { + return (long) ((BaseInputStream) activeStreams.get(0)).payloadLength / 2; } + return value.length(); } /** diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index dfa9fb12d..f61e38fee 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -5,9 +5,15 @@ package com.microsoft.sqlserver.jdbc; +import static java.nio.charset.StandardCharsets.UTF_16LE; + +import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; +import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.sql.Clob; @@ -50,7 +56,22 @@ public InputStream getAsciiStream() throws SQLException { @Override public Reader getCharacterStream() throws SQLException { - return super.getCharacterStream(); + checkClosed(); + + Reader getterStream = null; + if (null == value && !activeStreams.isEmpty()) { + InputStream inputStream = (InputStream) activeStreams.get(0); + try { + inputStream.reset(); + } catch (IOException e) { + throw new SQLServerException(e.getMessage(), null, 0, e); + } + getterStream = new BufferedReader(new InputStreamReader(inputStream, UTF_16LE)); + } else { + getterStream = new StringReader(value); + activeStreams.add(getterStream); + } + return getterStream; } @Override diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java new file mode 100644 index 000000000..75f101925 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java @@ -0,0 +1,250 @@ +package com.microsoft.sqlserver.jdbc.unit.lobs; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.util.RandomUtil; + + +@RunWith(JUnitPlatform.class) +public class lobsStreamingTest extends AbstractTest { + + private static final int LOB_ARRAY_SIZE = 250; // number of rows to insert into the table and compare + private static final int LOB_LENGTH_MIN = 4000; + private static final int LOB_LENGTH_MAX = 8000; + + static Connection conn = null; + static Statement stmt = null; + static String tableName; + static String escapedTableName; + + @BeforeAll + public static void init() throws SQLException { + conn = DriverManager.getConnection(connectionString); + stmt = conn.createStatement(); + + tableName = RandomUtil.getIdentifier("streamingTest"); + escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); + } + + @AfterAll + public static void terminate() throws SQLException { + if (null != conn) + conn.close(); + if (null != stmt) + stmt.close(); + } + + @AfterEach + public void dropTable() throws SQLException, InterruptedException { + stmt.execute("DROP TABLE [" + tableName + "]"); + } + + private String getRandomString(int length) { + String validCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+,./;'[]<>?:{}|`~\"\\"; + StringBuilder salt = new StringBuilder(); + Random rnd = new Random(); + while (salt.length() < length) { + int index = (int) (rnd.nextFloat() * validCharacters.length()); + salt.append(validCharacters.charAt(index)); + } + String saltStr = salt.toString(); + return saltStr; + + } + + private String getStringFromInputStream(InputStream is) { + try (java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A")) { + return s.hasNext() ? s.next() : ""; + } + } + + private String getStringFromReader(Reader r, long l) throws IOException { + // read the Reader contents into a buffer and return the complete string + final StringBuilder stringBuilder = new StringBuilder((int) l); + char[] buffer = new char[(int) l]; + while (true) { + int amountRead = r.read(buffer, 0, (int) l); + if (amountRead == -1) { + break; + } + stringBuilder.append(buffer, 0, amountRead); + } + return stringBuilder.toString(); + } + + @Test + @DisplayName("testClobsVarcharASCII") + public void testClobsVarcharASCII() throws SQLException { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach( + i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + pstmt.close(); + + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + + @Test + @DisplayName("testNClobsNVarcharASCII") + public void testNClobsVarcharASCII() throws SQLException { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach( + i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); + for (int i = 0; i < lobs.size(); i++) { + NClob c = conn.createNClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + NClob c = rs.getNClob(2); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + pstmt.close(); + + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + + @Test + @DisplayName("testClobsVarcharCHARA") + public void testClobsVarcharCHARA() throws SQLException, IOException { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach( + i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + pstmt.close(); + + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + + @Test + @DisplayName("testNClobsVarcharCHARA") + public void testNClobsVarcharCHARA() throws SQLException, IOException { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach( + i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); + for (int i = 0; i < lobs.size(); i++) { + NClob c = conn.createNClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + NClob c = rs.getNClob(2); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + pstmt.close(); + + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } +} From a6ad39a3a8710bf950f2ead4be4a24f41e866666 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 7 Sep 2018 09:43:24 -0700 Subject: [PATCH 04/25] cleaning up implementation --- .../sqlserver/jdbc/SQLServerClob.java | 14 +++++++++++--- .../sqlserver/jdbc/SQLServerNClob.java | 19 +++---------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 5b61e62ae..ee2317360 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -19,6 +19,7 @@ import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.charset.Charset; import java.sql.Clob; import java.sql.SQLException; import java.text.MessageFormat; @@ -180,8 +181,9 @@ final public String toString() { // Unique id generator for each instance (used for logging). static private final AtomicInteger baseID = new AtomicInteger(0); + private Charset defaultCharset = null; + // Returns unique id for each instance. - private static int nextInstanceID() { return baseID.incrementAndGet(); } @@ -305,7 +307,8 @@ public Reader getCharacterStream() throws SQLException { } catch (IOException e) { throw new SQLServerException(e.getMessage(), null, 0, e); } - getterStream = new BufferedReader(new InputStreamReader(inputStream, typeInfo.getCharset())); + Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset; + getterStream = new BufferedReader(new InputStreamReader(inputStream, cs)); } else { getterStream = new StringReader(value); activeStreams.add(getterStream); @@ -415,7 +418,8 @@ private void getStringFromStream() throws SQLServerException { } catch (IOException e) { throw new SQLServerException(e.getMessage(), null, 0, e); } - value = new String((stream).getBytes(), typeInfo.getCharset()); + Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset; + value = new String((stream).getBytes(), cs); } } @@ -664,6 +668,10 @@ public int setString(long pos, String str, int offset, int len) throws SQLExcept return len; } + + protected void setDefaultCharset(Charset c) { + this.defaultCharset = c; + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index f61e38fee..ab17121a8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -38,10 +38,12 @@ public final class SQLServerNClob extends SQLServerClobBase implements NClob { SQLServerNClob(SQLServerConnection connection) { super(connection, "", connection.getDatabaseCollation(), logger, null); + this.setDefaultCharset(UTF_16LE); } SQLServerNClob(BaseInputStream stream, TypeInfo typeInfo) throws SQLServerException, UnsupportedEncodingException { super(null, stream, typeInfo.getSQLCollation(), logger, typeInfo); + this.setDefaultCharset(UTF_16LE); } @Override @@ -56,22 +58,7 @@ public InputStream getAsciiStream() throws SQLException { @Override public Reader getCharacterStream() throws SQLException { - checkClosed(); - - Reader getterStream = null; - if (null == value && !activeStreams.isEmpty()) { - InputStream inputStream = (InputStream) activeStreams.get(0); - try { - inputStream.reset(); - } catch (IOException e) { - throw new SQLServerException(e.getMessage(), null, 0, e); - } - getterStream = new BufferedReader(new InputStreamReader(inputStream, UTF_16LE)); - } else { - getterStream = new StringReader(value); - activeStreams.add(getterStream); - } - return getterStream; + return super.getCharacterStream(); } @Override From 961954393b62f414fa25523b9d1ab3bae077a79d Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 7 Sep 2018 09:44:46 -0700 Subject: [PATCH 05/25] removing unused imports --- .../java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index ab17121a8..68fd38d63 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -7,13 +7,9 @@ import static java.nio.charset.StandardCharsets.UTF_16LE; -import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; -import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.sql.Clob; From 1ebc48c4268a0995cb79da97b5fbba83258bf42e Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 7 Sep 2018 10:41:21 -0700 Subject: [PATCH 06/25] added length check to tests and updated length() for clobs/nclobs --- .../java/com/microsoft/sqlserver/jdbc/SQLServerClob.java | 2 +- .../java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java | 6 +++++- .../sqlserver/jdbc/unit/lobs/lobsStreamingTest.java | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index ee2317360..aebeaa360 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -389,7 +389,7 @@ public String getSubString(long pos, int length) throws SQLException { public long length() throws SQLException { checkClosed(); if (value == null && activeStreams.get(0) instanceof BaseInputStream) { - return (long) ((BaseInputStream) activeStreams.get(0)).payloadLength / 2; + return (long) ((BaseInputStream) activeStreams.get(0)).payloadLength; } return value.length(); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 68fd38d63..5ce9986a7 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -69,7 +69,11 @@ public String getSubString(long pos, int length) throws SQLException { @Override public long length() throws SQLException { - return super.length(); + if (value == null && activeStreams.get(0) instanceof BaseInputStream) { + return super.length()/2; + } else { + return super.length(); + } } @Override diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java index 75f101925..bbcde0ae3 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java @@ -121,6 +121,7 @@ public void testClobsVarcharASCII() throws SQLException { ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); while (rs.next()) { Clob c = rs.getClob(2); + assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); lobsFromServer.add(c); String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string streamedStrings.add(recieved); @@ -158,6 +159,7 @@ public void testNClobsVarcharASCII() throws SQLException { ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); while (rs.next()) { NClob c = rs.getNClob(2); + assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); lobsFromServer.add(c); String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string streamedStrings.add(recieved); @@ -195,6 +197,7 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); while (rs.next()) { Clob c = rs.getClob(2); + assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); lobsFromServer.add(c); String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string streamedStrings.add(recieved); @@ -233,6 +236,7 @@ public void testNClobsVarcharCHARA() throws SQLException, IOException { ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); while (rs.next()) { NClob c = rs.getNClob(2); + assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); lobsFromServer.add(c); String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string streamedStrings.add(recieved); From 72b002ce26ff0e6cd3ec923630461225c8477d65 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 7 Sep 2018 15:59:40 -0700 Subject: [PATCH 07/25] enabled streaming for getAsciiStream --- .../sqlserver/jdbc/SQLServerClob.java | 22 +++++++++++++++---- .../sqlserver/jdbc/SQLServerNClob.java | 7 ++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index aebeaa360..4b0dec8b6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -282,9 +282,22 @@ public InputStream getAsciiStream() throws SQLException { if (null != sqlCollation && !sqlCollation.supportsAsciiConversion()) DataTypes.throwConversionError(getDisplayClassName(), "AsciiStream"); - getStringFromStream(); - InputStream getterStream = new BufferedInputStream( - new ReaderInputStream(new StringReader(value), US_ASCII, value.length())); + // Need to use a BufferedInputStream since the stream returned by this method is assumed to support mark/reset + InputStream getterStream; + if (null == value && !activeStreams.isEmpty()) { + InputStream inputStream = (InputStream) activeStreams.get(0); + try { + inputStream.reset(); + getterStream = new BufferedInputStream( + new ReaderInputStream(new InputStreamReader(inputStream), US_ASCII, inputStream.available())); + } catch (IOException e) { + throw new SQLServerException(e.getMessage(), null, 0, e); + } + } else { + getStringFromStream(); + getterStream = new BufferedInputStream( + new ReaderInputStream(new StringReader(value), US_ASCII, value.length())); + } activeStreams.add(getterStream); return getterStream; } @@ -310,9 +323,10 @@ public Reader getCharacterStream() throws SQLException { Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset; getterStream = new BufferedReader(new InputStreamReader(inputStream, cs)); } else { + getStringFromStream(); getterStream = new StringReader(value); - activeStreams.add(getterStream); } + activeStreams.add(getterStream); return getterStream; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 5ce9986a7..059db0eba 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -69,11 +69,8 @@ public String getSubString(long pos, int length) throws SQLException { @Override public long length() throws SQLException { - if (value == null && activeStreams.get(0) instanceof BaseInputStream) { - return super.length()/2; - } else { - return super.length(); - } + //If streaming, every 2 bytes represents 1 character. If not, length() just returns string length + return (value == null && activeStreams.get(0) instanceof BaseInputStream) ? super.length() / 2 : super.length(); } @Override From 6b7956d58c5ccc5da1eba8718eaaa4971b9f5a25 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 7 Sep 2018 16:50:14 -0700 Subject: [PATCH 08/25] cleaning up ascii stream implementation. --- .../java/com/microsoft/sqlserver/jdbc/SQLServerClob.java | 8 +++----- .../com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java | 7 ++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 4b0dec8b6..9a8d04a19 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -7,8 +7,8 @@ import static java.nio.charset.StandardCharsets.US_ASCII; -import java.io.BufferedInputStream; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; @@ -288,15 +288,13 @@ public InputStream getAsciiStream() throws SQLException { InputStream inputStream = (InputStream) activeStreams.get(0); try { inputStream.reset(); - getterStream = new BufferedInputStream( - new ReaderInputStream(new InputStreamReader(inputStream), US_ASCII, inputStream.available())); + getterStream = inputStream; } catch (IOException e) { throw new SQLServerException(e.getMessage(), null, 0, e); } } else { getStringFromStream(); - getterStream = new BufferedInputStream( - new ReaderInputStream(new StringReader(value), US_ASCII, value.length())); + getterStream = new ByteArrayInputStream(value.getBytes(US_ASCII)); } activeStreams.add(getterStream); return getterStream; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java index ed4755488..764310665 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java @@ -421,9 +421,8 @@ private void testLobsInsertRetrive(String types[], Class lobClass) throws Except nclob = rs.getNClob(2); assertEquals(nclob.length(), size); stream = nclob.getAsciiStream(); - BufferedInputStream is = new BufferedInputStream(stream); - is.read(chunk); - assertEquals(chunk.length, size); + chunk = stream.readAllBytes(); + assertEquals(chunk.length/2, size);//2 bytes per character when streaming } else { blob = rs.getBlob(2); stream = blob.getBinaryStream(); @@ -432,7 +431,6 @@ private void testLobsInsertRetrive(String types[], Class lobClass) throws Except while ((read = stream.read(chunk)) > 0) buffer.write(chunk, 0, read); assertEquals(chunk.length, size); - } } @@ -721,5 +719,4 @@ private static void dropTables(DBTable table) throws SQLException { stmt.executeUpdate("if object_id('" + table.getEscapedTableName() + "','U') is not null" + " drop table " + table.getEscapedTableName()); } - } From 07859324054844184d5534b6895001328bac6e3c Mon Sep 17 00:00:00 2001 From: rene-ye Date: Mon, 10 Sep 2018 10:07:15 -0700 Subject: [PATCH 09/25] length() for NClob --- .../java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 059db0eba..362338ded 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -69,8 +69,9 @@ public String getSubString(long pos, int length) throws SQLException { @Override public long length() throws SQLException { - //If streaming, every 2 bytes represents 1 character. If not, length() just returns string length - return (value == null && activeStreams.get(0) instanceof BaseInputStream) ? super.length() / 2 : super.length(); + // If streaming, every 2 bytes represents 1 character. If not, length() just returns string length + long length = super.length(); + return (value == null) ? length / 2 : length; } @Override From d2725028846deaee7563f01d7f29ab3e04d6c5ac Mon Sep 17 00:00:00 2001 From: rene-ye Date: Mon, 10 Sep 2018 14:39:40 -0700 Subject: [PATCH 10/25] reverting exposing private methods as protected methods --- src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 9a8d04a19..bdd59584f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -165,7 +165,7 @@ abstract class SQLServerClobBase extends SQLServerLob implements Serializable { * assumption that a Clob/NClob object is typically used either for input or output, and then only once. The array * size grows automatically if multiple streams are used. */ - protected ArrayList activeStreams = new ArrayList<>(1); + private ArrayList activeStreams = new ArrayList<>(1); transient SQLServerConnection con; @@ -261,7 +261,7 @@ public void free() throws SQLException { /** * Throws a SQLException if the LOB has been freed. */ - protected void checkClosed() throws SQLServerException { + private void checkClosed() throws SQLServerException { if (isClosed) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_isFreed")); SQLServerException.makeFromDriverError(con, null, form.format(new Object[] {getDisplayClassName()}), null, From 0cc0b909c6d4e3fff17ee4c42da94cd1b753338a Mon Sep 17 00:00:00 2001 From: rene-ye Date: Tue, 11 Sep 2018 17:09:46 -0700 Subject: [PATCH 11/25] update test --- .../sqlserver/jdbc/SQLServerClob.java | 4 +- .../sqlserver/jdbc/SQLServerNClob.java | 6 +- .../jdbc/unit/lobs/lobsStreamingTest.java | 303 +++++++++--------- 3 files changed, 152 insertions(+), 161 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index bdd59584f..f6621cc85 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -5,8 +5,6 @@ package com.microsoft.sqlserver.jdbc; -import static java.nio.charset.StandardCharsets.US_ASCII; - import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.Closeable; @@ -294,7 +292,7 @@ public InputStream getAsciiStream() throws SQLException { } } else { getStringFromStream(); - getterStream = new ByteArrayInputStream(value.getBytes(US_ASCII)); + getterStream = new ByteArrayInputStream(value.getBytes(java.nio.charset.StandardCharsets.US_ASCII)); } activeStreams.add(getterStream); return getterStream; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 362338ded..48ce0f306 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -5,8 +5,6 @@ package com.microsoft.sqlserver.jdbc; -import static java.nio.charset.StandardCharsets.UTF_16LE; - import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; @@ -34,12 +32,12 @@ public final class SQLServerNClob extends SQLServerClobBase implements NClob { SQLServerNClob(SQLServerConnection connection) { super(connection, "", connection.getDatabaseCollation(), logger, null); - this.setDefaultCharset(UTF_16LE); + this.setDefaultCharset(java.nio.charset.StandardCharsets.UTF_16LE); } SQLServerNClob(BaseInputStream stream, TypeInfo typeInfo) throws SQLServerException, UnsupportedEncodingException { super(null, stream, typeInfo.getSQLCollation(), logger, typeInfo); - this.setDefaultCharset(UTF_16LE); + this.setDefaultCharset(java.nio.charset.StandardCharsets.UTF_16LE); } @Override diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java index bbcde0ae3..050a86e63 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java @@ -18,9 +18,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; @@ -38,33 +36,15 @@ public class lobsStreamingTest extends AbstractTest { private static final int LOB_LENGTH_MIN = 4000; private static final int LOB_LENGTH_MAX = 8000; - static Connection conn = null; - static Statement stmt = null; static String tableName; static String escapedTableName; - @BeforeAll - public static void init() throws SQLException { - conn = DriverManager.getConnection(connectionString); - stmt = conn.createStatement(); - + @BeforeEach + public void init() throws SQLException { tableName = RandomUtil.getIdentifier("streamingTest"); escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); } - @AfterAll - public static void terminate() throws SQLException { - if (null != conn) - conn.close(); - if (null != stmt) - stmt.close(); - } - - @AfterEach - public void dropTable() throws SQLException, InterruptedException { - stmt.execute("DROP TABLE [" + tableName + "]"); - } - private String getRandomString(int length) { String validCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+,./;'[]<>?:{}|`~\"\\"; StringBuilder salt = new StringBuilder(); @@ -79,7 +59,9 @@ private String getRandomString(int length) { } private String getStringFromInputStream(InputStream is) { - try (java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A")) { + try (@SuppressWarnings("resource") + java.util.Scanner s = new java.util.Scanner(is, java.nio.charset.StandardCharsets.US_ASCII) + .useDelimiter("\\A")) { return s.hasNext() ? s.next() : ""; } } @@ -101,154 +83,167 @@ private String getStringFromReader(Reader r, long l) throws IOException { @Test @DisplayName("testClobsVarcharASCII") public void testClobsVarcharASCII() throws SQLException { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach( - i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - - PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string - } - rs.close(); - pstmt.close(); - - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming + // string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testNClobsNVarcharASCII") public void testNClobsVarcharASCII() throws SQLException { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach( - i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - - PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); - for (int i = 0; i < lobs.size(); i++) { - NClob c = conn.createNClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - NClob c = rs.getNClob(2); - assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string - } - rs.close(); - pstmt.close(); - - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + NClob c = conn.createNClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setNClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + NClob c = rs.getNClob(2); + assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming + // string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testClobsVarcharCHARA") public void testClobsVarcharCHARA() throws SQLException, IOException { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach( - i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - - PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string - } - rs.close(); - pstmt.close(); - - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), - lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + + } + } + stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testNClobsVarcharCHARA") public void testNClobsVarcharCHARA() throws SQLException, IOException { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach( - i -> lobs.add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - - PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)"); - for (int i = 0; i < lobs.size(); i++) { - NClob c = conn.createNClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - NClob c = rs.getNClob(2); - assertEquals(c.length(),lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string - } - rs.close(); - pstmt.close(); - - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), - lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + NClob c = conn.createNClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setNClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + NClob c = rs.getNClob(2); + assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + stmt.execute("DROP TABLE [" + tableName + "]"); } } } From 26df3df6c5dca31bd81ad683978488b283a7b9eb Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 14 Sep 2018 16:57:37 -0700 Subject: [PATCH 12/25] upped clob/nclob max length, added test for calling length() after retrieving stream but before consuming stream --- ...eamingTest.java => LobsStreamingTest.java} | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) rename src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/{lobsStreamingTest.java => LobsStreamingTest.java} (84%) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java similarity index 84% rename from src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java rename to src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index 050a86e63..40edbc8da 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -30,11 +30,11 @@ @RunWith(JUnitPlatform.class) -public class lobsStreamingTest extends AbstractTest { +public class LobsStreamingTest extends AbstractTest { private static final int LOB_ARRAY_SIZE = 250; // number of rows to insert into the table and compare - private static final int LOB_LENGTH_MIN = 4000; - private static final int LOB_LENGTH_MAX = 8000; + private static final int LOB_LENGTH_MIN = 8000; + private static final int LOB_LENGTH_MAX = 32000; static String tableName; static String escapedTableName; @@ -79,6 +79,39 @@ private String getStringFromReader(Reader r, long l) throws IOException { } return stringBuilder.toString(); } + + @Test + @DisplayName("testLengthAfterStream") + public void testLengthAfterStream() throws SQLException, IOException { + try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + Reader r = c.getCharacterStream(); + long clobLength = c.length(); + String recieved = getStringFromReader(r,clobLength);// streaming string + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + } + stmt.execute("DROP TABLE [" + tableName + "]"); + } + } @Test @DisplayName("testClobsVarcharASCII") From 4ffee2e5825850a5cfe52801d95b9a59246cd76f Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 10:24:28 -0700 Subject: [PATCH 13/25] changes addressing reviews --- .../sqlserver/jdbc/SQLServerClob.java | 18 +- .../sqlserver/jdbc/SQLServerNClob.java | 2 +- .../jdbc/unit/lobs/LobsStreamingTest.java | 339 ++++++++++-------- 3 files changed, 195 insertions(+), 164 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index f6621cc85..4aaf136d3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -281,20 +281,19 @@ public InputStream getAsciiStream() throws SQLException { DataTypes.throwConversionError(getDisplayClassName(), "AsciiStream"); // Need to use a BufferedInputStream since the stream returned by this method is assumed to support mark/reset - InputStream getterStream; + InputStream getterStream = null; if (null == value && !activeStreams.isEmpty()) { InputStream inputStream = (InputStream) activeStreams.get(0); try { inputStream.reset(); - getterStream = inputStream; } catch (IOException e) { - throw new SQLServerException(e.getMessage(), null, 0, e); + SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false); } + getterStream = inputStream; } else { - getStringFromStream(); getterStream = new ByteArrayInputStream(value.getBytes(java.nio.charset.StandardCharsets.US_ASCII)); + activeStreams.add(getterStream); } - activeStreams.add(getterStream); return getterStream; } @@ -314,12 +313,11 @@ public Reader getCharacterStream() throws SQLException { try { inputStream.reset(); } catch (IOException e) { - throw new SQLServerException(e.getMessage(), null, 0, e); + SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false); } Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset; getterStream = new BufferedReader(new InputStreamReader(inputStream, cs)); } else { - getStringFromStream(); getterStream = new StringReader(value); } activeStreams.add(getterStream); @@ -398,7 +396,7 @@ public String getSubString(long pos, int length) throws SQLException { */ public long length() throws SQLException { checkClosed(); - if (value == null && activeStreams.get(0) instanceof BaseInputStream) { + if (null == value && activeStreams.get(0) instanceof BaseInputStream) { return (long) ((BaseInputStream) activeStreams.get(0)).payloadLength; } return value.length(); @@ -426,10 +424,10 @@ private void getStringFromStream() throws SQLServerException { try { stream.reset(); } catch (IOException e) { - throw new SQLServerException(e.getMessage(), null, 0, e); + SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false); } Charset cs = (defaultCharset == null) ? typeInfo.getCharset() : defaultCharset; - value = new String((stream).getBytes(), cs); + value = new String(stream.getBytes(), cs); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 48ce0f306..9b5f64771 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -69,7 +69,7 @@ public String getSubString(long pos, int length) throws SQLException { public long length() throws SQLException { // If streaming, every 2 bytes represents 1 character. If not, length() just returns string length long length = super.length(); - return (value == null) ? length / 2 : length; + return (null == value) ? length / 2 : length; } @Override diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index 40edbc8da..975d24304 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.nio.charset.Charset; import java.sql.Clob; import java.sql.Connection; import java.sql.DriverManager; @@ -26,6 +27,7 @@ import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.Utils; import com.microsoft.sqlserver.testframework.util.RandomUtil; @@ -58,12 +60,9 @@ private String getRandomString(int length) { } - private String getStringFromInputStream(InputStream is) { - try (@SuppressWarnings("resource") - java.util.Scanner s = new java.util.Scanner(is, java.nio.charset.StandardCharsets.US_ASCII) - .useDelimiter("\\A")) { - return s.hasNext() ? s.next() : ""; - } + private String getStringFromInputStream(InputStream is, Charset c) { + java.util.Scanner s = new java.util.Scanner(is, c).useDelimiter("\\A"); + return s.hasNext() ? s.next() : ""; } private String getStringFromReader(Reader r, long l) throws IOException { @@ -83,200 +82,234 @@ private String getStringFromReader(Reader r, long l) throws IOException { @Test @DisplayName("testLengthAfterStream") public void testLengthAfterStream() throws SQLException, IOException { - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + try (Connection conn = DriverManager.getConnection(connectionString);) { + try (Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - Reader r = c.getCharacterStream(); - long clobLength = c.length(); - String recieved = getStringFromReader(r,clobLength);// streaming string - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + Reader r = c.getCharacterStream(); + long clobLength = c.length(); + String recieved = getStringFromReader(r, clobLength);// streaming string + assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + } + rs.close(); + } + } finally { + try (Statement stmt = conn.createStatement()) { + stmt.execute("DROP TABLE [" + tableName + "]"); } - rs.close(); } - stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testClobsVarcharASCII") public void testClobsVarcharASCII() throws SQLException { - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + try (Connection conn = DriverManager.getConnection(connectionString)) { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + Clob c = rs.getClob(2); + assertEquals(c.length(), lobs.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream(), + java.nio.charset.StandardCharsets.US_ASCII);// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream(), + java.nio.charset.StandardCharsets.US_ASCII);// non-streaming + // string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } } - rs.close(); - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming - // string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } finally { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); } } - stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testNClobsNVarcharASCII") - public void testNClobsVarcharASCII() throws SQLException { - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + public void testNClobsVarcharASCII() throws SQLException, IOException { + try (Connection conn = DriverManager.getConnection(connectionString)) { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - NClob c = conn.createNClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setNClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + NClob c = conn.createNClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setNClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - NClob c = rs.getNClob(2); - assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + NClob c = rs.getNClob(2); + assertEquals(c.length(), lobs.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream(), + java.nio.charset.StandardCharsets.UTF_16LE);// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream(), + java.nio.charset.StandardCharsets.US_ASCII);// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } } - rs.close(); - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming - // string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } finally { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); } } - stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testClobsVarcharCHARA") public void testClobsVarcharCHARA() throws SQLException, IOException { - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + try (Connection conn = DriverManager.getConnection(connectionString)) { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string - } - rs.close(); - - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), - lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + Clob c = rs.getClob(2); + assertEquals(c.length(), lobs.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } + } + } finally { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); } } - stmt.execute("DROP TABLE [" + tableName + "]"); } } @Test @DisplayName("testNClobsVarcharCHARA") public void testNClobsVarcharCHARA() throws SQLException, IOException { - try (Connection conn = DriverManager.getConnection(connectionString); Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + try (Connection conn = DriverManager.getConnection(connectionString)) { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); + stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); + ArrayList lobs = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs + .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - NClob c = conn.createNClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setNClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + NClob c = conn.createNClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setNClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - NClob c = rs.getNClob(2); - assertEquals(c.length(), lobs.get(rs.getInt(1)).length()); - lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string + ArrayList lobsFromServer = new ArrayList<>(); + ArrayList streamedStrings = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + NClob c = rs.getNClob(2); + assertEquals(c.length(), lobs.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + streamedStrings.add(recieved); + assertEquals(lobs.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lobs.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } } - rs.close(); - - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), - lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string + } finally { + try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); } } - stmt.execute("DROP TABLE [" + tableName + "]"); } } } From 557b4a1fc13edc8073840d08356966ce072887cf Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 10:31:44 -0700 Subject: [PATCH 14/25] returning bufferedinputstream instead of inputstream --- .../java/com/microsoft/sqlserver/jdbc/SQLServerClob.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java index 4aaf136d3..79df3191c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerClob.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.Closeable; @@ -289,11 +290,11 @@ public InputStream getAsciiStream() throws SQLException { } catch (IOException e) { SQLServerException.makeFromDriverError(con, null, e.getMessage(), null, false); } - getterStream = inputStream; + getterStream = new BufferedInputStream(inputStream); } else { getterStream = new ByteArrayInputStream(value.getBytes(java.nio.charset.StandardCharsets.US_ASCII)); - activeStreams.add(getterStream); } + activeStreams.add(getterStream); return getterStream; } From 9a0fd0caba62082ba01787451afaeb3c4a7c6f6c Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 11:00:16 -0700 Subject: [PATCH 15/25] formatting --- .../sqlserver/jdbc/unit/lobs/LobsStreamingTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index 975d24304..5c843829b 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -78,12 +78,13 @@ private String getStringFromReader(Reader r, long l) throws IOException { } return stringBuilder.toString(); } - + @Test @DisplayName("testLengthAfterStream") public void testLengthAfterStream() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString);) { try (Statement stmt = conn.createStatement()) { + Utils.dropTableIfExists(tableName, stmt); stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); ArrayList lobs = new ArrayList<>(); IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs @@ -107,11 +108,10 @@ public void testLengthAfterStream() throws SQLException, IOException { String recieved = getStringFromReader(r, clobLength);// streaming string assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string } - rs.close(); } } finally { try (Statement stmt = conn.createStatement()) { - stmt.execute("DROP TABLE [" + tableName + "]"); + Utils.dropTableIfExists(tableName, stmt); } } } @@ -154,8 +154,7 @@ public void testClobsVarcharASCII() throws SQLException { rs.close(); for (int i = 0; i < lobs.size(); i++) { String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream(), - java.nio.charset.StandardCharsets.US_ASCII);// non-streaming - // string + java.nio.charset.StandardCharsets.US_ASCII);// non-streaming string assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string } } @@ -254,7 +253,6 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), lobsFromServer.get(i).length());// non-streaming string assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string - } } } finally { From 1844970ed865c13f20299be089444ae5c54aadac Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 12:34:41 -0700 Subject: [PATCH 16/25] normalize nclob getAsciiStream behavior --- src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java | 3 +++ .../microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java index 9b5f64771..c3338278b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNClob.java @@ -47,6 +47,9 @@ public void free() throws SQLException { @Override public InputStream getAsciiStream() throws SQLException { + // NClobs are mapped to Nvarchar(max), and are always UTF-16 encoded. This API expects a US_ASCII stream. + // It's not possible to modify the stream without loading it into memory. Users should use getCharacterStream. + this.fillFromStream(); return super.getAsciiStream(); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index 5c843829b..cb3792f53 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -196,7 +196,7 @@ public void testNClobsVarcharASCII() throws SQLException, IOException { assertEquals(c.length(), lobs.get(index).length()); lobsFromServer.add(c); String recieved = getStringFromInputStream(c.getAsciiStream(), - java.nio.charset.StandardCharsets.UTF_16LE);// streaming string + java.nio.charset.StandardCharsets.US_ASCII);// streaming string streamedStrings.add(recieved); assertEquals(lobs.get(index), recieved);// compare streamed string to initial string } From e6132402393789c64406533b62049ad3ea14a35e Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 12:49:07 -0700 Subject: [PATCH 17/25] test fix --- .../java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java index 764310665..4d9b121e1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java @@ -422,7 +422,7 @@ private void testLobsInsertRetrive(String types[], Class lobClass) throws Except assertEquals(nclob.length(), size); stream = nclob.getAsciiStream(); chunk = stream.readAllBytes(); - assertEquals(chunk.length/2, size);//2 bytes per character when streaming + assertEquals(chunk.length, size); } else { blob = rs.getBlob(2); stream = blob.getBinaryStream(); From c692c6884553d36212f7458f3f8eeef2d0782713 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 12:54:15 -0700 Subject: [PATCH 18/25] use getCharacterStream for nclobs --- .../com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java index 4d9b121e1..ff6537880 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java @@ -420,9 +420,10 @@ private void testLobsInsertRetrive(String types[], Class lobClass) throws Except } else if (nClobType == classType(lobClass)) { nclob = rs.getNClob(2); assertEquals(nclob.length(), size); - stream = nclob.getAsciiStream(); - chunk = stream.readAllBytes(); - assertEquals(chunk.length, size); + Reader r = nclob.getCharacterStream(); + char[] c = new char[(int) nclob.length()]; + r.read(c); + assertEquals(c.length, size); } else { blob = rs.getBlob(2); stream = blob.getBinaryStream(); From c3fcc9d4e3d85d9dc3f35ec17bb953b4cc0adbe8 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Wed, 19 Sep 2018 15:34:07 -0700 Subject: [PATCH 19/25] removing redundant code --- .../jdbc/unit/lobs/LobsStreamingTest.java | 280 ++++++++---------- 1 file changed, 119 insertions(+), 161 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index cb3792f53..374a222e3 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -19,6 +19,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -34,21 +35,25 @@ @RunWith(JUnitPlatform.class) public class LobsStreamingTest extends AbstractTest { - private static final int LOB_ARRAY_SIZE = 250; // number of rows to insert into the table and compare + private static final int LOB_ARRAY_SIZE = 500; // number of rows to insert into the table and compare private static final int LOB_LENGTH_MIN = 8000; private static final int LOB_LENGTH_MAX = 32000; + private static final String ASCII_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+,./;'[]<>?:{}|`~\"\\"; + private static final String UNICODE_CHARACTERS = ASCII_CHARACTERS + + "Ǥ⚌c♮ƺåYèĢù⚏Ȓ★njäõpƸŃōoƝĤßuÙőƆE♹gLJÜŬȺDZ!Û☵ŦãǁĸNQŰǚǻTÖC]ǶýåÉbɉ☩=\\ȍáźŗǃĻýű☓☄¸T☑ö^k☏I:x☑⚀läiȉ☱☚⚅ǸǎãÂ"; + private static String tableName = null; - static String tableName; - static String escapedTableName; + private static enum LoB { + CLOB, + NCLOB + }; @BeforeEach public void init() throws SQLException { tableName = RandomUtil.getIdentifier("streamingTest"); - escapedTableName = AbstractSQLGenerator.escapeIdentifier(tableName); } - private String getRandomString(int length) { - String validCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-=_+,./;'[]<>?:{}|`~\"\\"; + private String getRandomString(int length, String validCharacters) { StringBuilder salt = new StringBuilder(); Random rnd = new Random(); while (salt.length() < length) { @@ -57,11 +62,12 @@ private String getRandomString(int length) { } String saltStr = salt.toString(); return saltStr; - } - private String getStringFromInputStream(InputStream is, Charset c) { - java.util.Scanner s = new java.util.Scanner(is, c).useDelimiter("\\A"); + // closing the scanner closes the Inputstream, and the driver needs the stream to fill LoBs + @SuppressWarnings("resource") + private String getStringFromInputStream(InputStream is) { + java.util.Scanner s = new java.util.Scanner(is, java.nio.charset.StandardCharsets.US_ASCII).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } @@ -79,35 +85,49 @@ private String getStringFromReader(Reader r, long l) throws IOException { return stringBuilder.toString(); } + private void createLobTable(Statement stmt, String table, LoB l) throws SQLException { + String columnType = (l == LoB.CLOB) ? "varchar(max)" : "nvarchar(max)"; + stmt.execute("CREATE TABLE [" + table + "] (id int, lobValue " + columnType + ")"); + } + + private ArrayList createRandomStringArray(LoB l) { + String characterPool = (l == LoB.CLOB) ? ASCII_CHARACTERS : UNICODE_CHARACTERS; + ArrayList string_array = new ArrayList<>(); + IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> string_array.add( + getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX), characterPool))); + return string_array; + } + + private void insertData(Connection conn, String table, ArrayList lobs) throws SQLException { + try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + table + "] VALUES(?,?)")) { + for (int i = 0; i < lobs.size(); i++) { + Clob c = conn.createClob(); + c.setString(1, lobs.get(i)); + pstmt.setInt(1, i); + pstmt.setClob(2, c); + pstmt.addBatch(); + } + pstmt.executeBatch(); + } + } + @Test @DisplayName("testLengthAfterStream") public void testLengthAfterStream() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString);) { try (Statement stmt = conn.createStatement()) { Utils.dropTableIfExists(tableName, stmt); - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + createLobTable(stmt, tableName, LoB.CLOB); + ArrayList lob_data = createRandomStringArray(LoB.CLOB); + insertData(conn, tableName, lob_data); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - Reader r = c.getCharacterStream(); - long clobLength = c.length(); - String recieved = getStringFromReader(r, clobLength);// streaming string - assertEquals(lobs.get(rs.getInt(1)), recieved);// compare streamed string to initial string - } + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + Clob c = rs.getClob(2); + Reader r = c.getCharacterStream(); + long clobLength = c.length(); + String recieved = getStringFromReader(r, clobLength);// streaming string + assertEquals(lob_data.get(rs.getInt(1)), recieved);// compare streamed string to initial string } } finally { try (Statement stmt = conn.createStatement()) { @@ -123,40 +143,25 @@ public void testClobsVarcharASCII() throws SQLException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { Utils.dropTableIfExists(tableName, stmt); - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + createLobTable(stmt, tableName, LoB.CLOB); + ArrayList lob_data = createRandomStringArray(LoB.CLOB); + insertData(conn, tableName, lob_data); - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - Clob c = rs.getClob(2); - assertEquals(c.length(), lobs.get(index).length()); - lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream(), - java.nio.charset.StandardCharsets.US_ASCII);// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(index), recieved);// compare streamed string to initial string - } - rs.close(); - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream(), - java.nio.charset.StandardCharsets.US_ASCII);// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string - } + ArrayList lobsFromServer = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + Clob c = rs.getClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string + assertEquals(lob_data.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lob_data.size(); i++) { + String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming + // string + assertEquals(recieved, lob_data.get(i));// compare static string to streamed string } } finally { try (Statement stmt = conn.createStatement()) { @@ -172,40 +177,21 @@ public void testNClobsVarcharASCII() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { Utils.dropTableIfExists(tableName, stmt); - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); - - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - NClob c = conn.createNClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setNClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); + createLobTable(stmt, tableName, LoB.NCLOB); + // Testing AsciiStream, use Clob string set or characters will be converted to '?' + ArrayList lob_data = createRandomStringArray(LoB.CLOB); + insertData(conn, tableName, lob_data); - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - NClob c = rs.getNClob(2); - assertEquals(c.length(), lobs.get(index).length()); - lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream(), - java.nio.charset.StandardCharsets.US_ASCII);// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(index), recieved);// compare streamed string to initial string - } - rs.close(); - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream(), - java.nio.charset.StandardCharsets.US_ASCII);// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string - } + ArrayList lobsFromServer = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + NClob c = rs.getNClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromInputStream(c.getAsciiStream());// NClob AsciiStream is never + // streamed + assertEquals(lob_data.get(index), recieved);// compare string to initial string } } finally { try (Statement stmt = conn.createStatement()) { @@ -221,39 +207,25 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { Utils.dropTableIfExists(tableName, stmt); - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue varchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + createLobTable(stmt, tableName, LoB.CLOB); + ArrayList lob_data = createRandomStringArray(LoB.CLOB); + insertData(conn, tableName, lob_data); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - Clob c = conn.createClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - Clob c = rs.getClob(2); - assertEquals(c.length(), lobs.get(index).length()); - lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(index), recieved);// compare streamed string to initial string - } - rs.close(); - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), - lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string - } + ArrayList lobsFromServer = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + Clob c = rs.getClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + assertEquals(lob_data.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lob_data.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, lob_data.get(i));// compare static string to streamed string } } finally { try (Statement stmt = conn.createStatement()) { @@ -269,39 +241,25 @@ public void testNClobsVarcharCHARA() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { Utils.dropTableIfExists(tableName, stmt); - stmt.execute("CREATE TABLE [" + tableName + "] (id int, lobValue nvarchar(max))"); - ArrayList lobs = new ArrayList<>(); - IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> lobs - .add(getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX)))); + createLobTable(stmt, tableName, LoB.NCLOB); + ArrayList lob_data = createRandomStringArray(LoB.NCLOB); + insertData(conn, tableName, lob_data); - try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO [" + tableName + "] VALUES(?,?)")) { - for (int i = 0; i < lobs.size(); i++) { - NClob c = conn.createNClob(); - c.setString(1, lobs.get(i)); - pstmt.setInt(1, i); - pstmt.setNClob(2, c); - pstmt.addBatch(); - } - pstmt.executeBatch(); - - ArrayList lobsFromServer = new ArrayList<>(); - ArrayList streamedStrings = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - NClob c = rs.getNClob(2); - assertEquals(c.length(), lobs.get(index).length()); - lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - streamedStrings.add(recieved); - assertEquals(lobs.get(index), recieved);// compare streamed string to initial string - } - rs.close(); - for (int i = 0; i < lobs.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), - lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, streamedStrings.get(i));// compare static string to streamed string - } + ArrayList lobsFromServer = new ArrayList<>(); + ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); + while (rs.next()) { + int index = rs.getInt(1); + NClob c = rs.getNClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + assertEquals(lob_data.get(index), recieved);// compare streamed string to initial string + } + rs.close(); + for (int i = 0; i < lob_data.size(); i++) { + String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + lobsFromServer.get(i).length());// non-streaming string + assertEquals(recieved, lob_data.get(i));// compare static string to streamed string } } finally { try (Statement stmt = conn.createStatement()) { From 7ebaa44ec19b59619fbbe878d5e726d00beed747 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 21 Sep 2018 09:22:06 -0700 Subject: [PATCH 20/25] removing unused imports --- .../microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index 374a222e3..8d50bc2ba 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; -import java.nio.charset.Charset; import java.sql.Clob; import java.sql.Connection; import java.sql.DriverManager; @@ -19,14 +18,12 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; import com.microsoft.sqlserver.testframework.Utils; import com.microsoft.sqlserver.testframework.util.RandomUtil; From df7e79b372c236e506cd6b82baa01f4065f61224 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 21 Sep 2018 13:10:28 -0700 Subject: [PATCH 21/25] changing enum name --- .../jdbc/unit/lobs/LobsStreamingTest.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index 9796c400f..b13246199 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -40,7 +40,7 @@ public class LobsStreamingTest extends AbstractTest { + "Ǥ⚌c♮ƺåYèĢù⚏Ȓ★njäõpƸŃōoƝĤßuÙőƆE♹gLJÜŬȺDZ!Û☵ŦãǁĸNQŰǚǻTÖC]ǶýåÉbɉ☩=\\ȍáźŗǃĻýű☓☄¸T☑ö^k☏I:x☑⚀läiȉ☱☚⚅ǸǎãÂ"; private static String tableName = null; - private static enum LoB { + private static enum Lob { CLOB, NCLOB }; @@ -82,13 +82,13 @@ private String getStringFromReader(Reader r, long l) throws IOException { return stringBuilder.toString(); } - private void createLobTable(Statement stmt, String table, LoB l) throws SQLException { - String columnType = (l == LoB.CLOB) ? "varchar(max)" : "nvarchar(max)"; + private void createLobTable(Statement stmt, String table, Lob l) throws SQLException { + String columnType = (l == Lob.CLOB) ? "varchar(max)" : "nvarchar(max)"; stmt.execute("CREATE TABLE [" + table + "] (id int, lobValue " + columnType + ")"); } - private ArrayList createRandomStringArray(LoB l) { - String characterPool = (l == LoB.CLOB) ? ASCII_CHARACTERS : UNICODE_CHARACTERS; + private ArrayList createRandomStringArray(Lob l) { + String characterPool = (l == Lob.CLOB) ? ASCII_CHARACTERS : UNICODE_CHARACTERS; ArrayList string_array = new ArrayList<>(); IntStream.range(0, LOB_ARRAY_SIZE).forEach(i -> string_array.add( getRandomString(ThreadLocalRandom.current().nextInt(LOB_LENGTH_MIN, LOB_LENGTH_MAX), characterPool))); @@ -114,8 +114,8 @@ public void testLengthAfterStream() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString);) { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); - createLobTable(stmt, tableName, LoB.CLOB); - ArrayList lob_data = createRandomStringArray(LoB.CLOB); + createLobTable(stmt, tableName, Lob.CLOB); + ArrayList lob_data = createRandomStringArray(Lob.CLOB); insertData(conn, tableName, lob_data); ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); @@ -140,8 +140,8 @@ public void testClobsVarcharASCII() throws SQLException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); - createLobTable(stmt, tableName, LoB.CLOB); - ArrayList lob_data = createRandomStringArray(LoB.CLOB); + createLobTable(stmt, tableName, Lob.CLOB); + ArrayList lob_data = createRandomStringArray(Lob.CLOB); insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); @@ -174,9 +174,9 @@ public void testNClobsVarcharASCII() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); - createLobTable(stmt, tableName, LoB.NCLOB); + createLobTable(stmt, tableName, Lob.NCLOB); // Testing AsciiStream, use Clob string set or characters will be converted to '?' - ArrayList lob_data = createRandomStringArray(LoB.CLOB); + ArrayList lob_data = createRandomStringArray(Lob.CLOB); insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); @@ -204,8 +204,8 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); - createLobTable(stmt, tableName, LoB.CLOB); - ArrayList lob_data = createRandomStringArray(LoB.CLOB); + createLobTable(stmt, tableName, Lob.CLOB); + ArrayList lob_data = createRandomStringArray(Lob.CLOB); insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); @@ -238,8 +238,8 @@ public void testNClobsVarcharCHARA() throws SQLException, IOException { try (Connection conn = DriverManager.getConnection(connectionString)) { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); - createLobTable(stmt, tableName, LoB.NCLOB); - ArrayList lob_data = createRandomStringArray(LoB.NCLOB); + createLobTable(stmt, tableName, Lob.NCLOB); + ArrayList lob_data = createRandomStringArray(Lob.NCLOB); insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); From 9ac2149b37b31860830117550184fae79bddd59c Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 21 Sep 2018 13:36:39 -0700 Subject: [PATCH 22/25] refractor while loop --- .../sqlserver/jdbc/unit/lobs/LobsStreamingTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index b13246199..db19fa4a2 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -72,11 +72,8 @@ private String getStringFromReader(Reader r, long l) throws IOException { // read the Reader contents into a buffer and return the complete string final StringBuilder stringBuilder = new StringBuilder((int) l); char[] buffer = new char[(int) l]; - while (true) { - int amountRead = r.read(buffer, 0, (int) l); - if (amountRead == -1) { - break; - } + int amountRead = -1; + while ((amountRead = r.read(buffer, 0, (int) l)) != -1) { stringBuilder.append(buffer, 0, amountRead); } return stringBuilder.toString(); From 8260ce9eccb80176b28f2b8a4a04739802644792 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 21 Sep 2018 13:38:35 -0700 Subject: [PATCH 23/25] corrected spelling of 'recieved' to 'received' --- .../jdbc/unit/lobs/LobsStreamingTest.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index db19fa4a2..e4e4db633 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -120,8 +120,8 @@ public void testLengthAfterStream() throws SQLException, IOException { Clob c = rs.getClob(2); Reader r = c.getCharacterStream(); long clobLength = c.length(); - String recieved = getStringFromReader(r, clobLength);// streaming string - assertEquals(lob_data.get(rs.getInt(1)), recieved);// compare streamed string to initial string + String received = getStringFromReader(r, clobLength);// streaming string + assertEquals(lob_data.get(rs.getInt(1)), received);// compare streamed string to initial string } } finally { try (Statement stmt = conn.createStatement()) { @@ -148,14 +148,14 @@ public void testClobsVarcharASCII() throws SQLException { Clob c = rs.getClob(2); assertEquals(c.length(), lob_data.get(index).length()); lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string - assertEquals(lob_data.get(index), recieved);// compare streamed string to initial string + String received = getStringFromInputStream(c.getAsciiStream());// streaming string + assertEquals(lob_data.get(index), received);// compare streamed string to initial string } rs.close(); for (int i = 0; i < lob_data.size(); i++) { - String recieved = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming + String received = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming // string - assertEquals(recieved, lob_data.get(i));// compare static string to streamed string + assertEquals(received, lob_data.get(i));// compare static string to streamed string } } finally { try (Statement stmt = conn.createStatement()) { @@ -183,9 +183,9 @@ public void testNClobsVarcharASCII() throws SQLException, IOException { NClob c = rs.getNClob(2); assertEquals(c.length(), lob_data.get(index).length()); lobsFromServer.add(c); - String recieved = getStringFromInputStream(c.getAsciiStream());// NClob AsciiStream is never + String received = getStringFromInputStream(c.getAsciiStream());// NClob AsciiStream is never // streamed - assertEquals(lob_data.get(index), recieved);// compare string to initial string + assertEquals(lob_data.get(index), received);// compare string to initial string } } finally { try (Statement stmt = conn.createStatement()) { @@ -212,14 +212,14 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { Clob c = rs.getClob(2); assertEquals(c.length(), lob_data.get(index).length()); lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - assertEquals(lob_data.get(index), recieved);// compare streamed string to initial string + String received = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + assertEquals(lob_data.get(index), received);// compare streamed string to initial string } rs.close(); for (int i = 0; i < lob_data.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + String received = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, lob_data.get(i));// compare static string to streamed string + assertEquals(received, lob_data.get(i));// compare static string to streamed string } } finally { try (Statement stmt = conn.createStatement()) { @@ -246,14 +246,14 @@ public void testNClobsVarcharCHARA() throws SQLException, IOException { NClob c = rs.getNClob(2); assertEquals(c.length(), lob_data.get(index).length()); lobsFromServer.add(c); - String recieved = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - assertEquals(lob_data.get(index), recieved);// compare streamed string to initial string + String received = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + assertEquals(lob_data.get(index), received);// compare streamed string to initial string } rs.close(); for (int i = 0; i < lob_data.size(); i++) { - String recieved = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), + String received = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), lobsFromServer.get(i).length());// non-streaming string - assertEquals(recieved, lob_data.get(i));// compare static string to streamed string + assertEquals(received, lob_data.get(i));// compare static string to streamed string } } finally { try (Statement stmt = conn.createStatement()) { From d3179aa487d34d0c69f61d7bd3b58daa6b476f5d Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 21 Sep 2018 14:34:22 -0700 Subject: [PATCH 24/25] place rs in try-catch --- .../jdbc/unit/lobs/LobsStreamingTest.java | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index e4e4db633..b22c6cb74 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -115,13 +115,14 @@ public void testLengthAfterStream() throws SQLException, IOException { ArrayList lob_data = createRandomStringArray(Lob.CLOB); insertData(conn, tableName, lob_data); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - Clob c = rs.getClob(2); - Reader r = c.getCharacterStream(); - long clobLength = c.length(); - String received = getStringFromReader(r, clobLength);// streaming string - assertEquals(lob_data.get(rs.getInt(1)), received);// compare streamed string to initial string + try (ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC")) { + while (rs.next()) { + Clob c = rs.getClob(2); + Reader r = c.getCharacterStream(); + long clobLength = c.length(); + String received = getStringFromReader(r, clobLength);// streaming string + assertEquals(lob_data.get(rs.getInt(1)), received);// compare streamed string to initial string + } } } finally { try (Statement stmt = conn.createStatement()) { @@ -142,16 +143,16 @@ public void testClobsVarcharASCII() throws SQLException { insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - Clob c = rs.getClob(2); - assertEquals(c.length(), lob_data.get(index).length()); - lobsFromServer.add(c); - String received = getStringFromInputStream(c.getAsciiStream());// streaming string - assertEquals(lob_data.get(index), received);// compare streamed string to initial string + try (ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC")) { + while (rs.next()) { + int index = rs.getInt(1); + Clob c = rs.getClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String received = getStringFromInputStream(c.getAsciiStream());// streaming string + assertEquals(lob_data.get(index), received);// compare streamed string to initial string + } } - rs.close(); for (int i = 0; i < lob_data.size(); i++) { String received = getStringFromInputStream(lobsFromServer.get(i).getAsciiStream());// non-streaming // string @@ -177,15 +178,16 @@ public void testNClobsVarcharASCII() throws SQLException, IOException { insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - NClob c = rs.getNClob(2); - assertEquals(c.length(), lob_data.get(index).length()); - lobsFromServer.add(c); - String received = getStringFromInputStream(c.getAsciiStream());// NClob AsciiStream is never - // streamed - assertEquals(lob_data.get(index), received);// compare string to initial string + try (ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC")) { + while (rs.next()) { + int index = rs.getInt(1); + NClob c = rs.getNClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String received = getStringFromInputStream(c.getAsciiStream());// NClob AsciiStream is never + // streamed + assertEquals(lob_data.get(index), received);// compare string to initial string + } } } finally { try (Statement stmt = conn.createStatement()) { @@ -206,16 +208,16 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - Clob c = rs.getClob(2); - assertEquals(c.length(), lob_data.get(index).length()); - lobsFromServer.add(c); - String received = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - assertEquals(lob_data.get(index), received);// compare streamed string to initial string + try (ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC")) { + while (rs.next()) { + int index = rs.getInt(1); + Clob c = rs.getClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String received = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + assertEquals(lob_data.get(index), received);// compare streamed string to initial string + } } - rs.close(); for (int i = 0; i < lob_data.size(); i++) { String received = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), lobsFromServer.get(i).length());// non-streaming string @@ -240,16 +242,16 @@ public void testNClobsVarcharCHARA() throws SQLException, IOException { insertData(conn, tableName, lob_data); ArrayList lobsFromServer = new ArrayList<>(); - ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC"); - while (rs.next()) { - int index = rs.getInt(1); - NClob c = rs.getNClob(2); - assertEquals(c.length(), lob_data.get(index).length()); - lobsFromServer.add(c); - String received = getStringFromReader(c.getCharacterStream(), c.length());// streaming string - assertEquals(lob_data.get(index), received);// compare streamed string to initial string + try (ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC")) { + while (rs.next()) { + int index = rs.getInt(1); + NClob c = rs.getNClob(2); + assertEquals(c.length(), lob_data.get(index).length()); + lobsFromServer.add(c); + String received = getStringFromReader(c.getCharacterStream(), c.length());// streaming string + assertEquals(lob_data.get(index), received);// compare streamed string to initial string + } } - rs.close(); for (int i = 0; i < lob_data.size(); i++) { String received = getStringFromReader(lobsFromServer.get(i).getCharacterStream(), lobsFromServer.get(i).length());// non-streaming string From 8746b951aa6d6e3c3ed435e9759cf57b57e95c4a Mon Sep 17 00:00:00 2001 From: rene-ye Date: Mon, 24 Sep 2018 13:07:05 -0700 Subject: [PATCH 25/25] free lobs when not needed --- .../sqlserver/jdbc/unit/lobs/LobsStreamingTest.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java index b22c6cb74..55e8e1576 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/LobsStreamingTest.java @@ -121,6 +121,7 @@ public void testLengthAfterStream() throws SQLException, IOException { Reader r = c.getCharacterStream(); long clobLength = c.length(); String received = getStringFromReader(r, clobLength);// streaming string + c.free(); assertEquals(lob_data.get(rs.getInt(1)), received);// compare streamed string to initial string } } @@ -158,6 +159,9 @@ public void testClobsVarcharASCII() throws SQLException { // string assertEquals(received, lob_data.get(i));// compare static string to streamed string } + for (Clob c : lobsFromServer) { + c.free(); + } } finally { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); @@ -177,15 +181,14 @@ public void testNClobsVarcharASCII() throws SQLException, IOException { ArrayList lob_data = createRandomStringArray(Lob.CLOB); insertData(conn, tableName, lob_data); - ArrayList lobsFromServer = new ArrayList<>(); try (ResultSet rs = stmt.executeQuery("SELECT * FROM [" + tableName + "] ORDER BY id ASC")) { while (rs.next()) { int index = rs.getInt(1); NClob c = rs.getNClob(2); assertEquals(c.length(), lob_data.get(index).length()); - lobsFromServer.add(c); String received = getStringFromInputStream(c.getAsciiStream());// NClob AsciiStream is never // streamed + c.free(); assertEquals(lob_data.get(index), received);// compare string to initial string } } @@ -223,6 +226,9 @@ public void testClobsVarcharCHARA() throws SQLException, IOException { lobsFromServer.get(i).length());// non-streaming string assertEquals(received, lob_data.get(i));// compare static string to streamed string } + for (Clob c : lobsFromServer) { + c.free(); + } } finally { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt); @@ -257,6 +263,9 @@ public void testNClobsVarcharCHARA() throws SQLException, IOException { lobsFromServer.get(i).length());// non-streaming string assertEquals(received, lob_data.get(i));// compare static string to streamed string } + for (Clob c : lobsFromServer) { + c.free(); + } } finally { try (Statement stmt = conn.createStatement()) { TestUtils.dropTableIfExists(tableName, stmt);