モバイルアプリのデータベースマイグレーションを考える

モバイルアプリのデータベースのマイグレーションをORMで実装するにはどうしたらいいか考えている。

Perl界隈だと SQL::Translator::Diff というモジュールが知られていて、たとえば以下のようにDDLの「差分」をとることができる。

$ cpanm SQL::Translator::Diff

$ cat old.sql
CREATE TABLE foo (
    id INTEGER PRIMARY KEY,
    title TEXT
);

$ cat new.sql
CREATE TABLE foo (
    id INTEGER PRIMARY KEY,
    title TEXT,
    content TEXT
);

$ sqlt-diff old.sql=SQLite new.sql=SQLite
-- Convert schema 'old.sql' to 'new.sql':;

BEGIN;

ALTER TABLE foo ADD COLUMN content TEXT;

COMMIT;

これを実際のサーバーサイドアプリケーションの開発に取り入れるためのノウハウもある。

しかし、これは差分を人の目で確認することが前提となっていると思われる。たとえば、カラムやテーブルのrenameは単に追加と削除の組み合わせとして認識されてしまい、正しくrenameとはならない。DDLの差分としては正しいけど、マイグレーションとしては必ずしも適切ではないというわけだ。

モバイルアプリのマイグレーションは、SQLiteを使うという前提を置いたとしても、完全に自動化はできない。自動化できるのは、 CREATE TABLEALTER TABLE ADD COLUMN だけだ。それ以外については、Railsマイグレーションのように、一つ一つの差分を積み上げる形式がおそらく一番よい。

というわけで、モバイルアプリのマイグレーションは2つの方法で実装する。

  • 単純な CREATE TABLEALTER TABLE ADD COLUMN は自動的に検出して実行する
  • それ以外のマイグレーションは、Railsのように手動で行う
    • ただし、Railsのようにちょっとした変更のたびに細かく行うのはモバイルアプリでは実行コストがそれなりに高い
    • そこで、アプリケーションのバージョンがかわるごとに一度マイグレーションを行うものとする

このへんが妥当な線だと思う。また、マイグレーションテストを簡単に行うためのユーティリティも提供すべきだと思われる。

See also:

AndroidのORMに求めること、あるいはOrmaを開発した話 - Islands in the byte stream