apache/shardingsphere · error · SQLFeatureNotSupportedException

getCursorName

Error message

getCursorName

What it means

getCursorName() throws SQLFeatureNotSupportedException in the SQL Federation ResultSet. Cursor names exist for positioned UPDATE/DELETE ... WHERE CURRENT OF statements; federation result sets are not backed by an updatable server cursor, so the abstract class rejects cursor-name retrieval (method is final).

Source

Thrown at kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedOperationSQLFederationResultSet.java:145

    
    @Override
    public final boolean rowInserted() throws SQLException {
        throw new SQLFeatureNotSupportedException("rowInserted");
    }
    
    @Override
    public final boolean rowUpdated() throws SQLException {
        throw new SQLFeatureNotSupportedException("rowUpdated");
    }
    
    @Override
    public final boolean rowDeleted() throws SQLException {
        throw new SQLFeatureNotSupportedException("rowDeleted");
    }
    
    @Override
    public final String getCursorName() throws SQLException {
        throw new SQLFeatureNotSupportedException("getCursorName");
    }
    
    @Override
    public final int getHoldability() throws SQLException {
        throw new SQLFeatureNotSupportedException("getHoldability");
    }
    
    @Override
    public final NClob getNClob(final int columnIndex) throws SQLException {
        throw new SQLFeatureNotSupportedException("getNClob");
    }
    
    @Override
    public final NClob getNClob(final String columnLabel) throws SQLException {
        throw new SQLFeatureNotSupportedException("getNClob");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Replace positioned (WHERE CURRENT OF) updates with keyed UPDATE ... WHERE pk = ? statements
  2. Remove unconditional getCursorName() logging/metadata calls from generic ResultSet wrappers
  3. Guard utility code to skip cursor-name retrieval for federation datasources (check the connection/DataSource class or product name)

Example fix

// before
String cursor = rs.getCursorName();
stmt.execute("UPDATE t SET c = 1 WHERE CURRENT OF " + cursor);

// after
try (PreparedStatement ps = conn.prepareStatement("UPDATE t SET c = 1 WHERE id = ?")) {
    ps.setLong(1, currentId); ps.executeUpdate();
}
Defensive patterns

Strategy: try-catch

Validate before calling

try { rs.getCursorName(); /* positioned updates possible */ }
catch (final SQLFeatureNotSupportedException e) { /* no cursor name: use keyed UPDATE */ }

Type guard

private boolean supportsPositionedUpdate(final ResultSet rs) {
    try { rs.getCursorName(); return true; }
    catch (final SQLFeatureNotSupportedException e) { return false; }
}

Try / catch

String cursor;
try { cursor = rs.getCursorName(); }
catch (final SQLFeatureNotSupportedException e) { cursor = null; }
if (cursor == null) { executeKeyedUpdate(conn, table, changes, id); }

Prevention

When it happens

Trigger: Calling rs.getCursorName(), usually generated by positioned-update helpers (named-cursor pattern: SELECT ... FOR UPDATE + UPDATE ... WHERE CURRENT OF <cursor>) executed against a federation-routed statement.

Common situations: Code ported from DB2/Oracle/Sybase style positioned updates; framework utilities that always query getCursorName() for logging; wrappers that inspect ResultSet metadata and unconditionally fetch the cursor name on every result set, blowing up only when the statement happens to run under ShardingSphere federation.

Related errors


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