apache/shardingsphere · error · SQLFeatureNotSupportedException

isAfterLast

Error message

isAfterLast

What it means

isAfterLast() is unsupported on ShardingSphere result sets: the class makes it final and throws SQLFeatureNotSupportedException. A forward-only streaming merge never exposes an 'after last' position to user code — the iteration simply ends when next() returns false — so the driver forbids the probe.

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:45

/**
 * Unsupported {@code ResultSet} methods.
 */
public abstract class AbstractUnsupportedOperationResultSet extends AbstractUnsupportedUpdateOperationResultSet {
    
    @Override
    public final boolean previous() throws SQLException {
        throw new SQLFeatureNotSupportedException("previous");
    }
    
    @Override
    public final boolean isBeforeFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("isBeforeFirst");
    }
    
    @Override
    public final boolean isAfterLast() throws SQLException {
        throw new SQLFeatureNotSupportedException("isAfterLast");
    }
    
    @Override
    public final boolean isFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("isFirst");
    }
    
    @Override
    public final boolean isLast() throws SQLException {
        throw new SQLFeatureNotSupportedException("isLast");
    }
    
    @Override
    public final void beforeFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("beforeFirst");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Use while (rs.next()) as the loop condition; next()==false already means the cursor is past the last row.
  2. Materialize rows into a List if you need arbitrary position checks afterward.
  3. For row counts, issue a separate COUNT query or accumulate a counter during iteration.
  4. Shield third-party callers by handing them a CachedRowSet built from the forward-only result.

Example fix

// before
while (!rs.isAfterLast()) { rs.next(); process(rs); } // throws

// after
while (rs.next()) { process(rs); }
Defensive patterns

Strategy: validation

Validate before calling

if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
    // terminate loops with rs.next(), not !rs.isAfterLast()
}

Try / catch

try {
    while (!rs.isAfterLast()) { rs.next(); }
} catch (SQLFeatureNotSupportedException e) {
    while (rs.next()) { }
}

Prevention

When it happens

Trigger: Calling rs.isAfterLast() on a query result from ShardingSphereDataSource, e.g. loop guards like while (!rs.isAfterLast()) instead of while (rs.next()).

Common situations: Iteration idioms ported from scroll-insensitive cursors; frameworks that verify iteration completion with position predicates; code generated by tools that emit the JDBC tutorial-style position checks.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/ccfb097aeddcc561. Report an issue: GitHub.