scheman diff
https://github.com/r7kamura/scheman
旅行を兼ねて沖縄に開発合宿に来ているので、1日目の成果を書き出しておく。
目的
Webアプリの開発フローで次のような状態を実現したい。
- DBの変更のたびに変更用のSQLやMigrationファイルを人間が書かなくて良い
- migrationファイルを書く代わりに人間はスキーマを編集する
- スキーマはSQLで記述できる (DSLの使用を強制されない)
- SQL以外の言語でも記述できる (DSLを使用しても良い)
方針
次のような実装を試みた。
- SQLを構文解析してスキーマデータに変換する (解析器は事前に実装済み)
- 適用すべきSQLを2つのスキーマデータの差分から自動で計算する
- SQL以外の解析器も作成可能に
scheman diff
scheman diffというコマンドを実装した。
これは変更前後の二つのスキーマの差分を標準出力するコマンド。 変更前後のスキーマはファイルパスで指定できるほか、変更前のスキーマは標準入力からでも入力できる。 また、変更後のスキーマのパスは指定しなければデフォルトで./schema.sqlを利用する。 例えば、以下の行は全て同じ挙動になる。
$ scheman diff --before before.sql --after schema.sql $ cat before.sql | scheman diff --after schema.sql $ cat before.sql | scheman diff
with mysqldump
標準入力経由でスキーマを入力できるので、例えばmysqldumpの出力をschemanに入力できる。 mysqldumpは--no-dataと--compactオプションを付ければ、ほぼCREATE TABLEだけを生成するようになる。 これを現状のスキーマとして扱い、./schema.sqlを理想のスキーマとして扱うと、 以下のコマンドにより「理想のスキーマに変更するためにはどんなSQLを実行すれば良いか」が分かる。 更に、出力したSQLをmysqlコマンドに渡せば変更内容を適用できる。
$ mysqldump --no-data --compact db\_name | scheman diff $ mysqldump --no-data --compact db\_name | scheman diff | mysql db\_name
難しいところ
- 各種構文の理解 (情報が乏しい)
- DBを構成するデータ構造の理解 (例:「テーブル」の構成要素とは)
- DBと接続する部分との分離 (接続部分までサポートすべきでないという仮説を持っている)
改善するとしたらこの辺
- 既存のWebフレームワーク用のツール (例: rake db:migrateを置き換える)
- MySQLパーサのドキュメント (例: サポート済みの構文一覧)
- 他言語用のパーサ (例: PostgreSQL、SQLite)