prestodb/presto · error · SQLFeatureNotSupportedException

cancelRowUpdates

Error message

cancelRowUpdates

What it means

cancelRowUpdates() discards uncommitted updateXxx() changes on the current row of an updatable result set. Since Presto result sets are read-only and updateXxx() itself is unsupported, cancelRowUpdates() always throws SQLFeatureNotSupportedException("cancelRowUpdates").

Source

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

    @Override
    public void deleteRow()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("deleteRow");
    }

    @Override
    public void refreshRow()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("refreshRow");
    }

    @Override
    public void cancelRowUpdates()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("cancelRowUpdates");
    }

    @Override
    public void moveToInsertRow()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("moveToInsertRow");
    }

    @Override
    public void moveToCurrentRow()
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("moveToCurrentRow");
    }

    @Override
    public Statement getStatement()

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Remove the cursor-update code path entirely; Presto requires SQL UPDATE statements
  2. Use transaction rollback (connection.rollback()) if you need to discard SQL-level changes
  3. Guard the call behind a getConcurrency() check so it never executes against Presto

Example fix

// before
try {
    rs.updateInt("qty", 5);
    rs.updateRow();
} catch (SQLException e) {
    rs.cancelRowUpdates();
}
// after
try (PreparedStatement ps = conn.prepareStatement(
        "UPDATE orders SET qty = ? WHERE id = ?")) {
    ps.setInt(1, 5);
    ps.setLong(2, id);
    ps.executeUpdate();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
    // no cursor updates exist to cancel; use SQL/transactions instead
}

Try / catch

try {
    rs.cancelRowUpdates();
} catch (SQLFeatureNotSupportedException e) {
    // discard changes via connection.rollback() if in a transaction
}

Prevention

When it happens

Trigger: Calling cancelRowUpdates() after ResultSet.updateXxx() calls on a PrestoResultSet, typically in error-handling paths of cursor-update code.

Common situations: Ported OLTP CRUD code with rollback-style cursor handling; generic JDBC frameworks that call cancelRowUpdates() defensively after failed updates.

Related errors


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