Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed a bug where calling length() after obtaining a stream would close the stream for Clobs/NClobs #799

Merged
merged 27 commits into from
Sep 25, 2018

Conversation

rene-ye
Copy link
Member

@rene-ye rene-ye commented Sep 5, 2018

Addresses #788. Also addressed an issue where varchar(max)/Clob objects were always being encoded to UTF-16LE instead of using the Collation specified in the Clob object.

List of Changes (the following applies to NClob as well):

  1. calling Clob.length() no longer attempts to load the stream into a string. This fixes a null pointer issue as well as length() closing user streams.
  2. added streaming capabilities for Clob.getAsciiStream(). NClobs will always have a non-streaming implementation for getAsciiStream().
  3. Clobs no longer default to UTF-16LE. Clobs now respect the collation from the SQL Server. NClobs remain unchanged, will always be UTF-16LE encoding.

@codecov-io
Copy link

codecov-io commented Sep 5, 2018

Codecov Report

Merging #799 into dev will increase coverage by 0.07%.
The diff coverage is 76.66%.

Impacted file tree graph

@@             Coverage Diff              @@
##                dev     #799      +/-   ##
============================================
+ Coverage     48.53%   48.61%   +0.07%     
- Complexity     2806     2809       +3     
============================================
  Files           116      116              
  Lines         27862    27882      +20     
  Branches       4641     4645       +4     
============================================
+ Hits          13523    13554      +31     
+ Misses        12197    12195       -2     
+ Partials       2142     2133       -9
Flag Coverage Δ Complexity Δ
#JDBC42 48.08% <76.66%> (+0.43%) 2766 <3> (+30) ⬆️
#JDBC43 48.24% <76.66%> (-0.19%) 2781 <3> (-20)
Impacted Files Coverage Δ Complexity Δ
...om/microsoft/sqlserver/jdbc/SimpleInputStream.java 52.94% <ø> (ø) 11 <0> (ø) ⬇️
...a/com/microsoft/sqlserver/jdbc/PLPInputStream.java 58.33% <ø> (+5.35%) 33 <0> (+4) ⬆️
...a/com/microsoft/sqlserver/jdbc/SQLServerNClob.java 74.07% <100%> (+4.5%) 13 <3> (+1) ⬆️
...va/com/microsoft/sqlserver/jdbc/SQLServerClob.java 35.58% <72%> (+3.3%) 12 <0> (ø) ⬇️
...om/microsoft/sqlserver/jdbc/ReaderInputStream.java 43.95% <0%> (-4.4%) 15% <0%> (-1%)
...m/microsoft/sqlserver/jdbc/SQLServerException.java 77.27% <0%> (-1.52%) 32% <0%> (-1%)
...rc/main/java/com/microsoft/sqlserver/jdbc/DDC.java 44.63% <0%> (-1.1%) 106% <0%> (-1%)
...n/java/com/microsoft/sqlserver/jdbc/Parameter.java 63.52% <0%> (-0.21%) 64% <0%> (ø)
...rc/main/java/com/microsoft/sqlserver/jdbc/dtv.java 62.25% <0%> (-0.12%) 0% <0%> (ø)
...m/microsoft/sqlserver/jdbc/SQLServerResultSet.java 32.69% <0%> (-0.08%) 255% <0%> (-1%)
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 550d441...8746b95. Read the comment docs.

@cheenamalhotra cheenamalhotra added this to the 7.1.1 milestone Sep 17, 2018
try {
inputStream.reset();
} catch (IOException e) {
throw new SQLServerException(e.getMessage(), null, 0, e);
Copy link
Member

@cheenamalhotra cheenamalhotra Sep 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use "SQLServerException.makeFromDriverError" instead. Also applies to other locations in the changes made.

NClob c = rs.getNClob(2);
assertEquals(c.length(), lobs.get(rs.getInt(1)).length());
lobsFromServer.add(c);
String recieved = getStringFromInputStream(c.getAsciiStream());// streaming string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move Resultsets and Streams to try-with-resources. Avoid hidden streams calls.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resultsets are automatically closed when statement is closed, and statement is in try-with-resources. Inputstreams are closed when resultset is closed, and I manually call resultset.close() in order to load stream into memory.

InputStream inputStream = (InputStream) activeStreams.get(0);
try {
inputStream.reset();
getterStream = inputStream;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we close 'inputStream' here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same input stream that the user gets, if we close it, the stream returned to the user gets closed.

}
rs.close();
}
stmt.execute("DROP TABLE [" + tableName + "]");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop table in finally block to avoid table leftovers in case exception occurs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stmt was created in try-catch, cannot access in finally block.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. There is already dropTableIfExists() in Utils.java, consider using it.
  2. Move the drop table into a finally block. You can either create a new Statement for it or just use regular try-catch blocks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or a cleaner solution would be to modify dropTableIfExists() to create and close its own Statement.


if (value == null && activeStreams.get(0) instanceof PLPInputStream) {
return (long) ((PLPInputStream) activeStreams.get(0)).payloadLength / 2;
if (value == null && activeStreams.get(0) instanceof BaseInputStream) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null == value

assertEquals(lobs.get(index), recieved);// compare streamed string to initial string
}
rs.close();
for (int i = 0; i < lobs.size(); i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is unnecessary now.

assertEquals(c.length(), lobs.get(index).length());
lobsFromServer.add(c);
String recieved = getStringFromInputStream(c.getAsciiStream(),
java.nio.charset.StandardCharsets.US_ASCII);// streaming string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the comment (with explanation), we are not streaming anymore.

+ "Ǥ⚌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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seem to be odd camel casing B here??

while (true) {
int amountRead = r.read(buffer, 0, (int) l);
if (amountRead == -1) {
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm better if we do while ((amountRead = r.read(buffer, 0, (int) l)) != null)? then we don't have to break out of a while which makes me cringe a little when I see it... ha not big deal ;)

Clob c = rs.getClob(2);
Reader r = c.getCharacterStream();
long clobLength = c.length();
String recieved = getStringFromReader(r, clobLength);// streaming string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

received - "i before e except after c" ;)

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

received

lilgreenbird
lilgreenbird previously approved these changes Sep 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants