bf3830b6 by slene

orm add atomic set value

1 parent 278f8eb1
...@@ -382,17 +382,38 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -382,17 +382,38 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
382 382
383 join := tables.getJoinSql() 383 join := tables.getJoinSql()
384 384
385 var query string 385 var query, T, cols string
386 386
387 Q := d.ins.TableQuote() 387 Q := d.ins.TableQuote()
388 388
389 if d.ins.SupportUpdateJoin() { 389 if d.ins.SupportUpdateJoin() {
390 cols := strings.Join(columns, fmt.Sprintf("%s = ?, T0.%s", Q, Q)) 390 T = "T0."
391 query = fmt.Sprintf("UPDATE %s%s%s T0 %sSET T0.%s%s%s = ? %s", Q, mi.table, Q, join, Q, cols, Q, where) 391 }
392
393 for i, v := range columns {
394 col := fmt.Sprintf("%s%s%s%s", T, Q, v, Q)
395 if c, ok := values[i].(colValue); ok {
396 switch c.opt {
397 case Col_Add:
398 cols += col + " = " + col + " + ? "
399 case Col_Minus:
400 cols += col + " = " + col + " - ? "
401 case Col_Multiply:
402 cols += col + " = " + col + " * ? "
403 case Col_Except:
404 cols += col + " = " + col + " / ? "
405 }
406 values[i] = c.value
407 } else {
408 cols += col + " = ? "
409 }
410 }
411
412 if d.ins.SupportUpdateJoin() {
413 query = fmt.Sprintf("UPDATE %s%s%s T0 %sSET %s%s", Q, mi.table, Q, join, cols, where)
392 } else { 414 } else {
393 cols := strings.Join(columns, fmt.Sprintf("%s = ?, %s", Q, Q))
394 supQuery := fmt.Sprintf("SELECT T0.%s%s%s FROM %s%s%s T0 %s%s", Q, mi.fields.pk.column, Q, Q, mi.table, Q, join, where) 415 supQuery := fmt.Sprintf("SELECT T0.%s%s%s FROM %s%s%s T0 %s%s", Q, mi.fields.pk.column, Q, Q, mi.table, Q, join, where)
395 query = fmt.Sprintf("UPDATE %s%s%s SET %s%s%s = ? WHERE %s%s%s IN ( %s )", Q, mi.table, Q, Q, cols, Q, Q, mi.fields.pk.column, Q, supQuery) 416 query = fmt.Sprintf("UPDATE %s%s%s SET %sWHERE %s%s%s IN ( %s )", Q, mi.table, Q, cols, Q, mi.fields.pk.column, Q, supQuery)
396 } 417 }
397 418
398 d.ins.ReplaceMarks(&query) 419 d.ins.ReplaceMarks(&query)
......
...@@ -77,6 +77,7 @@ type User struct { ...@@ -77,6 +77,7 @@ type User struct {
77 Profile *Profile `orm:"null;rel(one);on_delete(set_null)"` 77 Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
78 Posts []*Post `orm:"reverse(many)" json:"-"` 78 Posts []*Post `orm:"reverse(many)" json:"-"`
79 ShouldSkip string `orm:"-"` 79 ShouldSkip string `orm:"-"`
80 Nums int
80 } 81 }
81 82
82 func (u *User) TableIndex() [][]string { 83 func (u *User) TableIndex() [][]string {
......
...@@ -4,6 +4,36 @@ import ( ...@@ -4,6 +4,36 @@ import (
4 "fmt" 4 "fmt"
5 ) 5 )
6 6
7 type colValue struct {
8 value int64
9 opt operator
10 }
11
12 type operator int
13
14 const (
15 Col_Add operator = iota
16 Col_Minus
17 Col_Multiply
18 Col_Except
19 )
20
21 func ColValue(opt operator, value interface{}) interface{} {
22 switch opt {
23 case Col_Add, Col_Minus, Col_Multiply, Col_Except:
24 default:
25 panic(fmt.Errorf("orm.ColValue wrong operator"))
26 }
27 v, err := StrTo(ToStr(value)).Int64()
28 if err != nil {
29 panic(fmt.Errorf("orm.ColValue doesn't support non string/numeric type, %s", err))
30 }
31 var val colValue
32 val.value = v
33 val.opt = opt
34 return val
35 }
36
7 type querySet struct { 37 type querySet struct {
8 mi *modelInfo 38 mi *modelInfo
9 cond *Condition 39 cond *Condition
......
...@@ -1230,6 +1230,35 @@ func TestUpdate(t *testing.T) { ...@@ -1230,6 +1230,35 @@ func TestUpdate(t *testing.T) {
1230 }) 1230 })
1231 throwFail(t, err) 1231 throwFail(t, err)
1232 throwFail(t, AssertIs(num, 1)) 1232 throwFail(t, AssertIs(num, 1))
1233
1234 num, err = qs.Filter("user_name", "slene").Update(Params{
1235 "Nums": ColValue(Col_Add, 100),
1236 })
1237 throwFail(t, err)
1238 throwFail(t, AssertIs(num, 1))
1239
1240 num, err = qs.Filter("user_name", "slene").Update(Params{
1241 "Nums": ColValue(Col_Minus, 50),
1242 })
1243 throwFail(t, err)
1244 throwFail(t, AssertIs(num, 1))
1245
1246 num, err = qs.Filter("user_name", "slene").Update(Params{
1247 "Nums": ColValue(Col_Multiply, 3),
1248 })
1249 throwFail(t, err)
1250 throwFail(t, AssertIs(num, 1))
1251
1252 num, err = qs.Filter("user_name", "slene").Update(Params{
1253 "Nums": ColValue(Col_Except, 5),
1254 })
1255 throwFail(t, err)
1256 throwFail(t, AssertIs(num, 1))
1257
1258 user := User{UserName: "slene"}
1259 err = dORM.Read(&user, "UserName")
1260 throwFail(t, err)
1261 throwFail(t, AssertIs(user.Nums, 30))
1233 } 1262 }
1234 1263
1235 func TestDelete(t *testing.T) { 1264 func TestDelete(t *testing.T) {
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!