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}
が変えたい部分なのだが、false
をtrue
に変える必要があるっぽいな
これは、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にうまく反映されるようになった