class BatchDmlExecutablePreparedStatement extends ExecutablePreparedStatementBase {
    private final List<ExecutablePreparedStatementBase> collectedStatements;
    private final Logger LOG = Scope.getCurrentScope().getLog(getClass());

    public BatchDmlExecutablePreparedStatement(
            Database database, String catalogName, String schemaName, String tableName,
            List<LoadDataColumnConfig> columns, ChangeSet changeSet, ResourceAccessor resourceAccessor,
            List<ExecutablePreparedStatementBase> statements) {
        super(database, catalogName, schemaName, tableName, new ArrayList<ColumnConfig>(columns), changeSet,
            resourceAccessor);
        this.collectedStatements = new ArrayList<>(statements);
    }

    /**
     * Returns the individual statements that are currently store in this batch.
     * @return the List of the stored statements (may be empty if none are stored)
     */
    public List<ExecutablePreparedStatementBase> getIndividualStatements() {
        return new ArrayList<>(collectedStatements);
    }

    @Override
    protected void attachParams(List<? extends ColumnConfig> ignored, PreparedStatement stmt)
            throws SQLException, DatabaseException {
        for (ExecutablePreparedStatementBase insertStatement : collectedStatements) {
            super.attachParams(insertStatement.getColumns(), stmt);
            stmt.addBatch();
        }
    }

    @Override
    protected String generateSql(List<ColumnConfig> cols) {<FILL_FUNCTION_BODY>}

    @Override
    protected void executePreparedStatement(PreparedStatement stmt) throws SQLException {
        int[] updateCounts = stmt.executeBatch();
        long sumUpdateCounts = 0;
        for (int updateCount : updateCounts) {
            sumUpdateCounts = updateCount;
        }
        LOG.info(String.format("Executing JDBC DML batch was successful. %d operations were executed, %d individual UPDATE events were confirmed by the database.",
                updateCounts.length, sumUpdateCounts));
    }

    @Override
    public boolean continueOnError() {
        return false;
    }
}

        // By convention, all of the statements are the same except the bind values. So it is sufficient to simply
        // return the first collected statement for generation.
        return collectedStatements.get(0).generateSql(cols);
    
<methods>public void execute(liquibase.database.PreparedStatementFactory) throws liquibase.exception.DatabaseException,public java.lang.String getCatalogName() ,public liquibase.changelog.ChangeSet getChangeSet() ,public List<? extends liquibase.change.ColumnConfig> getColumns() ,public liquibase.resource.ResourceAccessor getResourceAccessor() ,public java.lang.String getSchemaName() ,public java.lang.String getTableName() ,public boolean skipOnUnsupported() <variables>private final non-sealed java.lang.String catalogName,private final non-sealed liquibase.changelog.ChangeSet changeSet,private final non-sealed Set<java.io.Closeable> closeables,private final non-sealed List<? extends liquibase.change.ColumnConfig> columns,protected static java.util.ResourceBundle coreBundle,protected liquibase.database.Database database,private static java.lang.reflect.Method executeWithFlagsMethod,private static java.sql.PreparedStatement lastPreparedStatement,private static java.lang.String lastPreparedStatementSql,private final non-sealed liquibase.resource.ResourceAccessor resourceAccessor,private final non-sealed java.lang.String schemaName,private final Map<java.lang.String,java.lang.Object> snapshotScratchPad,private final non-sealed java.lang.String tableName