orm add atomic set value
Showing
4 changed files
with
86 additions
and
5 deletions
| ... | @@ -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) { | ... | ... |
-
Please register or sign in to post a comment