playのEvolutionsでハマったところがあったので備忘録として残しておきます。
ある日のこと
Evolutionsでテーブルを作成しようとした時の話。
以下のように1.sql
を作成し、Playを起動した。
# --- !Ups
create table clients {
id bigint auto_increment not null,
name varchar(255),
client_id varchar(255) not null,
secret varchar(255) not null,
email varchar(255) not null,
user_id varchar(255) not null
}
insert into clients values (default, "Hiroro", "Hiroro0970", "hogehoge", "hiroro@exampple.com", "fuga298")
# --- !Downs
drop table clients;
しかし、画面上にはDatabase 'default' is in an inconsistent
の文字が。
よくみると'create table'のかっこが{}
になっていたので1.sql
を以下のように修正して再起動。
# --- !Ups
create table clients (
id bigint auto_increment not null,
name varchar(255),
client_id varchar(255) not null,
secret varchar(255) not null,
email varchar(255) not null,
user_id varchar(255) not null
)
insert into clients values (default, "Hiroro", "Hiroro0970", "hogehoge", "hiroro@exampple.com", "fuga298")
# --- !Downs
drop table clients;
ところが、またもや画面上にはDatabase 'default' is in an inconsistent
の文字が。
表示されているクエリをみると、以前のものが表示されており反映されていない様子。
キャッシュが残っているのかと思い、何度もプロジェクトをクリーン&ビルドしたが一向に直る気配がない。
エラーログをみても心当たりがないものばかり。
play.api.db.evolutions.InconsistentDatabase: Database 'default' is in an inconsistent state![An evolution has not been applied properly. Please check the problem and resolve it manually before marking it as resolved.]
at play.api.db.evolutions.DatabaseEvolutions.$anonfun$checkEvolutionsState$3(EvolutionsApi.scala:309)
at play.api.db.evolutions.DatabaseEvolutions.$anonfun$checkEvolutionsState$3$adapted(EvolutionsApi.scala:294)
at play.api.db.evolutions.DatabaseEvolutions.executeQuery(EvolutionsApi.scala:341)
at play.api.db.evolutions.DatabaseEvolutions.checkEvolutionsState(EvolutionsApi.scala:294)
at play.api.db.evolutions.DatabaseEvolutions.evolve(EvolutionsApi.scala:263)
at play.api.db.evolutions.DefaultEvolutionsApi.evolve(EvolutionsApi.scala:104)
at play.api.db.evolutions.EvolutionsWebCommands.handleWebCommand(ApplicationEvolutions.scala:496)
at play.core.DefaultWebCommands.$anonfun$handleWebCommand$1(WebCommands.scala:42)
at scala.collection.immutable.Stream.flatMap(Stream.scala:195)
at play.core.DefaultWebCommands.handleWebCommand(WebCommands.scala:42)
原因
ネットで検索してもなかなか解決策が見つからなかったので、ひとまずコンソールに出力されたエラーログから分析していくことにした。
すると、EvolutionsApi.scala
の293行目に
{"select id, hash, apply_script, revert_script, state, last_problem from ${schema}play_evolutions where state like 'applying_%'"
の一文を発見。
どうやら知らぬ間にデータベース内にplay_evolutions
と言うテーブルが作成されているようだ。
何が入っているのかを知るためにとりあえずMySQL(使っているDB)に接続して
select * from play_evolutions;
で中身を見てみる。
出力はこんな感じだった。
id | hash | applied_at | apply_script | revert_script | state | last_problem |
---|---|---|---|---|---|---|
1 | ad61f40497895f0274086616dc2bc8e519244216 | 2019-10-07 22:43:56 | create table clients { id bigint auto_increment not null, name varchar(255), client_id varchar(255) not null, secret varchar(255) not null, email varchar(255) not null, user_id varchar(255) not null } insert into clients values (default, "Hiroro", "Hiroro0970", "hogehoge", "hiroro@exampple.com", "fuga298") | drop table clients | applying_up | You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{ id bigint auto_increment not null, name varchar(255), client_id varchar(255) n' at line 1 [ERROR:1064, SQLSTATE:42000] |
apply_script
のカラムを見てみると、そこには修正前のSQLが!?
どうやら直接1.sql
を起動しているのではなく、このテーブル内のapply_script
に記載されているクエリを実行しているようだった。
解決方法
play_evolutions
内のデータを削除して、Playを再起動してみた。
すると、クエリが更新され、修正した1.sqlが正しく実行された。
以前H2DB(in-memory)
を使ってEvolutionsしていた頃は再起動かけたらきちんと動作してくれたんだけど、よく考えたらそれはin-memoryDBは文字通りインメモリだから再起動かけたらデータベース自体が全て初期化されるからだ。
MySQLとかを使うときはクエリを更新かけたらplay_evolutions
テーブルのデータを削除してから再度試してみよう。