diff --git a/session.go b/session.go index ea7ae3c6..222d398c 100644 --- a/session.go +++ b/session.go @@ -39,7 +39,8 @@ type Session struct { beforeClosures []func(interface{}) afterClosures []func(interface{}) - stmtCache map[uint32]*core.Stmt //key: hash.Hash32 of (queryStr, len(queryStr)) + stmtCache map[uint32]*core.Stmt //key: hash.Hash32 of (queryStr, len(queryStr)) + cascadeDeep int } // Method Init reset the session as the init status. @@ -896,25 +897,23 @@ func (session *Session) Iterate(bean interface{}, fun IterFunc) error { rows, err := session.Rows(bean) if err != nil { return err - } else { - defer rows.Close() - //b := reflect.New(iterator.beanType).Interface() - i := 0 - for rows.Next() { - b := reflect.New(rows.beanType).Interface() - err = rows.Scan(b) - if err != nil { - return err - } - err = fun(i, b) - if err != nil { - return err - } - i++ - } - return err } - return nil + defer rows.Close() + //b := reflect.New(iterator.beanType).Interface() + i := 0 + for rows.Next() { + b := reflect.New(rows.beanType).Interface() + err = rows.Scan(b) + if err != nil { + return err + } + err = fun(i, b) + if err != nil { + return err + } + i++ + } + return err } func (session *Session) doPrepare(sqlStr string) (stmt *core.Stmt, err error) { @@ -2452,6 +2451,38 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, } fieldValue.Set(reflect.ValueOf(&x)) default: + if fieldType.Elem().Kind() == reflect.Struct { + if session.Statement.UseCascade { + structInter := reflect.New(fieldType.Elem()) + fmt.Println(structInter, fieldType.Elem()) + table := session.Engine.autoMapType(structInter.Elem()) + if table != nil { + x, err := strconv.ParseInt(string(data), 10, 64) + if err != nil { + return fmt.Errorf("arg %v as int: %s", key, err.Error()) + } + if x != 0 { + // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch + // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne + // property to be fetched lazily + newsession := session.Engine.NewSession() + defer newsession.Close() + has, err := newsession.Id(x).Get(structInter.Interface()) + if err != nil { + return err + } + if has { + v = structInter.Interface() + fieldValue.Set(reflect.ValueOf(v)) + } else { + return errors.New("cascade obj is not exist!") + } + } + } + } else { + return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String()) + } + } return fmt.Errorf("unsupported type in Scan: %s", reflect.TypeOf(v).String()) } default: