Diary

Diary

日々学んだことをアウトプットする場として初めてみました

SQLBoilerで null.String を扱う

SQLBoilerで null.String を扱う

SQLBoilerを使っていて null.String 型の定義のフィールドにアクセスするのに苦労したのでメモしておく

SQLBoilerとは

  • SQLBoilerはデータベースファーストのORマッパーである
    • あらかじめDBを生成しておくと、その定義に基づいて構造体を自動生成してくれる

自動生成してくれる構造体の例

type Room struct {
    RoomID        int         `boil:"room_id" json:"room_id" toml:"room_id" yaml:"room_id"`
    RoomName      null.String `boil:"room_name" json:"room_name,omitempty" toml:"room_name" yaml:"room_name,omitempty"`
    IsGroup       null.Bool   `boil:"is_group" json:"is_group,omitempty" toml:"is_group" yaml:"is_group,omitempty"`
    LatestContent null.String `boil:"latest_content" json:"latest_content,omitempty" toml:"latest_content" yaml:"latest_content,omitempty"`
    CreatedAt     null.Time   `boil:"created_at" json:"created_at,omitempty" toml:"created_at" yaml:"created_at,omitempty"`
    UpdatedAt     null.Time   `boil:"updated_at" json:"updated_at,omitempty" toml:"updated_at" yaml:"updated_at,omitempty"`

    R *roomR `boil:"-" json:"-" toml:"-" yaml:"-"`
    L roomL  `boil:"-" json:"-" toml:"-" yaml:"-"`
}

null.String?

基本的には、INSERTなどに使える関数も含め全て自動生成してくれたファイルに書いてある

使い方としては例えば次のようになる

u := &models.User{Name: name, Password: pwHash, Email: email}
err := u.Insert(Ctx, DB, boil.Infer())

ところが、上で紹介したRoomの構造体に現れるnull.Stringなどの「null+何か」みたいなものに対し、普通にstringと思ってやろうとするとエラーになる

{
  ...
  room, _ := models.FindRoom(Ctx, DB, room_id)
  room.LatestContent = content
  fmt.Println(room)
  _, err := room.Update(Ctx, DB, boil.Infer())
  ...
}
> cannot use content (type string) as type null.String in assignment

どうやらこのnull.Stringは1つの構造体らしい

試しに構造体の定義から、null.Stringに飛んでみると

// String is a nullable string. It supports SQL and JSON serialization.
type String struct {
    String string
    Valid  bool
}

と定義があった(null/v8の中)。

そうと分かれば、構造体の中のStringフィールドにアクセスしたら良さそう

{
  ...
    room, _ := models.FindRoom(Ctx, DB, room_id)
    room.LatestContent.String = content
    _, err := room.Update(Ctx, DB, boil.Infer())
  ...
}

エラーは出ないけど、DBに反映されない!

roomを1回出力してみる

{
  ...
    room, _ := models.FindRoom(Ctx, DB, room_id)
    room.LatestContent.String = content
         fmt.Println(room)
    _, err := room.Update(Ctx, DB, boil.Infer())
  ...
}
> &{3 {Group1 true} {false true} {content false} {2021-06-06 20:46:48.478066 +0000 +0000 true} {2021-06-06 22:49:19.573172 +0000 +0000 true} <nil> {}}

このなかの3つ目くらいの{content false}が変えたい部分なのだが、falsetrueに変える必要があるっぽいな

これは、null.Stringの定義のValidに当たる部分だと思う

{
  ...
    room, _ := models.FindRoom(Ctx, DB, room_id)
    room.LatestContent.String = content
  room.LatestContent.Valid = true
    _, err := room.Update(Ctx, DB, boil.Infer())
  ...
}

これでようやくDBにうまく反映されるようになった