martinthenth / uuidv7

UUID v7 implementation and Ecto.Type for Elixir
https://hexdocs.pm/uuidv7
MIT License
82 stars 7 forks source link

Ecto.Multi.insert_all fails with uuidv7 #63

Closed tomciopp closed 1 month ago

tomciopp commented 1 month ago

So this is a bit of a weird failure, but if you have not set the id when inserting multiple records the id will not be generated and the insert will fail.

Something like this is broken with UUIDv7

Ecto.Multi.new(
|> Ecto.Multi.insert_all(:users, User, user_records(data), placeholders: %{now: DateTime.utc_now()})

defp user_records(data) do 
  Enum.map(data, fn user -> 
    %{
      name: user["name"],
      inserted_at: {:placeholder, :now},
      updated_at: {:placeholder, :now}
    }
  end)
end

The fix is this:

Ecto.Multi.new(
|> Ecto.Multi.insert_all(:users, User, user_records(data), placeholders: %{now: DateTime.utc_now()})

defp user_records(data) do 
  Enum.map(data, fn user -> 
    %{
      id: UUIDv7.generate(),
      name: user["name"],
      inserted_at: {:placeholder, :now},
      updated_at: {:placeholder, :now}
    }
  end)
end

But I'm unsure if this is something that is broken in uuidv7 or I was relying on some behavior that I do not understand.

martinthenth commented 1 month ago

Hi @tomciopp,

If I remember correctly it works like that with Ecto.UUID as well. The issue would be that bigserial from Postgres / other database generates the primary key in the database rather than in the application.

Let me know if it's not the case.