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");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Replace result-set editing with an explicit INSERT via PreparedStatement.executeUpdate(); ShardingSphere will route it correctly.
- Remove CONCUR_UPDATABLE hints — they give no capability here and mislead maintainers.
- For batch inserts, use addBatch()/executeBatch() on the PreparedStatement.
- 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
- Treat sharded result sets as strictly read-only; write through INSERT/UPDATE/DELETE statements so routing works.
- Do not request CONCUR_UPDATABLE — it silently changes nothing here.
- Route editable UI tables to a direct datasource or convert them to statement-based persistence.
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.