apache/shardingsphere · error · SQLFeatureNotSupportedException

last

Error message

last

What it means

last() — jumping to the final row — requires knowing the end of the result ahead of arrival, impossible for ShardingSphere's streaming forward-only merge across shards. The driver therefore declares it final and it throws SQLFeatureNotSupportedException at runtime.

Source

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

    
    @Override
    public final void beforeFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("beforeFirst");
    }
    
    @Override
    public final void afterLast() throws SQLException {
        throw new SQLFeatureNotSupportedException("afterLast");
    }
    
    @Override
    public final boolean first() throws SQLException {
        throw new SQLFeatureNotSupportedException("first");
    }
    
    @Override
    public final boolean last() throws SQLException {
        throw new SQLFeatureNotSupportedException("last");
    }
    
    @Override
    public final boolean absolute(final int row) throws SQLException {
        throw new SQLFeatureNotSupportedException("absolute");
    }
    
    @Override
    public final boolean relative(final int rows) throws SQLException {
        throw new SQLFeatureNotSupportedException("relative");
    }
    
    @Override
    public final int getRow() throws SQLException {
        throw new SQLFeatureNotSupportedException("getRow");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Get row counts with SELECT COUNT(*) as a separate query.
  2. Fetch the last logical row with ORDER BY <col> DESC LIMIT 1 (or OFFSET-based pagination), not cursor jumping.
  3. Materialize rows into a List and take list.get(list.size()-1).
  4. If a library relies on last(), hand it a CachedRowSet copy of the data.

Example fix

// before
rs.last(); // throws
int count = rs.getRow();

// after
try (ResultSet c = conn.createStatement().executeQuery("SELECT COUNT(*) FROM t_order")) {
    c.next(); int count = c.getInt(1);
}
Defensive patterns

Strategy: fallback

Validate before calling

if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
    // cannot jump to last row: use ORDER BY ... DESC LIMIT 1 or COUNT(*) instead
}

Try / catch

try {
    rs.last();
    int count = rs.getRow();
} catch (SQLFeatureNotSupportedException e) {
    // run SELECT COUNT(*) for the total
}

Prevention

When it happens

Trigger: Calling rs.last() to read the newest/last record, often followed by getRow() as a row-count trick, on results from the ShardingSphere driver.

Common situations: row-count idiom rs.last(); int n = rs.getRow(); rs.beforeFirst();; fetching the latest entry by cursor position instead of ORDER BY ... LIMIT 1; report code ported from scrollable cursors.

Related errors


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