SQL の方言を翻訳する SQLGlot が面白い
こんにちは。rch850 です。jig.jp Advent Calendar 2024 の9日目の記事です。先日の記事ではウェブグループのグループマネージャーを名乗っていましたが、データ分析グループにも所属しているので、今回はその目線で書いています。
jig 社員の出身地は結構バラバラなので、方言の話で盛り上がることがよくあります。例えば茨城出身の自分の場合だと「雪がしみじみ降ってきたなー」「しみじみって、随分感傷的だな」「いや、そうじゃなくて、本格的に降ってきたなって意味なんだけど」とか。つい最近だと、方言じゃないですが今が旬のブリの呼び方が話題に出てました。ここ福井だと小さいのがフクラギと呼ばれていて、安くて美味しくてオススメです。
さて、話をエンジニアブログに急旋回させますが、SQL にも色々方言があります。特に 2024 年はいろいろな方言へのニーズが出てきたように感じています。
- DuckDB が盛り上がった(個人の感想です)
- re:Invent で Amazon S3 Tables が発表され、Iceberg テーブルに対する Spark クエリが盛り上がりそうな予感
- 同じく re:Invent で Amazon Aurora DSQL が発表され、PostgreSQL 互換とのことですが、もしかしたら新たな方言が誕生するかも?
これらの SQL の方言について、文法にも若干の違いがあったり、関数は同じことをしたいのに名前や引数の順序が違ってたりで、個人的にはなかなか覚えられません。こういった SQL の方言を翻訳してくれる Python のパッケージが SQLGlot です。
SQL の方言の中でも、私が特に詰まるのが、日付や時刻の操作をする関数です。例えば MySQL で有効な SELECT DATE_FORMAT(l.started_at, "%Y-%m") FROM l
というクエリについて考えます。テーブル l
の started_at
という列を DATE_FORMAT
関数で 2024-12
といった文字列に変換して取得するクエリです。これを BigQuery、DuckDB、Athena ではどう書くのでしょうか。
SQLGlot では、 transpile
という関数で翻訳できます。実際のコードは次のようにとてもシンプルなものです。
>>> import sqlglot
>>> sql = "
... SELECT DATE_FORMAT(l.started_at, "%Y-%m")
... FROM l
... """
>>> print(sqlglot.transpile(sql, read="mysql", write="bigquery"))
["SELECT FORMAT_DATE('%Y-%m', l.started_at) FROM l"]
>>> print(sqlglot.transpile(sql, read="mysql", write="duckdb"))
["SELECT STRFTIME(l.started_at, '%Y-%m') FROM l"]
>>> print(sqlglot.transpile(sql, read="mysql", write="athena"))
["SELECT DATE_FORMAT(l.started_at, '%Y-%m') FROM l"]
BigQuery では FORMAT_DATE
に、DuckDB では STRFTIME
に翻訳されましたね。引数の順序も入れ替わってます。
ここで取り上げた方言以外にも、PostgreSQL や SQLite など、様々な方言に対応しています。詳しくはサブモジュール dialects のドキュメントを参照してください。
SQLGlot には、他にもクエリをパースして AST にしたり、クエリを最適化するなどの機能があります。気になったらぜひ調べてみてください。
Discussion