🖱️
sqlc の emit_pointers_for_null_types を使って sql.Null* 地獄から脱却する
まとめ
- sql.Null* を使わなくて良くなる
- SQL の
spam TEXT
がspam *string
として生成される - SQL の
spam TEXT NOT NULL
はspam string
として生成される - SQL の結果を JSON に変換するとき楽になる
sqlc って何?
sqlc は、SQL からタイプセーフな Go コードを生成してくれるツールです。
以下の記事がわかりやすいのでオススメです。
sql.Null* からの脱却
sqlc を使う場合、 NULL を許容した際に sql.Null* に置き換えられることでそのまま JSON にできないので、何かしら一工夫が必要になります。
多くの場合は sqlc の overrides を使うパターンだと思います。
ただ、これははっきり言ってめんどくさいです。テスト書くときもめんどくさいです。
そこで最近になって追加された emit_pointers_for_null_types
を紹介します。
emit_pointers_for_null_types
は pgx を利用している場合のみに利用できる機能で、簡単に言うと NULL を許容した場合に sql.NullString ではなく *string として Go のコードを生成するような仕組みを作ってくれます。
version: "2"
sql:
- queries: "query.sql"
schema: "query.sql"
engine: "postgresql"
gen:
go:
package: "sqlc"
out: "./gen/sqlc"
sql_package: "pgx/v4"
emit_json_tags: true
emit_prepared_queries: false
emit_interface: true
emit_exact_table_names: false
emit_empty_slices: true
emit_pointers_for_null_types: true
適当な SQL 例で説明します。
CREATE TABLE author (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL,
bio TEXT,
created_at TIMESTAMPTZ NOT NULL,
deleted_at TIMESTAMPTZ
);
それで sqlc generate
で生成したモデルのコードが以下になります。
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.16.0
package sqlc
import (
"time"
)
type Author struct {
ID int64 `json:"id"`
Name string `json:"name"`
Bio *string `json:"bio"`
CreatedAt time.Time `json:"created_at"`
DeletedAt *time.Time `json:"deleted_at"`
}
これだけです。
SELECT や INSERT するときも *string が利用できるようになりますし、 *time.Time も利用できるようになります。
これで sql.NullString や sql.NullTime 地獄から抜け出せるようになりました。
sqlc と PostgreSQL を利用している方は是非 pgx を利用して emit_pointers_for_null_types
の利用、オススメです。
資料
-
https://github.com/kyleconroy/sqlc/pull/1571
- emit_pointers_for_null_types を追加する PR
-
https://github.com/kyleconroy/sqlc/pull/2046
- emit_pointers_for_null_types で *time.Time じに import time されない問題を解決した PR
Discussion