OSDN Git Service

versoin1.1.9 (#594)
[bytom/vapor.git] / vendor / github.com / jinzhu / gorm / update_test.go
1 package gorm_test
2
3 import (
4         "testing"
5         "time"
6
7         "github.com/jinzhu/gorm"
8 )
9
10 func TestUpdate(t *testing.T) {
11         product1 := Product{Code: "product1code"}
12         product2 := Product{Code: "product2code"}
13
14         DB.Save(&product1).Save(&product2).Update("code", "product2newcode")
15
16         if product2.Code != "product2newcode" {
17                 t.Errorf("Record should be updated")
18         }
19
20         DB.First(&product1, product1.Id)
21         DB.First(&product2, product2.Id)
22         updatedAt1 := product1.UpdatedAt
23
24         if DB.First(&Product{}, "code = ?", product1.Code).RecordNotFound() {
25                 t.Errorf("Product1 should not be updated")
26         }
27
28         if !DB.First(&Product{}, "code = ?", "product2code").RecordNotFound() {
29                 t.Errorf("Product2's code should be updated")
30         }
31
32         if DB.First(&Product{}, "code = ?", "product2newcode").RecordNotFound() {
33                 t.Errorf("Product2's code should be updated")
34         }
35
36         DB.Table("products").Where("code in (?)", []string{"product1code"}).Update("code", "product1newcode")
37
38         var product4 Product
39         DB.First(&product4, product1.Id)
40         if updatedAt1.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) {
41                 t.Errorf("updatedAt should be updated if something changed")
42         }
43
44         if !DB.First(&Product{}, "code = 'product1code'").RecordNotFound() {
45                 t.Errorf("Product1's code should be updated")
46         }
47
48         if DB.First(&Product{}, "code = 'product1newcode'").RecordNotFound() {
49                 t.Errorf("Product should not be changed to 789")
50         }
51
52         if DB.Model(product2).Update("CreatedAt", time.Now().Add(time.Hour)).Error != nil {
53                 t.Error("No error should raise when update with CamelCase")
54         }
55
56         if DB.Model(&product2).UpdateColumn("CreatedAt", time.Now().Add(time.Hour)).Error != nil {
57                 t.Error("No error should raise when update_column with CamelCase")
58         }
59
60         var products []Product
61         DB.Find(&products)
62         if count := DB.Model(Product{}).Update("CreatedAt", time.Now().Add(2*time.Hour)).RowsAffected; count != int64(len(products)) {
63                 t.Error("RowsAffected should be correct when do batch update")
64         }
65
66         DB.First(&product4, product4.Id)
67         updatedAt4 := product4.UpdatedAt
68         DB.Model(&product4).Update("price", gorm.Expr("price + ? - ?", 100, 50))
69         var product5 Product
70         DB.First(&product5, product4.Id)
71         if product5.Price != product4.Price+100-50 {
72                 t.Errorf("Update with expression")
73         }
74         if product4.UpdatedAt.Format(time.RFC3339Nano) == updatedAt4.Format(time.RFC3339Nano) {
75                 t.Errorf("Update with expression should update UpdatedAt")
76         }
77 }
78
79 func TestUpdateWithNoStdPrimaryKeyAndDefaultValues(t *testing.T) {
80         animal := Animal{Name: "Ferdinand"}
81         DB.Save(&animal)
82         updatedAt1 := animal.UpdatedAt
83
84         DB.Save(&animal).Update("name", "Francis")
85
86         if updatedAt1.Format(time.RFC3339Nano) == animal.UpdatedAt.Format(time.RFC3339Nano) {
87                 t.Errorf("updatedAt should not be updated if nothing changed")
88         }
89
90         var animals []Animal
91         DB.Find(&animals)
92         if count := DB.Model(Animal{}).Update("CreatedAt", time.Now().Add(2*time.Hour)).RowsAffected; count != int64(len(animals)) {
93                 t.Error("RowsAffected should be correct when do batch update")
94         }
95
96         animal = Animal{From: "somewhere"}              // No name fields, should be filled with the default value (galeone)
97         DB.Save(&animal).Update("From", "a nice place") // The name field shoul be untouched
98         DB.First(&animal, animal.Counter)
99         if animal.Name != "galeone" {
100                 t.Errorf("Name fields shouldn't be changed if untouched, but got %v", animal.Name)
101         }
102
103         // When changing a field with a default value, the change must occur
104         animal.Name = "amazing horse"
105         DB.Save(&animal)
106         DB.First(&animal, animal.Counter)
107         if animal.Name != "amazing horse" {
108                 t.Errorf("Update a filed with a default value should occur. But got %v\n", animal.Name)
109         }
110
111         // When changing a field with a default value with blank value
112         animal.Name = ""
113         DB.Save(&animal)
114         DB.First(&animal, animal.Counter)
115         if animal.Name != "" {
116                 t.Errorf("Update a filed to blank with a default value should occur. But got %v\n", animal.Name)
117         }
118 }
119
120 func TestUpdates(t *testing.T) {
121         product1 := Product{Code: "product1code", Price: 10}
122         product2 := Product{Code: "product2code", Price: 10}
123         DB.Save(&product1).Save(&product2)
124         DB.Model(&product1).Updates(map[string]interface{}{"code": "product1newcode", "price": 100})
125         if product1.Code != "product1newcode" || product1.Price != 100 {
126                 t.Errorf("Record should be updated also with map")
127         }
128
129         DB.First(&product1, product1.Id)
130         DB.First(&product2, product2.Id)
131         updatedAt2 := product2.UpdatedAt
132
133         if DB.First(&Product{}, "code = ? and price = ?", product2.Code, product2.Price).RecordNotFound() {
134                 t.Errorf("Product2 should not be updated")
135         }
136
137         if DB.First(&Product{}, "code = ?", "product1newcode").RecordNotFound() {
138                 t.Errorf("Product1 should be updated")
139         }
140
141         DB.Table("products").Where("code in (?)", []string{"product2code"}).Updates(Product{Code: "product2newcode"})
142         if !DB.First(&Product{}, "code = 'product2code'").RecordNotFound() {
143                 t.Errorf("Product2's code should be updated")
144         }
145
146         var product4 Product
147         DB.First(&product4, product2.Id)
148         if updatedAt2.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) {
149                 t.Errorf("updatedAt should be updated if something changed")
150         }
151
152         if DB.First(&Product{}, "code = ?", "product2newcode").RecordNotFound() {
153                 t.Errorf("product2's code should be updated")
154         }
155
156         updatedAt4 := product4.UpdatedAt
157         DB.Model(&product4).Updates(map[string]interface{}{"price": gorm.Expr("price + ?", 100)})
158         var product5 Product
159         DB.First(&product5, product4.Id)
160         if product5.Price != product4.Price+100 {
161                 t.Errorf("Updates with expression")
162         }
163         // product4's UpdatedAt will be reset when updating
164         if product4.UpdatedAt.Format(time.RFC3339Nano) == updatedAt4.Format(time.RFC3339Nano) {
165                 t.Errorf("Updates with expression should update UpdatedAt")
166         }
167 }
168
169 func TestUpdateColumn(t *testing.T) {
170         product1 := Product{Code: "product1code", Price: 10}
171         product2 := Product{Code: "product2code", Price: 20}
172         DB.Save(&product1).Save(&product2).UpdateColumn(map[string]interface{}{"code": "product2newcode", "price": 100})
173         if product2.Code != "product2newcode" || product2.Price != 100 {
174                 t.Errorf("product 2 should be updated with update column")
175         }
176
177         var product3 Product
178         DB.First(&product3, product1.Id)
179         if product3.Code != "product1code" || product3.Price != 10 {
180                 t.Errorf("product 1 should not be updated")
181         }
182
183         DB.First(&product2, product2.Id)
184         updatedAt2 := product2.UpdatedAt
185         DB.Model(product2).UpdateColumn("code", "update_column_new")
186         var product4 Product
187         DB.First(&product4, product2.Id)
188         if updatedAt2.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) {
189                 t.Errorf("updatedAt should not be updated with update column")
190         }
191
192         DB.Model(&product4).UpdateColumn("price", gorm.Expr("price + 100 - 50"))
193         var product5 Product
194         DB.First(&product5, product4.Id)
195         if product5.Price != product4.Price+100-50 {
196                 t.Errorf("UpdateColumn with expression")
197         }
198         if product5.UpdatedAt.Format(time.RFC3339Nano) != product4.UpdatedAt.Format(time.RFC3339Nano) {
199                 t.Errorf("UpdateColumn with expression should not update UpdatedAt")
200         }
201 }
202
203 func TestSelectWithUpdate(t *testing.T) {
204         user := getPreparedUser("select_user", "select_with_update")
205         DB.Create(user)
206
207         var reloadUser User
208         DB.First(&reloadUser, user.Id)
209         reloadUser.Name = "new_name"
210         reloadUser.Age = 50
211         reloadUser.BillingAddress = Address{Address1: "New Billing Address"}
212         reloadUser.ShippingAddress = Address{Address1: "New ShippingAddress Address"}
213         reloadUser.CreditCard = CreditCard{Number: "987654321"}
214         reloadUser.Emails = []Email{
215                 {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"},
216         }
217         reloadUser.Company = Company{Name: "new company"}
218
219         DB.Select("Name", "BillingAddress", "CreditCard", "Company", "Emails").Save(&reloadUser)
220
221         var queryUser User
222         DB.Preload("BillingAddress").Preload("ShippingAddress").
223                 Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id)
224
225         if queryUser.Name == user.Name || queryUser.Age != user.Age {
226                 t.Errorf("Should only update users with name column")
227         }
228
229         if queryUser.BillingAddressID.Int64 == user.BillingAddressID.Int64 ||
230                 queryUser.ShippingAddressId != user.ShippingAddressId ||
231                 queryUser.CreditCard.ID == user.CreditCard.ID ||
232                 len(queryUser.Emails) == len(user.Emails) || queryUser.Company.Id == user.Company.Id {
233                 t.Errorf("Should only update selected relationships")
234         }
235 }
236
237 func TestSelectWithUpdateWithMap(t *testing.T) {
238         user := getPreparedUser("select_user", "select_with_update_map")
239         DB.Create(user)
240
241         updateValues := map[string]interface{}{
242                 "Name":            "new_name",
243                 "Age":             50,
244                 "BillingAddress":  Address{Address1: "New Billing Address"},
245                 "ShippingAddress": Address{Address1: "New ShippingAddress Address"},
246                 "CreditCard":      CreditCard{Number: "987654321"},
247                 "Emails": []Email{
248                         {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"},
249                 },
250                 "Company": Company{Name: "new company"},
251         }
252
253         var reloadUser User
254         DB.First(&reloadUser, user.Id)
255         DB.Model(&reloadUser).Select("Name", "BillingAddress", "CreditCard", "Company", "Emails").Update(updateValues)
256
257         var queryUser User
258         DB.Preload("BillingAddress").Preload("ShippingAddress").
259                 Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id)
260
261         if queryUser.Name == user.Name || queryUser.Age != user.Age {
262                 t.Errorf("Should only update users with name column")
263         }
264
265         if queryUser.BillingAddressID.Int64 == user.BillingAddressID.Int64 ||
266                 queryUser.ShippingAddressId != user.ShippingAddressId ||
267                 queryUser.CreditCard.ID == user.CreditCard.ID ||
268                 len(queryUser.Emails) == len(user.Emails) || queryUser.Company.Id == user.Company.Id {
269                 t.Errorf("Should only update selected relationships")
270         }
271 }
272
273 func TestOmitWithUpdate(t *testing.T) {
274         user := getPreparedUser("omit_user", "omit_with_update")
275         DB.Create(user)
276
277         var reloadUser User
278         DB.First(&reloadUser, user.Id)
279         reloadUser.Name = "new_name"
280         reloadUser.Age = 50
281         reloadUser.BillingAddress = Address{Address1: "New Billing Address"}
282         reloadUser.ShippingAddress = Address{Address1: "New ShippingAddress Address"}
283         reloadUser.CreditCard = CreditCard{Number: "987654321"}
284         reloadUser.Emails = []Email{
285                 {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"},
286         }
287         reloadUser.Company = Company{Name: "new company"}
288
289         DB.Omit("Name", "BillingAddress", "CreditCard", "Company", "Emails").Save(&reloadUser)
290
291         var queryUser User
292         DB.Preload("BillingAddress").Preload("ShippingAddress").
293                 Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id)
294
295         if queryUser.Name != user.Name || queryUser.Age == user.Age {
296                 t.Errorf("Should only update users with name column")
297         }
298
299         if queryUser.BillingAddressID.Int64 != user.BillingAddressID.Int64 ||
300                 queryUser.ShippingAddressId == user.ShippingAddressId ||
301                 queryUser.CreditCard.ID != user.CreditCard.ID ||
302                 len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id {
303                 t.Errorf("Should only update relationships that not omitted")
304         }
305 }
306
307 func TestOmitWithUpdateWithMap(t *testing.T) {
308         user := getPreparedUser("select_user", "select_with_update_map")
309         DB.Create(user)
310
311         updateValues := map[string]interface{}{
312                 "Name":            "new_name",
313                 "Age":             50,
314                 "BillingAddress":  Address{Address1: "New Billing Address"},
315                 "ShippingAddress": Address{Address1: "New ShippingAddress Address"},
316                 "CreditCard":      CreditCard{Number: "987654321"},
317                 "Emails": []Email{
318                         {Email: "new_user_1@example1.com"}, {Email: "new_user_2@example2.com"}, {Email: "new_user_3@example2.com"},
319                 },
320                 "Company": Company{Name: "new company"},
321         }
322
323         var reloadUser User
324         DB.First(&reloadUser, user.Id)
325         DB.Model(&reloadUser).Omit("Name", "BillingAddress", "CreditCard", "Company", "Emails").Update(updateValues)
326
327         var queryUser User
328         DB.Preload("BillingAddress").Preload("ShippingAddress").
329                 Preload("CreditCard").Preload("Emails").Preload("Company").First(&queryUser, user.Id)
330
331         if queryUser.Name != user.Name || queryUser.Age == user.Age {
332                 t.Errorf("Should only update users with name column")
333         }
334
335         if queryUser.BillingAddressID.Int64 != user.BillingAddressID.Int64 ||
336                 queryUser.ShippingAddressId == user.ShippingAddressId ||
337                 queryUser.CreditCard.ID != user.CreditCard.ID ||
338                 len(queryUser.Emails) != len(user.Emails) || queryUser.Company.Id != user.Company.Id {
339                 t.Errorf("Should only update relationships not omitted")
340         }
341 }
342
343 func TestSelectWithUpdateColumn(t *testing.T) {
344         user := getPreparedUser("select_user", "select_with_update_map")
345         DB.Create(user)
346
347         updateValues := map[string]interface{}{"Name": "new_name", "Age": 50}
348
349         var reloadUser User
350         DB.First(&reloadUser, user.Id)
351         DB.Model(&reloadUser).Select("Name").UpdateColumn(updateValues)
352
353         var queryUser User
354         DB.First(&queryUser, user.Id)
355
356         if queryUser.Name == user.Name || queryUser.Age != user.Age {
357                 t.Errorf("Should only update users with name column")
358         }
359 }
360
361 func TestOmitWithUpdateColumn(t *testing.T) {
362         user := getPreparedUser("select_user", "select_with_update_map")
363         DB.Create(user)
364
365         updateValues := map[string]interface{}{"Name": "new_name", "Age": 50}
366
367         var reloadUser User
368         DB.First(&reloadUser, user.Id)
369         DB.Model(&reloadUser).Omit("Name").UpdateColumn(updateValues)
370
371         var queryUser User
372         DB.First(&queryUser, user.Id)
373
374         if queryUser.Name != user.Name || queryUser.Age == user.Age {
375                 t.Errorf("Should omit name column when update user")
376         }
377 }
378
379 func TestUpdateColumnsSkipsAssociations(t *testing.T) {
380         user := getPreparedUser("update_columns_user", "special_role")
381         user.Age = 99
382         address1 := "first street"
383         user.BillingAddress = Address{Address1: address1}
384         DB.Save(user)
385
386         // Update a single field of the user and verify that the changed address is not stored.
387         newAge := int64(100)
388         user.BillingAddress.Address1 = "second street"
389         db := DB.Model(user).UpdateColumns(User{Age: newAge})
390         if db.RowsAffected != 1 {
391                 t.Errorf("Expected RowsAffected=1 but instead RowsAffected=%v", DB.RowsAffected)
392         }
393
394         // Verify that Age now=`newAge`.
395         freshUser := &User{Id: user.Id}
396         DB.First(freshUser)
397         if freshUser.Age != newAge {
398                 t.Errorf("Expected freshly queried user to have Age=%v but instead found Age=%v", newAge, freshUser.Age)
399         }
400
401         // Verify that user's BillingAddress.Address1 is not changed and is still "first street".
402         DB.First(&freshUser.BillingAddress, freshUser.BillingAddressID)
403         if freshUser.BillingAddress.Address1 != address1 {
404                 t.Errorf("Expected user's BillingAddress.Address1=%s to remain unchanged after UpdateColumns invocation, but BillingAddress.Address1=%s", address1, freshUser.BillingAddress.Address1)
405         }
406 }
407
408 func TestUpdatesWithBlankValues(t *testing.T) {
409         product := Product{Code: "product1", Price: 10}
410         DB.Save(&product)
411
412         DB.Model(&Product{Id: product.Id}).Updates(&Product{Price: 100})
413
414         var product1 Product
415         DB.First(&product1, product.Id)
416
417         if product1.Code != "product1" || product1.Price != 100 {
418                 t.Errorf("product's code should not be updated")
419         }
420 }
421
422 type ElementWithIgnoredField struct {
423         Id           int64
424         Value        string
425         IgnoredField int64 `sql:"-"`
426 }
427
428 func (e ElementWithIgnoredField) TableName() string {
429         return "element_with_ignored_field"
430 }
431
432 func TestUpdatesTableWithIgnoredValues(t *testing.T) {
433         elem := ElementWithIgnoredField{Value: "foo", IgnoredField: 10}
434         DB.Save(&elem)
435
436         DB.Table(elem.TableName()).
437                 Where("id = ?", elem.Id).
438                 // DB.Model(&ElementWithIgnoredField{Id: elem.Id}).
439                 Updates(&ElementWithIgnoredField{Value: "bar", IgnoredField: 100})
440
441         var elem1 ElementWithIgnoredField
442         err := DB.First(&elem1, elem.Id).Error
443         if err != nil {
444                 t.Errorf("error getting an element from database: %s", err.Error())
445         }
446
447         if elem1.IgnoredField != 0 {
448                 t.Errorf("element's ignored field should not be updated")
449         }
450 }
451
452 func TestUpdateDecodeVirtualAttributes(t *testing.T) {
453         var user = User{
454                 Name:     "jinzhu",
455                 IgnoreMe: 88,
456         }
457
458         DB.Save(&user)
459
460         DB.Model(&user).Updates(User{Name: "jinzhu2", IgnoreMe: 100})
461
462         if user.IgnoreMe != 100 {
463                 t.Errorf("should decode virtual attributes to struct, so it could be used in callbacks")
464         }
465 }