Closed Danwhy closed 5 years ago
The Ecto uniqueness constraint works on the database level. You need to create a unique index, which will then throw an error if duplicate fields are inserted into the database. Ecto.Changeset.unique_constraint
just catches this error and reports it back.
So we'll have to create our own unique
function that actually checks if a field already exists in the database, in the insert
function, and also in the update
function if the entry_id
does not match.
If possible, we should also detect if a database has a unique index, and throw an error if Alog is used with it.
The following query will return any unique indexes on a table, that aren't the primary key:
SELECT * FROM pg_indexes WHERE tablename = $1 and indexname NOT LIKE '%_pkey' AND indexdef LIKE 'CREATE UNIQUE INDEX%';
, where $1 is the name of our table
We can use this to throw an error if people try to use alog with a table that has a unique index.
Unfortunately it's only possible to perform this check at runtime (unlike checking the presence of fields in the schema which can happen at compile time). We're therefore having to check for indexes every time a user inserts or updates an entry. If anyone can think of a better/more efficient way of doing this, please let me know.
When you apply unique_constraint
to a changeset, it gets added to a constraints
field (which isn't visible if you inspect it, but can be retrieved with Map.get(changeset, :constraints)
, or Ecto.Changeset.constraints(changeset)
in Ecto 3).
We can use this field to validate all constraints before we insert or update an item.
We can't currently use
unique_constraint
with alog because as we append data, it will no longer be unique, and will throw an error when it shouldn't.We will need a way to make sure unique constraint errors are returned only when they should. (ie. in an insert function, but not an update).
Is there a way we can use the existing
unique_constraint
functionality, or will we have to create a new function? Also, will we have a problem if people create aunique_index
in their migration?