apache/shardingsphere · error · SQLFeatureNotSupportedException
updateXXX
Error message
updateXXX
What it means
ShardingSphere's driver deliberately does not support updatable ResultSets. AbstractUnsupportedUpdateOperationResultSet.updateNull(int) throws SQLFeatureNotSupportedException('updateXXX'). Read-only result sets are a documented limitation: the sharding driver merges results from multiple real ResultSets, so in-place row mutation (updateRow/insertRow model) cannot be implemented.
Source
Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedUpdateOperationResultSet.java:46
import java.sql.Date;
import java.sql.NClob;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
/**
* Unsupported {@code ResultSet} methods.
*/
public abstract class AbstractUnsupportedUpdateOperationResultSet extends WrapperAdapter implements ResultSet {
@Override
public final void updateNull(final int columnIndex) throws SQLException {
throw new SQLFeatureNotSupportedException("updateXXX");
}
@Override
public final void updateNull(final String columnLabel) throws SQLException {
throw new SQLFeatureNotSupportedException("updateXXX");
}
@Override
public final void updateBoolean(final int columnIndex, final boolean x) throws SQLException {
throw new SQLFeatureNotSupportedException("updateXXX");
}
@Override
public final void updateBoolean(final String columnLabel, final boolean x) throws SQLException {
throw new SQLFeatureNotSupportedException("updateXXX");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Rewrite the positioned update as a normal UPDATE statement: UPDATE t SET col = NULL WHERE id = ? executed via PreparedStatement (this also routes correctly through sharding).
- Remove ResultSet.CONCUR_UPDATABLE from your createStatement/prepareStatement calls so drivers and frameworks do not attempt the updatable path.
- If in-place editing is essential for a screen/flow, connect that flow directly to the physical database driver.
Example fix
// before
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("SELECT note FROM t WHERE id=1");
rs.next();
rs.updateNull(1);
rs.updateRow();
// after
try (PreparedStatement ps = conn.prepareStatement("UPDATE t SET note = NULL WHERE id = ?")) {
ps.setInt(1, 1);
ps.executeUpdate();
} Defensive patterns
Strategy: validation
Validate before calling
DatabaseMetaData md = conn.getMetaData();
boolean updatableOk = md.supportsResultSetConcurrency(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
if (!updatableOk) {
throw new UnsupportedOperationException("positioned updates unavailable; use UPDATE SQL");
} Type guard
private static boolean canPositionUpdate(Connection c) throws SQLException {
try {
return c.getMetaData().supportsResultSetConcurrency(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
} catch (SQLException e) {
return false;
}
} Try / catch
try {
rs.updateNull(colIdx);
} catch (SQLFeatureNotSupportedException e) {
// rewrite path: fall back to UPDATE SQL
throw new IllegalStateException("Updatable ResultSet unsupported; use UPDATE SQL", e);
} Prevention
- Always create statements CONCUR_READ_ONLY unless the target driver is verified to support updatable result sets.
- Standardize on SQL UPDATE statements for all writes through sharding datasources.
- Add a coding-standard rule banning updateRow()/insertRow()/deleteRow() usage in sharded services.
- Cover write paths with integration tests against the real (sharded) datasource before release.
When it happens
Trigger: Creating a statement with ResultSet.CONCUR_UPDATABLE and calling rs.updateNull(columnIndex) before rs.updateRow() — i.e. the classic JDBC positioned-update pattern.
Common situations: Porting desktop/J2EE-era code that edits rows via updatable ResultSet instead of UPDATE SQL; frameworks or DAO helpers that auto-detect CONCUR_UPDATABLE; the same code worked against the plain MySQL Connector/J or PostgreSQL driver before adding jdbc:shardingsphere:.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/d41ee90461890fe8.
Report an issue: GitHub.