Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[CONJ-434] ResultSet.next position error when streaming and ScrollTyp…
…e != ResultSet.TYPE_FORWARD_ONLY

ResultSet.isAfterLast() may return wrong result when streaming and ScrollType != ResultSet.TYPE_FORWARD_ONLY
  • Loading branch information
rusher committed Feb 21, 2017
1 parent 6ec5a29 commit 0138932
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 5 deletions.
Expand Up @@ -574,8 +574,17 @@ public boolean next() throws SQLException {
} finally {
lock.unlock();
}
rowPointer = 0;
return resultSetSize > 0;

if (resultSetScrollType == TYPE_FORWARD_ONLY) {
//resultSet has been cleared. next value is pointer 0.
rowPointer = 0;
return resultSetSize > 0;
} else {
// cursor can move backward, so driver must keep the results.
// results have been added to current resultSet
rowPointer++;
return resultSetSize > rowPointer;
}
}

//all data are reads and pointer is after last
Expand Down Expand Up @@ -649,7 +658,8 @@ public boolean isAfterLast() throws SQLException {
ReentrantLock lock = protocol.getLock();
lock.lock();
try {
nextStreamingValue();
//this time, fetch is added even for forward type to keep current pointer row.
addStreamingValue();
} catch (IOException ioe) {
throw new SQLException("Server has closed the connection. If result set contain huge amount of data, Server expects client to"
+ " read off the result set relatively fast. "
Expand All @@ -660,8 +670,8 @@ public boolean isAfterLast() throws SQLException {
} finally {
lock.unlock();
}
rowPointer = 0;
return resultSetSize == 0;

return resultSetSize == rowPointer;
}

//has read all data and pointer is after last result
Expand Down
110 changes: 110 additions & 0 deletions src/test/java/org/mariadb/jdbc/ResultSetTest.java
Expand Up @@ -420,4 +420,114 @@ private void checkLastResultSet(Statement statement) throws SQLException {
}

}

@Test
public void testStreamInsensitive() throws Exception {
createTable("testStreamInsensitive", "s1 varchar(20)");

for (int r = 0; r < 20; r++) {
sharedConnection.createStatement().executeUpdate("insert into testStreamInsensitive values('V" + r + "')");
}
Statement stmt = sharedConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(10);

//reading forward
ResultSet rs = stmt.executeQuery("select * from testStreamInsensitive");
for (int i = 0; i < 20; i++) {
assertTrue(rs.next());
assertEquals("V" + i, rs.getString(1));
}
assertFalse(rs.next());

rs = stmt.executeQuery("select * from testStreamInsensitive");
for (int i = 0; i < 20; i++) {
assertFalse(rs.isAfterLast());
assertTrue(rs.next());
assertEquals("V" + i, rs.getString(1));
assertFalse(rs.isAfterLast());
}
assertFalse(rs.isAfterLast());
assertFalse(rs.next());
assertTrue(rs.isAfterLast());

rs = stmt.executeQuery("select * from testStreamInsensitive");
assertTrue(rs.absolute(20));
assertEquals("V19", rs.getString(1));
assertFalse(rs.isAfterLast());
assertFalse(rs.absolute(21));
assertTrue(rs.isAfterLast());

//reading backward
rs = stmt.executeQuery("select * from testStreamInsensitive");
rs.afterLast();
for (int i = 19; i >= 0; i--) {
assertTrue(rs.previous());
assertEquals("V" + i, rs.getString(1));
}
assertFalse(rs.previous());

rs = stmt.executeQuery("select * from testStreamInsensitive");
rs.last();
assertEquals("V19", rs.getString(1));

rs.first();
assertEquals("V0", rs.getString(1));

}

@Test
public void testStreamForward() throws Exception {
createTable("testStreamForward", "s1 varchar(20)");

for (int r = 0; r < 20; r++) {
sharedConnection.createStatement().executeUpdate("insert into testStreamForward values('V" + r + "')");
}
Statement stmt = sharedConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(10);

//reading forward
ResultSet rs = stmt.executeQuery("select * from testStreamForward");
for (int i = 0; i < 20; i++) {
assertTrue(rs.next());
assertEquals("V" + i, rs.getString(1));
}
assertFalse(rs.next());

//checking isAfterLast that may need to fetch next result
rs = stmt.executeQuery("select * from testStreamForward");
for (int i = 0; i < 20; i++) {
assertFalse(rs.isAfterLast());
assertTrue(rs.next());
assertEquals("V" + i, rs.getString(1));
assertFalse(rs.isAfterLast());
}
assertFalse(rs.isAfterLast());
assertFalse(rs.next());
assertTrue(rs.isAfterLast());

//reading backward
rs = stmt.executeQuery("select * from testStreamForward");
rs.afterLast();
try {
rs.previous();
fail("Must have thrown exception since previous is not possible when fetching");
} catch (SQLException sqle) {
assertTrue(sqle.getMessage().contains("Invalid operation for result set type TYPE_FORWARD_ONLY"));
}

rs = stmt.executeQuery("select * from testStreamForward");
rs.last();
assertEquals("V19", rs.getString(1));

try {
rs.first();
fail("Must have thrown exception since previous is not possible when fetching");
} catch (SQLException sqle) {
assertTrue(sqle.getMessage().contains("Invalid operation for result set type TYPE_FORWARD_ONLY"));
}

}

}

0 comments on commit 0138932

Please sign in to comment.