apache/shardingsphere · error · SQLFeatureNotSupportedException

isBeforeFirst

Error message

isBeforeFirst

What it means

isBeforeFirst() reports whether the cursor sits before the first row, but ShardingSphere's forward-only merged ResultSet implements it as a final method that throws SQLFeatureNotSupportedException. Position metadata outside the forward stream is not tracked for streaming merge results, so the driver rejects the query rather than guess.

Source

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

import java.sql.Ref;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Map;

/**
 * Unsupported {@code ResultSet} methods.
 */
public abstract class AbstractUnsupportedOperationResultSet extends AbstractUnsupportedUpdateOperationResultSet {
    
    @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

View on GitHub (pinned to e952770a21)

Solutions

  1. Detect emptiness with the return value of the first rs.next() call instead.
  2. Count rows while iterating forward, or run SELECT COUNT(*) if you need the total.
  3. If you need position queries repeatedly, materialize rows into a List first and check isEmpty().
  4. Wrap third-party components that call isBeforeFirst() with a pre-materialized CachedRowSet.

Example fix

// before
ResultSet rs = ps.executeQuery();
if (!rs.isBeforeFirst()) { log.info("empty"); } // throws

// after
ResultSet rs = ps.executeQuery();
boolean empty = !rs.next();
if (empty) { log.info("empty"); }
Defensive patterns

Strategy: validation

Validate before calling

// emptiness must be derived from next(), never position probes
if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
    boolean empty = !rs.next(); // supported everywhere
}

Try / catch

try {
    boolean before = rs.isBeforeFirst();
} catch (SQLFeatureNotSupportedException e) {
    boolean empty = !rs.next();
}

Prevention

When it happens

Trigger: Calling rs.isBeforeFirst() on any ResultSet from a ShardingSphere-driver query — commonly as an empty-result check before the first next() call.

Common situations: Code that detects 'no rows' via isBeforeFirst()==false after a next(); libraries like Apache POI/JasperReports or home-grown exporters that probe cursor position; copying examples written for scrollable cursors.

Related errors


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