prestodb/presto · error · SQLFeatureNotSupportedException

insertRow

Error message

insertRow

What it means

Presto's JDBC driver implements read-only, forward-only result sets. insertRow() is part of the JDBC updatable-resultset API, which Presto does not support, so the method unconditionally throws SQLFeatureNotSupportedException with the method name as the message. The driver exposes the method only to satisfy the java.sql.ResultSet interface.

Source

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

    @Override
    public void updateObject(String columnLabel, Object x, int scaleOrLength)
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("updateObject");
    }

    @Override
    public void updateObject(String columnLabel, Object x)
            throws SQLException
    {
        throw new SQLFeatureNotSupportedException("updateObject");
    }

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

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

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

    @Override
    public void refreshRow()

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Rewrite the code to INSERT via Statement/PreparedStatement (executeUpdate of an INSERT statement) instead of using ResultSet row insertion
  2. Check result-set capabilities first with resultSet.getConcurrency() == ResultSet.CONCUR_READ_ONLY and take the SQL path when updatable is unavailable
  3. If row writes through a cursor are required, use a database that supports updatable result sets; Presto results are read-only by design

Example fix

// before
ResultSet rs = stmt.executeQuery("SELECT * FROM orders");
rs.moveToInsertRow();
rs.updateString("status", "SHIPPED");
rs.insertRow();
// after
try (PreparedStatement ps = conn.prepareStatement(
        "INSERT INTO orders (status) VALUES (?)")) {
    ps.setString(1, "SHIPPED");
    ps.executeUpdate();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
    // use SQL INSERT instead of rs.insertRow()
}

Type guard

static boolean supportsInsertRow(ResultSet rs) {
    try {
        return rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;
    } catch (SQLException e) {
        return false;
    }
}

Try / catch

try {
    rs.insertRow();
} catch (SQLFeatureNotSupportedException e) {
    // fall back to PreparedStatement INSERT
}

Prevention

When it happens

Trigger: Calling insertRow() on a java.sql.ResultSet obtained from a PrestoConnection (via PrestoStatement), typically after moveToInsertRow() in code written for updatable result sets.

Common situations: Porting legacy MySQL/PostgreSQL JDBC code that writes rows through ResultSet objects to Presto; ORM or report-builder code that assumes a CONCUR_UPDATABLE result set; generic JDBC frameworks that probe updatable-resultset capabilities.

Related errors


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