Thanks to visit codestin.com
Credit goes to github.com

Skip to content

foreignKey in Preload sometimes matches wrong field; joinForeignKey works correctly #7677

@xiaose-A

Description

@xiaose-A
# Inconsistent behavior between foreignKey and joinForeignKey in Preload causing incorrect SQL JOIN field

## Description

When using struct associations in GORM, I encountered the following issue:

Dependencies:

github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/google/uuid v1.5.0
golang.org/x/crypto v0.17.0
gorm.io/driver/sqlite v1.5.4
gorm.io/gorm v1.25.5


### Scenario

```go
type ChannelPartnerApp struct {
	ID               string         `gorm:"primaryKey;type:varchar(36)" json:"id"`
	ChannelPartnerID string         `gorm:"type:varchar(36);not null;index" json:"channelPartnerId"`
	AppID            string         `gorm:"type:varchar(36);not null;index;column:app_id" json:"appId"`
	Key              string         `gorm:"type:varchar(64);not null;uniqueIndex" json:"key"`

	ChannelPartner ChannelPartner `gorm:"foreignKey:ChannelPartnerID;references:ID" json:"channelPartner,omitempty"`
	App            App            `gorm:"foreignKey:AppID;references:ID" json:"app,omitempty"`
}

type ChannelPartner struct {
	ID      string   `gorm:"primaryKey;type:varchar(36)" json:"id"`
	Name    string   `gorm:"type:varchar(255);not null" json:"name"`
	Contact string   `gorm:"type:varchar(100)" json:"contact"`

	Apps []App `gorm:"many2many:channel_partner_apps;" json:"apps,omitempty"`
}

type App struct {
	ID                string            `gorm:"primaryKey;type:varchar(36);column:id" json:"id"`
	AppID             string            `gorm:"type:varchar(100)" json:"appId"`

	ChannelPartners []ChannelPartner   `gorm:"many2many:channel_partner_apps;" json:"channelPartners,omitempty"`
}
  • The target table App has ID as its primary key.
  • I am using Preload("App") to load associated data.

Observed Behavior

  • When using:
App App `gorm:"foreignKey:AppID;references:ID" json:"app,omitempty"`

The generated SQL is:

[0.047ms] [rows:1] SELECT * FROM `apps` WHERE `apps`.`app_id` = "bb699b70-1787-4c7b-8b76-dd616f250cbc" AND `apps`.`deleted_at` IS NULL
SELECT * FROM `channel_partners` WHERE `channel_partners`.`id` = "2e1efe7b-f9ee-42e4-a2b4-80ac19ab7848" AND `channel_partners`.`deleted_at` IS NULL
SELECT * FROM `channel_partner_apps` WHERE channel_partner_id = "2e1efe7b-f9ee-42e4-a2b4-80ac19ab7848" AND `channel_partner_apps`.`deleted_at` IS NULL

In fact, "bb699b70-1787-4c7b-8b76-dd616f250cbc" is ChannelPartnerApp.ID, not App.ID.

  • If I use:
foreignKey:ID;references:AppID

I get the correct SQL:

SELECT * FROM `apps` WHERE `apps`.`id` = "e70d3716-64a1-438a-9d91-b4b7d56a637f" AND `apps`.`deleted_at` IS NULL

Where "e70d3716-64a1-438a-9d91-b4b7d56a637f" is App.ID and matches ChannelPartnerApp.AppID.

  • Using joinForeignKey:AppID also produces the correct result.

Comparison with ChannelPartner

For:

ChannelPartner ChannelPartner `gorm:"foreignKey:ChannelPartnerID;references:ID" json:"channelPartner,omitempty"`

Both

  • foreignKey:ChannelPartnerID;references:ID
  • foreignKey:ID;references:ChannelPartnerID

produce the expected SQL:

SELECT * FROM `channel_partners` WHERE `channel_partners`.`id` = "2e1efe7b-f9ee-42e4-a2b4-80ac19ab7848" AND `channel_partners`.`deleted_at` IS NULL

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions