Modify foreign key in Ecto
I ended up with the following solution:
def up do
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
end
def down do
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
alter table(:videos) do
modify :user_id, references(:users, on_delete: :nothing)
end
end
this drops the constraint before ecto tries to recreate it
Copied from the question.
You can drop the index before calling alter
:
drop_if_exists index(:videos, [:user_id])
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
Doing the opposite is a little trickier:
execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey"
create_if_not_exists index(:videos, [:user_id])
I'm not sure when this was added to Ecto, but at least in 2.1.6 there's no need for raw SQL anymore. drop/1
now supports constraints (drop_if_exists/1
doesn't though):
def up do
drop constraint(:videos, "videos_user_id_fkey")
alter table(:videos) do
modify :user_id, references(:users, on_delete: :delete_all)
end
end
def down do
drop constraint(:videos, "videos_user_id_fkey")
alter table(:videos) do
modify :user_id, references(:users, on_delete: :nothing)
end
end
In Ecto SQL 3.4.3:
"If the :from
value is a %Reference{}
, the adapter will try to drop the corresponding foreign key constraints before modifying the type."
modify :user_id, references(:users, on_delete: :delete_all), from: references(:users)
Should work. In working on a rollback, I worked out that this worked to clear the FK and remove the column:
remove :user_id, references(:users)