初めて OSS にコントリビュートした

2023-05-11

きっかけ

普段業務では BigQuery に export された GA4 (Google Analytics 4) のデータを加工して社内に提供しています。 加工クエリは BigQuery 内で GoogleSQL 用いて行っています。 GoogleSQL 特有の関数や記法があるため、クエリのテストをローカルで実行するようなことがやりづらかったりします。

そんなときに見つけたのが BigQuery emulator です。 その名の通り BigQuery をエミュレートしてくれるものです。

しかし困ったことに、NET.HOST 等の関数群に対応していませんでした。 GA4 のログを加工する際に NET.* 関数はわりと使うので、これさえ対応してくれていればなーと思いました。

そこで、欲しい機能があるなら PR を送ったらいいじゃないと思ってコントリビュートすることにしました。 GoogleSQL をエミュレートする実装は goccy/go-zetasqlite にあるため、今回 PR を送ったのはこちらのリポジトリです。

作業

まずはコードを読んで、どんなふうに動作するのかを理解するところからはじめました。

README の How it works を見ると、ZetaSQL を SQLite に変換して実行すると書かれています。

でも一方で、実装 を見ると、以下のように Go 言語内で処理しているように見えます。

func CURRENT_DATE(zone string) (Value, error) {
	loc, err := toLocation(zone)
	if err != nil {
		return nil, err
	}
	return CURRENT_DATE_WITH_TIME(time.Now().In(loc))
}

結局どっちで処理してるの?という疑問を取り除くところからはじめました。

go-zetasqlite は go-sqlite3 に依存していますが、これには Go の関数を SQL の関数として登録する機能があるようですね (ref)。

// RegisterFunc makes a Go function available as a SQLite function.

これのおかげで、Go 言語の関数として実装すれば良いということでした。

具体的な作業は PR の中身 を見ると分かるのですが、Go の net/url 等のコアライブラリを呼び出しているだけですね。 でも普段 Go 言語を書かないので、どのライブラリにどんな API があるかも知らなかったため、最適なものを探すのに時間がかかりました。

感想

goccy さんには丁寧に対応していただきましたし、修正を加えてからの再レビューも早く、良い contributer experience でした。

よく OSS の issue で、「こういう機能は考えてないの?」というコメントに対してメンテナーが「いいアイデアがあれば PR 送ってね!」と返しているのを見かけたりしますが、その通りですね。エンジニアとして、欲しけりゃ作れ精神は大切にしたいものです。