apache/shardingsphere · error · SQLFeatureNotSupportedException

deleteRow

Error message

deleteRow

What it means

AbstractUnsupportedOperationResultSet declares deleteRow() final and throws SQLFeatureNotSupportedException, so the sharding ResultSet never supports positioned deletes. A row in the merged result may originate from any shard, and the driver cannot reliably resolve which physical cursor row to delete.

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:105

    
    @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
    public final void moveToInsertRow() throws SQLException {
        throw new SQLFeatureNotSupportedException("moveToInsertRow");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Issue an explicit DELETE statement with a WHERE key predicate via PreparedStatement and let ShardingSphere route it.
  2. Force read-only concurrency (Statement创建时 CONCUR_READ_ONLY) so frameworks never attempt positioned deletes.
  3. Fall back to the physical datasource connection when positioned deletes are truly required.

Example fix

// before
rs.absolute(3);
rs.deleteRow(); // throws

// after
try (PreparedStatement ps = conn.prepareStatement("DELETE FROM t WHERE id = ?")) {
    ps.setLong(1, id);
    ps.executeUpdate();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
    // use SQL DELETE instead of rs.deleteRow()
}

Type guard

boolean supportsPositionedDelete(ResultSet rs) throws SQLException {
    return rs.getConcurrency() != ResultSet.CONCUR_READ_ONLY;
}

Try / catch

try {
    rs.deleteRow();
} catch (SQLFeatureNotSupportedException e) {
    executeKeyedDelete(id);
}

Prevention

When it happens

Trigger: Calling ResultSet.deleteRow() on a ResultSet produced by ShardingSphereDataSource — directly, or via generic data-editing tools/ORMs that delete through the current cursor row instead of SQL.

Common situations: GUI SQL clients or admin tools wired to the sharding URL that edit rows via positioned deletes; legacy DAO code using positioned deletes; migration from a single-DB driver that supported CONCUR_UPDATABLE.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/cd800009cfcec69a. Report an issue: GitHub.