GORM Playground Link
https://github.com/go-gorm/playground/pull/701
Description
There are two struct User
and Profile
. Before I add UserID
field in User, the test is passed.
After I add UserID field, the test failed. And the select sql look like
SELECT * FROM `users` WHERE `users`.`user_id` = 1
SELECT * FROM `profiles`
Here is the code I wrote.
package test
import (
"github.com/glebarez/sqlite" // Pure go SQLite driver, checkout https://github.com/glebarez/sqlite for details
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gorm.io/gorm"
//"gorm.io/driver/sqlite" // Sqlite driver based on CGO
"testing"
)
func TestGormTestSuite(t *testing.T) {
suite.Run(t, new(GormTestSuite))
}
type GormTestSuite struct {
suite.Suite
gormDB *gorm.DB
}
func (suite *GormTestSuite) SetupTest() {
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
require.NoError(suite.T(), err)
suite.gormDB = db
err = suite.gormDB.Migrator().DropTable(&User{}, &Profile{})
require.NoError(suite.T(), err)
err = suite.gormDB.Migrator().AutoMigrate(&User{}, &Profile{})
require.NoError(suite.T(), err)
}
func (suite *GormTestSuite) Test_Preload() {
suite.givenUser(User{ID: 1, Name: "user1"})
suite.givenProfile(Profile{ID: 1, UserID: 1, Description: "profile1"})
var p Profile
err := suite.gormDB.Debug().Preload("User").Find(&p).Error
require.NoError(suite.T(), err)
require.Equal(suite.T(), "user1", p.User.Name)
}
func (suite *GormTestSuite) givenProfile(profile Profile) {
err := suite.gormDB.Create(&profile).Error
require.NoError(suite.T(), err)
}
func (suite *GormTestSuite) givenUser(user User) {
err := suite.gormDB.Create(&user).Error
require.NoError(suite.T(), err)
}
type User struct {
ID int
Name string
UserID int
}
type Profile struct {
ID int
UserID int
User User `gorm:"foreignKey:UserID"`
Description string
}
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: PoundXI
I had the same issue and spent quite some time debugging, thinking I used the wrong relation type (BelongsTo vs HasOne). Turns out, GORM fails to preload correctly when both child and parent structs have a field with the same name as the foreign key (e.g. UserID), resulting in a null relation.
A temporary workaround is to rename the foreign key fields in both structs to something else, and explicitly map the column name using the gorm:"column:..." tag to keep the actual DB column name unchanged.
Here’s an example:
type User struct {
ID int
Name string
UserUserID int `gorm:"column:user_id;"`
}
type Profile struct {
ID int
ProfileUserID int `gorm:"column:user_id;"`
User User `gorm:"foreignKey:ProfileUserID"`
Description string
}
This works, but adds complexity - particularly when using struct embedding (e.g. a base struct for audit fields) and wanting to reuse common field names like UserID, CreatedBy, or UpdatedBy.
Would be great if GORM could handle this edge case more gracefully.
Comment From: xinnjie
I am experiencing this bug as well. When the foreign key field name in the ownee matches the reference key field in the owner, and the PostgreSQL driver is used, the foreign key constraint is added to the owner table instead of the ownee table.