Changelog

View Source

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

v0.5.1 - 2026-07-05

Docs-only release: this package has been renamed to bulkinup, and bulk_upsert will receive no further updates. BulkUpsert.bulk_upsert/4 is now Bulkinup.upsert/4 — same arguments, same options, same return shape. See the migration guide. The README and moduledoc now carry the same notice; no code changed.

v0.5.0 - 2026-07-04

Added

  • attrs_list now accepts any Enumerable, including a lazy Stream: items are validated and upserted chunk-by-chunk, so memory stays bounded for arbitrarily large inputs. Plain lists behave as before, and skipped rows are still summarized in a single :warning log per call
  • Option :max_concurrency to upsert chunks concurrently, each in its own transaction. Setting it trades the single-transaction guarantee for insert throughput — see the option's documentation for the consequences before using it

Changed

  • bulk_upsert/4 now raises an ArgumentError when :chunk_size is not a positive integer (previously an invalid value failed deeper in the pipeline with an unclear error)

v0.4.0 - 2026-07-04

Changed

  • Breaking: bulk_upsert/4 now raises an ArgumentError on unknown option names, and on BulkUpsert options nested inside :insert_all_opts values (previously both were silently ignored). :timeout and :placeholders remain valid inside :insert_all_opts, since insert_all/3 also accepts them
  • Skipped rows are now summarized in a single :warning log per call (schema, counts, and up to 50 skipped primary keys in the metadata), with per-row detail moved to the :debug level. Previously each skipped row logged its own :warning, which could flood the log during large imports of dirty data

v0.3.0 - 2026-07-04

Added

  • Nested associations are now upserted recursively at any depth (previously only the parent's direct associations were handled, and a child carrying its own nested associations crashed)
  • :recover_changeset_errors now applies recursively to nested association and embedded changesets, with fallbacks looked up by each changeset's schema (previously only the parent schema's changesets were recovered, and any nested error caused the row to be skipped)

Changed

  • Breaking: bulk_upsert/4 now returns {:ok, %{upserted: count, skipped: count}} (counts of top-level attrs) instead of :ok, making silently skipped invalid rows visible to callers
  • Require ecto ~> 3.6 (the :placeholders option has required Ecto v3.6.0 all along; the previous ~> 3.0 requirement overstated compatibility)
  • Skipped rows are now logged at the :warning level instead of :debug, since silently dropping invalid rows is data loss

Fixed

  • Wrap the entire bulk upsert in a single transaction. Previously each chunk of :chunk_size parents ran in its own transaction, so a failure in a later chunk left earlier chunks committed
  • Placeholder fields can now be included in the changeset's validate_required/2. Each placeholder value is injected into the attrs (at every nesting level) before the changeset is built, so the field is cast and validated like any other field. Previously the value was absent during validation, so requiring a placeholder field silently skipped every row

v0.2.0 - 2026-05-31

Added

  • Support for has_one associations
  • Support for many_to_many associations (related records and join table rows)
  • Option :placeholders to set fields from shared values via Ecto's insert_all/3 placeholders

Fixed

  • Default :insert_all_opts to a map so string-keyed sources (e.g. join tables) work

v0.1.5 - 2026-03-23

Fixed

  • Apply chunk_size option to has_many association upserts

v0.1.4 - 2026-02-23

Fixed

  • Use separate variable for parent insert_all_opts

v0.1.3 - 2026-02-20

Fixed

  • "Has many" assoc upserts now working

Added

  • Option :chunk_size (used to specify the maximum number of items to upsert in a single query)

v0.1.2 - 2025-05-03

Added

  • Add changelog to HexDocs

v0.1.1 - 2025-04-29

Added

  • Fix issues with docs

v0.1.0 - 2025-04-28

Added

  • Initial release