-
Notifications
You must be signed in to change notification settings - Fork 48
Questions regarding binary_id
columns and the binary_id_type
configuration
#70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The original implementation was from about a year ago here #52 and I am having trouble recalling the rationale for the "why". @LostKobrakai could maybe shed some light.
The parameter exists as far as I can tell to maybe bridge existing sqlite databases that were created with tables using a different affinity for the column type.
I do agree that the string type may be the better default choice. I do believe that it being stored as a binary blob is smaller because you do not have the We probably should make the change to be more inline with
I think this is just a product of trying to support databases that were initially created by a different process or the older ecto2 adapter that used |
As mentioned this for one part is to allow a migration from esqlite/sqlite_ecto2, which stored uuids as binaries. iex(1)> byte_size(Ecto.UUID.generate())
36
iex(2)> byte_size(Ecto.UUID.bingenerate())
16
Neither postgres nor mysql store UUIDs in their string form. In postgres the native You're assumption of ecto_sql storing uuids as strings in the db is not correct here. That's probably also why your perception of the loader is wrong. For loading a stringly stored uuid there's nothing to convert between db value and runtime (both are strings), but for the
Loaders and dumpers are about the mapping between values you see in elixir and the values you see stored in the db. Postgres and MySQL always convert string <-> binary as explained. Exqlite started out storing Personally I would've loved a switch in default behaviour, but it would be/have been a breaking change and given sqlite clients afaik can't automatically convert the stored bytes to a "human readable" uuid I can also see people liking the string storage in spite of the more than 2x storage need. Footnotes
|
This is actually a really good explanation @LostKobrakai, we should probably throw that into a doc string or a nice comment block for those methods. |
Ok so let me write down my updated understanding to make sure it's correct. In all of Postgres, MySQL, SQLite (depending on options) and probably MSSQL too, So from the way loaders are configured (see below), we can see that the only conversion that happens is when using the As for the @impl Ecto.Adapter
def loaders(:binary_id, type) do
case Application.get_env(:ecto_sqlite3, :binary_id_type, :string) do
:string -> [type]
:binary -> [Ecto.UUID, type]
end
end
@impl Ecto.Adapter
def loaders(:uuid, type) do
case Application.get_env(:ecto_sqlite3, :uuid_type, :string) do
:string -> []
:binary -> [type]
end
end
Agreed! |
That part is not correct.
If |
I can confirm this being a bug with the |
If I'm not mistaken the issues comes from the fact that The MSSQL adapter overrides |
While I think having binary storage be the default option would've been the better initial decision, with more context I don't really think a breaking change is really worth it. Just having the option documented would be enough imo. That said, the longer things stay like this, the harder it's going to be to introduce a breaking change 🤷 |
I think we are given the allowance to make a breaking change like that prior to bumping the major. |
I took the liberty of opening a PR with a fix for this: #72 |
I think #73 wraps up the questions I had initially. Thanks a lot @warmwaffles and @LostKobrakai for your help! |
When I tried using
binary_id
primary keys for my tables, I was surprised to see IDs in elixir's binary format rather than strings. After some research, I found the (undocumented):binary_id_type
option.The option supports either
:string
(default) or:binary
as values. I was surprised to find in the loader forbinary_id
that the:binary
(rather than:string
) type usesEcto.UUID
(and consequently handles IDs as strings). The actual SQLite column types do seem to match the configuration more intuitively::binary
->UUID
column withBLOB
affinity,:string
->TEXT_UUID
column withTEXT
affinity.My resulting questions are:
:string
configuration be the one to useEcto.UUID
(and therefore handles IDs as plain strings). That would be much more intuitive to me.Ecto.UUID
and handle binary ids as strings.:uuid
column type and:uuid_type
configuration play into this? From my quick testing this type seems to always be handled as strings,:uuid_type
only affecting the type of the column in SQLite itself.When I get some clarification on this I'd be more than happy to contribute the necessary documentation (and code if applicable).
The text was updated successfully, but these errors were encountered: