123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- package gorm_test
- import (
- "os"
- "reflect"
- "sort"
- "testing"
- )
- 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;AssociationForeignKey:id"`
- LocaleTags []Tag `gorm:"many2many:locale_blog_tags;ForeignKey:id,locale;AssociationForeignKey:id"`
- }
- type Tag struct {
- ID uint `gorm:"primary_key"`
- Locale string `gorm:"primary_key"`
- Value string
- Blogs []*Blog `gorm:"many2many:blogs_tags"`
- }
- func compareTags(tags []Tag, contents []string) bool {
- var tagContents []string
- for _, tag := range tags {
- tagContents = append(tagContents, tag.Value)
- }
- sort.Strings(tagContents)
- sort.Strings(contents)
- return reflect.DeepEqual(tagContents, contents)
- }
- func TestManyToManyWithMultiPrimaryKeys(t *testing.T) {
- if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" {
- DB.DropTable(&Blog{}, &Tag{})
- DB.DropTable("blog_tags")
- DB.CreateTable(&Blog{}, &Tag{})
- blog := Blog{
- Locale: "ZH",
- Subject: "subject",
- Body: "body",
- Tags: []Tag{
- {Locale: "ZH", Value: "tag1"},
- {Locale: "ZH", Value: "tag2"},
- },
- }
- DB.Save(&blog)
- if !compareTags(blog.Tags, []string{"tag1", "tag2"}) {
- t.Errorf("Blog should has two tags")
- }
- // Append
- var tag3 = &Tag{Locale: "ZH", Value: "tag3"}
- DB.Model(&blog).Association("Tags").Append([]*Tag{tag3})
- if !compareTags(blog.Tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Blog should has three tags after Append")
- }
- if DB.Model(&blog).Association("Tags").Count() != 3 {
- t.Errorf("Blog should has three tags after Append")
- }
- var tags []Tag
- DB.Model(&blog).Related(&tags, "Tags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Should find 3 tags with Related")
- }
- var blog1 Blog
- DB.Preload("Tags").Find(&blog1)
- if !compareTags(blog1.Tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Preload many2many relations")
- }
- // Replace
- var tag5 = &Tag{Locale: "ZH", Value: "tag5"}
- var tag6 = &Tag{Locale: "ZH", Value: "tag6"}
- DB.Model(&blog).Association("Tags").Replace(tag5, tag6)
- var tags2 []Tag
- DB.Model(&blog).Related(&tags2, "Tags")
- if !compareTags(tags2, []string{"tag5", "tag6"}) {
- t.Errorf("Should find 2 tags after Replace")
- }
- if DB.Model(&blog).Association("Tags").Count() != 2 {
- t.Errorf("Blog should has three tags after Replace")
- }
- // Delete
- DB.Model(&blog).Association("Tags").Delete(tag5)
- var tags3 []Tag
- DB.Model(&blog).Related(&tags3, "Tags")
- if !compareTags(tags3, []string{"tag6"}) {
- t.Errorf("Should find 1 tags after Delete")
- }
- if DB.Model(&blog).Association("Tags").Count() != 1 {
- t.Errorf("Blog should has three tags after Delete")
- }
- DB.Model(&blog).Association("Tags").Delete(tag3)
- var tags4 []Tag
- DB.Model(&blog).Related(&tags4, "Tags")
- if !compareTags(tags4, []string{"tag6"}) {
- t.Errorf("Tag should not be deleted when Delete with a unrelated tag")
- }
- // Clear
- DB.Model(&blog).Association("Tags").Clear()
- if DB.Model(&blog).Association("Tags").Count() != 0 {
- t.Errorf("All tags should be cleared")
- }
- }
- }
- func TestManyToManyWithCustomizedForeignKeys(t *testing.T) {
- if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" {
- DB.DropTable(&Blog{}, &Tag{})
- DB.DropTable("shared_blog_tags")
- DB.CreateTable(&Blog{}, &Tag{})
- blog := Blog{
- Locale: "ZH",
- Subject: "subject",
- Body: "body",
- SharedTags: []Tag{
- {Locale: "ZH", Value: "tag1"},
- {Locale: "ZH", Value: "tag2"},
- },
- }
- DB.Save(&blog)
- blog2 := Blog{
- ID: blog.ID,
- Locale: "EN",
- }
- DB.Create(&blog2)
- if !compareTags(blog.SharedTags, []string{"tag1", "tag2"}) {
- t.Errorf("Blog should has two tags")
- }
- // Append
- var tag3 = &Tag{Locale: "ZH", Value: "tag3"}
- DB.Model(&blog).Association("SharedTags").Append([]*Tag{tag3})
- if !compareTags(blog.SharedTags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Blog should has three tags after Append")
- }
- if DB.Model(&blog).Association("SharedTags").Count() != 3 {
- t.Errorf("Blog should has three tags after Append")
- }
- if DB.Model(&blog2).Association("SharedTags").Count() != 3 {
- t.Errorf("Blog should has three tags after Append")
- }
- var tags []Tag
- DB.Model(&blog).Related(&tags, "SharedTags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Should find 3 tags with Related")
- }
- DB.Model(&blog2).Related(&tags, "SharedTags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Should find 3 tags with Related")
- }
- var blog1 Blog
- DB.Preload("SharedTags").Find(&blog1)
- if !compareTags(blog1.SharedTags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Preload many2many relations")
- }
- var tag4 = &Tag{Locale: "ZH", Value: "tag4"}
- DB.Model(&blog2).Association("SharedTags").Append(tag4)
- DB.Model(&blog).Related(&tags, "SharedTags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3", "tag4"}) {
- t.Errorf("Should find 3 tags with Related")
- }
- DB.Model(&blog2).Related(&tags, "SharedTags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3", "tag4"}) {
- t.Errorf("Should find 3 tags with Related")
- }
- // Replace
- var tag5 = &Tag{Locale: "ZH", Value: "tag5"}
- var tag6 = &Tag{Locale: "ZH", Value: "tag6"}
- DB.Model(&blog2).Association("SharedTags").Replace(tag5, tag6)
- var tags2 []Tag
- DB.Model(&blog).Related(&tags2, "SharedTags")
- if !compareTags(tags2, []string{"tag5", "tag6"}) {
- t.Errorf("Should find 2 tags after Replace")
- }
- DB.Model(&blog2).Related(&tags2, "SharedTags")
- if !compareTags(tags2, []string{"tag5", "tag6"}) {
- t.Errorf("Should find 2 tags after Replace")
- }
- if DB.Model(&blog).Association("SharedTags").Count() != 2 {
- t.Errorf("Blog should has three tags after Replace")
- }
- // Delete
- DB.Model(&blog).Association("SharedTags").Delete(tag5)
- var tags3 []Tag
- DB.Model(&blog).Related(&tags3, "SharedTags")
- if !compareTags(tags3, []string{"tag6"}) {
- t.Errorf("Should find 1 tags after Delete")
- }
- if DB.Model(&blog).Association("SharedTags").Count() != 1 {
- t.Errorf("Blog should has three tags after Delete")
- }
- DB.Model(&blog2).Association("SharedTags").Delete(tag3)
- var tags4 []Tag
- DB.Model(&blog).Related(&tags4, "SharedTags")
- if !compareTags(tags4, []string{"tag6"}) {
- t.Errorf("Tag should not be deleted when Delete with a unrelated tag")
- }
- // Clear
- DB.Model(&blog2).Association("SharedTags").Clear()
- if DB.Model(&blog).Association("SharedTags").Count() != 0 {
- t.Errorf("All tags should be cleared")
- }
- }
- }
- func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) {
- if dialect := os.Getenv("GORM_DIALECT"); dialect != "" && dialect != "sqlite" && dialect != "mssql" {
- DB.DropTable(&Blog{}, &Tag{})
- DB.DropTable("locale_blog_tags")
- DB.CreateTable(&Blog{}, &Tag{})
- blog := Blog{
- Locale: "ZH",
- Subject: "subject",
- Body: "body",
- LocaleTags: []Tag{
- {Locale: "ZH", Value: "tag1"},
- {Locale: "ZH", Value: "tag2"},
- },
- }
- DB.Save(&blog)
- blog2 := Blog{
- ID: blog.ID,
- Locale: "EN",
- }
- DB.Create(&blog2)
- // Append
- var tag3 = &Tag{Locale: "ZH", Value: "tag3"}
- DB.Model(&blog).Association("LocaleTags").Append([]*Tag{tag3})
- if !compareTags(blog.LocaleTags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Blog should has three tags after Append")
- }
- if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
- t.Errorf("Blog should has three tags after Append")
- }
- if DB.Model(&blog2).Association("LocaleTags").Count() != 0 {
- t.Errorf("EN Blog should has 0 tags after ZH Blog Append")
- }
- var tags []Tag
- DB.Model(&blog).Related(&tags, "LocaleTags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Should find 3 tags with Related")
- }
- DB.Model(&blog2).Related(&tags, "LocaleTags")
- if len(tags) != 0 {
- t.Errorf("Should find 0 tags with Related for EN Blog")
- }
- var blog1 Blog
- DB.Preload("LocaleTags").Find(&blog1, "locale = ? AND id = ?", "ZH", blog.ID)
- if !compareTags(blog1.LocaleTags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Preload many2many relations")
- }
- var tag4 = &Tag{Locale: "ZH", Value: "tag4"}
- DB.Model(&blog2).Association("LocaleTags").Append(tag4)
- DB.Model(&blog).Related(&tags, "LocaleTags")
- if !compareTags(tags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("Should find 3 tags with Related for EN Blog")
- }
- DB.Model(&blog2).Related(&tags, "LocaleTags")
- if !compareTags(tags, []string{"tag4"}) {
- t.Errorf("Should find 1 tags with Related for EN Blog")
- }
- // Replace
- var tag5 = &Tag{Locale: "ZH", Value: "tag5"}
- var tag6 = &Tag{Locale: "ZH", Value: "tag6"}
- DB.Model(&blog2).Association("LocaleTags").Replace(tag5, tag6)
- var tags2 []Tag
- DB.Model(&blog).Related(&tags2, "LocaleTags")
- if !compareTags(tags2, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("CN Blog's tags should not be changed after EN Blog Replace")
- }
- var blog11 Blog
- DB.Preload("LocaleTags").First(&blog11, "id = ? AND locale = ?", blog.ID, blog.Locale)
- if !compareTags(blog11.LocaleTags, []string{"tag1", "tag2", "tag3"}) {
- t.Errorf("CN Blog's tags should not be changed after EN Blog Replace")
- }
- DB.Model(&blog2).Related(&tags2, "LocaleTags")
- if !compareTags(tags2, []string{"tag5", "tag6"}) {
- t.Errorf("Should find 2 tags after Replace")
- }
- var blog21 Blog
- DB.Preload("LocaleTags").First(&blog21, "id = ? AND locale = ?", blog2.ID, blog2.Locale)
- if !compareTags(blog21.LocaleTags, []string{"tag5", "tag6"}) {
- t.Errorf("EN Blog's tags should be changed after Replace")
- }
- if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
- t.Errorf("ZH Blog should has three tags after Replace")
- }
- if DB.Model(&blog2).Association("LocaleTags").Count() != 2 {
- t.Errorf("EN Blog should has two tags after Replace")
- }
- // Delete
- DB.Model(&blog).Association("LocaleTags").Delete(tag5)
- if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
- t.Errorf("ZH Blog should has three tags after Delete with EN's tag")
- }
- if DB.Model(&blog2).Association("LocaleTags").Count() != 2 {
- t.Errorf("EN Blog should has two tags after ZH Blog Delete with EN's tag")
- }
- DB.Model(&blog2).Association("LocaleTags").Delete(tag5)
- if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
- t.Errorf("ZH Blog should has three tags after EN Blog Delete with EN's tag")
- }
- if DB.Model(&blog2).Association("LocaleTags").Count() != 1 {
- t.Errorf("EN Blog should has 1 tags after EN Blog Delete with EN's tag")
- }
- // Clear
- DB.Model(&blog2).Association("LocaleTags").Clear()
- if DB.Model(&blog).Association("LocaleTags").Count() != 3 {
- t.Errorf("ZH Blog's tags should not be cleared when clear EN Blog's tags")
- }
- if DB.Model(&blog2).Association("LocaleTags").Count() != 0 {
- t.Errorf("EN Blog's tags should be cleared when clear EN Blog's tags")
- }
- DB.Model(&blog).Association("LocaleTags").Clear()
- if DB.Model(&blog).Association("LocaleTags").Count() != 0 {
- t.Errorf("ZH Blog's tags should be cleared when clear ZH Blog's tags")
- }
- if DB.Model(&blog2).Association("LocaleTags").Count() != 0 {
- t.Errorf("EN Blog's tags should be cleared")
- }
- }
- }
|