読者です 読者をやめる 読者になる 読者になる

SQL::Translator の罠

今までデータベースのマイグレーション

DBIx::Migration - Seamless DB schema up- and downgrades - metacpan.org

を使っていた。スキーマを変えるためのクエリをそのまま保存すれば migrate できるので非常にお手軽。ではあったものの、変更の数があまり多くなると現在のスキーマを確認するのが面倒臭くなってきたので、別の方法を探していたところ、

papix.hatenablog.com

などを見つけた。が、 Anego も GitDDL も、ちょっと求めているものとは違う感じなので、 SQL::Translator を生で使おうかといろいろ試したのだが、これがまあ酷い品質だった。

本当はもっときっちりまとめたかったが、数が数なんで箇条書きで。なお GitHub で一応開発は続いているようで、このうちの1つ2つは直っているっぽい。ちゃんと確認はしていないが。

  • ファイルの読み込みで encode してくれないので、非 ASCII 文字は化ける。 filename() は使わず自前で読み込んで、 data() に渡せばおけ。
  • SQL::Translator::Schema::Table->options にデータを追加する方法がわかりづらい。 ListAttr という独自の Moo::Role を使っている上、 options を読み込む SQL::Translator::Producer::MySQL 側のコードもわかりづらい。
    • $table->options({ $key => $value }, { ... }, ...)の形か、追加モードなので options() を複数回実効してもいい、模様。
  • SQL::Translator::Parser::DBI::MySQL からスキーマを持って来ると、 AUTO_INCREMENT の初期値まで入るので鬱陶しいが、その初期値を SQL::Translator::Schema::Table->options から削除するのがまたやっかい。
  • DBI->connect の第4引数が固定。つまり mysql_enable_utf8 とか使えない……。 dbh を生で渡せるので、自前で用意して渡す。ただし、 SQL::Translator::Parser::DBI 側のデフォルトの第4引数に追加する形にしないと問題が出うる。
  • ほとんどのメソッドが die せず戻り値が偽であることによってエラーを表現している。ぜんぶチェックするのは大変なので、 new() か translate() あたりにぜんぶパラメータ突っ込んで、まとめて対応するのがよさそう。
  • filters() 周りの挙動が、ドキュメントと実装でかなり異なっている。
  • SQL::Translator::Filter::DefaultExtra がどうも完全に壊れている。十分に検証はできていないが。
  • SQL::Translator::Parser::MySQL でコメント周りのパースがおかしく、コメントの位置によっては落ちる。
  • これは MySQL の仕様的なところもあるが、 BOOL などはデータベースから引いてくると tinyint(1) になるがその辺を吸収してくれない。

どうにもコードが汚くて読むのが本当につらかった。これ Moo ベースなんだけど、せめて Moo なしだったならもうちょっと読みやすかったんじゃないだろうか。

あと、自分の使い方的には INSERT も見て欲しいんだけどそこは無視される。まあ仕方ないけど、どうしたもんだろう。

機能的には便利なので、これベースで簡単なスクリプト書いて DBIx::Migration の代わりにするつもり。