Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Can't rollback change_column #169

Open
zedalaye opened this issue Aug 28, 2014 · 1 comment
Open

Can't rollback change_column #169

zedalaye opened this issue Aug 28, 2014 · 1 comment

Comments

@zedalaye
Copy link

I coded this migration :

class ChangeForeignKeyConstraints < ActiveRecord::Migration

  def self.up
    change_column :profiles, :company_id, :integer, foreign_key: { references: :companies, on_update: :cascade, on_delete: :cascade }
    [ :addresses, :web_links, :distributors, :customers ].each do |table|
      change_column table, :profile_id, :integer, foreign_key: { references: :profiles, on_update: :cascade, on_delete: :cascade }
    end
  end

  def self.down
    [ :addresses, :web_links, :distributors, :customers ].reverse.each do |table|
      change_column table, :profile_id, :integer, foreign_key: { references: :profiles, on_update: :no_action, on_delete: :no_action }
    end
    change_column :profiles, :company_id, :integer, foreign_key: { references: :companies, on_update: :no_action, on_delete: :no_action }
  end

end

What's strange is that the "up" migration works while "down" fails with this message :

StandardError: An error has occurred, this and all later migrations canceled:

PG::DuplicateTable: ERREUR:  the relation « fk__customers_profile_id » already exists: 
CREATE INDEX "fk__customers_profile_id" ON "customers" ("profile_id")

Please note that even for the "up" migration, the foreign key ALREADY exists. I just wanted to alter on_delete and on_update to :cascade (and revert them to :no_action on rollback)

@zedalaye
Copy link
Author

More interresting is that after the "up migration" call to change_column an index fk__[table]_[reftable]_[refcolumn] has been created.

This index cause the rollback migration to fail (and the prevent the "up migration" to be run again).

The fact is that this index is a duplicate as foreign keys are already indexed with PostgreSQL. Seems that add_column (or t.integer :column, :foreign_key => true) takes that in account while change_column don't.

This is how the distributors table looks like in schema.rb after running the "up migration" :

  create_table "distributors", force: true do |t|
    t.integer :profile_id
    # ... fields ...
    t.datetime "created_at"
    t.datetime "updated_at"
    t.index ["profile_id"], :name => "fk__distributors_profile_id"
    t.index ["profile_id"], :name => "index_distributors_on_profile_id"
    t.foreign_key ["profile_id"], "profiles", ["id"], :on_update => :cascade, :on_delete => :cascade, :name => "fk_distributors_profile_id"
  end

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant