apache/shardingsphere · error · SQLFeatureNotSupportedException

rowDeleted

Error message

rowDeleted

What it means

rowDeleted() throws SQLFeatureNotSupportedException in the SQL Federation ResultSet. JDBC delete-visibility detection requires an updatable cursor implementation; the federation ResultSet is read-only and final, so it rejects all calls to rowDeleted() regardless of data or state.

Source

Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.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. Use logical-delete flags (deleted=1 / deleted_at) in the schema and filter with WHERE conditions instead of rowDeleted()
  2. Maintain a delete ledger in application state when your own code deletes rows and the loop must skip them
  3. Remove visibility-method usage from shared row-iteration helpers before enabling SQL Federation

Example fix

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

// after
ResultSet rs = stmt.executeQuery("SELECT ... FROM t WHERE deleted = 0");
while (rs.next()) { process(rs); }
Defensive patterns

Strategy: try-catch

Validate before calling

try { rs.rowDeleted(); /* supported */ }
catch (final SQLFeatureNotSupportedException e) { /* visibility unsupported: use logical-delete flags */ }

Type guard

private boolean isFederationVisibilitySupported(final ResultSet rs) {
    return rs.getClass().getName().startsWith("org.apache.shardingsphere.sqlfederation") == false;
}

Try / catch

boolean deleted;
try { deleted = rs.rowDeleted(); }
catch (final SQLFeatureNotSupportedException e) { deleted = rs.getBoolean("deleted_flag"); }

Prevention

When it happens

Trigger: Calling rs.rowDeleted() in a row loop over a federated ResultSet, e.g. skipping logically deleted rows via if (rs.rowDeleted()) continue;, often alongside rowInserted()/rowUpdated() visibility checks.

Common situations: ETL/replication jobs distinguishing soft deletes; GUIs collapsing rows deleted by other sessions; code originally validated on a single-node driver (PostgreSQL updatable cursors raise errors, MySQL supports visibility flags) and then moved behind federation without auditing these calls.

Related errors


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