2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ecto.migrationでPostgreSQLのカラム属性をstringからintegerに変更時の注意点

Last updated at Posted at 2022-01-18

経緯

カラムの属性をintegerで作るつもりだったのに phx.gen.html 時にタイプミスしてしまって、stringに:scream:

$ mix phx.gen.html MovieCxt Movie movies title:string summary:string year integer

year:integerとすべきところを year integerとしてしまったために、
year:stringinteger:stringのカラムが作られてしまった:sweat:  

yearカラムの属性をintegerに変更し、integerカラムは削除したい。

まず試したこと

migrationファイルを作成し・・・

mix ecto.gen.migration mod_col_movies

priv/repo/migrations/<タイムスタンプ>_mod_col_movies.exsファイルを編集

priv/repo/migrations/<タイムスタンプ>_mod_col_movies.exs
  def change do
    alter table("movies") do
      modify :year, :integer
      remove :integer 
    end
  end

そしてmigrate...

$ mix ecto.migrate

見事に失敗

15:37:10.229 [info]  alter table movies
** (Postgrex.Error) ERROR 42804 (datatype_mismatch) 列"year"は型integerには自動的に型変換できません

    hint: 必要に応じて"USING year::integer"を追加してください。
    (ecto_sql 3.7.1) lib/ecto/adapters/sql.ex:760: Ecto.Adapters.SQL.raise_sql_call_error/1
    (elixir 1.13.1) lib/enum.ex:1593: Enum."-map/2-lists^map/1-0-"/2
    (ecto_sql 3.7.1) lib/ecto/adapters/sql.ex:852: Ecto.Adapters.SQL.execute_ddl/4
    (ecto_sql 3.7.1) lib/ecto/migration/runner.ex:343: Ecto.Migration.Runner.log_and_execute_ddl/3
    (ecto_sql 3.7.1) lib/ecto/migration/runner.ex:117: anonymous fn/6 in Ecto.Migration.Runner.flush/0
    (elixir 1.13.1) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto_sql 3.7.1) lib/ecto/migration/runner.ex:116: Ecto.Migration.Runner.flush/0
    (ecto_sql 3.7.1) lib/ecto/migration/runner.ex:280: Ecto.Migration.Runner.perform_operation/3

よくわからんけどポスグレ固有の問題?

 次に試したこと

 余計なカラムをまず消す

問題の切り分けにもなるので、
とりあえず、integerカラムは先に消すことに。
先ほどのファイルを変更

  def change do
    alter table("movies") do
      remove :integer 
    end
  end

そしてmigrate。これは成功
※ 実際は、この後、html.heexやモデルから該当カラムを削除。本題から外れるので記述は省略。

$ mix ecto.migrate

15:47:35.899 [info]  == Running 20220118054701 StdApp.Repo.Migrations.ModColToMovies.change/0 forward

15:47:35.906 [info]  alter table movies

15:47:35.950 [info]  == Migrated 20220118054701 in 0.0s

executeでalter table文発行

このままstringでもバリデーションで逃げてもいいかなと思ったけど、elixirforumで以下の投稿を発見

どうやら、PostgreSQLのalter table 文を直接書くらしい。 ありがたく参考にさせてもらうことにした。

新たにmigrationファイルを作成

$ mix ecto.gen.migration mod_col_attr_movies

以下のように記述

defmodule StdApp.Repo.Migrations.ModColAttrMovies do
  use Ecto.Migration

   def up do
      execute """
        alter table movies alter column year type integer using (year::integer)
       """
   end

   def down do
      execute """
        alter table movies alter column year type varchar(255);
       """
   end
end

migrate...

$ mix ecto.migrate

16:02:13.928 [info]  == Running 20220118065531 StdApp.Repo.Migrations.ModColAttrMovies.up/0 forward

16:02:13.939 [info]  execute " alter table movies alter column year type integer using (year::integer)\n"

16:02:14.107 [info]  == Migrated 20220118065531 in 0.1s

成功!

モデルの属性も忘れずに変更

    <省略>
  schema "movies" do
    <省略>
        field :year, :integer
    <省略>
  end
  <省略>

タイプミスしたおかげで、余計な時間がかかってしまった。。
でも記事のネタができたからヨシとするか:sweat_smile:

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?