prestodb/presto · info · SQLFeatureNotSupportedException

rowDeleted

Error message

rowDeleted

What it means

PrestoResultSet.rowDeleted() is an unimplemented JDBC method. Presto result sets are immutable, read-only snapshots of query output, so detecting deletes is meaningless and the driver throws SQLFeatureNotSupportedException unconditionally. The thrown exception is part of the driver's deliberate stubbing of updatable/row-visibility ResultSet APIs.

Source

Thrown at presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoResultSet.java:767

    @Override
    public boolean rowUpdated()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("rowUpdated");
    }

    @Override
    public boolean rowInserted()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("rowInserted");
    }

    @Override
    public boolean rowDeleted()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("rowDeleted");
    }

    @Override
    public void updateNull(int columnIndex)
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("updateNull");
    }

    @Override
    public void updateBoolean(int columnIndex, boolean x)
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("updateBoolean");
    }

    @Override
    public void updateByte(int columnIndex, byte x)

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Remove the rowDeleted() call; deletes can never be detected in a read-only Presto result set
  2. Gate the call on DatabaseMetaData.deletesAreDetected(type) returning true (it is false for Presto)
  3. If delete feedback is needed, execute DELETE statements and inspect update counts instead
  4. Catch SQLFeatureNotSupportedException and treat the row as not deleted when using generic JDBC code

Example fix

// before
if (rs.rowDeleted()) continue;
// after
if (meta.deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY) && rs.rowDeleted()) continue;
Defensive patterns

Strategy: try-catch

Validate before calling

DatabaseMetaData md = conn.getMetaData();
boolean supported = md.deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY); // false for Presto
if (!supported) { /* skip rowDeleted() */ }

Type guard

boolean supportsDeleteDetection(Connection c) {
    try { return c.getMetaData().deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY); }
    catch (SQLException e) { return false; }
}

Try / catch

try {
    if (rs.rowDeleted()) { continue; }
} catch (SQLFeatureNotSupportedException e) {
    // Presto result sets are read-only; nothing can be deleted
}

Prevention

When it happens

Trigger: Calling rs.rowDeleted() on any ResultSet produced by the Presto JDBC driver while iterating or post-processing rows.

Common situations: Portable JDBC data-access layers that call rowDeleted() on every row to filter out phantom rows; code ported from MySQL/Oracle (where this is meaningful) to Presto.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/7ac98951e0e0e470. Report an issue: GitHub.