🖱️

sqlc の emit_pointers_for_null_types を使って sql.Null* 地獄から脱却する

2023/02/04に公開

まとめ

  • sql.Null* を使わなくて良くなる
  • SQL の spam TEXTspam *string として生成される
  • SQL の spam TEXT NOT NULLspam 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 の利用、オススメです。

資料

Discussion