Your Question

This query generates error sql and cannot work anyway. I use AutoMigrate to create the tables.

type UserGroups struct {
    ID uint `gorm:"primarykey"`
    // User.ID
    UID uint `gorm:"index;index:user_group_idx,unique;not null;column:uid;"`
    User  User  `gorm:"foreignKey:uid;constraint:OnDelete:CASCADE"`
    // Group.ID
    GID uint `gorm:"index;index:user_group_idx,unique;not null;column:gid"`
    Group Group `gorm:"foreignKey:gid;constraint:OnDelete:RESTRICT"`
}

func (a *UserGroups) GetAllUnfrozen(tx *gorm.DB) ([]UserGroups, error) {
    var t []UserGroups
    return t, tx.Model(a).
        Joins("INNER JOIN users ON users.id=user_groups.uid AND users.deleted_at IS NULL").
        Find(&t).Error
}

the sql is

SELECT `user_groups`.`id`,`user_groups`.`uid`,`user_groups`.`gid`,`user_groups`.`user` FROM `user_groups` INNER JOIN users ON users.id=user_groups.uid AND users.deleted_at IS NULL WHERE `user_groups`.`user` IS NULL

There is a strange sql statement in it: WHERE user_groups.user IS NULL. Either delete joins or use db.Table("table") will cause this error.

If I add gorm:"-;" to the User User fields, most of sql will become as expected, the strange sql will disappear. But in this function, the error is more serious:

SELECT `user_groups`.`id`,`user_groups`.`uid`,`user_groups`.`gid`,`user_groups`.`user` FROM `user_groups` INNER JOIN users ON users.id=user_groups.uid AND users.deleted_at IS NULL WHERE `user_groups`. IS NULL

The bigger error appears at the end of this sql: WHERE user_groups. IS NULL

Neither use Omit(clause.Associations) nor Select("user_groups.*") can solve the above two problems.

I also tried detaching the model, but the error didn't change.

type UserGroupModel struct {
    ID uint `gorm:"primarykey"`
    // User.ID
    UID uint `gorm:"index;index:user_group_idx,unique;not null;column:uid;"`
    // Group.ID
    GID uint `gorm:"index;index:user_group_idx,unique;not null;column:gid"`
}

type UserGroups struct {
    UserGroupModel
    User  User  `gorm:"-;foreignKey:uid;constraint:OnDelete:CASCADE"`
    Group Group `gorm:"-;foreignKey:gid;constraint:OnDelete:RESTRICT"`
}

func (a *UserGroups) GetAllUnfrozen(tx *gorm.DB) ([]UserGroupModel, error) {
    var t []UserGroupModel
    return t, tx.Model(a).
        Joins("INNER JOIN users ON users.id=user_groups.uid AND users.deleted_at IS NULL").
        Find(&t).Error
}

sql:

SELECT `user_groups`.`id`,`user_groups`.`uid`,`user_groups`.`gid` FROM `user_groups` INNER JOIN users ON users.id=user_groups.uid AND users.deleted_at IS NULL WHERE `user_groups`.` IS NULL

If I use tx.Table("user_groups") instead based on this, sql will become normal but gorm will make an error during the scan process.

2023/05/01 18:30:00 C:/Users/Mmx/project/github.com/ncuhome/GeniusAuthoritarian/internal/db/dao/UserGroups.go:47
[40.035ms] [rows:0] SELECT `user_groups`.`id`,`user_groups`.`uid`,`user_groups`.`gid` FROM `user_groups` INNER JOIN users ON users.id=user_groups.uid AND users.deleted_at IS NULL
panic: reflect: call of reflect.Value.Field on uint Value

goroutine 1 [running]:
reflect.Value.Field({0x14d08a0?, 0xc00084c000?, 0xd53ada?}, 0x207e85845d8?)
        C:/Users/Mmx/go/go1.20.1/src/reflect/value.go:1268 +0xe5

The document you expected this should be explained

https://gorm.io/docs/associations.html

Expected answer

Is there something wrong with the way I use gorm? How should I get my sql to bypass auto associations.

Comment From: Mmx233

The issue can be solved by using dual automatic migration, but I don't think it's very elegant.

func init() {
    var e error
    if e = DB.AutoMigrate(
        &UserGroupsWithForeignKey{},
    ); e != nil {
        log.Fatalln("AutoMigration failed:", e)
    }

    if e = DB.AutoMigrate(
        &UserGroups{},
    ); e != nil {
        log.Fatalln("AutoMigration failed:", e)
    }
}

type UserGroupsWithForeignKey struct {
    UserGroups `gorm:"embedded"`
    User       User  `gorm:"foreignKey:UID;constraint:OnDelete:CASCADE"`
    Group      Group `gorm:"foreignKey:GID;constraint:OnDelete:RESTRICT"`
}

func (a *UserGroupsWithForeignKey) TableName() string {
    return "user_groups"
}

type UserGroups struct {
    ID uint `gorm:"primarykey"`
    // User.ID
    UID uint `gorm:"index;index:user_group_idx,unique;not null;column:uid;"`
    // Group.ID
    GID uint `gorm:"index;index:user_group_idx,unique;not null;column:gid"`
}

func (a *UserGroups) GetAllUnfrozen(tx *gorm.DB) ([]UserGroups, error) {
    var t []UserGroups
    return t, tx.Model(a).Joins("INNER JOIN users u ON u.id=user_groups.uid").
        Where("u.deleted_at IS NULL").Find(&t).Error
}