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)