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)
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)
}

View File

@ -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 (

View File

@ -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()

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) {
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

View File

@ -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("<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
}
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("<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) {

View File

@ -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))
}
}

View File

@ -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)
}