apache/shardingsphere · error · SQLFeatureNotSupportedException
cancelRowUpdates
Error message
cancelRowUpdates
What it means
cancelRowUpdates() — undoing pending updateXXX() edits on the current row — throws SQLFeatureNotSupportedException because the federation ResultSet is read-only and never accepts row updates in the first place. The method is final in AbstractUnsupportedOperationSQLFederationResultSet, so the rejection is unconditional.
Source
Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.java:115
@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
public final boolean rowInserted() throws SQLException {
throw new SQLFeatureNotSupportedException("rowInserted");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Drop the cursor-edit pattern entirely: track pending edits in application objects and issue explicit UPDATE statements on save
- In UI editors, disable inline editing for federation connections so cancelRowUpdates is never reached
- Route the affected statement outside federation if cursor editing is a hard requirement
Example fix
// before
rs.updateString("name", draft);
if (!valid) { rs.cancelRowUpdates(); }
// after
if (valid) {
try (PreparedStatement ps = conn.prepareStatement("UPDATE t SET name = ? WHERE id = ?")) {
ps.setString(1, draft); ps.setLong(2, id); ps.executeUpdate();
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
// cancelRowUpdates() unreachable by design: edits were never accepted
} Type guard
private boolean isUpdatable(final ResultSet rs) throws SQLException {
return rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;
} Try / catch
try {
rs.cancelRowUpdates();
} catch (final SQLFeatureNotSupportedException e) {
// read-only result set: nothing to cancel, discard local pending edits
pendingEdits.clear();
} Prevention
- Model pending edits in application state, not cursor state
- Skip cancelRowUpdates when getConcurrency() is READ_ONLY
- Avoid cursor-edit flows entirely on federation connections
When it happens
Trigger: Calling rs.cancelRowUpdates() in an updatable-result-set edit flow (updateXXX ... then cancel) executed against a federation-routed statement.
Common situations: Cancel-edit actions in grid editors; rollback-on-validation-failure logic written for updatable cursors on a standalone database; the call usually follows earlier failed updateRow() usage, indicating the whole cursor-editing pattern must be replaced for federation datasources.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/578257205b4f6efe.
Report an issue: GitHub.