From 41dd6e580da4376dbda81423068e1c8977bbb3e0 Mon Sep 17 00:00:00 2001 From: slene Date: Mon, 9 Sep 2013 22:33:41 +0800 Subject: [PATCH] orm 1. complete QueryRow/QueryRows api 2. QuerySeter.All support *[]Type and *[]*Type --- orm/db.go | 22 ++- orm/models.go | 11 +- orm/models_test.go | 15 +- orm/models_utils.go | 2 +- orm/orm_raw.go | 360 +++++++++++++++++++++++++++++++++++++++- orm/orm_test.go | 389 +++++++++++++++++++++++++++++++++++--------- orm/utils.go | 2 + 7 files changed, 702 insertions(+), 99 deletions(-) diff --git a/orm/db.go b/orm/db.go index 75328356..4fa2b467 100644 --- a/orm/db.go +++ b/orm/db.go @@ -479,15 +479,19 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ind := reflect.Indirect(val) errTyp := true - one := true + isPtr := true if val.Kind() == reflect.Ptr { fn := "" if ind.Kind() == reflect.Slice { one = false - if ind.Type().Elem().Kind() == reflect.Ptr { - typ := ind.Type().Elem().Elem() + typ := ind.Type().Elem() + switch typ.Kind() { + case reflect.Ptr: + fn = getFullName(typ.Elem()) + case reflect.Struct: + isPtr = false fn = getFullName(typ) } } else { @@ -601,13 +605,21 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi if one { ind.Set(mind) } else { - slice = reflect.Append(slice, mind.Addr()) + if cnt == 0 { + slice = reflect.New(ind.Type()).Elem() + } + + if isPtr { + slice = reflect.Append(slice, mind.Addr()) + } else { + slice = reflect.Append(slice, mind) + } } } cnt++ } - if one == false { + if one == false && cnt > 0 { ind.Set(slice) } diff --git a/orm/models.go b/orm/models.go index 277e5d0f..1cb25c4c 100644 --- a/orm/models.go +++ b/orm/models.go @@ -5,11 +5,12 @@ import ( ) const ( - od_CASCADE = "cascade" - od_SET_NULL = "set_null" - od_SET_DEFAULT = "set_default" - od_DO_NOTHING = "do_nothing" - defaultStructTagName = "orm" + od_CASCADE = "cascade" + od_SET_NULL = "set_null" + od_SET_DEFAULT = "set_default" + od_DO_NOTHING = "do_nothing" + defaultStructTagName = "orm" + defaultStructTagDelim = ";" ) var ( diff --git a/orm/models_test.go b/orm/models_test.go index 32dc3c2e..113dd14d 100644 --- a/orm/models_test.go +++ b/orm/models_test.go @@ -16,7 +16,7 @@ type Data struct { Char string `orm:"size(50)"` Text string `orm:"type(text)"` Date time.Time `orm:"type(date)"` - DateTime time.Time + DateTime time.Time `orm:"column(datetime)"` Byte byte Rune rune Int int @@ -37,10 +37,10 @@ type Data struct { type DataNull struct { Id int Boolean bool `orm:"null"` - Char string `orm:"size(50);null"` - Text string `orm:"type(text);null"` - Date time.Time `orm:"type(date);null"` - DateTime time.Time `orm:"null"` + Char string `orm:"null;size(50)"` + Text string `orm:"null;type(text)"` + Date time.Time `orm:"null;type(date)"` + DateTime time.Time `orm:"null;column(datetime)""` Byte byte `orm:"null"` Rune rune `orm:"null"` Int int `orm:"null"` @@ -174,7 +174,10 @@ var ( IsPostgres = DBARGS.Driver == "postgres" ) -var dORM Ormer +var ( + dORM Ormer + dDbBaser dbBaser +) func init() { Debug, _ = StrTo(DBARGS.Debug).Bool() diff --git a/orm/models_utils.go b/orm/models_utils.go index 7f50c7d0..2dcbd646 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -114,7 +114,7 @@ func getFieldType(val reflect.Value) (ft int, err error) { func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) { attr := make(map[string]bool) tag := make(map[string]string) - for _, v := range strings.Split(data, ";") { + for _, v := range strings.Split(data, defaultStructTagDelim) { v = strings.TrimSpace(v) if supportTag[v] == 1 { attr[v] = true diff --git a/orm/orm_raw.go b/orm/orm_raw.go index f2c4f9f2..c7dae5b4 100644 --- a/orm/orm_raw.go +++ b/orm/orm_raw.go @@ -4,6 +4,8 @@ import ( "database/sql" "fmt" "reflect" + "strings" + "time" ) type rawPrepare struct { @@ -64,14 +66,362 @@ func (o *rawSet) Exec() (sql.Result, error) { return o.orm.db.Exec(query, args...) } -func (o *rawSet) QueryRow(...interface{}) error { - //TODO +func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { + switch ind.Kind() { + case reflect.Bool: + if value == nil { + ind.SetBool(false) + } else if v, ok := value.(bool); ok { + ind.SetBool(v) + } else { + v, _ := StrTo(ToStr(value)).Bool() + ind.SetBool(v) + } + + case reflect.String: + if value == nil { + ind.SetString("") + } else { + ind.SetString(ToStr(value)) + } + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if value == nil { + ind.SetInt(0) + } else { + val := reflect.ValueOf(value) + switch val.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + ind.SetInt(val.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + ind.SetInt(int64(val.Uint())) + default: + v, _ := StrTo(ToStr(value)).Int64() + ind.SetInt(v) + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if value == nil { + ind.SetUint(0) + } else { + val := reflect.ValueOf(value) + switch val.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + ind.SetUint(uint64(val.Int())) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + ind.SetUint(val.Uint()) + default: + v, _ := StrTo(ToStr(value)).Uint64() + ind.SetUint(v) + } + } + case reflect.Float64, reflect.Float32: + if value == nil { + ind.SetFloat(0) + } else { + val := reflect.ValueOf(value) + switch val.Kind() { + case reflect.Float64: + ind.SetFloat(val.Float()) + default: + v, _ := StrTo(ToStr(value)).Float64() + ind.SetFloat(v) + } + } + + case reflect.Struct: + if value == nil { + ind.Set(reflect.Zero(ind.Type())) + + } else if _, ok := ind.Interface().(time.Time); ok { + var str string + switch d := value.(type) { + case time.Time: + o.orm.alias.DbBaser.TimeFromDB(&d, o.orm.alias.TZ) + ind.Set(reflect.ValueOf(d)) + case []byte: + str = string(d) + case string: + str = d + } + if str != "" { + if len(str) >= 19 { + str = str[:19] + t, err := time.ParseInLocation(format_DateTime, str, o.orm.alias.TZ) + if err == nil { + t = t.In(DefaultTimeLoc) + ind.Set(reflect.ValueOf(t)) + } + } else if len(str) >= 10 { + str = str[:10] + t, err := time.ParseInLocation(format_Date, str, DefaultTimeLoc) + if err == nil { + ind.Set(reflect.ValueOf(t)) + } + } + } + } + } +} + +func (o *rawSet) loopInitRefs(typ reflect.Type, refsPtr *[]interface{}, sIdxesPtr *[][]int) { + sIdxes := *sIdxesPtr + refs := *refsPtr + + if typ.Kind() == reflect.Struct { + if typ.String() == "time.Time" { + var ref interface{} + refs = append(refs, &ref) + sIdxes = append(sIdxes, []int{0}) + } else { + idxs := []int{} + outFor: + for idx := 0; idx < typ.NumField(); idx++ { + ctyp := typ.Field(idx) + + tag := ctyp.Tag.Get(defaultStructTagName) + for _, v := range strings.Split(tag, defaultStructTagDelim) { + if v == "-" { + continue outFor + } + } + + tp := ctyp.Type + if tp.Kind() == reflect.Ptr { + tp = tp.Elem() + } + + if tp.String() == "time.Time" { + var ref interface{} + refs = append(refs, &ref) + + } else if tp.Kind() != reflect.Struct { + var ref interface{} + refs = append(refs, &ref) + + } else { + // skip other type + continue + } + + idxs = append(idxs, idx) + } + sIdxes = append(sIdxes, idxs) + } + } else { + var ref interface{} + refs = append(refs, &ref) + sIdxes = append(sIdxes, []int{0}) + } + + *sIdxesPtr = sIdxes + *refsPtr = refs +} + +func (o *rawSet) loopSetRefs(refs []interface{}, sIdxes [][]int, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) { + nInds := *nIndsPtr + + cur := 0 + for i, idxs := range sIdxes { + sInd := sInds[i] + eTyp := eTyps[i] + + typ := eTyp + isPtr := false + if typ.Kind() == reflect.Ptr { + isPtr = true + typ = typ.Elem() + } + if typ.Kind() == reflect.Ptr { + isPtr = true + typ = typ.Elem() + } + + var nInd reflect.Value + if init { + nInd = reflect.New(sInd.Type()).Elem() + } else { + nInd = nInds[i] + } + + val := reflect.New(typ) + ind := val.Elem() + + tpName := ind.Type().String() + + if ind.Kind() == reflect.Struct { + if tpName == "time.Time" { + value := reflect.ValueOf(refs[cur]).Elem().Interface() + if isPtr && value == nil { + val = reflect.New(val.Type()).Elem() + } else { + o.setFieldValue(ind, value) + } + cur++ + } else { + hasValue := false + for _, idx := range idxs { + tind := ind.Field(idx) + value := reflect.ValueOf(refs[cur]).Elem().Interface() + if value != nil { + hasValue = true + } + if tind.Kind() == reflect.Ptr { + if value == nil { + tindV := reflect.New(tind.Type()).Elem() + tind.Set(tindV) + } else { + tindV := reflect.New(tind.Type().Elem()) + o.setFieldValue(tindV.Elem(), value) + tind.Set(tindV) + } + } else { + o.setFieldValue(tind, value) + } + cur++ + } + if hasValue == false && isPtr { + val = reflect.New(val.Type()).Elem() + } + } + } else { + value := reflect.ValueOf(refs[cur]).Elem().Interface() + if isPtr && value == nil { + val = reflect.New(val.Type()).Elem() + } else { + o.setFieldValue(ind, value) + } + cur++ + } + + if nInd.Kind() == reflect.Slice { + if isPtr { + nInd = reflect.Append(nInd, val) + } else { + nInd = reflect.Append(nInd, ind) + } + } else { + if isPtr { + nInd.Set(val) + } else { + nInd.Set(ind) + } + } + + nInds[i] = nInd + } +} + +func (o *rawSet) QueryRow(containers ...interface{}) error { + if len(containers) == 0 { + panic(" need at least one arg") + } + + refs := make([]interface{}, 0, len(containers)) + sIdxes := make([][]int, 0) + sInds := make([]reflect.Value, 0) + eTyps := make([]reflect.Type, 0) + + for _, container := range containers { + val := reflect.ValueOf(container) + ind := reflect.Indirect(val) + + if val.Kind() != reflect.Ptr { + panic(" all args must be use ptr") + } + + etyp := ind.Type() + typ := etyp + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + + sInds = append(sInds, ind) + eTyps = append(eTyps, etyp) + + o.loopInitRefs(typ, &refs, &sIdxes) + } + + query := o.query + o.orm.alias.DbBaser.ReplaceMarks(&query) + + args := getFlatParams(nil, o.args, o.orm.alias.TZ) + row := o.orm.db.QueryRow(query, args...) + + if err := row.Scan(refs...); err == sql.ErrNoRows { + return ErrNoRows + } else if err != nil { + return err + } + + nInds := make([]reflect.Value, len(sInds)) + o.loopSetRefs(refs, sIdxes, sInds, &nInds, eTyps, true) + for i, sInd := range sInds { + nInd := nInds[i] + sInd.Set(nInd) + } + return nil } -func (o *rawSet) QueryRows(...interface{}) (int64, error) { - //TODO - return 0, nil +func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { + refs := make([]interface{}, 0) + sIdxes := make([][]int, 0) + sInds := make([]reflect.Value, 0) + eTyps := make([]reflect.Type, 0) + + for _, container := range containers { + val := reflect.ValueOf(container) + sInd := reflect.Indirect(val) + if val.Kind() != reflect.Ptr || sInd.Kind() != reflect.Slice { + panic(" all args must be use ptr slice") + } + + etyp := sInd.Type().Elem() + typ := etyp + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + + sInds = append(sInds, sInd) + eTyps = append(eTyps, etyp) + + o.loopInitRefs(typ, &refs, &sIdxes) + } + + query := o.query + o.orm.alias.DbBaser.ReplaceMarks(&query) + + args := getFlatParams(nil, o.args, o.orm.alias.TZ) + rows, err := o.orm.db.Query(query, args...) + if err != nil { + return 0, err + } + + nInds := make([]reflect.Value, len(sInds)) + + var cnt int64 + for rows.Next() { + if err := rows.Scan(refs...); err != nil { + return 0, err + } + + o.loopSetRefs(refs, sIdxes, sInds, &nInds, eTyps, cnt == 0) + + cnt++ + } + + if cnt > 0 { + for i, sInd := range sInds { + nInd := nInds[i] + sInd.Set(nInd) + } + } + + return cnt, nil } func (o *rawSet) readValues(container interface{}) (int64, error) { diff --git a/orm/orm_test.go b/orm/orm_test.go index bf3aacb2..92952fbf 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -216,6 +216,7 @@ func TestRegisterModels(t *testing.T) { BootStrap() dORM = NewOrm() + dDbBaser = getDbAlias("default").DbBaser } func TestModelSyntax(t *testing.T) { @@ -629,9 +630,23 @@ func TestOperators(t *testing.T) { func TestAll(t *testing.T) { var users []*User qs := dORM.QueryTable("user") - num, err := qs.All(&users) + num, err := qs.OrderBy("Id").All(&users) throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 3)) + throwFailNow(t, AssertIs(num, T_Equal, 3)) + + throwFail(t, AssertIs(users[0].UserName, T_Equal, "slene")) + throwFail(t, AssertIs(users[1].UserName, T_Equal, "astaxie")) + throwFail(t, AssertIs(users[2].UserName, T_Equal, "nobody")) + + var users2 []User + qs = dORM.QueryTable("user") + num, err = qs.OrderBy("Id").All(&users2) + throwFail(t, err) + throwFailNow(t, AssertIs(num, T_Equal, 3)) + + throwFailNow(t, AssertIs(users2[0].UserName, T_Equal, "slene")) + throwFailNow(t, AssertIs(users2[1].UserName, T_Equal, "astaxie")) + throwFailNow(t, AssertIs(users2[2].UserName, T_Equal, "nobody")) qs = dORM.QueryTable("user") num, err = qs.Filter("user_name", "nothing").All(&users) @@ -645,8 +660,14 @@ func TestOne(t *testing.T) { err := qs.One(&user) throwFail(t, AssertIs(err, T_Equal, ErrMultiRows)) + user = User{} + err = qs.OrderBy("Id").Limit(1).One(&user) + throwFailNow(t, err) + throwFail(t, AssertIs(user.UserName, T_Equal, "slene")) + err = qs.Filter("user_name", "nothing").One(&user) throwFail(t, AssertIs(err, T_Equal, ErrNoRows)) + } func TestValues(t *testing.T) { @@ -836,91 +857,305 @@ func TestPrepareInsert(t *testing.T) { throwFail(t, AssertIs(err, T_Equal, ErrStmtClosed)) } -func TestRawQueryRow(t *testing.T) { +func TestRawExec(t *testing.T) { + Q := dDbBaser.TableQuote() + query := fmt.Sprintf("UPDATE %suser%s SET %suser_name%s = ? WHERE %suser_name%s = ?", Q, Q, Q, Q, Q, Q) + res, err := dORM.Raw(query, "testing", "slene").Exec() + throwFail(t, err) + num, err := res.RowsAffected() + throwFail(t, AssertIs(num, T_Equal, 1), err) + + res, err = dORM.Raw(query, "slene", "testing").Exec() + throwFail(t, err) + num, err = res.RowsAffected() + throwFail(t, AssertIs(num, T_Equal, 1), err) } -func TestRawQueryRows(t *testing.T) { +func TestRawQueryRow(t *testing.T) { + var ( + Boolean bool + Char string + Text string + Date time.Time + DateTime time.Time + Byte byte + Rune rune + Int int + Int8 int + Int16 int16 + Int32 int32 + Int64 int64 + Uint uint + Uint8 uint8 + Uint16 uint16 + Uint32 uint32 + Uint64 uint64 + Float32 float32 + Float64 float64 + Decimal float64 + ) + data_values := make(map[string]interface{}, len(Data_Values)) + + for k, v := range Data_Values { + data_values[strings.ToLower(k)] = v + } + + Q := dDbBaser.TableQuote() + + cols := []string{ + "id", "boolean", "char", "text", "date", "datetime", "byte", "rune", "int", "int8", "int16", "int32", + "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "decimal", + } + sep := fmt.Sprintf("%s, %s", Q, Q) + query := fmt.Sprintf("SELECT %s%s%s FROM data WHERE id = ?", Q, strings.Join(cols, sep), Q) + var id int + values := []interface{}{ + &id, &Boolean, &Char, &Text, &Date, &DateTime, &Byte, &Rune, &Int, &Int8, &Int16, &Int32, + &Int64, &Uint, &Uint8, &Uint16, &Uint32, &Uint64, &Float32, &Float64, &Decimal, + } + err := dORM.Raw(query, 1).QueryRow(values...) + throwFailNow(t, err) + for i, col := range cols { + vu := values[i] + v := reflect.ValueOf(vu).Elem().Interface() + switch col { + case "id": + throwFail(t, AssertIs(id, T_Equal, 1)) + case "date": + v = v.(time.Time).In(DefaultTimeLoc) + value := data_values[col].(time.Time).In(DefaultTimeLoc) + throwFail(t, AssertIs(v, T_Equal, value, test_Date)) + case "datetime": + v = v.(time.Time).In(DefaultTimeLoc) + value := data_values[col].(time.Time).In(DefaultTimeLoc) + throwFail(t, AssertIs(v, T_Equal, value, test_DateTime)) + default: + throwFail(t, AssertIs(v, T_Equal, data_values[col])) + } + } + + type Tmp struct { + Skip0 string + Id int + Char *string + Skip1 int `orm:"-"` + Date time.Time + DateTime time.Time + } + + Boolean = false + Text = "" + Int64 = 0 + Uint = 0 + + tmp := new(Tmp) + + cols = []string{ + "int", "char", "date", "datetime", "boolean", "text", "int64", "uint", + } + query = fmt.Sprintf("SELECT NULL, %s%s%s FROM data WHERE id = ?", Q, strings.Join(cols, sep), Q) + values = []interface{}{ + tmp, &Boolean, &Text, &Int64, &Uint, + } + err = dORM.Raw(query, 1).QueryRow(values...) + throwFailNow(t, err) + + for _, col := range cols { + switch col { + case "id": + throwFail(t, AssertIs(tmp.Id, T_Equal, data_values[col])) + case "char": + c := tmp.Char + throwFail(t, AssertIs(*c, T_Equal, data_values[col])) + case "date": + v := tmp.Date.In(DefaultTimeLoc) + value := data_values[col].(time.Time).In(DefaultTimeLoc) + throwFail(t, AssertIs(v, T_Equal, value, test_Date)) + case "datetime": + v := tmp.DateTime.In(DefaultTimeLoc) + value := data_values[col].(time.Time).In(DefaultTimeLoc) + throwFail(t, AssertIs(v, T_Equal, value, test_DateTime)) + case "boolean": + throwFail(t, AssertIs(Boolean, T_Equal, data_values[col])) + case "text": + throwFail(t, AssertIs(Text, T_Equal, data_values[col])) + case "int64": + throwFail(t, AssertIs(Int64, T_Equal, data_values[col])) + case "uint": + throwFail(t, AssertIs(Uint, T_Equal, data_values[col])) + } + } + + var ( + uid int + status *int + pid *int + ) + + cols = []string{ + "id", "status", "profile_id", + } + query = fmt.Sprintf("SELECT %s%s%s FROM %suser%s WHERE id = ?", Q, strings.Join(cols, sep), Q, Q, Q) + err = dORM.Raw(query, 4).QueryRow(&uid, &status, &pid) + throwFail(t, err) + throwFail(t, AssertIs(uid, T_Equal, 4)) + throwFail(t, AssertIs(*status, T_Equal, 3)) + throwFail(t, AssertIs(pid, T_Equal, nil)) +} + +func TestQueryRows(t *testing.T) { + Q := dDbBaser.TableQuote() + + cols := []string{ + "id", "boolean", "char", "text", "date", "datetime", "byte", "rune", "int", "int8", "int16", "int32", + "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "decimal", + } + + var datas []*Data + var dids []int + + sep := fmt.Sprintf("%s, %s", Q, Q) + query := fmt.Sprintf("SELECT %s%s%s, id FROM %sdata%s", Q, strings.Join(cols, sep), Q, Q, Q) + num, err := dORM.Raw(query).QueryRows(&datas, &dids) + throwFailNow(t, err) + throwFailNow(t, AssertIs(num, T_Equal, 1)) + throwFailNow(t, AssertIs(len(datas), T_Equal, 1)) + throwFailNow(t, AssertIs(len(dids), T_Equal, 1)) + throwFailNow(t, AssertIs(dids[0], T_Equal, 1)) + + ind := reflect.Indirect(reflect.ValueOf(datas[0])) + + for name, value := range Data_Values { + e := ind.FieldByName(name) + vu := e.Interface() + switch name { + case "Date": + vu = vu.(time.Time).In(DefaultTimeLoc).Format(test_Date) + value = value.(time.Time).In(DefaultTimeLoc).Format(test_Date) + case "DateTime": + vu = vu.(time.Time).In(DefaultTimeLoc).Format(test_DateTime) + value = value.(time.Time).In(DefaultTimeLoc).Format(test_DateTime) + } + throwFail(t, AssertIs(vu == value, T_Equal, true), value, vu) + } + + type Tmp struct { + Id int + Name string + Skiped0 string `orm:"-"` + Pid *int + Skiped1 Data + Skiped2 *Data + } + + var ( + ids []int + userNames []string + profileIds1 []int + profileIds2 []*int + createds []time.Time + updateds []time.Time + tmps1 []*Tmp + tmps2 []Tmp + ) + cols = []string{ + "id", "user_name", "profile_id", "profile_id", "id", "user_name", "profile_id", "id", "user_name", "profile_id", "created", "updated", + } + query = fmt.Sprintf("SELECT %s%s%s FROM %suser%s ORDER BY id", Q, strings.Join(cols, sep), Q, Q, Q) + num, err = dORM.Raw(query).QueryRows(&ids, &userNames, &profileIds1, &profileIds2, &tmps1, &tmps2, &createds, &updateds) + throwFailNow(t, err) + throwFailNow(t, AssertIs(num, T_Equal, 3)) + + var users []User + dORM.QueryTable("user").OrderBy("Id").All(&users) + + for i := 0; i < 3; i++ { + id := ids[i] + name := userNames[i] + pid1 := profileIds1[i] + pid2 := profileIds2[i] + created := createds[i] + updated := updateds[i] + + user := users[i] + throwFailNow(t, AssertIs(id, T_Equal, user.Id)) + throwFailNow(t, AssertIs(name, T_Equal, user.UserName)) + if user.Profile != nil { + throwFailNow(t, AssertIs(pid1, T_Equal, user.Profile.Id)) + throwFailNow(t, AssertIs(*pid2, T_Equal, user.Profile.Id)) + } else { + throwFailNow(t, AssertIs(pid1, T_Equal, 0)) + throwFailNow(t, AssertIs(pid2, T_Equal, nil)) + } + throwFailNow(t, AssertIs(created, T_Equal, user.Created, test_Date)) + throwFailNow(t, AssertIs(updated, T_Equal, user.Updated, test_DateTime)) + + tmp := tmps1[i] + tmp1 := *tmp + throwFailNow(t, AssertIs(tmp1.Id, T_Equal, user.Id)) + throwFailNow(t, AssertIs(tmp1.Name, T_Equal, user.UserName)) + if user.Profile != nil { + pid := tmp1.Pid + throwFailNow(t, AssertIs(*pid, T_Equal, user.Profile.Id)) + } else { + throwFailNow(t, AssertIs(tmp1.Pid, T_Equal, nil)) + } + + tmp2 := tmps2[i] + throwFailNow(t, AssertIs(tmp2.Id, T_Equal, user.Id)) + throwFailNow(t, AssertIs(tmp2.Name, T_Equal, user.UserName)) + if user.Profile != nil { + pid := tmp2.Pid + throwFailNow(t, AssertIs(*pid, T_Equal, user.Profile.Id)) + } else { + throwFailNow(t, AssertIs(tmp2.Pid, T_Equal, nil)) + } + } + + type Sec struct { + Id int + Name string + } + + var tmp []*Sec + query = fmt.Sprintf("SELECT NULL, NULL FROM %suser%s LIMIT 1", Q, Q) + num, err = dORM.Raw(query).QueryRows(&tmp) + throwFail(t, err) + throwFail(t, AssertIs(num, T_Equal, 1)) + throwFail(t, AssertIs(tmp[0], T_Equal, nil)) } func TestRawValues(t *testing.T) { - switch { - case IsMysql || IsSqlite: + Q := dDbBaser.TableQuote() - res, err := dORM.Raw("UPDATE user SET user_name = ? WHERE user_name = ?", "testing", "slene").Exec() - throwFail(t, err) - num, err := res.RowsAffected() - throwFail(t, AssertIs(num, T_Equal, 1), err) + var maps []Params + query := fmt.Sprintf("SELECT %suser_name%s FROM %suser%s WHERE %sstatus%s = ?", Q, Q, Q, Q, Q, Q) + num, err := dORM.Raw(query, 1).Values(&maps) + throwFail(t, err) + throwFail(t, AssertIs(num, T_Equal, 1)) + if num == 1 { + throwFail(t, AssertIs(maps[0]["user_name"], T_Equal, "slene")) + } - res, err = dORM.Raw("UPDATE user SET user_name = ? WHERE user_name = ?", "slene", "testing").Exec() - throwFail(t, err) - num, err = res.RowsAffected() - throwFail(t, AssertIs(num, T_Equal, 1), err) + var lists []ParamsList + num, err = dORM.Raw(query, 1).ValuesList(&lists) + throwFail(t, err) + throwFail(t, AssertIs(num, T_Equal, 1)) + if num == 1 { + throwFail(t, AssertIs(lists[0][0], T_Equal, "slene")) + } - var maps []Params - num, err = dORM.Raw("SELECT user_name FROM user WHERE status = ?", 1).Values(&maps) - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 1)) - if num == 1 { - throwFail(t, AssertIs(maps[0]["user_name"], T_Equal, "slene")) - } - - var lists []ParamsList - num, err = dORM.Raw("SELECT user_name FROM user WHERE status = ?", 1).ValuesList(&lists) - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 1)) - if num == 1 { - throwFail(t, AssertIs(lists[0][0], T_Equal, "slene")) - } - - var list ParamsList - num, err = dORM.Raw("SELECT profile_id FROM user ORDER BY id ASC").ValuesFlat(&list) - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 3)) - 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, nil)) - } - - case IsPostgres: - - res, err := dORM.Raw(`UPDATE "user" SET "user_name" = ? WHERE "user_name" = ?`, "testing", "slene").Exec() - throwFail(t, err) - num, err := res.RowsAffected() - throwFail(t, AssertIs(num, T_Equal, 1), err) - - res, err = dORM.Raw(`UPDATE "user" SET "user_name" = ? WHERE "user_name" = ?`, "slene", "testing").Exec() - throwFail(t, err) - num, err = res.RowsAffected() - throwFail(t, AssertIs(num, T_Equal, 1), err) - - var maps []Params - num, err = dORM.Raw(`SELECT "user_name" FROM "user" WHERE "status" = ?`, 1).Values(&maps) - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 1)) - if num == 1 { - throwFail(t, AssertIs(maps[0]["user_name"], T_Equal, "slene")) - } - - var lists []ParamsList - num, err = dORM.Raw(`SELECT "user_name" FROM "user" WHERE "status" = ?`, 1).ValuesList(&lists) - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 1)) - if num == 1 { - throwFail(t, AssertIs(lists[0][0], T_Equal, "slene")) - } - - var list ParamsList - num, err = dORM.Raw(`SELECT "profile_id" FROM "user" ORDER BY id ASC`).ValuesFlat(&list) - throwFail(t, err) - throwFail(t, AssertIs(num, T_Equal, 3)) - 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, nil)) - } + query = fmt.Sprintf("SELECT %sprofile_id%s FROM %suser%s ORDER BY %sid%s ASC", Q, Q, Q, Q, Q, Q) + var list ParamsList + num, err = dORM.Raw(query).ValuesFlat(&list) + throwFail(t, err) + throwFail(t, AssertIs(num, T_Equal, 3)) + 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, nil)) } } diff --git a/orm/utils.go b/orm/utils.go index b3e827e5..8bc093d1 100644 --- a/orm/utils.go +++ b/orm/utils.go @@ -115,6 +115,8 @@ func ToStr(value interface{}, args ...int) (s string) { s = strconv.FormatUint(v, argInt(args).Get(0, 10)) case string: s = v + case []byte: + s = string(v) default: s = fmt.Sprintf("%v", v) }