PlayのEvolutionsでクエリが更新されてなくて困った時の話

playのEvolutionsでハマったところがあったので備忘録として残しておきます。

## ある日のこと
Evolutionsでテーブルを作成しようとした時の話。
以下のように`1.sql`を作成し、Playを起動した。

```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`の文字が。

<img width="1276" alt="スクリーンショット 2019-10-08 12.40.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412663/fc4a2e70-ea7c-e34e-d9bf-570ca6370dde.png">

よくみると'create table'のかっこが`{}`になっていたので`1.sql`を以下のように修正して再起動。

```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`の文字が。

<img width="1276" alt="スクリーンショット 2019-10-08 12.40.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412663/fc4a2e70-ea7c-e34e-d9bf-570ca6370dde.png">


表示されているクエリをみると、以前のものが表示されており反映されていない様子。
キャッシュが残っているのかと思い、何度もプロジェクトをクリーン&ビルドしたが一向に直る気配がない。

エラーログをみても心当たりがないものばかり。

```
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`テーブルのデータを削除してから再度試してみよう。