🔨

【Rails】Ridgepole 使用時に主キーを変更すると起こるエラー

2023/07/12に公開

はじめに

RidgepoleでRailsのDBスキーマ管理をしている際に出会った[ERROR] PG::DuplicateColumn: ERROR: column "***" of relation "***" already existsのエラーについてまとめます。

エラー概要

下のようにprimary_keyがcodeカラムになるようにSchemafileを記述していました。

Schemafile
create_table "companies", force: :cascade, id: false do |t|
  t.string "code", primary_key: true, comment: "企業コード"
  t.string "name", comment: "企業名"
end

2回目以降のapply時に下のような[WARNING]と[ERROR]が発生していました。

$ ridgepole --config config/database.yml --apply --file db/Schemafile # 1回目
Apply `db/Schemafile`
-- create_table("companies", {:id=>false})
   -> 0.0058s

$ ridgepole --config config/database.yml --apply --file db/Schemafile # 2回目
Apply `db/Schemafile`
[WARNING] Primary key definition of `companies` differ but `allow_pk_change` option is false
  from: {:id=>{:type=>:string, :comment=>"企業コード"}}
    to: {:id=>false}

[WARNING] PostgreSQL doesn't support adding a new column except for the last position. companies.code will be added to the last.
-- add_column("companies", "code", :string, {:primary_key=>true, :comment=>"企業コード"})
[ERROR] PG::DuplicateColumn: ERROR:  column "code" of relation "companies" already exists

* 1: add_column("companies", "code", :string, **{:primary_key=>true, :comment=>"企業コード"})
	/usr/local/bundle/gems/activerecord-7.0.5/lib/active_record/connection_adapters/postgresql/database_statements.rb:48:in `exec'

警告とエラー内容を見てみても、

  • [WARNING] Primary key definition of companies differ but allow_pk_change option is false...
  • [WARNING] PostgreSQL doesn't support adding a new column except for the last position. companies.code will be added to the last.
  • [ERROR] PG::DuplicateColumn: ERROR: column "code" of relation "companies" already exists

何が間違っているのかわかりませんねー
本来は、変更をしていない場合2回目以降のapplyにはNo changeと表示されるはずです。

解決方法

下のようにSchemafileを書き換えました。

Schemafile
create_table "companies", force: :cascade, primary_key: "code", id: { type: :string, comment: "企業コード" } do |t|
  t.string "name", comment: "企業名"
end

id: falseの代わりにprimary_key:を指定するように変更しました。

修正後に再度applyを実行すると、

$ ridgepole --config config/database.yml --apply --file db/Schemafile
Apply `db/Schemafile`
No change

primary_keyをid以外に設定しても、2回目以降のapply時にエラーが発生しなくなりました。

Discussion