1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-25 21:11:29 +00:00

orm 1. complete QueryRow/QueryRows api 2. QuerySeter.All support *[]Type and *[]*Type

This commit is contained in:
slene 2013-09-09 22:33:41 +08:00
parent 22d2de9fc7
commit 41dd6e580d
7 changed files with 702 additions and 99 deletions

View File

@ -479,15 +479,19 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
ind := reflect.Indirect(val) ind := reflect.Indirect(val)
errTyp := true errTyp := true
one := true one := true
isPtr := true
if val.Kind() == reflect.Ptr { if val.Kind() == reflect.Ptr {
fn := "" fn := ""
if ind.Kind() == reflect.Slice { if ind.Kind() == reflect.Slice {
one = false one = false
if ind.Type().Elem().Kind() == reflect.Ptr { typ := ind.Type().Elem()
typ := ind.Type().Elem().Elem() switch typ.Kind() {
case reflect.Ptr:
fn = getFullName(typ.Elem())
case reflect.Struct:
isPtr = false
fn = getFullName(typ) fn = getFullName(typ)
} }
} else { } else {
@ -601,13 +605,21 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
if one { if one {
ind.Set(mind) ind.Set(mind)
} else { } else {
if cnt == 0 {
slice = reflect.New(ind.Type()).Elem()
}
if isPtr {
slice = reflect.Append(slice, mind.Addr()) slice = reflect.Append(slice, mind.Addr())
} else {
slice = reflect.Append(slice, mind)
}
} }
} }
cnt++ cnt++
} }
if one == false { if one == false && cnt > 0 {
ind.Set(slice) ind.Set(slice)
} }

View File

@ -10,6 +10,7 @@ const (
od_SET_DEFAULT = "set_default" od_SET_DEFAULT = "set_default"
od_DO_NOTHING = "do_nothing" od_DO_NOTHING = "do_nothing"
defaultStructTagName = "orm" defaultStructTagName = "orm"
defaultStructTagDelim = ";"
) )
var ( var (

View File

@ -16,7 +16,7 @@ type Data struct {
Char string `orm:"size(50)"` Char string `orm:"size(50)"`
Text string `orm:"type(text)"` Text string `orm:"type(text)"`
Date time.Time `orm:"type(date)"` Date time.Time `orm:"type(date)"`
DateTime time.Time DateTime time.Time `orm:"column(datetime)"`
Byte byte Byte byte
Rune rune Rune rune
Int int Int int
@ -37,10 +37,10 @@ type Data struct {
type DataNull struct { type DataNull struct {
Id int Id int
Boolean bool `orm:"null"` Boolean bool `orm:"null"`
Char string `orm:"size(50);null"` Char string `orm:"null;size(50)"`
Text string `orm:"type(text);null"` Text string `orm:"null;type(text)"`
Date time.Time `orm:"type(date);null"` Date time.Time `orm:"null;type(date)"`
DateTime time.Time `orm:"null"` DateTime time.Time `orm:"null;column(datetime)""`
Byte byte `orm:"null"` Byte byte `orm:"null"`
Rune rune `orm:"null"` Rune rune `orm:"null"`
Int int `orm:"null"` Int int `orm:"null"`
@ -174,7 +174,10 @@ var (
IsPostgres = DBARGS.Driver == "postgres" IsPostgres = DBARGS.Driver == "postgres"
) )
var dORM Ormer var (
dORM Ormer
dDbBaser dbBaser
)
func init() { func init() {
Debug, _ = StrTo(DBARGS.Debug).Bool() Debug, _ = StrTo(DBARGS.Debug).Bool()

View File

@ -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) { func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) {
attr := make(map[string]bool) attr := make(map[string]bool)
tag := make(map[string]string) tag := make(map[string]string)
for _, v := range strings.Split(data, ";") { for _, v := range strings.Split(data, defaultStructTagDelim) {
v = strings.TrimSpace(v) v = strings.TrimSpace(v)
if supportTag[v] == 1 { if supportTag[v] == 1 {
attr[v] = true attr[v] = true

View File

@ -4,6 +4,8 @@ import (
"database/sql" "database/sql"
"fmt" "fmt"
"reflect" "reflect"
"strings"
"time"
) )
type rawPrepare struct { type rawPrepare struct {
@ -64,14 +66,362 @@ func (o *rawSet) Exec() (sql.Result, error) {
return o.orm.db.Exec(query, args...) return o.orm.db.Exec(query, args...)
} }
func (o *rawSet) QueryRow(...interface{}) error { func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) {
//TODO 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("<RawSeter.QueryRow> 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("<RawSeter.QueryRow> 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 return nil
} }
func (o *rawSet) QueryRows(...interface{}) (int64, error) { func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) {
//TODO refs := make([]interface{}, 0)
return 0, nil 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("<RawSeter.QueryRows> 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) { func (o *rawSet) readValues(container interface{}) (int64, error) {

View File

@ -216,6 +216,7 @@ func TestRegisterModels(t *testing.T) {
BootStrap() BootStrap()
dORM = NewOrm() dORM = NewOrm()
dDbBaser = getDbAlias("default").DbBaser
} }
func TestModelSyntax(t *testing.T) { func TestModelSyntax(t *testing.T) {
@ -629,9 +630,23 @@ func TestOperators(t *testing.T) {
func TestAll(t *testing.T) { func TestAll(t *testing.T) {
var users []*User var users []*User
qs := dORM.QueryTable("user") qs := dORM.QueryTable("user")
num, err := qs.All(&users) num, err := qs.OrderBy("Id").All(&users)
throwFail(t, err) 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") qs = dORM.QueryTable("user")
num, err = qs.Filter("user_name", "nothing").All(&users) num, err = qs.Filter("user_name", "nothing").All(&users)
@ -645,8 +660,14 @@ func TestOne(t *testing.T) {
err := qs.One(&user) err := qs.One(&user)
throwFail(t, AssertIs(err, T_Equal, ErrMultiRows)) 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) err = qs.Filter("user_name", "nothing").One(&user)
throwFail(t, AssertIs(err, T_Equal, ErrNoRows)) throwFail(t, AssertIs(err, T_Equal, ErrNoRows))
} }
func TestValues(t *testing.T) { func TestValues(t *testing.T) {
@ -836,30 +857,282 @@ func TestPrepareInsert(t *testing.T) {
throwFail(t, AssertIs(err, T_Equal, ErrStmtClosed)) 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) { func TestRawValues(t *testing.T) {
switch { Q := dDbBaser.TableQuote()
case IsMysql || IsSqlite:
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 var maps []Params
num, err = dORM.Raw("SELECT user_name FROM user WHERE status = ?", 1).Values(&maps) 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, err)
throwFail(t, AssertIs(num, T_Equal, 1)) throwFail(t, AssertIs(num, T_Equal, 1))
if num == 1 { if num == 1 {
@ -867,15 +1140,16 @@ func TestRawValues(t *testing.T) {
} }
var lists []ParamsList var lists []ParamsList
num, err = dORM.Raw("SELECT user_name FROM user WHERE status = ?", 1).ValuesList(&lists) num, err = dORM.Raw(query, 1).ValuesList(&lists)
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(num, T_Equal, 1)) throwFail(t, AssertIs(num, T_Equal, 1))
if num == 1 { if num == 1 {
throwFail(t, AssertIs(lists[0][0], T_Equal, "slene")) throwFail(t, AssertIs(lists[0][0], T_Equal, "slene"))
} }
query = fmt.Sprintf("SELECT %sprofile_id%s FROM %suser%s ORDER BY %sid%s ASC", Q, Q, Q, Q, Q, Q)
var list ParamsList var list ParamsList
num, err = dORM.Raw("SELECT profile_id FROM user ORDER BY id ASC").ValuesFlat(&list) num, err = dORM.Raw(query).ValuesFlat(&list)
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(num, T_Equal, 3)) throwFail(t, AssertIs(num, T_Equal, 3))
if num == 3 { if num == 3 {
@ -883,45 +1157,6 @@ func TestRawValues(t *testing.T) {
throwFail(t, AssertIs(list[1], T_Equal, "3")) throwFail(t, AssertIs(list[1], T_Equal, "3"))
throwFail(t, AssertIs(list[2], T_Equal, nil)) 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))
}
}
} }
func TestRawPrepare(t *testing.T) { func TestRawPrepare(t *testing.T) {

View File

@ -115,6 +115,8 @@ func ToStr(value interface{}, args ...int) (s string) {
s = strconv.FormatUint(v, argInt(args).Get(0, 10)) s = strconv.FormatUint(v, argInt(args).Get(0, 10))
case string: case string:
s = v s = v
case []byte:
s = string(v)
default: default:
s = fmt.Sprintf("%v", v) s = fmt.Sprintf("%v", v)
} }