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

View on GitHub (pinned to e952770a21)

Solutions

  1. Replace the positioned update with an explicit SQL UPDATE executed through PreparedStatement (e.g. UPDATE t SET col=? WHERE pk=?) so it routes normally.
  2. If updateRow is issued by a framework, disable updatable-result-set features in that framework (request ResultSet.CONCUR_READ_ONLY when creating the Statement).
  3. 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

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.