sqlc がちょっと惜しい
概要
Go 言語でデータベース操作をする方法は、標準パッケージ・GORM・sqlx などいくつかあります。
今回はそのうちの一つの sqlc を使ってみたので、所感をまとめておこうと思います。
sqlc とは
sqlc を使うために必要なファイルは3つあります。
- スキーマファイル(
database/migrations/users.sql
) - 使用するデータベースの種類やパッケージ名などを指定する設定ファイル(
sqlc.yaml
) - 使うクエリをまとめたファイル(
query.sql
)
-- users.sql
CREATE TABLE IF NOT EXISTS users(
id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
age INTEGER NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# sqlc.yaml
version: 1
packages:
- path: "repository"
name: "repository"
engine: "mysql"
schema: "database/migrations/"
queries: "query.sql"
emit_db_tags: true
-- query.sql
-- name: InsertUser :exec
INSERT INTO users(name, age) VALUES (?, ?);
query.sql
にあるコメントは sqlc
独自なので詳しくはドキュメントを参考にしてください。
これらを用意して、sqlc generate
を実行すると path
に指定した名前でディレクトリが作られます。パッケージ名は name
で指定できます。
中には query.sql.go
と db.go
、models.go
の3つのファイルができます。
これらのコードを使うことで、データベースにアクセスする層を簡単に作れます。
sqlc は標準パッケージの database/sql
を使っているので速度が早く、クエリを自分で定義するのでどのようなクエリが発行されているかブラックボックスにならないです。
sqlc がちょっと惜しい
使いやすく良い感じなのですが、現状だとできないクエリがあったので採用を見送ることにしました。
それは IN
句を使ったクエリです。下のように IN
を使ったクエリのユースケースはあると思いますが、sqlc だと現状使えないです。(参照)
これを query.sql
に書いて sqlc generate
をしても意図したコードにならないです。
SELECT * FROM users WHERE id IN (?);
以下のように IN
で指定する代わりに一回ずつ取得することも可能ですが、データベースへのアクセスが増えてしまいパフォーマンスの劣化につながります。
SELECT * FROM users WHERE id = 1
SELECT * FROM users WHERE id = 2
SELECT * FROM users WHERE id = 3
まとめ
データベースにアクセスするコードを自動生成できて便利なのですが、本番で使うにはまだ機能が足りないかなという感じです。
マイグレーションだったり一部分だけ使うなど、工夫する必要がありそうです。
Discussion
こんにちは!この記事を書かれた時点では無かったかもしれませんが、現在は sqlc.sliceという機能を用いることでスライスを使ったIN句の指定が出来るようになっています。
また触れられている機能不足に関しては、特にMySQLを対象生成した際が顕著でしてpgx(Postgresql)ではかなり多くの機能に対応しているなーという所感です。
ご参考になれば幸いです!
こんにちは!
今はできるようになっているんですね。ここ最近 sqlc を使っている会社のテックブログなどをよく見かけるのでまた勉強してみようと思います
なるほど。自分が普段 MySQL を使うのでその前提で記事を書いていました。次からはその辺りも考慮して記事を書こうと思います。ありがとうございます