prkhrkat

prkhrkat

Found a bug in Ecto changeset unique_constraint function

I have a table in which I have put unique constraints on the combination of two fields. I had also defined this in changeset.

def changeset(asset, attrs) do
    asset
    |> cast(attrs, @create_attrs)
    |> validate_required(@required_attrs)
    |> unique_constraint([:serial_number, :organization_id])
  end

But I keep getting this error instead of the object {:error, #Ecto.Changeset…} -

Server: localhost:4000 (http)
Request: POST /api/create_asset
** (exit) an exception was raised:
    ** (Ecto.ConstraintError) constraint error when attempting to insert struct:

    * "assets_organization_id_serial_number_index" (unique_constraint)

If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `unique_constraint/3` on your changeset with the constraint
`:name` as an option.


Until I found out that order also matters when writing the unique_constraint. It worked when i changed it to -

unique_constraint([:organization_id, :serial_number])

So I just wanted to put it here, so that we can fix this bug in the new release. Would also love to contribute if I’m able to fix it by myself.

Thanks

Most Liked

sodapopcan

sodapopcan

This isn’t a bug, the “order” matters at the database level too. Ecto is using :org_id and :serial_number to create the name of the index. Otherwise, the order of compound indexes, at least in postgres, does matter.

al2o3cr

al2o3cr

The default behavior of unique_constraint is tripping you up here:

  • Putting organization_id first in the index makes sense since Postgres can use partial indexes from the left-hand side.
  • But putting serial_number first in the unique_constraint call makes sense too, since you likely want the “is already taken” message on the serial number rather than the organization ID.

One or the other of these has to change. Either:

  • tell unique_constraint the correct name of the index to use with the name: "assets_organization_id_serial_number_index" option
  • pass the fields to unique_constraint in the same order as the index (so the name can be automatically generated), then tell it to put the error on serial_number instead with error_key
prkhrkat

prkhrkat

Thanks @sodapopcan and @al2o3cr It makes sense.

Where Next?

Popular in Discussions Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54921 245
New
AstonJ
I’ve just started the Phoenix part of the utterly brilliant online course by @pragdave. On generating the Phoenix app he uses the --no-ec...
New
chulkilee
Here are the list of HTTP client libraries/wrappers, and some thoughts on HTTP client in general. I’d like to hear from others how they w...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40042 209
New
eteeselink
Hi all, In the last days, two things happened: A blog post titled “They might never tell you it’s broken” made the rounds. It’s about ...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New
AstonJ
Can you believe the first professionally published Elixir book was published just 8 years ago? Since then I think we’ve seen more books f...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54921 245
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement