package stardb import ( "errors" "reflect" "time" ) func (star *StarRows) setAllRefValue(stc interface{}, skey string, rows int) error { t := reflect.TypeOf(stc) v := reflect.ValueOf(stc) if t.Kind() == reflect.Ptr { v = v.Elem() } if t.Kind() != reflect.Ptr && !v.CanSet() { return errors.New("interface{} is not writable") } if t.Kind() == reflect.Ptr { t = t.Elem() } if v.Kind() != reflect.Struct { return errors.New("interface{} is not a struct") } for i := 0; i < t.NumField(); i++ { tp := t.Field(i) srFrd := v.Field(i) seg := tp.Tag.Get(skey) if seg == "" && !tp.IsExported() { continue } if srFrd.Kind() == reflect.Ptr && reflect.TypeOf(srFrd.Interface()).Elem().Kind() == reflect.Struct { if seg == "" { continue } if seg == "---" { sp := reflect.New(reflect.TypeOf(srFrd.Interface()).Elem()).Interface() star.setAllRefValue(sp, skey, rows) v.Field(i).Set(reflect.ValueOf(sp)) continue } } if srFrd.Kind() == reflect.Struct { if seg == "" { continue } if seg == "---" { sp := reflect.New(reflect.TypeOf(v.Field(i).Interface())).Interface() star.setAllRefValue(sp, skey, rows) v.Field(i).Set(reflect.ValueOf(sp).Elem()) continue } } if _, ok := star.Row(rows).columnref[seg]; !ok { continue } myInt64 := star.Row(rows).MustInt64(seg) myUint64 := star.Row(rows).MustUint64(seg) switch v.Field(i).Kind() { case reflect.String: v.Field(i).SetString(star.Row(rows).MustString(seg)) case reflect.Int64: v.Field(i).SetInt(myInt64) case reflect.Int32: v.Field(i).SetInt(int64(star.Row(rows).MustInt32(seg))) case reflect.Int16: v.Field(i).SetInt(int64(int16(myInt64))) case reflect.Int8: v.Field(i).SetInt(int64(int8(myInt64))) case reflect.Uint64: v.Field(i).SetUint(myUint64) case reflect.Uint32: v.Field(i).SetUint(uint64(uint32(myUint64))) case reflect.Uint16: v.Field(i).SetUint(uint64(uint16(myUint64))) case reflect.Uint8: v.Field(i).SetUint(uint64(uint8(myUint64))) case reflect.Bool: v.Field(i).SetBool(star.Row(rows).MustBool(seg)) case reflect.Float64: v.Field(i).SetFloat(star.Row(rows).MustFloat64(seg)) case reflect.Float32: v.Field(i).SetFloat(float64(star.Row(rows).MustFloat32(seg))) case reflect.Slice, reflect.Array: if t.Field(i).Type.Elem().Kind() == reflect.Uint8 { v.Field(i).SetBytes(star.Row(rows).MustBytes(seg)) } case reflect.Interface, reflect.Struct, reflect.Ptr: inf := star.Row(rows).Result[star.columnref[seg]] switch vtype := inf.(type) { case time.Time: v.Field(i).Set(reflect.ValueOf(vtype)) } default: } } return nil } func setRefValue(stc interface{}, skey, key string, value interface{}) error { t := reflect.TypeOf(stc) v := reflect.ValueOf(stc).Elem() if t.Kind() != reflect.Ptr || !v.CanSet() { return errors.New("interface{} is not writable") } if v.Kind() != reflect.Struct { return errors.New("interface{} is not a struct") } t = t.Elem() for i := 0; i < t.NumField(); i++ { tp := t.Field(i) seg := tp.Tag.Get(skey) if seg == "" || key != seg { continue } v.Field(i).Set(reflect.ValueOf(value)) } return nil } func getAllRefValue(stc interface{}, skey string) (map[string]interface{}, error) { result := make(map[string]interface{}) t := reflect.TypeOf(stc) v := reflect.ValueOf(stc) if t.Kind() == reflect.Ptr { if v.IsNil() { return nil, errors.New("ptr interface{} is nil") } t = t.Elem() v = v.Elem() } if v.Kind() != reflect.Struct { return nil, errors.New("interface{} is not a struct") } for i := 0; i < t.NumField(); i++ { tp := t.Field(i) srFrd := v.Field(i) seg := tp.Tag.Get(skey) if seg == "" && !tp.IsExported() { continue } if srFrd.Kind() == reflect.Ptr && reflect.TypeOf(srFrd.Interface()).Elem().Kind() == reflect.Struct { if srFrd.IsNil() { continue } if seg == "---" { res, err := getAllRefValue(reflect.ValueOf(srFrd.Elem().Interface()).Interface(), skey) if err != nil { return result, err } for k, v := range res { result[k] = v } continue } } if v.Field(i).Kind() == reflect.Struct { res, err := getAllRefValue(v.Field(i).Interface(), skey) if seg == "---" { if err != nil { return result, err } for k, v := range res { result[k] = v } continue } } if seg == "" { continue } value := v.Field(i) if !value.CanInterface() { continue } result[seg] = value.Interface() } return result, nil } func getAllRefKey(stc interface{}, skey string) ([]string, error) { var result []string _, isStruct := isWritableStruct(stc) if !isStruct { return []string{}, errors.New("interface{} is not a struct") } t := reflect.TypeOf(stc) v := reflect.ValueOf(stc) if t.Kind() == reflect.Ptr { if v.IsNil() { return []string{}, errors.New("ptr interface{} is nil") } t = t.Elem() v = v.Elem() } for i := 0; i < t.NumField(); i++ { srFrd := v.Field(i) profile := t.Field(i) seg := profile.Tag.Get(skey) if seg == "" && !profile.IsExported() { continue } if srFrd.Kind() == reflect.Ptr && reflect.TypeOf(srFrd.Interface()).Elem().Kind() == reflect.Struct { if srFrd.IsNil() { continue } if seg == "---" { res, err := getAllRefKey(reflect.ValueOf(srFrd.Elem().Interface()).Interface(), skey) if err != nil { return result, err } for _, v := range res { result = append(result, v) } continue } } if v.Field(i).Kind() == reflect.Struct && seg == "---" { res, err := getAllRefKey(v.Field(i).Interface(), skey) if err != nil { return result, err } for _, v := range res { result = append(result, v) } } if seg != "" { result = append(result, seg) } } return result, nil } func isWritableStruct(stc interface{}) (isWritable bool, isStruct bool) { t := reflect.TypeOf(stc) v := reflect.ValueOf(stc) if t.Kind() == reflect.Ptr || v.CanSet() { isWritable = true } if v.Kind() == reflect.Struct { isStruct = true } return }