Test HasMany Association for Slice
This commit is contained in:
		
							parent
							
								
									5d9b57cc4e
								
							
						
					
					
						commit
						135d9f8b03
					
				| @ -185,6 +185,7 @@ func (association *Association) Delete(values ...interface{}) error { | |||||||
| 			primaryFields, foreignFields []*schema.Field | 			primaryFields, foreignFields []*schema.Field | ||||||
| 			foreignKeys                  []string | 			foreignKeys                  []string | ||||||
| 			updateAttrs                  = map[string]interface{}{} | 			updateAttrs                  = map[string]interface{}{} | ||||||
|  | 			conds                        []clause.Expression | ||||||
| 		) | 		) | ||||||
| 
 | 
 | ||||||
| 		for _, ref := range rel.References { | 		for _, ref := range rel.References { | ||||||
| @ -193,6 +194,8 @@ func (association *Association) Delete(values ...interface{}) error { | |||||||
| 				foreignFields = append(foreignFields, ref.ForeignKey) | 				foreignFields = append(foreignFields, ref.ForeignKey) | ||||||
| 				foreignKeys = append(foreignKeys, ref.ForeignKey.DBName) | 				foreignKeys = append(foreignKeys, ref.ForeignKey.DBName) | ||||||
| 				updateAttrs[ref.ForeignKey.DBName] = nil | 				updateAttrs[ref.ForeignKey.DBName] = nil | ||||||
|  | 			} else { | ||||||
|  | 				conds = append(conds, clause.Eq{Column: ref.ForeignKey.DBName, Value: ref.PrimaryValue}) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -205,12 +208,11 @@ func (association *Association) Delete(values ...interface{}) error { | |||||||
| 			) | 			) | ||||||
| 
 | 
 | ||||||
| 			column, values := schema.ToQueryValues(foreignKeys, queryValues) | 			column, values := schema.ToQueryValues(foreignKeys, queryValues) | ||||||
|  | 			conds = append(conds, clause.IN{Column: column, Values: values}) | ||||||
| 			relColumn, relValues := schema.ToQueryValues(rel.FieldSchema.PrimaryFieldDBNames, relQueryValues) | 			relColumn, relValues := schema.ToQueryValues(rel.FieldSchema.PrimaryFieldDBNames, relQueryValues) | ||||||
|  | 			conds = append(conds, clause.IN{Column: relColumn, Values: relValues}) | ||||||
| 
 | 
 | ||||||
| 			tx.Session(&Session{}).Model(modelValue).Clauses( | 			tx.Session(&Session{}).Model(modelValue).Clauses(conds...).UpdateColumns(updateAttrs) | ||||||
| 				clause.IN{Column: column, Values: values}, |  | ||||||
| 				clause.IN{Column: relColumn, Values: relValues}, |  | ||||||
| 			).UpdateColumns(updateAttrs) |  | ||||||
| 		case schema.BelongsTo: | 		case schema.BelongsTo: | ||||||
| 			var ( | 			var ( | ||||||
| 				modelValue        = reflect.New(rel.Schema.ModelType).Interface() | 				modelValue        = reflect.New(rel.Schema.ModelType).Interface() | ||||||
| @ -219,12 +221,11 @@ func (association *Association) Delete(values ...interface{}) error { | |||||||
| 			) | 			) | ||||||
| 
 | 
 | ||||||
| 			column, values := schema.ToQueryValues(rel.Schema.PrimaryFieldDBNames, queryValues) | 			column, values := schema.ToQueryValues(rel.Schema.PrimaryFieldDBNames, queryValues) | ||||||
|  | 			conds = append(conds, clause.IN{Column: column, Values: values}) | ||||||
| 			relColumn, relValues := schema.ToQueryValues(foreignKeys, relQueryValues) | 			relColumn, relValues := schema.ToQueryValues(foreignKeys, relQueryValues) | ||||||
|  | 			conds = append(conds, clause.IN{Column: relColumn, Values: relValues}) | ||||||
| 
 | 
 | ||||||
| 			tx.Session(&Session{}).Model(modelValue).Clauses( | 			tx.Session(&Session{}).Model(modelValue).Clauses(conds...).UpdateColumns(updateAttrs) | ||||||
| 				clause.IN{Column: column, Values: values}, |  | ||||||
| 				clause.IN{Column: relColumn, Values: relValues}, |  | ||||||
| 			).UpdateColumns(updateAttrs) |  | ||||||
| 		case schema.Many2Many: | 		case schema.Many2Many: | ||||||
| 			modelValue := reflect.New(rel.JoinTable.ModelType).Interface() | 			modelValue := reflect.New(rel.JoinTable.ModelType).Interface() | ||||||
| 			conds := rel.ToQueryConditions(reflectValue) | 			conds := rel.ToQueryConditions(reflectValue) | ||||||
|  | |||||||
| @ -87,6 +87,9 @@ func (p *processor) Execute(db *DB) { | |||||||
| 
 | 
 | ||||||
| 		if stmt.Dest != nil { | 		if stmt.Dest != nil { | ||||||
| 			stmt.ReflectValue = reflect.Indirect(reflect.ValueOf(stmt.Dest)) | 			stmt.ReflectValue = reflect.Indirect(reflect.ValueOf(stmt.Dest)) | ||||||
|  | 			for stmt.ReflectValue.Kind() == reflect.Ptr { | ||||||
|  | 				stmt.ReflectValue = stmt.ReflectValue.Elem() | ||||||
|  | 			} | ||||||
| 			if !stmt.ReflectValue.IsValid() { | 			if !stmt.ReflectValue.IsValid() { | ||||||
| 				db.AddError(fmt.Errorf("invalid value")) | 				db.AddError(fmt.Errorf("invalid value")) | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -125,7 +125,7 @@ func SaveAfterAssociations(db *gorm.DB) { | |||||||
| 						if _, isZero := rel.FieldSchema.PrioritizedPrimaryField.ValueOf(rv); isZero { | 						if _, isZero := rel.FieldSchema.PrioritizedPrimaryField.ValueOf(rv); isZero { | ||||||
| 							elems = reflect.Append(elems, rv) | 							elems = reflect.Append(elems, rv) | ||||||
| 						} else { | 						} else { | ||||||
| 							db.Session(&gorm.Session{}).Save(rv.Interface()) | 							db.Session(&gorm.Session{}).Save(rv.Addr().Interface()) | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| @ -192,7 +192,7 @@ func SaveAfterAssociations(db *gorm.DB) { | |||||||
| 								elems = reflect.Append(elems, elem.Addr()) | 								elems = reflect.Append(elems, elem.Addr()) | ||||||
| 							} | 							} | ||||||
| 						} else { | 						} else { | ||||||
| 							db.Session(&gorm.Session{}).Save(elem.Interface()) | 							db.Session(&gorm.Session{}).Save(elem.Addr().Interface()) | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | |||||||
| @ -606,7 +606,7 @@ func TestHasManyAssociationForSlice(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 	AssertAssociationCount(t, users, "Pets", 4, "after delete") | 	AssertAssociationCount(t, users, "Pets", 4, "after delete") | ||||||
| 
 | 
 | ||||||
| 	if err := DB.Debug().Model(&users).Association("Pets").Delete(users[0].Pets[0], users[1].Pets[1]); err != nil { | 	if err := DB.Model(&users).Association("Pets").Delete(users[0].Pets[0], users[1].Pets[1]); err != nil { | ||||||
| 		t.Errorf("no error should happend when deleting pet, but got %v", err) | 		t.Errorf("no error should happend when deleting pet, but got %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -616,3 +616,153 @@ func TestHasManyAssociationForSlice(t *testing.T) { | |||||||
| 	DB.Model(&users).Association("Pets").Clear() | 	DB.Model(&users).Association("Pets").Clear() | ||||||
| 	AssertAssociationCount(t, users, "Pets", 0, "After Clear") | 	AssertAssociationCount(t, users, "Pets", 0, "After Clear") | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestPolymorphicHasManyAssociation(t *testing.T) { | ||||||
|  | 	var user = *GetUser("hasmany", Config{Toys: 2}) | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Create(&user).Error; err != nil { | ||||||
|  | 		t.Fatalf("errors happened when create: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	CheckUser(t, user, user) | ||||||
|  | 
 | ||||||
|  | 	// Find
 | ||||||
|  | 	var user2 User | ||||||
|  | 	DB.Find(&user2, "id = ?", user.ID) | ||||||
|  | 	DB.Model(&user2).Association("Toys").Find(&user2.Toys) | ||||||
|  | 	CheckUser(t, user2, user) | ||||||
|  | 
 | ||||||
|  | 	// Count
 | ||||||
|  | 	AssertAssociationCount(t, user, "Toys", 2, "") | ||||||
|  | 
 | ||||||
|  | 	// Append
 | ||||||
|  | 	var toy = Toy{Name: "toy-has-many-append"} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Append(&toy); err != nil { | ||||||
|  | 		t.Fatalf("Error happened when append account, got %v", err) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | 
 | ||||||
|  | 	if toy.ID == 0 { | ||||||
|  | 		t.Fatalf("Toy's ID should be created") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	user.Toys = append(user.Toys, toy) | ||||||
|  | 	CheckUser(t, user2, user) | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, user, "Toys", 3, "AfterAppend") | ||||||
|  | 
 | ||||||
|  | 	var toys = []Toy{{Name: "toy-has-many-append-1-1"}, {Name: "toy-has-many-append-1-1"}} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Append(&toys); err != nil { | ||||||
|  | 		t.Fatalf("Error happened when append toy, got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, toy := range toys { | ||||||
|  | 		var toy = toy | ||||||
|  | 		if toy.ID == 0 { | ||||||
|  | 			t.Fatalf("Toy's ID should be created") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		user.Toys = append(user.Toys, toy) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	CheckUser(t, user2, user) | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, user, "Toys", 5, "AfterAppendSlice") | ||||||
|  | 
 | ||||||
|  | 	// Replace
 | ||||||
|  | 	var toy2 = Toy{Name: "toy-has-many-replace"} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Replace(&toy2); err != nil { | ||||||
|  | 		t.Fatalf("Error happened when append toy, got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if toy2.ID == 0 { | ||||||
|  | 		t.Fatalf("toy2's ID should be created") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	user.Toys = []Toy{toy2} | ||||||
|  | 	CheckUser(t, user2, user) | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, user2, "Toys", 1, "AfterReplace") | ||||||
|  | 
 | ||||||
|  | 	// Delete
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Delete(&Toy{}); err != nil { | ||||||
|  | 		t.Fatalf("Error happened when delete toy, got %v", err) | ||||||
|  | 	} | ||||||
|  | 	AssertAssociationCount(t, user2, "Toys", 1, "after delete non-existing data") | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Delete(&toy2); err != nil { | ||||||
|  | 		t.Fatalf("Error happened when delete Toys, got %v", err) | ||||||
|  | 	} | ||||||
|  | 	AssertAssociationCount(t, user2, "Toys", 0, "after delete") | ||||||
|  | 
 | ||||||
|  | 	// Prepare Data for Clear
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Append(&toy); err != nil { | ||||||
|  | 		t.Fatalf("Error happened when append Toys, got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, user2, "Toys", 1, "after prepare data") | ||||||
|  | 
 | ||||||
|  | 	// Clear
 | ||||||
|  | 	if err := DB.Model(&user2).Association("Toys").Clear(); err != nil { | ||||||
|  | 		t.Errorf("Error happened when clear Toys, got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, user2, "Toys", 0, "after clear") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestPolymorphicHasManyAssociationForSlice(t *testing.T) { | ||||||
|  | 	var users = []User{ | ||||||
|  | 		*GetUser("slice-hasmany-1", Config{Toys: 2}), | ||||||
|  | 		*GetUser("slice-hasmany-2", Config{Toys: 0}), | ||||||
|  | 		*GetUser("slice-hasmany-3", Config{Toys: 4}), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	DB.Create(&users) | ||||||
|  | 
 | ||||||
|  | 	// Count
 | ||||||
|  | 	AssertAssociationCount(t, users, "Toys", 6, "") | ||||||
|  | 
 | ||||||
|  | 	// Find
 | ||||||
|  | 	var toys []Toy | ||||||
|  | 	if DB.Model(&users).Association("Toys").Find(&toys); len(toys) != 6 { | ||||||
|  | 		t.Errorf("toys count should be %v, but got %v", 6, len(toys)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Append
 | ||||||
|  | 	DB.Model(&users).Association("Toys").Append( | ||||||
|  | 		&Toy{Name: "toy-slice-append-1"}, | ||||||
|  | 		[]Toy{{Name: "toy-slice-append-2-1"}, {Name: "toy-slice-append-2-2"}}, | ||||||
|  | 		&Toy{Name: "toy-slice-append-3"}, | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, users, "Toys", 10, "After Append") | ||||||
|  | 
 | ||||||
|  | 	// Replace -> same as append
 | ||||||
|  | 	DB.Model(&users).Association("Toys").Replace( | ||||||
|  | 		[]*Toy{{Name: "toy-slice-replace-1-1"}, {Name: "toy-slice-replace-1-2"}}, | ||||||
|  | 		[]*Toy{{Name: "toy-slice-replace-2-1"}, {Name: "toy-slice-replace-2-2"}}, | ||||||
|  | 		&Toy{Name: "toy-slice-replace-3"}, | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, users, "Toys", 5, "After Append") | ||||||
|  | 
 | ||||||
|  | 	// Delete
 | ||||||
|  | 	if err := DB.Model(&users).Association("Toys").Delete(&users[2].Toys); err != nil { | ||||||
|  | 		t.Errorf("no error should happend when deleting toy, but got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, users, "Toys", 4, "after delete") | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Model(&users).Association("Toys").Delete(users[0].Toys[0], users[1].Toys[1]); err != nil { | ||||||
|  | 		t.Errorf("no error should happend when deleting toy, but got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	AssertAssociationCount(t, users, "Toys", 2, "after delete") | ||||||
|  | 
 | ||||||
|  | 	// Clear
 | ||||||
|  | 	DB.Model(&users).Association("Toys").Clear() | ||||||
|  | 	AssertAssociationCount(t, users, "Toys", 0, "After Clear") | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu