GORM Playground Link
https://github.com/go-gorm/playground/pull/612
Description
Calling DB.Create(&model) in a nested gin handler results in incorrectly formatted SQL which causes failure.
Eg. m := User{Name: "dan"} results in INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`) VALUES (no values present).
Comment From: github-actions[bot]
The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout https://github.com/go-gorm/playground for details. it will be closed in 30 days if no further activity occurs. if you are asking question, please use the Question template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ Search Before Asking ✨
Comment From: black-06
A minimal example:
func TestGORM2(t *testing.T) {
type Test struct {
ID uint
Name string
}
DB := GetConn()
DB.Migrator().DropTable(&Test{})
DB.AutoMigrate(&Test{})
if err := create(DB, Test{Name: "thing"}); err != nil {
t.Fatalf("got error: %v", err)
}
}
func create(db *gorm.DB, model interface{}) error {
return db.Create(&model).Error
}
In SQLite:
unsupported data
[0.000ms] [rows:0] INSERT INTO `tests` (`name`) VALUES RETURNING `id`
You should do:
// model is a pointer
// create(DB, &Test{Name: "foo"})
func create(db *gorm.DB, mode interface{}) error {
return db.Create(model).Error
}
Comment From: dteh
So is this a bug or not? It just seems that GORM has issues when the type is interface{}. Seems strange that getting a pointer to the interface breaks it.
Comment From: black-06
It's not a bug. GORM set values by reflect (e.g. model.ID).
DB.Create(Test{Name: "thing"}) // not ok, struct is unaddressable value
DB.Create(&Test{Name: "thing"}) // ok
func MyCreate(db *gorm.DB, model interface{}) error { // why error?
return db.Create(&model).Error
}
Although the MyCreate provides a pointer for GORM, the model in GORM is *interface{} | Test.
The struct is still unaddressable, GORM returned an error.
Comment From: dteh
I see, the error returned by GORM in this case is just unsupported data, should we maybe change the error to struct unaddressable? Or add to documentation this will happen?
Comment From: black-06
should we maybe change the error to struct unaddressable?
My personal understanding is that gorm.ErrInvalidValue includes unaddressable value.
Or add to documentation this will happen
Welcome to submit PR in go-gorm/gorm.io to help us improve the documentation.
Comment From: hirokinakano
Hi, there. I have had the same problem and have had trouble with the same issue. If the Issue here has not been addressed, can I handle the addition of documentation on my end?
Also, if possible, can I add the struct unaddressable error as it is hard to notice when the error occurs?
Comment From: black-06
can I handle the addition of documentation on my end?
Of course 😘
can I add the struct unaddressable error as it is hard to notice when the error occurs?
Do we need to add this error? @a631807682
Comment From: a631807682
can I handle the addition of documentation on my end?
Of course 😘
can I add the struct unaddressable error as it is hard to notice when the error occurs?
Do we need to add this error? @a631807682
I think ErrInvalidValue returns as expected, but we sometimes return ErrInvalidData which is a bit ambiguous. Do we need to replace it? Or fill in more information?
Comment From: black-06
Do we need to replace it? Or fill in more information?
Filling in more information seems to be a better choice. But it means that we have to modify the error, current ErrInvalidValue cannot be filled with information.
Or keep the status quo and elaborate in the documentation...
Comment From: a631807682
invalid value, should be pointer to struct or slice
https://github.com/go-gorm/gorm/blob/master/errors.go#L43
Changing the error message is not a breaking change, you can populate it with a more complete message.
Of course, gorm use built-in error is not the best option, especially when it comes to database returns to errors, and we usually need to keep the original information, but there are currently no plans to change it.
Comment From: dmitriitimoshenko
here are two models I have:
type User struct {
BaseModel
Password string `gorm:"column:password;size:255;not null"`
Role string `gorm:"column:role;size:255;not null"`
}
type UserContact struct {
BaseModel
User User `gorm:"column:user_id;foreignKey:UserID;references:ID;unique;not null"`
UserID uint64
Address Address `gorm:"column:address_id;foreignKey:AddressID;references:ID;not null"`
AddressID uint64
Email string `gorm:"column:email;size:255;unique;not null"`
Firstname string `gorm:"column:firstname;size:255;not null"`
Lastname string `gorm:"column:lastname;size:255;not null"`
PhoneNumber *string `gorm:"column:phone_number;size:255;unique"`
}
on this code i have the following error:
func (us *userService) Create(email, password, firstname, lastname string) (*model.User, error) {
encryptedPassword, err := us.hashPassword(password)
if err != nil {
return nil, err
}
user := &model.User{
Password: string(encryptedPassword),
Role: enums.UserRoles.PortalUser().String(),
}
us.db.Create(user)
contact := &model.UserContact{
Email: email,
Firstname: firstname,
Lastname: lastname,
User: *user,
}
us.db.Create(contact)
return user, nil
}
app-1 | 2024/05/14 18:39:46 /app/internal/pkg/service/user.go:38 cannot convert {{1 2024-05-14 18:39:46.397391868 +0000 UTC 2024-05-14 18:39:46.397391868 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} $2a$08$.LZgf6D1F3VRvK5eNHaO0OuasbZsSvqUUBjy/sPGSO.He55485pfS portal-user} to Int8
can you help me here? Is it a bug or i'm wrong somewhere?
Comment From: SaiHLu
got the same issues, example struct
type MyStruct {
...other fields
DeletedAt gorm.DeleatedAt `json:"deleted_at" gorm:"type:timestamptz"`
}
got error: convert field 6 failed: parsing time "\x00\x02\xaf\xfe\xb7*\xa2\xc0" as "2006-01-02 15:04:05.999999999Z07": cannot parse "\x00\x02\xaf\xfe\xb7*\xa2\xc0" as "2006"