defmodule EctoSavepoint do @moduledoc """ Simple Ecto extension to use savepoints. Works with both postgrex and myxql. **Disclaimer:** savepoints are not officially supported by Ecto for a reason. If you run into unexpected behaviour, please report so these cases can be documented here. Add this line in your Repo: use EctoSavepoint And you can now do: MyRepo.transaction(fn -> MyRepo.insert(...) MyRepo.savepoint("my_savepoint") MyRepo.insert(...) MyRepo.rollback_to_savepoint("my_savepoint") MyRepo.insert(...) end) This way, the insertions between savepoint and rollback are rolled back. If you don't want to `use`, you can do the calls directly, as in: EctoSavepoint.savepoint(MyRepo, "my_savepoint") """ @doc """ Creates a savepoint Should be called within a transaction """ @spec savepoint(repo :: module, name :: binary | atom) :: term def savepoint(repo, name) do repo.query("SAVEPOINT #{name}") end @doc """ Creates a savepoint Should be called within the same transaction that created the savepoint """ @spec rollback_to_savepoint(repo :: module, name :: binary | atom) :: term def rollback_to_savepoint(repo, name) do repo.query("ROLLBACK TO SAVEPOINT #{name}") end defmacro __using__(_opts) do quote do def savepoint(name), do: EctoSavepoint.savepoint(get_dynamic_repo(), name) def rollback_to_savepoint(name), do: EctoSavepoint.rollback_to_savepoint(get_dynamic_repo(), name) end end end