sensiblearts
I had a unique constraint,
def change do
create table(:couplets, primary_key: false) do
add :id, :binary_id, primary_key: true
add :idx, :integer
add :dkey_id, references(:dkeys, on_delete: :delete_all, type: :binary_id)
timestamps()
end
create unique_index(:couplets, [:dkey_id, :idx])
end
But it was failing on this:
Repo.transaction(fn() ->
with {:ok, deleted_couplet} <- Repo.delete(couplet)
do
{:ok, _previous} = update_previous_couplet(previous, from_lead, nil)
{:ok, dkey} = Guide.update_dkey(dkey, %{couplet_count: idx})
# fails here:
(from c in Couplet, where: c.idx > ^couplet.idx)
|> Repo.update_all(inc: [idx: -1])
{deleted_couplet, dkey}
else
{:error, changeset} ->
Repo.rollback(changeset)
end
end)
Which led me to this potential fix:
…which looks like this:
defmodule Treeteacher.Repo.Migrations.ModifyCoupletsDkeyIdIdxUniqueConstraint do
use Ecto.Migration
def up do
execute("""
DROP INDEX couplets_dkey_id_idx_index;
""")
execute("""
ALTER TABLE couplets
ADD CONSTRAINT unique_couplet_dkey_id_idx unique (dkey_id, idx)
DEFERRABLE INITIALLY IMMEDIATE;
""")
end
def down do
execute("""
ALTER TABLE couplets
DROP CONSTRAINT unique_couplet_dkey_id_idx;
""")
execute("""
CREATE UNIQUE INDEX couplets_dkey_id_idx_index
ON couplets
USING btree (dkey_id, idx);
""")
end
end
and
Repo.transaction(fn() ->
# ...
# still fails here:
Repo.query!("SET CONSTRAINTS unique_couplet_dkey_id_idx DEFERRED")
(from c in Couplet, where: c.idx > ^couplet.idx)
|> Repo.update_all(inc: [idx: -1])
# ...
end)
Also, I tried it both with INITIALLY IMMEDIATE outside the transaction; or with INITIALLY DEFERRED, but there is no difference – constraint is still violated.
Could it be because of the transaction?
Trending in Questions
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
Anyone here using Honeybadger?
My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of
Bandit.HTTPError...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
There are three potential reasons for members of this forum to have a look at https://vutuv.de
You are tired or annoyed of LinkedIn.
Yo...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 5- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
krasenyp
I believe your approach doesn’t work because one of the columns of the deferred constraint is a foreign key. Take a look at the accepted answer - https://dba.stackexchange.com/questions/104987/avoid-unique-violation-in-atomic-transaction.
sensiblearts
Interesting. Thank you, I’ll report back.
sensiblearts
The two solutions I could think of: 1) just remove the constraint and put checks in the elixir code, or 2) clone the value in the FK field (:dkey_id) to another field (:c_dkeyid) in the same schema, then build the deferred constraint on [:c_dkey_id, :idx].
I opted for (2), and it seems to work fine.
Thanks for your help.
krasenyp
Did you try with plain SQL? Your update is so simple, it can be written as a single statement.
sensiblearts
I don’t understand why hand-written SQL would be any better than ecto-written SQL to get arround the fact the “the referenced columns must be the columns of a non-deferrable unique or primary key constraint in the referenced table.”
My uniqueness constraint has to include the :dkey_id field, whis is a FK.
But if I copy the value of :dkey_id into another non-FK column, then I can have the constraint deferred.
Am I missing something?
Thanks.