apache/shardingsphere · error · SQLFeatureNotSupportedException

insertRow

Error message

insertRow

What it means

insertRow() belongs to the JDBC updatable-result-set API: it inserts the insert-row buffer into the table. ShardingSphere result sets are read-only, forward-only merge streams, so insertRow() is final and throws SQLFeatureNotSupportedException; writes must go through proper INSERT statements so they can be parsed, rewritten, and routed to shards.

Source

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

    
    @Override
    public final boolean absolute(final int row) throws SQLException {
        throw new SQLFeatureNotSupportedException("absolute");
    }
    
    @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

View on GitHub (pinned to e952770a21)

Solutions

  1. Replace result-set editing with an explicit INSERT via PreparedStatement.executeUpdate(); ShardingSphere will route it correctly.
  2. Remove CONCUR_UPDATABLE hints — they give no capability here and mislead maintainers.
  3. For batch inserts, use addBatch()/executeBatch() on the PreparedStatement.
  4. If a UI component requires updatable result sets, isolate that component on a direct, non-sharded DataSource.

Example fix

// before
rs.moveToInsertRow();
rs.updateString(2, "PAID");
rs.insertRow(); // throws

// after
PreparedStatement ps = conn.prepareStatement("INSERT INTO t_order(status) VALUES (?)");
ps.setString(1, "PAID");
ps.executeUpdate();
Defensive patterns

Strategy: validation

Validate before calling

int concurrency = rs.getConcurrency();
if (concurrency == ResultSet.CONCUR_READ_ONLY) {
    // insertRow()/updateRow() unavailable: issue INSERT/UPDATE statements instead
}

Try / catch

try {
    rs.insertRow();
} catch (SQLFeatureNotSupportedException e) {
    try (PreparedStatement ps = conn.prepareStatement("INSERT INTO t(...) VALUES (?,?)")) {
        bind(ps); ps.executeUpdate();
    }
}

Prevention

When it happens

Trigger: Calling rs.moveToInsertRow(); rs.updateString(...); rs.insertRow(); on a ResultSet produced by a ShardingSphere-driver query — the updatable-result-set editing pattern.

Common situations: Swing/SWT table editors and generic CRUD frameworks that edit via updatable result sets; code ported from drivers where CONCUR_UPDATABLE is supported; attempts to avoid writing INSERT SQL.

Related errors


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