apache/shardingsphere · error · SQLFeatureNotSupportedException
refreshRow
Error message
refreshRow
What it means
refreshRow() — re-reading the current row from the database — throws SQLFeatureNotSupportedException in the federation ResultSet. Refreshing requires re-executing positioned reads against the underlying storage, which the one-shot federation result stream does not model, so the abstract class rejects it unconditionally.
Source
Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.java:110
@Override
public final void insertRow() throws SQLException {
throw new SQLFeatureNotSupportedException("insertRow");
}
@Override
public final void updateRow() throws SQLException {
throw new SQLFeatureNotSupportedException("updateRow");
}
@Override
public final void deleteRow() throws SQLException {
throw new SQLFeatureNotSupportedException("deleteRow");
}
@Override
public final void refreshRow() throws SQLException {
throw new SQLFeatureNotSupportedException("refreshRow");
}
@Override
public final void cancelRowUpdates() throws SQLException {
throw new SQLFeatureNotSupportedException("cancelRowUpdates");
}
@Override
public final void moveToInsertRow() throws SQLException {
throw new SQLFeatureNotSupportedException("moveToInsertRow");
}
@Override
public final void moveToCurrentRow() throws SQLException {
throw new SQLFeatureNotSupportedException("moveToCurrentRow");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Re-execute the query (or a keyed SELECT of the row) to observe current data instead of refreshRow()
- Shorten ResultSet lifetime: read rows into DTOs promptly so stale-snapshot refresh becomes a non-issue
- Ensure the statement bypasses federation if positioned refresh semantics are required by the application contract
Example fix
// before
rs.refreshRow();
// after
try (PreparedStatement ps = conn.prepareStatement("SELECT * FROM t WHERE id = ?")) {
ps.setLong(1, id);
try (ResultSet fresh = ps.executeQuery()) { ... }
} Defensive patterns
Strategy: try-catch
Validate before calling
if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
// refreshRow() unsupported: re-query the row by primary key instead
} Type guard
private boolean canRefresh(final ResultSet rs) throws SQLException {
return rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;
} Try / catch
try {
rs.refreshRow();
} catch (final SQLFeatureNotSupportedException e) {
reloadRowByKey(conn, tableName, id); // re-query fallback
} Prevention
- Prefer short-lived ResultSets; read into DTOs early
- Use keyed re-select instead of refreshRow
- Add version/updated_at columns for change detection
When it happens
Trigger: Calling rs.refreshRow() on a federated ResultSet, typically to pick up concurrent external changes to the row being displayed (optimistic-refresh pattern in editors or long-lived result screens).
Common situations: Optimistic-concurrency UIs that refresh rows before commit; tools that call refreshRow() after a save; migrating long-lived ResultSet usage from a native driver (where refreshRow may be supported) to ShardingSphere federation, where the ResultSet is a static snapshot of the federated result.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/214816aeacfc95d3.
Report an issue: GitHub.