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");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. 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).
  2. Remove ResultSet.CONCUR_UPDATABLE from your createStatement/prepareStatement calls so drivers and frameworks do not attempt the updatable path.
  3. 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

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.