apache/shardingsphere · error · SQLFeatureNotSupportedException
last
Error message
last
What it means
last() is not supported by the SQL Federation ResultSet. The federation engine returns a forward-only result stream, so the abstract base class overrides last() to throw SQLFeatureNotSupportedException instead of jumping the cursor to the final row. The throw is unconditional; it is not a data- or state-dependent failure.
Source
Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.java:75
@Override
public void beforeFirst() throws SQLException {
throw new SQLFeatureNotSupportedException("beforeFirst");
}
@Override
public void afterLast() throws SQLException {
throw new SQLFeatureNotSupportedException("afterLast");
}
@Override
public boolean first() throws SQLException {
throw new SQLFeatureNotSupportedException("first");
}
@Override
public boolean last() throws SQLException {
throw new SQLFeatureNotSupportedException("last");
}
@Override
public boolean absolute(final int row) throws SQLException {
throw new SQLFeatureNotSupportedException("absolute");
}
@Override
public boolean relative(final int rows) throws SQLException {
throw new SQLFeatureNotSupportedException("relative");
}
@Override
public int getRow() throws SQLException {
throw new SQLFeatureNotSupportedException("getRow");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Issue a separate SELECT COUNT(*) federated query for totals instead of last()/getRow()
- For the final row only, use ORDER BY <pk> DESC LIMIT 1 and read the single forward result
- Cache results in a scroll-insensitive client RowSet if last() navigation is unavoidable
Example fix
// before rs.last(); int total = rs.getRow(); rs.beforeFirst(); // after int total = executeCount(stmt.getConnection(), countSql);
Defensive patterns
Strategy: try-catch
Validate before calling
if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
// last() unsupported: use a COUNT(*) query for totals
} Type guard
private boolean supportsLast(final ResultSet rs) throws SQLException {
return rs.getType() != ResultSet.TYPE_FORWARD_ONLY;
} Try / catch
try {
rs.last();
total = rs.getRow();
} catch (final SQLFeatureNotSupportedException e) {
total = countViaSql(conn, countSql); // fallback COUNT query
} Prevention
- Ban the last()/getRow() count idiom in shared code
- Always use SELECT COUNT(*) for pagination totals
- Create statements with TYPE_SCROLL_INSENSITIVE only for non-federation connections
When it happens
Trigger: Calling rs.last() (often followed by getRow()) on a federated query ResultSet to count rows or inspect the final row, e.g. pagination code that uses last()/getRow() to compute total result size.
Common situations: Row-counting idioms ported from MySQL Connector/J (where last()+getRow() is a common COUNT emulation); pagination helpers in older Struts/Spring JDBC code; switching a datasource URL from a native driver to ShardingSphere Proxy with sql-federation enabled for the affected statements.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/ae820c4f07f51c35.
Report an issue: GitHub.