apache/shardingsphere · error · SQLFeatureNotSupportedException

execute with SQL for PreparedStatement

Error message

execute with SQL for PreparedStatement

What it means

ShardingSphere's PreparedStatement does not support execute(String sql) — the boolean-returning execute that accepts a new SQL string. Because the routed and rewritten SQL is fixed when prepareStatement(sql) is called, executing a different statement through the same object would defeat sharding. All String overloads of execute are final and throw SQLFeatureNotSupportedException.

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationPreparedStatement.java:114

    
    @Override
    public final int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
        throw new SQLFeatureNotSupportedException("executeUpdate with SQL for PreparedStatement");
    }
    
    @Override
    public final int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
        throw new SQLFeatureNotSupportedException("executeUpdate with SQL for PreparedStatement");
    }
    
    @Override
    public final int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
        throw new SQLFeatureNotSupportedException("executeUpdate with SQL for PreparedStatement");
    }
    
    @Override
    public final boolean execute(final String sql) throws SQLException {
        throw new SQLFeatureNotSupportedException("execute with SQL for PreparedStatement");
    }
    
    @Override
    public final boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
        throw new SQLFeatureNotSupportedException("execute with SQL for PreparedStatement");
    }
    
    @Override
    public final boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
        throw new SQLFeatureNotSupportedException("execute with SQL for PreparedStatement");
    }
    
    @Override
    public final boolean execute(final String sql, final String[] columnNames) throws SQLException {
        throw new SQLFeatureNotSupportedException("execute with SQL for PreparedStatement");
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Call the parameterless ps.execute() and keep the SQL only in prepareStatement(sql).
  2. If the code needs to know whether a ResultSet came back, use the boolean return of execute() and then getResultSet()/getUpdateCount().
  3. Use ps.executeQuery() or ps.executeUpdate() directly when the statement kind is known.
  4. For truly dynamic SQL strings per call, use Statement.execute(sql) instead.

Example fix

// before
PreparedStatement ps = conn.prepareStatement(sql);
boolean isRs = ps.execute(sql); // throws

// after
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 42);
boolean isRs = ps.execute();
Defensive patterns

Strategy: try-catch

Validate before calling

if (stmt instanceof PreparedStatement && sqlArgument != null) {
    throw new IllegalArgumentException("execute(String) unsupported on PreparedStatement (ShardingSphere)");
}

Try / catch

try {
    boolean isRs = ps.execute(sql);
} catch (SQLFeatureNotSupportedException e) {
    boolean isRs = ps.execute();
}

Prevention

When it happens

Trigger: Calling ps.execute("SELECT ...") or ps.execute("INSERT ...") — any boolean execute(String ...) — on a PreparedStatement from ShardingSphereDataSource. Works on vanilla drivers, throws here.

Common situations: Generic DAO layers that decide between query and update at runtime by calling execute(sql) regardless of statement type; dynamic-SQL frameworks; code migrated from Statement where execute(String) was the norm.

Related errors


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