Skip to content

Conversation

bradurani
Copy link
Contributor

This is a fix for a bug I discovered while using changesets to insert binaries into :binary_id columns. If you try to insert a value that is already a 16 byte binary, instead of a hyphenated string, ecto raises an error such as:

[error] #PID<0.1306.0> running Dashboard.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /applications
** (exit) an exception was raised:
    ** (Ecto.ChangeError) value `<<184, 235, 134, 244, 95, 86, 74, 133, 159, 153, 31, 111, 16, 28, 76, 15>>` for `Dashboard.Application.user_id` in `insert` does not match type :binary_id
        (ecto) lib/ecto/repo/schema.ex:610: Ecto.Repo.Schema.dump_field!/6
        (ecto) lib/ecto/repo/schema.ex:619: anonymous fn/6 in Ecto.Repo.Schema.dump_fields!/5
        (stdlib) lists.erl:1262: :lists.foldl/3
        (ecto) lib/ecto/repo/schema.ex:617: Ecto.Repo.Schema.dump_fields!/5
        (ecto) lib/ecto/repo/schema.ex:566: Ecto.Repo.Schema.dump_changes!/6
        (ecto) lib/ecto/repo/schema.ex:182: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
        (ecto) lib/ecto/repo/schema.ex:595: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
        (ecto) lib/ecto/adapters/sql.ex:472: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
        (db_connection) lib/db_connection.ex:973: DBConnection.transaction_run/4
        (db_connection) lib/db_connection.ex:897: DBConnection.run_begin/3
        (db_connection) lib/db_connection.ex:671: DBConnection.transaction/3
        (dashboard) web/controllers/application_controller.ex:16: Dashboard.ApplicationController.create/2
        (dashboard) web/controllers/application_controller.ex:1: Dashboard.ApplicationController.action/2
        (dashboard) web/controllers/application_controller.ex:1: Dashboard.ApplicationController.phoenix_controller_pipeline/2
        (dashboard) lib/dashboard/endpoint.ex:1: Dashboard.Endpoint.instrument/4
        (dashboard) lib/phoenix/router.ex:261: Dashboard.Router.dispatch/2
        (dashboard) web/router.ex:1: Dashboard.Router.do_call/2
        (dashboard) lib/dashboard/endpoint.ex:1: Dashboard.Endpoint.phoenix_pipeline/1
        (dashboard) lib/plug/debugger.ex:93: Dashboard.Endpoint."call (overridable 3)"/2
        (dashboard) lib/dashboard/endpoint.ex:1: Dashboard.Endpoint.call/2

I got this when I selected a record with a primary key that's a :binary_id, and tried to insert that id into the foreign key column of another table that's also a :binary_id. It seems currently Ecto is expecting that value to be converted to a formatted string such as XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX at some point, as if it were being submitted from a form.
This PR allows it to be retrieved as a binary from one table and inserted into another table as a binary without being converted to a string first.

@bradurani bradurani force-pushed the fix_uuid_dump_error branch from dfa6713 to 6b5a6bd Compare July 18, 2016 07:08
@josevalim
Copy link
Member

Thank you but this is not a bug. Ecto.UUID expects the data to be formatted as a string instead of a binary. If you have a binary, you have the wrong data, even if that is meant to be its final shape. For example, should we allow datetimes to kept as binaries as well in the format it is used by the database? I don't think we should. If you want binaries, then you should declare its type as :binary.

@josevalim josevalim closed this Jul 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants