From 8f5ca303b5e783beb69c22959aa58131843b2f95 Mon Sep 17 00:00:00 2001 From: slene Date: Fri, 30 Aug 2013 12:32:05 +0800 Subject: [PATCH] orm fix when use uint as pk --- orm/db.go | 6 +- orm/db_utils.go | 6 +- orm/models_test.go | 3 +- orm/orm.go | 12 +++- orm/orm_object.go | 6 +- orm/orm_test.go | 153 +++++++++++++++++++++++++++------------------ 6 files changed, 118 insertions(+), 68 deletions(-) diff --git a/orm/db.go b/orm/db.go index 433061f9..7fe2b414 100644 --- a/orm/db.go +++ b/orm/db.go @@ -304,7 +304,11 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. if num > 0 { if mi.fields.pk.auto { - ind.Field(mi.fields.pk.fieldIndex).SetInt(0) + if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { + ind.Field(mi.fields.pk.fieldIndex).SetUint(0) + } else { + ind.Field(mi.fields.pk.fieldIndex).SetInt(0) + } } err := d.deleteRels(q, mi, []interface{}{pkValue}, tz) diff --git a/orm/db_utils.go b/orm/db_utils.go index 0773f457..4dcdaf18 100644 --- a/orm/db_utils.go +++ b/orm/db_utils.go @@ -10,7 +10,11 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac fi := mi.fields.pk v := ind.Field(fi.fieldIndex) - if fi.fieldType&IsIntegerField > 0 { + if fi.fieldType&IsPostiveIntegerField > 0 { + vu := v.Uint() + exist = vu > 0 + value = vu + } else if fi.fieldType&IsIntegerField > 0 { vu := v.Int() exist = vu > 0 value = vu diff --git a/orm/models_test.go b/orm/models_test.go index fe7c3e2d..32dc3c2e 100644 --- a/orm/models_test.go +++ b/orm/models_test.go @@ -60,7 +60,8 @@ type DataNull struct { // only for mysql type UserBig struct { - Id uint64 + Id uint64 + Name string } type User struct { diff --git a/orm/orm.go b/orm/orm.go index 6be35ae9..c4a52631 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -70,7 +70,11 @@ func (o *orm) Insert(md interface{}) (int64, error) { } if id > 0 { if mi.fields.pk.auto { - ind.Field(mi.fields.pk.fieldIndex).SetInt(id) + if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { + ind.Field(mi.fields.pk.fieldIndex).SetUint(uint64(id)) + } else { + ind.Field(mi.fields.pk.fieldIndex).SetInt(id) + } } } return id, nil @@ -93,7 +97,11 @@ func (o *orm) Delete(md interface{}) (int64, error) { } if num > 0 { if mi.fields.pk.auto { - ind.Field(mi.fields.pk.fieldIndex).SetInt(0) + if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { + ind.Field(mi.fields.pk.fieldIndex).SetUint(0) + } else { + ind.Field(mi.fields.pk.fieldIndex).SetInt(0) + } } } return num, nil diff --git a/orm/orm_object.go b/orm/orm_object.go index ee6566fc..c189e615 100644 --- a/orm/orm_object.go +++ b/orm/orm_object.go @@ -34,7 +34,11 @@ func (o *insertSet) Insert(md interface{}) (int64, error) { } if id > 0 { if o.mi.fields.pk.auto { - ind.Field(o.mi.fields.pk.fieldIndex).SetInt(id) + if o.mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { + ind.Field(o.mi.fields.pk.fieldIndex).SetUint(uint64(id)) + } else { + ind.Field(o.mi.fields.pk.fieldIndex).SetInt(id) + } } } return id, nil diff --git a/orm/orm_test.go b/orm/orm_test.go index bbca3831..bf3aacb2 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -211,6 +211,7 @@ func TestRegisterModels(t *testing.T) { RegisterModel(new(Post)) RegisterModel(new(Tag)) RegisterModel(new(Comment)) + RegisterModel(new(UserBig)) BootStrap() @@ -231,33 +232,34 @@ func TestModelSyntax(t *testing.T) { } } +var Data_Values = map[string]interface{}{ + "Boolean": true, + "Char": "char", + "Text": "text", + "Date": time.Now(), + "DateTime": time.Now(), + "Byte": byte(1<<8 - 1), + "Rune": rune(1<<31 - 1), + "Int": int(1<<31 - 1), + "Int8": int8(1<<7 - 1), + "Int16": int16(1<<15 - 1), + "Int32": int32(1<<31 - 1), + "Int64": int64(1<<63 - 1), + "Uint": uint(1<<32 - 1), + "Uint8": uint8(1<<8 - 1), + "Uint16": uint16(1<<16 - 1), + "Uint32": uint32(1<<32 - 1), + "Uint64": uint64(1<<63 - 1), // uint64 values with high bit set are not supported + "Float32": float32(100.1234), + "Float64": float64(100.1234), + "Decimal": float64(100.1234), +} + func TestDataTypes(t *testing.T) { - values := map[string]interface{}{ - "Boolean": true, - "Char": "char", - "Text": "text", - "Date": time.Now(), - "DateTime": time.Now(), - "Byte": byte(1<<8 - 1), - "Rune": rune(1<<31 - 1), - "Int": int(1<<31 - 1), - "Int8": int8(1<<7 - 1), - "Int16": int16(1<<15 - 1), - "Int32": int32(1<<31 - 1), - "Int64": int64(1<<63 - 1), - "Uint": uint(1<<32 - 1), - "Uint8": uint8(1<<8 - 1), - "Uint16": uint16(1<<16 - 1), - "Uint32": uint32(1<<32 - 1), - "Uint64": uint64(1<<63 - 1), // uint64 values with high bit set are not supported - "Float32": float32(100.1234), - "Float64": float64(100.1234), - "Decimal": float64(100.1234), - } d := Data{} ind := reflect.Indirect(reflect.ValueOf(&d)) - for name, value := range values { + for name, value := range Data_Values { e := ind.FieldByName(name) e.Set(reflect.ValueOf(value)) } @@ -272,7 +274,7 @@ func TestDataTypes(t *testing.T) { ind = reflect.Indirect(reflect.ValueOf(&d)) - for name, value := range values { + for name, value := range Data_Values { e := ind.FieldByName(name) vu := e.Interface() switch name { @@ -376,6 +378,17 @@ func TestCRUD(t *testing.T) { u = &User{Id: 100} err = dORM.Read(u) throwFail(t, AssertIs(err, T_Equal, ErrNoRows)) + + ub := UserBig{} + ub.Name = "name" + id, err = dORM.Insert(&ub) + throwFail(t, err) + throwFail(t, AssertIs(id, T_Equal, 1)) + + ub = UserBig{Id: 1} + err = dORM.Read(&ub) + throwFail(t, err) + throwFail(t, AssertIs(ub.Name, T_Equal, "name")) } func TestInsertTestData(t *testing.T) { @@ -823,7 +836,15 @@ func TestPrepareInsert(t *testing.T) { throwFail(t, AssertIs(err, T_Equal, ErrStmtClosed)) } -func TestRaw(t *testing.T) { +func TestRawQueryRow(t *testing.T) { + +} + +func TestRawQueryRows(t *testing.T) { + +} + +func TestRawValues(t *testing.T) { switch { case IsMysql || IsSqlite: @@ -860,42 +881,7 @@ func TestRaw(t *testing.T) { if num == 3 { throwFail(t, AssertIs(list[0], T_Equal, "2")) throwFail(t, AssertIs(list[1], T_Equal, "3")) - throwFail(t, AssertIs(list[2], T_Equal, "")) - } - - pre, err := dORM.Raw("INSERT INTO tag (name) VALUES (?)").Prepare() - throwFail(t, err) - if pre != nil { - r, err := pre.Exec("name1") - throwFail(t, err) - - tid, err := r.LastInsertId() - throwFail(t, err) - throwFail(t, AssertIs(tid, T_Large, 0)) - - r, err = pre.Exec("name2") - throwFail(t, err) - - id, err := r.LastInsertId() - throwFail(t, err) - throwFail(t, AssertIs(id, T_Equal, tid+1)) - - r, err = pre.Exec("name3") - throwFail(t, err) - - id, err = r.LastInsertId() - throwFail(t, err) - throwFail(t, AssertIs(id, T_Equal, tid+2)) - - err = pre.Close() - throwFail(t, err) - - res, err := dORM.Raw("DELETE FROM tag WHERE name IN (?, ?, ?)", []string{"name1", "name2", "name3"}).Exec() - throwFail(t, err) - - num, err := res.RowsAffected() - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 3)) + throwFail(t, AssertIs(list[2], T_Equal, nil)) } case IsPostgres: @@ -933,8 +919,51 @@ func TestRaw(t *testing.T) { if num == 3 { throwFail(t, AssertIs(list[0], T_Equal, "2")) throwFail(t, AssertIs(list[1], T_Equal, "3")) - throwFail(t, AssertIs(list[2], T_Equal, "")) + throwFail(t, AssertIs(list[2], T_Equal, nil)) } + } +} + +func TestRawPrepare(t *testing.T) { + switch { + case IsMysql || IsSqlite: + + pre, err := dORM.Raw("INSERT INTO tag (name) VALUES (?)").Prepare() + throwFail(t, err) + if pre != nil { + r, err := pre.Exec("name1") + throwFail(t, err) + + tid, err := r.LastInsertId() + throwFail(t, err) + throwFail(t, AssertIs(tid, T_Large, 0)) + + r, err = pre.Exec("name2") + throwFail(t, err) + + id, err := r.LastInsertId() + throwFail(t, err) + throwFail(t, AssertIs(id, T_Equal, tid+1)) + + r, err = pre.Exec("name3") + throwFail(t, err) + + id, err = r.LastInsertId() + throwFail(t, err) + throwFail(t, AssertIs(id, T_Equal, tid+2)) + + err = pre.Close() + throwFail(t, err) + + res, err := dORM.Raw("DELETE FROM tag WHERE name IN (?, ?, ?)", []string{"name1", "name2", "name3"}).Exec() + throwFail(t, err) + + num, err := res.RowsAffected() + throwFail(t, err) + throwFail(t, AssertIs(num, T_Equal, 3)) + } + + case IsPostgres: pre, err := dORM.Raw(`INSERT INTO "tag" ("name") VALUES (?) RETURNING "id"`).Prepare() throwFail(t, err)