Android SQLite用にスキーマの差分DDLを生成するモジュールを書いた

前回のエントリの続きです。

gfx.hatenablog.com

SQL::Translator::Diffを真似て、Androidマイグレーションモジュールを書いてみました。Orma projectの一部です。

実装は SchemaDiffMigration.java です。

たとえばexampleのTodoクラスはこんな感じになっていますが:

@Table
public class Todo {

    @PrimaryKey
    public long id;

    @Column(indexed = true)
    public String title;

    @Column
    @Nullable
    public String content;

    @Column
    public long createdTimeMillis;
}

これにカラムを一つ追加するとします:

+ @Column
+ @Nullable // nullableでないとカラムのnon-null制約に引っかかるため
+ public Set<String> tags;

そしてアプリを起動するとマイグレーションが走ります*1

CREATE TABLE "__temp_Todo" ("id" INTEGER PRIMARY KEY, "title" TEXT NOT NULL, "content" TEXT NULL, "createdTimeMillis" INTEGER NOT NULL, "tags" BLOB NOT NULL)
INSERT INTO "__temp_Todo" ("title", "createdTimeMillis", "content", "id") SELECT "title", "createdTimeMillis", "content", "id" FROM "Todo"
DROP TABLE "Todo"

カラムの追加だけなら ALTER TABLE ADD CLUMN でもいけますが、SQLiteのALTER TABLE ADD COLUMNは制限が強く、条件の判定が難しいので今はどんなスキーマ変更もテーブルを再定義するようにしています。

スキーマのバージョンは PackageInfo#lastUpdateTime で判断しており、実際にマイグレーションするかどうかはアプリがもっているモデルのスキーマとデータベースのスキーマを比較して判断します。つまりスキーマのバージョンを手動で設定する必要はありません。

とまあこんな感じで、だいたい動くようになりました。まだ作りこみがあまい部分はありますが、かなり便利になりそうな手応えは感じます。

関連エントリ

*1:debug buildでSQLがログ出力されます。