prestodb/presto · error · SQLException

Batch prepared statement must be executed using executeBatch

Error message

Batch prepared statement must be executed using executeBatch method

What it means

requireNonBatchStatement() guards every single-execution entry point (executeQuery, executeUpdate, executeLargeUpdate, execute). If addBatch() has been called (isBatch is true), the accumulated batch must be run with executeBatch(); mixing single-shot execution with a pending batch is rejected to avoid silently dropping the queued batch rows.

Source

Thrown at presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoPreparedStatement.java:821

    private static List<String> toValues(Map<Integer, String> parameters)
            throws SQLException
    {
        ImmutableList.Builder<String> values = ImmutableList.builder();
        for (int index = 0; index < parameters.size(); index++) {
            if (!parameters.containsKey(index)) {
                throw new SQLException("No value specified for parameter " + (index + 1));
            }
            values.add(parameters.get(index));
        }
        return values.build();
    }

    private void requireNonBatchStatement()
            throws SQLException
    {
        if (isBatch) {
            throw new SQLException("Batch prepared statement must be executed using executeBatch method");
        }
    }

    private static String getExecuteSql(String statementName, List<String> values)
    {
        StringBuilder sql = new StringBuilder();
        sql.append("EXECUTE ").append(statementName);
        if (!values.isEmpty()) {
            sql.append(" USING ");
            Joiner.on(", ").appendTo(sql, values);
        }
        return sql.toString();
    }

    private static String formatLiteral(String type, String x)
    {
        return type + " " + formatStringLiteral(x);
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Call executeBatch() (and process its results) instead of execute/executeUpdate when batching
  2. Call clearBatch() to discard a pending batch before switching to single-statement execution
  3. Restructure code so a given statement instance is used either for batches or single execution, not both
  4. Reuse a fresh PreparedStatement (or clearBatch) when falling back from a failed batch to per-row execution

Example fix

// before
ps.setInt(1, 1);
ps.addBatch();
int n = ps.executeUpdate(); // throws
// after
ps.setInt(1, 1);
ps.addBatch();
int[] counts = ps.executeBatch();
Defensive patterns

Strategy: validation

Validate before calling

if (hasPendingBatch) {
    ps.executeBatch(); // or ps.clearBatch() before single execution
} else {
    ps.executeUpdate();
}

Try / catch

catch (SQLException e) {
    if (e.getMessage().contains("must be executed using executeBatch")) {
        ps.clearBatch(); // discard pending batch, then retry as single statement
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling executeQuery/executeUpdate/execute on a PreparedStatement after at least one addBatch() call, without calling executeBatch() (or clearBatch()) first.

Common situations: Code paths that sometimes batch and sometimes execute directly; retry/error-handling logic that abandons a batch halfway and re-executes as a single statement; reused statement objects where a previous operation left a pending batch.

Related errors


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