Perl製のデータベースマイグレーションツール｢Anego｣入門

# ｢Anego｣とは?

[Anego](https://metacpan.org/release/PAPIX/Anego-0.01_01)という, Perl製のデータベースマイグレーションツールを作りました.

Ruby on Railsであれば標準でデータベースのマイグレーションのための仕組みが用意されていますが, Perlの場合その辺りは自前で用意しなければなりません.
CPANには, データベースのマイグレーションとして[DBIx::Migrate](https://metacpan.org/pod/DBIx::Migrate), [DBIx::Migration](https://metacpan.org/pod/DBIx::Migration), [GitDDL](https://metacpan.org/pod/GitDDL), [GitDDL::Migrator](https://metacpan.org/pod/GitDDL::Migrator)などが提供されていますが,

- DBIx::Migrate ... 最終更新が2003年
- DBIx::Migration ... 最終更新が2010年
- GitDDL / GitDDL::Migrator ... 自分のユースケースでは少しオーバースペックに感じた
    - スキーマのバージョンを保存するための~~データベース~~テーブルを生成するところなど

というわけで, PerlのWebアプリケーションを開発する場面では, [SQL::Translator::DiffでDBスキーマに追従させる方法](http://memo.sugyan.com/entry/20121214/1355471891)を参考に, SQL::Translator::Diffを使った独自のマイグレーションスクリプトを用意して開発を進めていました.

とはいえ, 毎回プロジェクトが始まる度に用意するのも面倒ですし, 機能追加をする度に反映させていくのも正直面倒になってきたので, この機会にモジュールとして切り出そう! ということで出来上がったのが, Anegoです.

...ちなみに, Anegoという名前は, @karupanerura さんが開発されているPerl製のORM, [Aniki](https://metacpan.org/pod/Aniki)にインスパイア(?)されて名づけました.
実際, AnegoはAnikiと非常に簡単に組み合わせることが出来るので, 興味があれば是非Anikiも試してみてください.

# ｢Anego｣のインストール

Anegoは現在Developer Releaseですので, 次のようにバージョンを指定してインストールする必要があります:

```
$ cpanm Anego@0.01_01
--> Working on Anego
Fetching http://www.cpan.org/authors/id/P/PA/PAPIX/Anego-0.01_01.tar.gz ... OK
Configuring Anego-0.01_01 ... OK
Building and testing Anego-0.01_01 ... OK
Successfully installed Anego-0.01_01
1 distribution installed
```

`cpanfile`に記載する場合は, 次のようにしましょう:

```cpanfile:perl
requires 'Anego', '== 0.01_01';
```

# ｢Anego｣入門

それでは, 具体的なAnegoの使い方を説明していきます.
※なお, この記述はAnego 0.01_01に準拠しています.

## スキーマの作成 - DBIx::Schema::DSL

まずは, Anegoで管理するデータベースのスキーマを作っていきましょう.
Anegoでは, MySQLなどのDDLではなく, [DBIx::Schema::DSL](https://metacpan.org/pod/DBIx::Schema::DSL)を使ってスキーマを定義し, これを管理します(既にDDLやデータベースが存在する場合, [DBIx::Schema::DSL::Dumper](https://metacpan.org/pod/DBIx::Schema::DSL::Dumper)から生成するのがオススメです).

ここでは, `lib/MyApp/DB/Schema.pm`というファイルに, `MyAPP::DB::Schema`というクラスとして設置することにしましょう.

```perl:lib/MyApp/DB/Schema.pm
package MyApp::DB::Schema;
use strict;
use warnings;

use DBIx::Schema::DSL;

create_table 'module' => columns {
    integer 'id', primary_key, auto_increment;
    varchar 'name';
    integer 'author_id';

    add_index 'author_id_idx' => ['author_id'];

    belongs_to 'author';
};

create_table 'author' => columns {
    integer 'id', primary_key, auto_increment;
    varchar 'name', unique;
};
```

## 設定ファイル - `.anego.pl`

続いて, Anegoの設定ファイルを用意します.
Anegoの設定ファイルは, `.anego.pl`として保存します:

```perl:.anego.pl
+{
    "connect_info" => ["dbi:mysql:database=anego;host=localhost", "root"],
    "schema_class" => "MyApp::DB::Schema",
}
```

`connect_info`はデータベースに接続する為の情報, `schema_class`は先ほどDBIx::Schema::DSLで定義したスキーマのクラス名を指定します(このクラスを, 以降"スキーマ定義用クラス"と呼ぶことにします).

これで準備は完了です.

## マイグレーション実行 - `anego migrate`

マイグレーションを実行は, `anego migrate`コマンドです.

```
$ anego migrate
Migrated
```

`anego migrate`の場合, 現在の最新のスキーマ(現時点のスキーマ定義用クラスで定義されているスキーマ)でマイグレーションが行われます.

```
$ anego migrate
target schema == database schema, should no differences
```

`anego migrate`コマンドによるマイグレーションは, データベースの現状のスキーマと, マイグレーション対象となるスキーマに差分があるときだけ行われます.
そのため, もう一度`anego migrate`でマイグレーションを行おうとすると, 上記のように｢スキーマに違いがありません｣という結果になります.

## ステータスの表示 - `anego status`

`anego status`コマンドは, 現在のAnegoの設定を表示します:

```
$ anego status

RDBMS:        MySQL
Database:     anego
Schema class: MyApp::DB::Schema (lib/MyApp/DB/Schema.pm)

Hash     Commit message
--------------------------------------------------
8514849  initial commit
```

RDBMS, データベースの名前, そしてスキーマ定義用クラスのクラス名と, そのパスが表示されます.

更に, Gitのコミットログの情報を使って, スキーマ定義用クラスが変更されたコミットについて, そのコミットのハッシュ値と, コミットメッセージも表示します.

例えば, `MyApp::DB::Schema`ので定義した`module`テーブルに, `text`型の`description`カラムを追加してから, `fix schema`というコミットメッセージでコミットしたとすると, `anego migration`の結果は次のようになります:

```
$ anego status

RDBMS:        MySQL
Database:     anego
Schema class: MyApp::DB::Schema (lib/MyApp/DB/Schema.pm)

Hash     Commit message
--------------------------------------------------
3b9b127  fix schema
8514849  initial commit
```

## 任意のスキーマへのマイグレーション - `anego migrate revision [HASH]`

`anego migrate revision [HASH]`で, 任意のコミットのハッシュ値(`[HASH]`)におけるスキーマ定義用クラスの状態へ, データベースをマイグレーションすることができます.

先ほどの`anego status`で出てきた, `3b9b127`というコミットハッシュ値で表されるコミット時のスキーマ定義用クラスの内容にデータベースをマイグレーションさせたい場合, 次のようにします.

```
$ anego migrate revision 3b9b127
Migrated!
```

# まとめ

Perl製のデータベースマイグレーションツール｢Anego｣の使い方について, 簡単に説明しました.
まだまだ開発版なので, 今後機能追加や仕様変更などあるかもしれません. また, IssueやPull Requestも募集中です.

ご興味があれば, この機会に是非Anegoを使ってみてください!