apache/shardingsphere · error · SQLFeatureNotSupportedException

isFirst

Error message

isFirst

What it means

isFirst() — asking whether the cursor is on the first row — is a final, throwing method in ShardingSphere's AbstractUnsupportedOperationResultSet. Forward-only merged results do not maintain row-number state for position introspection, so the call fails with SQLFeatureNotSupportedException.

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:50

    
    @Override
    public final boolean previous() throws SQLException {
        throw new SQLFeatureNotSupportedException("previous");
    }
    
    @Override
    public final boolean isBeforeFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("isBeforeFirst");
    }
    
    @Override
    public final boolean isAfterLast() throws SQLException {
        throw new SQLFeatureNotSupportedException("isAfterLast");
    }
    
    @Override
    public final boolean isFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("isFirst");
    }
    
    @Override
    public final boolean isLast() throws SQLException {
        throw new SQLFeatureNotSupportedException("isLast");
    }
    
    @Override
    public final void beforeFirst() throws SQLException {
        throw new SQLFeatureNotSupportedException("beforeFirst");
    }
    
    @Override
    public final void afterLast() throws SQLException {
        throw new SQLFeatureNotSupportedException("afterLast");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Track the position yourself with a boolean or row counter updated as you call next().
  2. Pre-buffer all rows into a List and use index-based checks (i == 0).
  3. If you must special-case the first row, read it once before entering the loop for the remainder.
  4. For heavyweight frameworks needing position APIs, feed them a CachedRowSet or RowSetProvider copy.

Example fix

// before
while (rs.next()) { if (rs.isFirst()) writeHeader(); writeRow(rs); } // throws

// after
boolean first = true;
while (rs.next()) { if (first) { writeHeader(); first = false; } writeRow(rs); }
Defensive patterns

Strategy: validation

Validate before calling

if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
    // track first-row state in a local boolean, never rs.isFirst()
}

Try / catch

try {
    if (rs.isFirst()) { ... }
} catch (SQLFeatureNotSupportedException e) {
    // fall back to your own row counter (row == 1 means first)
}

Prevention

When it happens

Trigger: Calling rs.isFirst() inside an iteration loop, e.g. to skip a separator/header only on the first row, on a result set produced via the ShardingSphere driver.

Common situations: CSV/JSON exporters that special-case the first row; pagination logic that branches on cursor position; generic row visitors copied from code written against scrollable result sets.

Related errors


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