😺

sqlc がちょっと惜しい

2021/11/01に公開

概要

Go 言語でデータベース操作をする方法は、標準パッケージ・GORM・sqlx などいくつかあります。
今回はそのうちの一つの sqlc を使ってみたので、所感をまとめておこうと思います。

sqlc とは

sqlc を使うために必要なファイルは3つあります。

  1. スキーマファイル(database/migrations/users.sql)
  2. 使用するデータベースの種類やパッケージ名などを指定する設定ファイル(sqlc.yaml)
  3. 使うクエリをまとめたファイル(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.godb.gomodels.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