apache/shardingsphere · error · SQLFeatureNotSupportedException
updateRow
Error message
updateRow
What it means
ShardingSphere's sharding ResultSet (ShardingSphereResultSet extends AbstractUnsupportedOperationResultSet) permanently disables row-updatable ResultSet operations. updateRow() always throws SQLFeatureNotSupportedException because the driver merges rows from multiple physical ResultSets across shards and cannot map a modified merged row back to exactly one underlying cursor for a positioned UPDATE.
Source
Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:100
@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
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");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Replace the positioned update with an explicit SQL UPDATE executed through PreparedStatement (e.g. UPDATE t SET col=? WHERE pk=?) so it routes normally.
- If updateRow is issued by a framework, disable updatable-result-set features in that framework (request ResultSet.CONCUR_READ_ONLY when creating the Statement).
- For a single-table, non-sharded path, obtain a plain Connection from the underlying physical datasource and perform the positioned update there.
Example fix
// before
rs.updateString(2, "newVal");
rs.updateRow(); // SQLFeatureNotSupportedException under ShardingSphere
// after
try (PreparedStatement ps = conn.prepareStatement("UPDATE t SET col = ? WHERE id = ?")) {
ps.setString(1, "newVal");
ps.setLong(2, id);
ps.executeUpdate();
} Defensive patterns
Strategy: try-catch
Validate before calling
// before any positioned update, confirm the cursor is updatable
if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
// ShardingSphere always reports read-only: use SQL UPDATE instead
} Type guard
boolean supportsRowUpdate(ResultSet rs) throws SQLException {
return rs.getConcurrency() != ResultSet.CONCUR_READ_ONLY;
} Try / catch
try {
rs.updateRow();
} catch (SQLFeatureNotSupportedException e) {
// fall back to keyed UPDATE SQL
LOGGER.warn("driver does not support positioned updates; using SQL UPDATE", e);
executeKeyedUpdate(id, newValues);
} Prevention
- Create Statements with ResultSet.CONCUR_READ_ONLY so frameworks never attempt positioned updates.
- Route all modifications through PreparedStatement DML with explicit WHERE keys.
- Audit migrated code for updateRow/deleteRow/insertRow before switching the JDBC URL to ShardingSphere.
When it happens
Trigger: Calling ResultSet.updateRow() on a ResultSet obtained from org.apache.shardingsphere.driver.jdbc.core.datasource.ShardingSphereDataSource — typically after updateXxx(...) calls, or via ORM/framework code (e.g. Hibernate updatable result sets, JDBI, Spring's ColumnMapRowMapper flows) that assumes CONCUR_UPDATABLE semantics.
Common situations: Porting an existing JDBC application that uses updatable ResultSets to a sharding datasource; ORMs or reporting tools configured for scrollable/updatable cursors; copy-paste of client-server DB code (Oracle/DB2 positioned updates) onto MySQL shards.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/951654f8c5c28f87.
Report an issue: GitHub.