join_table_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package gorm_test
  2. import (
  3. "fmt"
  4. "strconv"
  5. "testing"
  6. "time"
  7. "github.com/jinzhu/gorm"
  8. )
  9. type Person struct {
  10. Id int
  11. Name string
  12. Addresses []*Address `gorm:"many2many:person_addresses;"`
  13. }
  14. type PersonAddress struct {
  15. gorm.JoinTableHandler
  16. PersonID int
  17. AddressID int
  18. DeletedAt *time.Time
  19. CreatedAt time.Time
  20. }
  21. func (*PersonAddress) Add(handler gorm.JoinTableHandlerInterface, db *gorm.DB, foreignValue interface{}, associationValue interface{}) error {
  22. foreignPrimaryKey, _ := strconv.Atoi(fmt.Sprint(db.NewScope(foreignValue).PrimaryKeyValue()))
  23. associationPrimaryKey, _ := strconv.Atoi(fmt.Sprint(db.NewScope(associationValue).PrimaryKeyValue()))
  24. if result := db.Unscoped().Model(&PersonAddress{}).Where(map[string]interface{}{
  25. "person_id": foreignPrimaryKey,
  26. "address_id": associationPrimaryKey,
  27. }).Update(map[string]interface{}{
  28. "person_id": foreignPrimaryKey,
  29. "address_id": associationPrimaryKey,
  30. "deleted_at": gorm.Expr("NULL"),
  31. }).RowsAffected; result == 0 {
  32. return db.Create(&PersonAddress{
  33. PersonID: foreignPrimaryKey,
  34. AddressID: associationPrimaryKey,
  35. }).Error
  36. }
  37. return nil
  38. }
  39. func (*PersonAddress) Delete(handler gorm.JoinTableHandlerInterface, db *gorm.DB, sources ...interface{}) error {
  40. return db.Delete(&PersonAddress{}).Error
  41. }
  42. func (pa *PersonAddress) JoinWith(handler gorm.JoinTableHandlerInterface, db *gorm.DB, source interface{}) *gorm.DB {
  43. table := pa.Table(db)
  44. return db.Joins("INNER JOIN person_addresses ON person_addresses.address_id = addresses.id").Where(fmt.Sprintf("%v.deleted_at IS NULL OR %v.deleted_at <= '0001-01-02'", table, table))
  45. }
  46. func TestJoinTable(t *testing.T) {
  47. DB.Exec("drop table person_addresses;")
  48. DB.AutoMigrate(&Person{})
  49. DB.SetJoinTableHandler(&Person{}, "Addresses", &PersonAddress{})
  50. address1 := &Address{Address1: "address 1"}
  51. address2 := &Address{Address1: "address 2"}
  52. person := &Person{Name: "person", Addresses: []*Address{address1, address2}}
  53. DB.Save(person)
  54. DB.Model(person).Association("Addresses").Delete(address1)
  55. if DB.Find(&[]PersonAddress{}, "person_id = ?", person.Id).RowsAffected != 1 {
  56. t.Errorf("Should found one address")
  57. }
  58. if DB.Model(person).Association("Addresses").Count() != 1 {
  59. t.Errorf("Should found one address")
  60. }
  61. if DB.Unscoped().Find(&[]PersonAddress{}, "person_id = ?", person.Id).RowsAffected != 2 {
  62. t.Errorf("Found two addresses with Unscoped")
  63. }
  64. if DB.Model(person).Association("Addresses").Clear(); DB.Model(person).Association("Addresses").Count() != 0 {
  65. t.Errorf("Should deleted all addresses")
  66. }
  67. }
  68. func TestEmbeddedMany2ManyRelationship(t *testing.T) {
  69. type EmbeddedPerson struct {
  70. ID int
  71. Name string
  72. Addresses []*Address `gorm:"many2many:person_addresses;"`
  73. }
  74. type NewPerson struct {
  75. EmbeddedPerson
  76. ExternalID uint
  77. }
  78. DB.Exec("drop table person_addresses;")
  79. DB.AutoMigrate(&NewPerson{})
  80. address1 := &Address{Address1: "address 1"}
  81. address2 := &Address{Address1: "address 2"}
  82. person := &NewPerson{ExternalID: 100, EmbeddedPerson: EmbeddedPerson{Name: "person", Addresses: []*Address{address1, address2}}}
  83. if err := DB.Save(person).Error; err != nil {
  84. t.Errorf("no error should return when save embedded many2many relationship, but got %v", err)
  85. }
  86. if err := DB.Model(person).Association("Addresses").Delete(address1).Error; err != nil {
  87. t.Errorf("no error should return when delete embedded many2many relationship, but got %v", err)
  88. }
  89. association := DB.Model(person).Association("Addresses")
  90. if count := association.Count(); count != 1 || association.Error != nil {
  91. t.Errorf("Should found one address, but got %v, error is %v", count, association.Error)
  92. }
  93. if association.Clear(); association.Count() != 0 {
  94. t.Errorf("Should deleted all addresses")
  95. }
  96. }