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

Blob fix #595

Merged
merged 27 commits into from
Mar 6, 2018
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4758485
Blob fix
rene-ye Jan 3, 2018
5f96797
changed function accessability
rene-ye Jan 4, 2018
83da731
Length fix
rene-ye Jan 26, 2018
c8cc20b
Merge pull request #11 from Microsoft/dev
rene-ye Jan 30, 2018
923c220
Kerberos DC
rene-ye Feb 8, 2018
25301e6
Added information to error message
rene-ye Feb 5, 2018
506e070
Merge pull request #14 from rene-ye/KerbConsDel
rene-ye Feb 8, 2018
4a0e69d
Merge pull request #15 from rene-ye/UnexpectedErrMsg
rene-ye Feb 8, 2018
7a640c2
Merge pull request #16 from v-afrafi/retryLogic
rene-ye Feb 9, 2018
748aed7
Merge pull request #17 from Microsoft/dev
rene-ye Feb 19, 2018
45c65f5
Merge pull request #18 from rene-ye/blobStream
rene-ye Feb 19, 2018
f421d4c
Merge pull request #19 from Microsoft/dev
rene-ye Feb 19, 2018
91bf4d3
minor stream verification
rene-ye Feb 22, 2018
3ba5f1b
Reimplemented Blob fixes
rene-ye Feb 22, 2018
9a1300e
Additional tests
rene-ye Feb 22, 2018
19e8339
merge conflict #1
rene-ye Feb 22, 2018
bc074f2
Merge branch 'allChangesForTesting' into blobStream
rene-ye Feb 22, 2018
09fe7e4
Revert "Merge branch 'allChangesForTesting' into blobStream"
rene-ye Feb 22, 2018
b071f23
comment edit
rene-ye Feb 22, 2018
4d91bc9
slight adjustments to implementation
rene-ye Feb 23, 2018
48b9b85
SimpleInputStream fix
rene-ye Feb 23, 2018
ca0e6c0
Added a free() test
rene-ye Feb 28, 2018
345cfa4
Merge pull request #25 from Microsoft/dev
rene-ye Mar 1, 2018
7169a3c
Merge branch 'dev' into blobStream
rene-ye Mar 5, 2018
625a721
code style changes
rene-ye Mar 6, 2018
2512abf
remove indent
rene-ye Mar 6, 2018
152e71b
Merge branch 'dev' into blobStream
rene-ye Mar 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerBlob.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,23 @@ public byte[] getBytes(long pos,
*/
public long length() throws SQLException {
checkClosed();
if (value == null && activeStreams.get(0) instanceof PLPInputStream) {
return (long)((PLPInputStream)activeStreams.get(0)).payloadLength;
}
getBytesFromStream();
return value.length;
}

/**
* Function for the result set to maintain blobs it has created
* @throws SQLException
*/
void fillByteArray() throws SQLException {
if(!isClosed) {
getBytesFromStream();
}
}

/**
* Converts stream to byte[]
* @throws SQLServerException
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ final void setCurrentRowType(RowType rowType) {
* occurs
*/
private Closeable activeStream;
private Blob activeBlob;

/**
* A window of fetchSize quickly accessible rows for scrollable result sets
Expand Down Expand Up @@ -669,6 +670,7 @@ final Column getColumn(int columnIndex) throws SQLServerException {
// before moving to another one.
if (null != activeStream) {
try {
fillBlobs();
activeStream.close();
}
catch (IOException e) {
Expand Down Expand Up @@ -747,6 +749,7 @@ private Column loadColumn(int index) throws SQLServerException {
/* ----------------- JDBC API methods ------------------ */

private void moverInit() throws SQLServerException {
fillBlobs();
cancelInsert();
cancelUpdates();
}
Expand Down Expand Up @@ -1035,6 +1038,7 @@ public boolean next() throws SQLServerException {
public boolean wasNull() throws SQLServerException {
loggerExternal.entering(getClassNameLogging(), "wasNull");
checkClosed();
fillBlobs();
loggerExternal.exiting(getClassNameLogging(), "wasNull", lastValueWasNull);
return lastValueWasNull;
}
Expand Down Expand Up @@ -1892,6 +1896,7 @@ Column getterGetColumn(int index) throws SQLServerException {
if (logger.isLoggable(java.util.logging.Level.FINER))
logger.finer(toString() + " Getting Column:" + index);

fillBlobs();
return loadColumn(index);
}

Expand Down Expand Up @@ -2657,6 +2662,7 @@ public Blob getBlob(int i) throws SQLServerException {
checkClosed();
Blob value = (Blob) getValue(i, JDBCType.BLOB);
loggerExternal.exiting(getClassNameLogging(), "getBlob", value);
activeBlob = value;
return value;
}

Expand All @@ -2665,6 +2671,7 @@ public Blob getBlob(String colName) throws SQLServerException {
checkClosed();
Blob value = (Blob) getValue(findColumn(colName), JDBCType.BLOB);
loggerExternal.exiting(getClassNameLogging(), "getBlob", value);
activeBlob = value;
return value;
}

Expand Down Expand Up @@ -6507,6 +6514,24 @@ final void doServerFetch(int fetchType,
scrollWindow.reset();
}
}

/*
* Iterates through the list of objects which rely on the stream that's about to be closed, filling them with their data
* Will skip over closed blobs, implemented in SQLServerBlob
*/
private void fillBlobs() {
if (null != activeBlob && activeBlob instanceof SQLServerBlob) {
try {
((SQLServerBlob)activeBlob).fillByteArray();
} catch (SQLException e) {
if (logger.isLoggable(java.util.logging.Level.FINER)) {
logger.finer(toString() + "Filling blobs before closing: " + e.getMessage());
}
} finally {
activeBlob = null;
}
}
}

/**
* Discards the contents of the current fetch buffer.
Expand All @@ -6519,6 +6544,9 @@ final void doServerFetch(int fetchType,
* fetch buffer is considered to be discarded.
*/
private void discardFetchBuffer() {
//fills blobs before discarding anything
fillBlobs();

// Clear the TDSReader mark at the start of the fetch buffer
fetchBuffer.clearStartMark();

Expand Down
139 changes: 139 additions & 0 deletions src/test/java/com/microsoft/sqlserver/jdbc/unit/lobs/lobsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,59 @@ else if (lobClass == Blob.class)
}
}

@Test
@DisplayName("testFreedBlobs")
private void testFreedBlobs(Class lobClass,
boolean isResultSet) throws SQLException {
String types[] = {"varbinary(max)"};
try {
table = createTable(table, types, false); // create empty table
int size = 10000;

byte[] data = new byte[size];
ThreadLocalRandom.current().nextBytes(data);

Blob blob = null;
InputStream stream = null;
for (int i = 0; i < 5; i++)
{
PreparedStatement ps = conn.prepareStatement("INSERT INTO " + table.getEscapedTableName() + " VALUES(?)");
blob = conn.createBlob();
blob.setBytes(1, data);
ps.setBlob(1, blob);
ps.executeUpdate();
}

byte[] chunk = new byte[size];
ResultSet rs = stmt.executeQuery("select * from " + table.getEscapedTableName());
for (int i = 0; i < 5; i++)
{
rs.next();

blob = rs.getBlob(1);
stream = blob.getBinaryStream();
while (stream.available() > 0)
stream.read();
blob.free();
try {
stream = blob.getBinaryStream();
} catch (SQLException e) {
assertTrue(e.getMessage().contains("This Blob object has been freed."));
}
}
rs.close();
try {
stream = blob.getBinaryStream();
} catch (SQLException e) {
assertTrue(e.getMessage().contains("This Blob object has been freed."));
}
}
catch (Exception e) {
this.dropTables(table);
e.printStackTrace();
}
}

@Test
@DisplayName("testMultipleCloseCharacterStream")
public void testMultipleCloseCharacterStream() throws Exception {
Expand Down Expand Up @@ -413,6 +466,92 @@ public void testUpdatorClob() throws Exception {
String types[] = {"varchar(max)"};
testUpdateLobs(types, Clob.class);
}

@Test
@DisplayName("readBlobStreamAfterClosingRS")
public void readBlobStreamAfterClosingRS() throws Exception {
String types[] = {"varbinary(max)"};
table = createTable(table, types, false); // create empty table
int size = 10000;

byte[] data = new byte[size];
ThreadLocalRandom.current().nextBytes(data);

Blob blob = null;
InputStream stream = null;
PreparedStatement ps = conn.prepareStatement("INSERT INTO " + table.getEscapedTableName() + " VALUES(?)");
blob = conn.createBlob();
blob.setBytes(1, data);
ps.setBlob(1, blob);
ps.executeUpdate();

byte[] chunk = new byte[size];
ResultSet rs = stmt.executeQuery("select * from " + table.getEscapedTableName());
rs.next();

blob = rs.getBlob(1);
stream = blob.getBinaryStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read = 0;
while ((read = stream.read(chunk)) > 0)
buffer.write(chunk, 0, read);
assertEquals(chunk.length, size);
rs.close();
stream = blob.getBinaryStream();
buffer = new ByteArrayOutputStream();
read = 0;
while ((read = stream.read(chunk)) > 0)
buffer.write(chunk, 0, read);
assertEquals(chunk.length, size);

if (null != blob)
blob.free();
dropTables(table);
}

@Test
@DisplayName("readMultipleBlobStreamsThenCloseRS")
public void readMultipleBlobStreamsThenCloseRS() throws Exception {
String types[] = {"varbinary(max)"};
table = createTable(table, types, false);
int size = 10000;

byte[] data = new byte[size];
Blob[] blobs = {null, null, null, null, null};
InputStream stream = null;
for (int i = 0; i < 5; i++)//create 5 blobs
{
PreparedStatement ps = conn.prepareStatement("INSERT INTO " + table.getEscapedTableName() + " VALUES(?)");
blobs[i] = conn.createBlob();
ThreadLocalRandom.current().nextBytes(data);
blobs[i].setBytes(1, data);
ps.setBlob(1, blobs[i]);
ps.executeUpdate();
}
byte[] chunk = new byte[size];
ResultSet rs = stmt.executeQuery("select * from " + table.getEscapedTableName());
for (int i = 0; i < 5; i++)
{
rs.next();
blobs[i] = rs.getBlob(1);
stream = blobs[i].getBinaryStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read = 0;
while ((read = stream.read(chunk)) > 0)
buffer.write(chunk, 0, read);
assertEquals(chunk.length, size);
}
rs.close();
for (int i = 0; i < 5; i++)
{
stream = blobs[i].getBinaryStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read = 0;
while ((read = stream.read(chunk)) > 0)
buffer.write(chunk, 0, read);
assertEquals(chunk.length, size);
}
}

private void testUpdateLobs(String types[],
Class lobClass) throws Exception {
Expand Down