GoからZetaSQLを使う

yamaguchi naoto
6 min readDec 4, 2021

--

この記事は 2021 Go Advent Calendar 4日目 の記事です。

Photo by David Thielen on Unsplash

Introduction

Goを使ってBigQueryやSpannerのSQLをフォーマットしたりパースしたりしたいなと思い調べたらGoogleが公開しているZetaSQLというライブラリにたどり着きました。

ただZetaSQLはC++とJavaで書かれていたのですが、他にGo製のOSSなどもなく自前でSQLパーサーをちゃんと書くのも大変なのでこれを使ってどうにかできないか模索した話になります。

最終的にはGoからZetaSQLを呼び出すserverを作りました。↓

naoto0822/zetasql-server

What’s ZetaSQL

google/zetasql

ZetaSQLはGoogleの標準SQLの方言であり、BigQueryのクエリエンジンであるDremelでも使われてるそうです。

ちゃんとした公式の情報がないですがApache BeamでもサポートされておりDataFlow SQLはこのSQLに則っていると思われます。

Calling from Go

Goが好きなので、このZetaSQLをGoから扱えるようにしようと思います。

このZetaSQL本体はBazelでビルドされているので、Bazelを使って取り込めます。またC++ライブラリとしてビルドできればCGOを使ってGoにバインドすることが可能です。

設定にあたっては下記のレポジトリがとても参考になりました。

apstndb/zetasql-format-server

ebendutoit/zetasql-analyzer-server

1. CGO

まずはGoとZetaSQLをリンクさせるコードです。今回一つの関数を例にコードを貼っていきます。まずは ZetaSQLの必要なファイルをimportして、C++側からZetaSQLをコールするラッパーを定義します。C++に慣れた人なら多分問題ないのでしょうが、普段Goばっか書いてるので自分は手こずりました。↓

次にGoとC部分をリンクします。 import C の上にコメントとしてCの定義を書けば、コンパイルする際に読み込まれてCの型やincludeした関数にアクセスできます。↓

これでGoの関数として呼び出すことができます。zetasql-serverではこれをサーバの結果として返すようにしました。

2. Build

前述の通りBazelを使ってビルドします。

時間の関係で .bazelrcCROSSTOOL の細かい設定の説明は実際のソース見てもらえればと思いますが、端折るとWORKSPACE の記述により google/zetasql を取り込みます。これは google/zetasql 側で定義されてる関数を呼び出すことでビルドしています。

実際に google/zetasql 内でも同様に定義されています。

またBuildに関しては下記の BUILDファイル↓の 定義よりCGOをTrueとすることで、Cを取り込めます。これで bazel build ://zetasql-server でビルドすることができます。

ただZetaSQLのビルドにとても時間がかかるようで、自分マシンでbazelコマンドを実行すると15〜20分ぐらいかかってしまって検証がとても非効率です、、、。

(ZetaSQLのビルドをなんとかしたい、、、)

3. Run

Dockerfileを見てもらえればわかりますが、かなり泥臭いです。bazelでビルドしたGoのバイナリを拾ってそれを実行しています。

bazel runしても動くので環境によってはそれでも大丈夫かなと思います。

4.In the Future

今後としては、ビルドできたのならわざわざサーバーじゃなくてcliとして扱えるほうが良いよなと思っており別レポジトリ作って新たなラッパーを作ろうかなと思っています。

またASTを構造化(JSONとか)した形で返せるようにしたいので、もう少しCGOについて学ぼうかなと思っています。

現時点ではZetaSQLのASTのDebug出力をJSONにするというパーサーは強引に書いたのですが、そもそもZetaSQLからGoにわたすところを工夫できないかなと考えています。パーサーに関しては下記の記事で書きました。

Conclusion

Goを使ってSpannerやBigQueryのSQLで遊びたかっただけなのですが、まさかこんなに大変なことになるとは思っていませんでした。あまり google/zetasql 自体にアップデートが頻繁にあるわけではなさそうですが、 仕事でGCPを使ってる以上は引き続きウォッチし続けていきたいなと思います。

Thanks!!!

References

--

--

yamaguchi naoto
yamaguchi naoto

No responses yet