I am handling postgresql db with Gorm in Golang. And I'm using the pgtype package to handle nullable fields. To insert a null value into a field, I have to set the status to pgtype.null as follows.
type Person struct {
ID string
Age int
Nickname pgtype.Text
}
func CreatePerson(){
john := &Person{
ID: "John",
Age: 30,
Nickname: pgtype.Text{Status: pgtype.Null},
}
DB.Create(john) // ID: John, Age: 30, Nickname: NULL
}
However, When I load the data from the DB, the null field will be converted to Zero value for pgtypte.Text, that is, its status is Undefined.
func GetPerson(){
john := &Person{}
DB.Where("id = ?", "John").First(john) // ID: John, Nickname: NUL
/* john = {
ID: "John",
Age: 30,
Nickname: pgtype.Text{Status: pgtype.Undefined},
}
*/
}
Here, it is unnatural that the gorm struct that used to save in the DB is different from the gorm struct loaded from the DB.
Also, when I modify some of the fields of the struct and save it again, an error occurs due to the status of undefined.
func GetAndSave(){
john := &Person{}
DB.Where("id = ?", "John").First(john) // ID: John, Nickname: NUL
/* john = {
ID: "John",
Age: 30,
Nickname: pgtype.Text{Status: pgtype.Undefined},
}
*/
john.Age = 31
DB.Select("*").Update(john) // Error since its nickname has undefined status
}
Therefore, I want to make pgtype fields automatically have null status for null fields when I load data with the null field from the db. How can I do this?
You can use BeforeCreate hook to set the default value for fields.
try
func (person *Person) BeforeCreate(_ *gorm.DB) error {
if person.Nickname.Status == pgtype.Undefined {
person.Nickname.Status = pgtype.Null
}
return nil
}
This will check the pgtype field is Undefined
and set that as Null
for Person
struct before creating the entry in the database. And you will be able to omit the Nickname
field while creating
john := &Person{
ID: "John",
Age: 30,
}
DB.Create(john) // ID: John, Age: 30, Nickname: NULL
Same way, you can use AfterFind
hook to update the resulting response fields
func (person *Person) AfterFind(_ *gorm.DB) error {
if person.Nickname.Status == pgtype.Undefined {
person.Nickname.Status = pgtype.Null
}
return nil
}
Hope this helps