apache/shardingsphere · error · SQLFeatureNotSupportedException

moveToInsertRow

Error message

moveToInsertRow

What it means

moveToInsertRow() is final in AbstractUnsupportedOperationResultSet and always throws SQLFeatureNotSupportedException. The insert-row staging area only exists on CONCUR_UPDATABLE cursors, which the sharding ResultSet deliberately does not implement.

Source

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

    
    @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
    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

View on GitHub (pinned to e952770a21)

Solutions

  1. Insert with an explicit INSERT statement via PreparedStatement; ShardingSphere will shard it correctly.
  2. Configure the tool/ORM to use statement-based inserts instead of cursor-based inserts.
  3. For non-sharded single tables, use the physical datasource connection where cursor inserts work if the backend driver supports them.

Example fix

// before
rs.moveToInsertRow(); // throws
rs.updateString(1, "v");
rs.insertRow();

// after
try (PreparedStatement ps = conn.prepareStatement("INSERT INTO t (col) VALUES (?)")) {
    ps.setString(1, "v");
    ps.executeUpdate();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
    // insert via INSERT SQL; cursor insert-row is unavailable
}

Try / catch

try {
    rs.moveToInsertRow();
} catch (SQLFeatureNotSupportedException e) {
    executeInsert(row); // PreparedStatement INSERT
}

Prevention

When it happens

Trigger: Calling ResultSet.moveToInsertRow() followed by updateXxx/insertRow to insert via cursor — a pattern used by some ORM internals, RAD tools, and legacy codebases — on a ResultSet from ShardingSphereDataSource.

Common situations: Older VisualBasic/JDBC-style 'AddNew' insert flows ported to Java; form builders and low-code platforms that insert via the insert row; migration from MySQL Connector/J with updatable result sets to the sharding driver.

Related errors


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