bugfix> elixir > 投稿

現在、参照といくつかの一意のインデックスを持ついくつかのテーブルを作成する多数の移行を行っています。 mix ecto.migrate でテーブルを移行したいとき、これはうまく機能しているようですしかし、 mix ecto.rollback をロールバックしたい場合以下のエラーをせきます。ロールバック中にインデックスを処理するために何かを追加するために移行を変更する必要がありますか?

移行手順:

defmodule App.Repo.Migrations.CreateTokens do
  use Ecto.Migration
  def change do
    create table(:tokens) do
      add :token, :string
      add :user_id, references(:users, on_delete: :delete_all, on_update: :update_all)
      timestamps()
    end
    create index(:tokens, [:user_id])
    create unique_index(:tokens, [:token], unique: true, name: :unique_tokens_index)
  end
end

エラーログ:

[info] == Running App.Repo.Migrations.CreateTokens.change/0 backward
[info] drop index unique_tokens_index
[info] drop index tokens_user_id_index
** (Mariaex.Error) (1553): Cannot drop index 'tokens_user_id_index': needed in a foreign key constraint
    (ecto) lib/ecto/adapters/sql.ex:200: Ecto.Adapters.SQL.query!/5
    (ecto) lib/ecto/adapters/mysql.ex:118: anonymous fn/4 in Ecto.Adapters.MySQL.execute_ddl/3
    (elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/adapters/mysql.ex:118: Ecto.Adapters.MySQL.execute_ddl/3
    (ecto) lib/ecto/migration/runner.ex:104: anonymous fn/2 in Ecto.Migration.Runner.flush/0
    (elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/migration/runner.ex:102: Ecto.Migration.Runner.flush/0
    (stdlib) timer.erl:181: :timer.tc/2
    (ecto) lib/ecto/migration/runner.ex:26: Ecto.Migration.Runner.run/6
    (ecto) lib/ecto/migrator.ex:128: Ecto.Migrator.attempt/6
    (ecto) lib/ecto/migrator.ex:106: anonymous fn/4 in Ecto.Migrator.do_down/4
    (ecto) lib/ecto/adapters/sql.ex:576: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
    (db_connection) lib/db_connection.ex:1283: DBConnection.transaction_run/4
    (db_connection) lib/db_connection.ex:1207: DBConnection.run_begin/3
    (db_connection) lib/db_connection.ex:798: DBConnection.transaction/3
    (ecto) lib/ecto/migrator.ex:262: anonymous fn/4 in Ecto.Migrator.migrate/4
    (elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
    (ecto) lib/mix/tasks/ecto.rollback.ex:79: anonymous fn/4 in Mix.Tasks.Ecto.Rollback.run/2
    (elixir) lib/enum.ex:737: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:737: Enum.each/2

回答 1 件
  • ecto.rollback  通常、インデックスなどがある場合でも機能します。エラーメッセージを読むと、他のテーブルで外部キーとして使用されているキーを持つテーブルをロールバックしようとしていることが問題のようです。おそらく、移行の順序に問題がある可能性があります。

    たとえば、この移行がある場合

    defmodule App.Repo.Migrations.CreateTokens do
      use Ecto.Migration
      def change do
        create table(:tokens) do
          add :token, :string
          add :user_id, references(:users, on_delete: :delete_all, on_update: :update_all)
          timestamps()
        end
        create index(:tokens, [:user_id])
        create unique_index(:tokens, [:token], unique: true, name: :unique_tokens_index)
      end
    end
    
    

    あなたの CreateUsers  CreateTokensは CreateUsers に依存しているため、最初に移行を作成する必要があります(これはファイル名のタイムスタンプが小さいことを意味します)  foreign_keysを確立します。

    このエラーは、おそらく移行を生成し、後で自分でそれを変更しようとしていることが原因です。移行は時間と順序に依存するため、Userテーブルも作成していない場合、ユーザーを参照するトークンテーブルを作成できないことに注意してください。

    mix ecto.reset を実行してみることができます  しかし、ロールバックしようとするとエラーが発生するため、 mix ecto.migrate を実行するとエラーが発生する可能性が高い

    解決策は、移行の順序を修正するか、さらに移行に分割することです...など:CreateUsers、CreateTokens、CreateForeignKeys

あなたの答え