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");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Re-execute the query (or a keyed SELECT of the row) to observe current data instead of refreshRow()
  2. Shorten ResultSet lifetime: read rows into DTOs promptly so stale-snapshot refresh becomes a non-issue
  3. 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

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.