Search code examples
jdbcfirebirdjaybird

Jaybird (Firebird JDBC) absolute() method


The absolute(int row) Java Doc says:

Moves the cursor to the given row number in this ResultSet object. If the row number is positive, the cursor moves to the given row number with respect to the beginning of the result set. The first row is row 1, the second is row 2, and so on.

If the given row number is negative, the cursor moves to an absolute row position with respect to the end of the result set. For example, calling the method absolute(-1) positions the cursor on the last row; calling the method absolute(-2) moves the cursor to the next-to-last row, and so on.

If the row number specified is zero, the cursor is moved to before the first row.

An attempt to position the cursor beyond the first/last row in the result set leaves the cursor before the first row or after the last row.

Note: Calling absolute(1) is the same as calling first(). Calling absolute(-1) is the same as calling last().

When passing 0 to absolute(int row) method should behave as beforeFirst() positioning the cursor just before the first row.

But using Jaybird I've got this Exception:

Exception in thread "main" org.firebirdsql.jdbc.FBSQLException: You cannot position to the row 0 with absolute() method.
    at org.firebirdsql.jdbc.FBCachedFetcher.absolute(FBCachedFetcher.java:243)
    at org.firebirdsql.jdbc.FBCachedFetcher.absolute(FBCachedFetcher.java:232)
    at org.firebirdsql.jdbc.AbstractResultSet.absolute(AbstractResultSet.java:1371)
    at chapterA.ResultSets.main(ResultSets.java:180)

Searching on Jaybird source (FBCachedFetcher.java) I found that when row parameter is 0, it throws a Exception:

private boolean absolute(int row, boolean internal) throws SQLException {
        checkScrollable();

        if (row < 0) {
            row = rows.size() + row + 1;
        }

        if (row == 0 && !internal) {
            throw new SQLException("You cannot position to row 0 with absolute() method.");
        }

Is there any reason for behaving like that?

Thanks in advance!


Solution

  • Given the Javadoc, this is a bug in Jaybird. I have created JDBC-453 to fix this in Jaybird 2.2.12 (and 3.0.0). I've done some archaeology to find out why this was implemented this way.

    Historically calling absolute(0) was not allowed in JDBC 2 / Java 1.3 (and earlier). The javadoc of ResultSet.absolute in Java 1.3.1 says (emphasis mine):

    Moves the cursor to the given row number in this ResultSet object.

    If the row number is positive, the cursor moves to the given row number with respect to the beginning of the result set. The first row is row 1, the second is row 2, and so on.

    If the given row number is negative, the cursor moves to an absolute row position with respect to the end of the result set. For example, calling the method absolute(-1) positions the cursor on the last row; calling the method absolute(-2) moves the cursor to the next-to-last row, and so on.

    An attempt to position the cursor beyond the first/last row in the result set leaves the cursor before the first row or after the last row.

    Note: Calling absolute(1) is the same as calling first(). Calling absolute(-1) is the same as calling last().

    Returns:
      true if the cursor is on the result set; false otherwise
    Throws:
      SQLException - if a database access error occurs, the row is 0, or the result set type is TYPE_FORWARD_ONLY

    In other words using 0 as the parameter value was not allowed. In that same entry however, the sentence "An attempt to position the cursor beyond the first/last row in the result set leaves the cursor before the first row or after the last row." suggests that it should have been allowed.

    For JDBC 3 / Java 1.4.2 (and Java 5) this was changed to:

    Throws: SQLException - if a database access error occurs, or the result set type is TYPE_FORWARD_ONLY

    The sentence you highlighted ("If the row number specified is zero, the cursor is moved to before the first row.") was only added in JDBC 4.1 (Java 7) for further clarification.

    However looking at the revision history of FBCachedFetcher, this restriction was added in July 2004 when Java 1.4.2 had been available for some time already (and Java 5 was almost ready). I hadn't yet joined the project at that time, but the only reason I can think of is that the code was tested with the JDBC 2 TCK (Technology Compatibility Kit) as that was the last one publicly available, and this was changed to address problems reported by the TCK.

    Disclosure: I'm a developer of Jaybird/Firebird JDBC driver.