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"