Cloud Spanner の DDL parser と DDL 変換ツールを作った
Cloud Spanner の DDL parser の Go 実装と、 Spanner DDL を MySQL DDL っぽいものに変換するツールを作りました。 本記事はこれらの紹介になります。
spar: Cloud Spanner DDL parser in Go
Spanner の DDL は こんな感じ で、 SQL 方言に見えるもののカラムの型だの INTERLEAVE
だの、仕様に対して独自の文法も結構な割合で持っているように見えます。
今回作った spar, DDL parser はこれらをパースして CREATE
文や ALTER
文などの構成要素をまとめて返してくれます。
同リポジトリに同梱した DDL syntax checker のコードがシンプルな使用例としても有用です。
parser
package の持つ Parse()
に読みたい DDL の Reader を渡すとパースした結果を返してくれます。
package main import ( "io/ioutil" "log" "os" "strings" "github.com/syucream/spar/src/parser" ) func main() { data, err := ioutil.ReadAll(os.Stdin) if err != nil { log.Fatal(err) } _, err = parser.Parse(strings.NewReader(string(data))) if err != nil { log.Fatal(err) } }
パーサー部分は goyacc を使って生成しています。 また lexer 部分の一部は https://github.com/benbjohnson/sql-parser を参考にしています。
jackup: Jack up your DDL and translate between MySQL and Spanner
スパナときたら今度は別の工具も欲しくなってくると思われます。ということでジャッキを作りました。
jackup は標準入力か -f
オプションで渡したパスのファイルの DDL を参照し、 spar
を使ってパースした後、(現在は CREATE TABLE
, CREATE INDEX
しか読んでくれませんが) MySQL の同じような構造を持つ DDL を出力してくれます。
残念ながら一部の変換、特にカラムの長さに関する制限が Spanner のほうがゆるい部分があり、無理やり変換したり変換せず無視したりもしています。
このツールは Spanner を捨てて MySQL に以降したりなどクリティカルなユースケースに対応するつもりはなく、もう少しゆるく変換したらどうなりそうか確認したり、 MySQL 周りのエコシステム、例えば MySQL Workbench による ER 図生成に食わせたりしてみるために作ってます。 なお、このあたりの SQL 方言とその間の相互変換は、現状良いソリューションが無く今回自分は自前で実装したのですが、今後は Apache Calcite に淡い期待を寄せてみてもいいのかなと思っています。