This is a variant of the ticket
CONJ-119 ResultSet cursor query methods does not behave as specified by the Java JDBC API
There are two ways to fetch a ResultSet with rows of data: streaming or cached. In MariaDB it is implemented in the classes StreamingSelectResult and CachedSelectResult respectively. Mysql has the similar feature in the classes RowDataDynamic and RowDataStatic respectively.
The current way for an application program to select the type of ResultSet is to use
That may be a bit strange since the Java API more talks about setting
But this ticket is not about that. This ticket is how well the is-methods work for a StreamingSelectResult. I’m mostly interested in isBeforeFirst(), but there are other methods as well (see
CONJ-119 for details about the others).
How to reproduce:
- Download the attached JUnit test class ResultSetStreamingCursorTest.java
- Run test cases using the MariaDB JDBC connector
- Run test cases uing Mysql JDBC connector: modify the file in getConnection() to use Mysql JDBC instead of MariaDB. For this to work you need to add Mysql JDBC as a dependency in the pom.xml and also make an adaption of the MariaDB JDBC code so it does not consumes the “jdbc:mysql” URL. See the comment in my code for details.
- Run the test cases using H2 JDBC connector: modify the file in getConnection() to use H2 JDBC. For this to work you need to add H2 as a dependency in pom.xml and also remove the row that sets statement.setFetchSize(Integer.MIN_VALUE);. H2 is used as an in-memory database and does not need a standalone server
- With MariaDB JDBC: all test cases fail because resultSet.isBeforeFirst() always returns true. I have written a comment in each test case showing where MariaDB JDBC will fail.
- With Mysql JDBC: isBeforeFirstTest() will pass and isBefore_First_ZeroRowsTest() will fail.
- With H2 JDBC: all test cases will pass. However I don’t think there is any options to select a streaming ResultSet in H2.
Actual but not using a streamed ResultSet:
If the code is modified and statement.setFetchSize(Integer.MIN_VALUE); is removed:
- With MariaDB JDBC: all test cases will pass.
- With Mysql JDBC: all test cases will pass.
The Java API documentation for isBeforeFirst() states:
Note:Support for the isBeforeFirst method is optional for ResultSets with a result set type of TYPE_FORWARD_ONLY
Am I’m using TYPE_FORWARD_ONLY? Yes and No! I have not explicitly chosen it in my code. But I’m using it since both MariaDB and Mysql uses the statement.setFetchSize(Integer.MIN_VALUE) and implicitly choose a forward only type for a streaming ResultSet. So I think it is a bit ambiguous about what the expected result of my test case should be.
MariaDB and Mysql behaves differently: Mysql produces the correct value when there are rows in the ResultSet. But MariaDB failes in the same scenario. It could be argued that MariaDB should behave as good a Mysql? Or perhaps even better?
How to implement the bug fix/enhancement request:
If the goal is to make only my test case isBeforeFirstTest() pass it would be easy just to flip the StreamingSelectResult.beforeFirst variable to false after the first call to next(). (And perhaps also fix the indentation in the next() method, because it is not correct).
If the goal is to implement StreamingSelectResult with full support for all is-methods it might take a bit more effort.