
use golangci/golangci-lint-action instead of reviewdog/action-golangci-lint as the second was not reporting any failures even if there was some. Report code coverage with codecov/codecov-action I have set some flags per dialect and go version Several linters has been fixed, some disabled so the build can pass
579 lines
15 KiB
Go
579 lines
15 KiB
Go
package schema_test
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/schema"
|
|
)
|
|
|
|
func checkStructRelation(t *testing.T, data interface{}, relations ...Relation) {
|
|
if s, err := schema.Parse(data, &sync.Map{}, schema.NamingStrategy{}); err != nil {
|
|
t.Errorf("Failed to parse schema")
|
|
} else {
|
|
for _, rel := range relations {
|
|
checkSchemaRelation(t, s, rel)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBelongsToOverrideForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile Profile `gorm:"ForeignKey:ProfileRefer"`
|
|
ProfileRefer int
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"ID", "Profile", "ProfileRefer", "User", "", false}},
|
|
})
|
|
}
|
|
|
|
func TestBelongsToOverrideReferences(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Refer string
|
|
Name string
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile Profile `gorm:"ForeignKey:ProfileID;References:Refer"`
|
|
ProfileID int
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "Profile", "ProfileID", "User", "", false}},
|
|
})
|
|
}
|
|
|
|
func TestBelongsToWithOnlyReferences(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Refer string
|
|
Name string
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile Profile `gorm:"References:Refer"`
|
|
ProfileRefer int
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "Profile", "ProfileRefer", "User", "", false}},
|
|
})
|
|
}
|
|
|
|
func TestBelongsToWithOnlyReferences2(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Refer string
|
|
Name string
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile Profile `gorm:"References:Refer"`
|
|
ProfileID int
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "Profile", "ProfileID", "User", "", false}},
|
|
})
|
|
}
|
|
|
|
func TestSelfReferentialBelongsTo(t *testing.T) {
|
|
type User struct {
|
|
ID int32 `gorm:"primaryKey"`
|
|
Name string
|
|
CreatorID *int32
|
|
Creator *User
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Creator", Type: schema.BelongsTo, Schema: "User", FieldSchema: "User",
|
|
References: []Reference{{"ID", "User", "CreatorID", "User", "", false}},
|
|
})
|
|
}
|
|
|
|
func TestSelfReferentialBelongsToOverrideReferences(t *testing.T) {
|
|
type User struct {
|
|
ID int32 `gorm:"primaryKey"`
|
|
Name string
|
|
CreatedBy *int32
|
|
Creator *User `gorm:"foreignKey:CreatedBy;references:ID"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Creator", Type: schema.BelongsTo, Schema: "User", FieldSchema: "User",
|
|
References: []Reference{{"ID", "User", "CreatedBy", "User", "", false}},
|
|
})
|
|
}
|
|
|
|
func TestHasOneOverrideForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile Profile `gorm:"ForeignKey:UserRefer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasOneOverrideReferences(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserID uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Refer string
|
|
Profile Profile `gorm:"ForeignKey:UserID;References:Refer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasOneOverrideReferences2(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
ProfileID uint `gorm:"column:profile_id"`
|
|
Profile *Profile `gorm:"foreignKey:ID;references:ProfileID"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"ProfileID", "User", "ID", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasOneWithOnlyReferences(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Refer string
|
|
Profile Profile `gorm:"References:Refer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "User", "UserRefer", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasOneWithOnlyReferences2(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserID uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Refer string
|
|
Profile Profile `gorm:"References:Refer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasManyOverrideForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile []Profile `gorm:"ForeignKey:UserRefer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasManyOverrideReferences(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserID uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Refer string
|
|
Profile []Profile `gorm:"ForeignKey:UserID;References:Refer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestMany2ManyOverrideForeignKeyAndReferences(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profiles []Profile `gorm:"many2many:user_profiles;ForeignKey:Refer;JoinForeignKey:UserReferID;References:UserRefer;JoinReferences:ProfileRefer"`
|
|
Profiles2 []Profile `gorm:"many2many:user_profiles2;ForeignKey:refer;JoinForeignKey:user_refer_id;References:user_refer;JoinReferences:profile_refer"`
|
|
Refer uint
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
|
JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"},
|
|
References: []Reference{
|
|
{"Refer", "User", "UserReferID", "user_profiles", "", true},
|
|
{"UserRefer", "Profile", "ProfileRefer", "user_profiles", "", false},
|
|
},
|
|
}, Relation{
|
|
Name: "Profiles2", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
|
JoinTable: JoinTable{Name: "user_profiles2", Table: "user_profiles2"},
|
|
References: []Reference{
|
|
{"Refer", "User", "User_refer_id", "user_profiles2", "", true},
|
|
{"UserRefer", "Profile", "Profile_refer", "user_profiles2", "", false},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestMany2ManyOverrideForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profiles []Profile `gorm:"many2many:user_profiles;ForeignKey:Refer;References:UserRefer"`
|
|
Refer uint
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
|
JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"},
|
|
References: []Reference{
|
|
{"Refer", "User", "UserRefer", "user_profiles", "", true},
|
|
{"UserRefer", "Profile", "ProfileUserRefer", "user_profiles", "", false},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestMany2ManyOverrideJoinForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profiles []Profile `gorm:"many2many:user_profile;JoinForeignKey:UserReferID;JoinReferences:ProfileRefer"`
|
|
Refer uint
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
|
JoinTable: JoinTable{Name: "user_profile", Table: "user_profile"},
|
|
References: []Reference{
|
|
{"ID", "User", "UserReferID", "user_profile", "", true},
|
|
{"ID", "Profile", "ProfileRefer", "user_profile", "", false},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestBuildReadonlyMany2ManyRelation(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profiles []Profile `gorm:"->;many2many:user_profile;JoinForeignKey:UserReferID;JoinReferences:ProfileRefer"`
|
|
Refer uint
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile",
|
|
JoinTable: JoinTable{Name: "user_profile", Table: "user_profile"},
|
|
References: []Reference{
|
|
{"ID", "User", "UserReferID", "user_profile", "", true},
|
|
{"ID", "Profile", "ProfileRefer", "user_profile", "", false},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestMany2ManyWithMultiPrimaryKeys(t *testing.T) {
|
|
type Tag struct {
|
|
ID uint `gorm:"primary_key"`
|
|
Locale string `gorm:"primary_key"`
|
|
Value string
|
|
}
|
|
|
|
type Blog struct {
|
|
ID uint `gorm:"primary_key"`
|
|
Locale string `gorm:"primary_key"`
|
|
Subject string
|
|
Body string
|
|
Tags []Tag `gorm:"many2many:blog_tags;"`
|
|
SharedTags []Tag `gorm:"many2many:shared_blog_tags;ForeignKey:id;References:id"`
|
|
LocaleTags []Tag `gorm:"many2many:locale_blog_tags;ForeignKey:id,locale;References:id"`
|
|
}
|
|
|
|
checkStructRelation(t, &Blog{},
|
|
Relation{
|
|
Name: "Tags", Type: schema.Many2Many, Schema: "Blog", FieldSchema: "Tag",
|
|
JoinTable: JoinTable{Name: "blog_tags", Table: "blog_tags"},
|
|
References: []Reference{
|
|
{"ID", "Blog", "BlogID", "blog_tags", "", true},
|
|
{"Locale", "Blog", "BlogLocale", "blog_tags", "", true},
|
|
{"ID", "Tag", "TagID", "blog_tags", "", false},
|
|
{"Locale", "Tag", "TagLocale", "blog_tags", "", false},
|
|
},
|
|
},
|
|
Relation{
|
|
Name: "SharedTags", Type: schema.Many2Many, Schema: "Blog", FieldSchema: "Tag",
|
|
JoinTable: JoinTable{Name: "shared_blog_tags", Table: "shared_blog_tags"},
|
|
References: []Reference{
|
|
{"ID", "Blog", "BlogID", "shared_blog_tags", "", true},
|
|
{"ID", "Tag", "TagID", "shared_blog_tags", "", false},
|
|
},
|
|
},
|
|
Relation{
|
|
Name: "LocaleTags", Type: schema.Many2Many, Schema: "Blog", FieldSchema: "Tag",
|
|
JoinTable: JoinTable{Name: "locale_blog_tags", Table: "locale_blog_tags"},
|
|
References: []Reference{
|
|
{"ID", "Blog", "BlogID", "locale_blog_tags", "", true},
|
|
{"Locale", "Blog", "BlogLocale", "locale_blog_tags", "", true},
|
|
{"ID", "Tag", "TagID", "locale_blog_tags", "", false},
|
|
},
|
|
},
|
|
)
|
|
}
|
|
|
|
func TestMultipleMany2Many(t *testing.T) {
|
|
type Thing struct {
|
|
ID int
|
|
}
|
|
|
|
type Person struct {
|
|
ID int
|
|
Likes []Thing `gorm:"many2many:likes"`
|
|
Dislikes []Thing `gorm:"many2many:dislikes"`
|
|
}
|
|
|
|
checkStructRelation(t, &Person{},
|
|
Relation{
|
|
Name: "Likes", Type: schema.Many2Many, Schema: "Person", FieldSchema: "Thing",
|
|
JoinTable: JoinTable{Name: "likes", Table: "likes"},
|
|
References: []Reference{
|
|
{"ID", "Person", "PersonID", "likes", "", true},
|
|
{"ID", "Thing", "ThingID", "likes", "", false},
|
|
},
|
|
},
|
|
Relation{
|
|
Name: "Dislikes", Type: schema.Many2Many, Schema: "Person", FieldSchema: "Thing",
|
|
JoinTable: JoinTable{Name: "dislikes", Table: "dislikes"},
|
|
References: []Reference{
|
|
{"ID", "Person", "PersonID", "dislikes", "", true},
|
|
{"ID", "Thing", "ThingID", "dislikes", "", false},
|
|
},
|
|
},
|
|
)
|
|
}
|
|
|
|
func TestSelfReferentialMany2Many(t *testing.T) {
|
|
type User struct {
|
|
ID int32 `gorm:"primaryKey"`
|
|
Name string
|
|
CreatedBy int32
|
|
Creators []User `gorm:"foreignKey:CreatedBy"`
|
|
AnotherPro interface{} `gorm:"-"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Creators", Type: schema.HasMany, Schema: "User", FieldSchema: "User",
|
|
References: []Reference{{"ID", "User", "CreatedBy", "User", "", true}},
|
|
})
|
|
|
|
user, err := schema.Parse(&User{}, &sync.Map{}, schema.NamingStrategy{})
|
|
if err != nil {
|
|
t.Fatalf("failed to parse schema")
|
|
}
|
|
|
|
relSchema := user.Relationships.Relations["Creators"].FieldSchema
|
|
if user != relSchema {
|
|
t.Fatalf("schema should be same, expects %p but got %p", user, relSchema)
|
|
}
|
|
}
|
|
|
|
type CreatedByModel struct {
|
|
CreatedByID uint
|
|
CreatedBy *CreatedUser
|
|
}
|
|
|
|
type CreatedUser struct {
|
|
gorm.Model
|
|
CreatedByModel
|
|
}
|
|
|
|
func TestEmbeddedRelation(t *testing.T) {
|
|
checkStructRelation(t, &CreatedUser{}, Relation{
|
|
Name: "CreatedBy", Type: schema.BelongsTo, Schema: "CreatedUser", FieldSchema: "CreatedUser",
|
|
References: []Reference{
|
|
{"ID", "CreatedUser", "CreatedByID", "CreatedUser", "", false},
|
|
},
|
|
})
|
|
|
|
userSchema, err := schema.Parse(&CreatedUser{}, &sync.Map{}, schema.NamingStrategy{})
|
|
if err != nil {
|
|
t.Fatalf("failed to parse schema, got error %v", err)
|
|
}
|
|
|
|
if len(userSchema.Relationships.Relations) != 1 {
|
|
t.Fatalf("expects 1 relations, but got %v", len(userSchema.Relationships.Relations))
|
|
}
|
|
|
|
if createdByRel, ok := userSchema.Relationships.Relations["CreatedBy"]; ok {
|
|
if createdByRel.FieldSchema != userSchema {
|
|
t.Fatalf("expects same field schema, but got new %p, old %p", createdByRel.FieldSchema, userSchema)
|
|
}
|
|
} else {
|
|
t.Fatalf("expects created by relations, but not found")
|
|
}
|
|
}
|
|
|
|
func TestSameForeignKey(t *testing.T) {
|
|
type UserAux struct {
|
|
gorm.Model
|
|
Aux string
|
|
UUID string
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Name string
|
|
UUID string
|
|
Aux *UserAux `gorm:"foreignkey:UUID;references:UUID"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{},
|
|
Relation{
|
|
Name: "Aux", Type: schema.HasOne, Schema: "User", FieldSchema: "UserAux",
|
|
References: []Reference{
|
|
{"UUID", "User", "UUID", "UserAux", "", true},
|
|
},
|
|
},
|
|
)
|
|
}
|
|
|
|
func TestBelongsToSameForeignKey(t *testing.T) {
|
|
type User struct {
|
|
gorm.Model
|
|
Name string
|
|
UUID string
|
|
}
|
|
|
|
type UserAux struct {
|
|
gorm.Model
|
|
Aux string
|
|
UUID string
|
|
User User `gorm:"ForeignKey:UUID;references:UUID;belongsTo"`
|
|
}
|
|
|
|
checkStructRelation(t, &UserAux{},
|
|
Relation{
|
|
Name: "User", Type: schema.BelongsTo, Schema: "UserAux", FieldSchema: "User",
|
|
References: []Reference{
|
|
{"UUID", "User", "UUID", "UserAux", "", false},
|
|
},
|
|
},
|
|
)
|
|
}
|
|
|
|
func TestHasOneWithSameForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
ProfileRefer int // not used in relationship
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
Profile Profile `gorm:"ForeignKey:ID;references:ProfileRefer"`
|
|
ProfileRefer int
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"ProfileRefer", "User", "ID", "Profile", "", true}},
|
|
})
|
|
}
|
|
|
|
func TestHasManySameForeignKey(t *testing.T) {
|
|
type Profile struct {
|
|
gorm.Model
|
|
Name string
|
|
UserRefer uint
|
|
}
|
|
|
|
type User struct {
|
|
gorm.Model
|
|
UserRefer uint
|
|
Profile []Profile `gorm:"ForeignKey:UserRefer"`
|
|
}
|
|
|
|
checkStructRelation(t, &User{}, Relation{
|
|
Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile",
|
|
References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}},
|
|
})
|
|
}
|