How do I recover properly from a unique constraint?

There is a table with a UNIQUE INDEX on the field “documento”. If I try to duplicate a record on this table, I get the following error from Ash:

{:error,
 %Ash.Error.Unknown{
   errors: [
     %Ash.Error.Unknown.UnknownError{
       error: "** (Ecto.ConstraintError) constraint error when attempting to insert struct:\n\n    * \"pessoas_documento_index\" (unique_constraint)\n\nIf you would like to stop this constraint violation from raising an\nexception and instead add it as an error to your changeset, please\ncall `unique_constraint/3` on your changeset with the constraint\n`:name` as an option.\n\nThe changeset defined the following constraints:\n\n    * \"pessoas_pkey\" (unique_constraint)\n",
       field: nil,
       changeset: nil,
       query: nil,
       error_context: [],
       vars: [],
       path: [],
       stacktrace: #Stacktrace<>,
       class: :unknown
     }
   ],
...

I’d like to properly catch this specific error (unique constraint) and act accordingly.

The main reason for that is that I have to “try” to insert a record on the table. If it does not exist, it should be inserted. If it already exists, I have to retrieve it. I can’t SELECT before INSERT because of race condition.

Are you using the migration generator? i.e is there an Ash identity corresponding to this unique constraint? If its something you added yourself, you’d need to configure it in the postgres block to tell Ash about it, like so:

postgres do
  ...
  unique_index_names [{[:the, :fields], "pessoas_documento_index", "your error message here"}]
end

Gotcha. Thanks, @zachdaniel.

BTW, I’m sorry I’m posting here in a daily basis, but I couldn’t find this kind of information on the docs. Before I come here, I try to find what I’m looking for there, but most part of the time I get stucked.

No problem :slight_smile: I’d recommend checking the DSL docs to look for options that seem like they might do what you want, i.e in ash_postgres the DSL for AshPostgres.DataLayer

https://hexdocs.pm/ash_postgres/dsl-ashpostgres-datalayer.html#postgres-unique_index_names

But it’s not a problem to ask questions :slight_smile: Perhaps in the future you can make some PRs to help us improve the docs :smiley:

1 Like

but I’ll be the first to admit that the DSL docs are not always clear. We’ll be improving docs significantly in the future.

1 Like

I’ll do that. Thanks for all your support, @zachdaniel. I’m moving on the project I’m developing. I’m not moving as fast as I’d like, but I’s still confident that Ash was/is the right bet.

2 Likes