apache/shardingsphere · error · SQLFeatureNotSupportedException
moveToInsertRow
Error message
moveToInsertRow
What it means
moveToInsertRow() throws SQLFeatureNotSupportedException in the SQL Federation ResultSet. The JDBC insert-row is a special cursor position only meaningful for updatable result sets; since federation results are read-only forward streams, the abstract base class rejects entering insert mode.
Source
Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.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");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Use PreparedStatement INSERT statements for new rows instead of the insert-row cursor API
- If a framework component issues moveToInsertRow, configure it to generate SQL inserts or point it at a non-federation datasource
- Review whether the query triggering federation can avoid the federation path so native driver capabilities are preserved
Example fix
// before
rs.moveToInsertRow();
rs.updateString(1, "v");
rs.insertRow();
// after
try (PreparedStatement ps = conn.prepareStatement("INSERT INTO t(c) VALUES (?)")) {
ps.setString(1, "v");
ps.executeUpdate();
} Defensive patterns
Strategy: validation
Validate before calling
if (rs.getConcurrency() != ResultSet.CONCUR_UPDATABLE) {
// moveToInsertRow() unsupported: use INSERT statements
} Type guard
private boolean isUpdatable(final ResultSet rs) throws SQLException {
return rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;
} Try / catch
try {
rs.moveToInsertRow();
} catch (final SQLFeatureNotSupportedException e) {
insertViaStatement(conn, rowValues);
} Prevention
- Never enter insert-row mode without checking CONCUR_UPDATABLE
- Use PreparedStatement INSERT for new rows
- Configure editors to generate SQL, not cursor mutations
When it happens
Trigger: Calling rs.moveToInsertRow() as the first step of the updatable-ResultSet insert pattern (moveToInsertRow -> updateXXX -> insertRow) on a federated query ResultSet.
Common situations: DB grid tools adding a new row; DAOs using insert-row mode to avoid writing INSERT SQL; code that worked against a native driver's updatable ResultSet and later ran on a ShardingSphere federation connection (e.g. after enabling federation for cross-shard queries).
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/d67dd4662018960a.
Report an issue: GitHub.