sqldefのリポジトリ
これは何か
Ridgepoleというツールをご存じでしょうか。
これはRubyのDSLでcreate_table
やadd_index
等を書いてスキーマ定義をしておくとそれと実際のスキーマの差異を埋めるために必要なDDLを自動で生成・適用できる便利なツールです。一方、
で言われているように、Ridgepoleを動作させるためにはRubyやActiveRecordといった依存をインストールする必要があり、Railsアプリケーション以外で使う場合には少々面倒なことになります。*1
そこで、Pure Goで書くことでワンバイナリにし、また別言語圏の人でも使いやすいよう、RubyのDSLのかわりに、誰でも知ってるSQLでCREATE TABLE
やALTER TABLE
を書いて同じことができるようにしたのがsqldefです。
使用例
現時点ではMySQLとPostgreSQLへの対応を目指しているのですが、このツールはmysqlコマンドやpsqlコマンドとインターフェースを揃えるため、 それぞれのDBに対しmysqldef、psqldefという別のコマンドを提供しています。
README用にgifアニメを用意しておいたので、こちらで雰囲気を感じてください。
どうやって動いているのか
mysqldef
簡単ですね。go-sql-driver/mysqlというPure GoのMySQLのDBドライバを使っており、mysql(1)やlibmysqlclientに依存していません。
psqldef
これもlib/pqというPostgreSQLのDBドライバがPure Goのため、こちらもpsql(1)やlibpqに依存していません。
pg_dump への依存は、クエリだけでスキーマを取れるようにし、そのうちなくせたらいいなと思ってます。
実装済の機能
- MySQL
- カラムの追加、削除
- テーブルの追加、削除
- インデックスの追加、削除
- PostgreSQL
- カラムの追加、削除
- テーブルの追加、削除
MySQLでの動作は多少遊べるくらいの水準で、PostgreSQLは僕があんまり詳しくないのと使ってるSQLパーサーの関係もあって割と壊れてる状態ですが、どちらもそのうちいい感じにするつもりです。カラムやインデックスの種類の変更の反映とか、外部キーの対応とか。
また、あまり無駄にシミュレートをがんばりたくないのと、どうせ対応しても僕は使わないので、CREATE TABLE
と一部のALTER TABLE
の羅列以外の入力に対応していません。DROPは常に書いてあるものを消すことで生成する想定です。
現状の問題点
vitessio/vitessというツールの内部から切り出されたxwb1989/sqlparserというSQLパーサを使っているのですが、どうもこれがDDLのパースのサポートが弱く、そもそもこのツール向きじゃないようです。
ADD INDEXもパースできなくて致命的なので既にフォークしてるんですが、パースエラーが発生してもerrorを返さない(ログを吐くだけ)インターフェースな上、エラーになった状態でASTにアクセスするとSEGVしてしまいます。特にPostgreSQLだと割と簡単な正常系でもこれを引く状態です。MySQLでも型名をtypoするとこれになります。
なのでまあ、SQLパーサはDDLに特化した簡単な奴を作り直して内部に持つようにしようと考えています。
お試しください
まだ本番じゃ全然使えないクオリティなんですが、ISUCONがMySQLで出題された場合とかは割と便利に使えるかもしれません。 sqldefがそのまま使えるスキーマ定義が置いてあることが多いようですし。*2
そういうわけで、よろしくお願いします