apache/shardingsphere · error · SQLFeatureNotSupportedException

deleteRow

Error message

deleteRow

What it means

deleteRow() always throws SQLFeatureNotSupportedException in the federation ResultSet. Deleting through a JDBC cursor requires an updatable, positioned ResultSet; the federation engine only materializes query output forward-only and read-only, and the method is final so no subclass can override it.

Source

Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.java:105

    
    @Override
    public 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 FROM t WHERE key = ? PreparedStatement instead of cursor deletion
  2. Configure DB browser/ORM to use statement-based deletes for this connection
  3. Check whether the query must run under federation; non-federated statements delegate to the backend driver and may keep native cursor capabilities

Example fix

// before
rs.deleteRow();

// 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) {
    // deleteRow() unsupported: use DELETE ... WHERE key = ?
}

Type guard

private boolean isUpdatable(final ResultSet rs) throws SQLException {
    return rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;
}

Try / catch

try {
    rs.deleteRow();
} catch (final SQLFeatureNotSupportedException e) {
    executeDelete(conn, tableName, id);
}

Prevention

When it happens

Trigger: Calling rs.deleteRow() while positioned on a row of a federated query ResultSet — the cursor-based delete pattern — in an application using ShardingSphere SQL Federation.

Common situations: Row deletions triggered from data-grid UIs; DAOs written against updatable cursors on a legacy database; testing a federated SELECT in a DB browser whose Delete Row action maps to rs.deleteRow().

Related errors


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