etimologia docs elixir phoenix-framework ecto

elixir - docs - ecto etimologia



Modificar clave foránea en ecto. (4)

No creo que se pueda lograr con alter table . Por ejemplo, de acuerdo con esta respuesta, Postgres no permite modificar restricciones en la declaración ALTER TABLE . MySQL tampoco permite modificar restricciones .

Lo más fácil sería eliminar el campo y volver a agregarlo si no tiene datos. De lo contrario, necesitas usar SQL en bruto con execute

Tengo esta migración original que ya se ha ejecutado y enviado en sentido ascendente:

create table(:videos) do add :url, :string add :title, :string add :description, :text add :user_id, references(:users, on_delete: :nothing) timestamps end create index(:videos, [:user_id])

Ahora deseo cambiar la clave foránea en user_id a eliminaciones en cascada, de modo que cuando un usuario sea eliminado, todos sus videos asociados también serán eliminados.

He intentado la siguiente migración:

alter table(:videos) do modify :user_id, references(:users, on_delete: :delete_all) end

Pero esto plantea un error:

(Postgrex.Error) ERROR (duplicate_object): constraint "videos_user_id_fkey" for relation "videos" already exists

¿Cómo puedo formular un script de migración que cambie esta clave externa de acuerdo con mi requerimiento?

ACTUALIZAR

Terminé con la siguiente solución:

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

esto elimina la restricción antes de que ecto intente volver a crearla.


No estoy seguro de cuándo se agregó a Ecto, pero al menos en 2.1.6 ya no hay necesidad de SQL en bruto. drop/1 ahora soporta restricciones :

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


Puedes soltar el índice antes de llamar a alter :

drop_if_exists index(:videos, [:user_id]) alter table(:videos) do modify :user_id, references(:users, on_delete: :delete_all) end

Hacer lo contrario es un poco más complicado:

execute "ALTER TABLE videos DROP CONSTRAINT videos_user_id_fkey" create_if_not_exists index(:videos, [:user_id])


Terminé con la siguiente solución:

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

esto elimina la restricción antes de que ecto intente volver a crearla

Copiado de la pregunta.