apache/shardingsphere · error · SQLFeatureNotSupportedException

rowDeleted

Error message

rowDeleted

What it means

rowDeleted() is final in AbstractUnsupportedOperationResultSet and always throws SQLFeatureNotSupportedException. Because deletes must go through SQL statements and never through the merged cursor, the sharding ResultSet cannot report cursor-visible deletions.

Source

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

    
    @Override
    public final void moveToCurrentRow() throws SQLException {
        throw new SQLFeatureNotSupportedException("moveToCurrentRow");
    }
    
    @Override
    public final boolean rowInserted() throws SQLException {
        throw new SQLFeatureNotSupportedException("rowInserted");
    }
    
    @Override
    public final boolean rowUpdated() throws SQLException {
        throw new SQLFeatureNotSupportedException("rowUpdated");
    }
    
    @Override
    public final boolean rowDeleted() throws SQLException {
        throw new SQLFeatureNotSupportedException("rowDeleted");
    }
    
    @Override
    public final String getCursorName() throws SQLException {
        throw new SQLFeatureNotSupportedException("getCursorName");
    }
    
    @Override
    public final int getHoldability() throws SQLException {
        throw new SQLFeatureNotSupportedException("getHoldability");
    }
    
    @Override
    public final NClob getNClob(final int columnIndex) throws SQLException {
        throw new SQLFeatureNotSupportedException("getNClob");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Track deletions in application state (a set of deleted keys recorded when DELETE statements execute).
  2. Use SQL to determine existence (SELECT ... WHERE key = ?) instead of asking the cursor.
  3. Remove cursor-delete flows entirely and re-query after deletes.

Example fix

// before
while (rs.next()) { if (rs.rowDeleted()) continue; ... } // throws

// after
Set<Long> deletedIds = new HashSet<>(); // maintained by your DELETE code
while (rs.next()) { if (deletedIds.contains(rs.getLong("id"))) continue; ... }
Defensive patterns

Strategy: try-catch

Validate before calling

// app-side existence check replaces the cursor probe
boolean deleted = deletedIds.contains(rs.getLong("id"));

Try / catch

try {
    boolean deleted = rs.rowDeleted();
} catch (SQLFeatureNotSupportedException e) {
    deleted = deletedIds.contains(id);
}

Prevention

When it happens

Trigger: Calling ResultSet.rowDeleted() on a ResultSet obtained from ShardingSphereDataSource — usually in grids that grey out rows deleted via deleteRow, or sync loops that skip rows removed since the last fetch.

Common situations: Row-filtering logic ported from single-database drivers that support updatable cursors; master-detail UIs that rely on visible-delete semantics; JDBC tutorial-derived utility classes.

Related errors


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