package DB import ( "TsDB2/DB/core/types" "encoding/binary" "fmt" "reflect" ) // structToFieldValues 将结构体转换为 core.InsertRow 所需的 FieldValue 切片 // activeColumns 为当前 DB schema 活跃列集合,只发送交集内的字段 func structToFieldValues(obj interface{}, model *ModelInfo, activeColumns map[string]bool) ([]types.FieldValue, error) { v := reflect.ValueOf(obj) if v.Kind() == reflect.Ptr { v = v.Elem() } if v.Kind() != reflect.Struct { return nil, fmt.Errorf("tsdb: expected struct, got %s", v.Kind()) } result := make([]types.FieldValue, 0, len(model.AllFields)) for _, fd := range model.AllFields { // 跳过不在当前 DB schema 中的字段 (如已删除列、或 struct 有但 DB 没有) if activeColumns != nil && !activeColumns[fd.ColName] { continue } fv := findField(v, fd.Name, model.StructType) if !fv.IsValid() { // 字段不在结构体中 (如自动添加的 _id),用零值填充 result = append(result, types.FieldValue{ FieldName: []byte(fd.ColName), Value: zeroValue(fd), }) continue } val := normalizeValue(fv, fd) result = append(result, types.FieldValue{ FieldName: []byte(fd.ColName), Value: val, }) } return result, nil } // fieldValuesToStruct 将 core 查询结果的 FieldValue 切片反序列化到结构体 func fieldValuesToStruct(fvs []types.FieldValue, model *ModelInfo, obj interface{}) error { v := reflect.ValueOf(obj) if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { return fmt.Errorf("tsdb: obj must be a pointer to struct") } v = v.Elem() // 建立列名 → FieldValue 映射 colMap := make(map[string]types.FieldValue, len(fvs)) for _, fv := range fvs { colMap[string(fv.FieldName)] = fv } for _, fd := range model.AllFields { fv, ok := colMap[fd.ColName] if !ok { continue } target := findSettableField(v, fd.Name, model.StructType) if !target.IsValid() || !target.CanSet() { continue } if err := setFieldFromValue(target, fv.Value, fd); err != nil { return fmt.Errorf("tsdb: set field %s: %w", fd.Name, err) } } return nil } // findField 在结构体中查找字段 (支持嵌入结构体) func findField(v reflect.Value, name string, t reflect.Type) reflect.Value { // 直接查找 if f := v.FieldByName(name); f.IsValid() { return f } // 在嵌入结构体中查找 for i := 0; i < t.NumField(); i++ { sf := t.Field(i) if sf.Anonymous { fv := v.Field(i) if sf.Type == baseModelType || sf.Type == timeSeriesModelType { if inner := fv.FieldByName(name); inner.IsValid() { return inner } } else if sf.Type.Kind() == reflect.Struct { if inner := findField(fv, name, sf.Type); inner.IsValid() { return inner } } } } return reflect.Value{} } // findSettableField 同 findField 但确保返回可设置的字段 func findSettableField(v reflect.Value, name string, t reflect.Type) reflect.Value { return findField(v, name, t) } // normalizeValue 将反射字段值转换为 core 可接受的值 func normalizeValue(fv reflect.Value, fd FieldDef) interface{} { iface := fv.Interface() switch fd.FieldType { case types.FieldType_1byte: return toInt8(iface) case types.FieldType_2byte: return toInt16(iface) case types.FieldType_4byte: return toInt32(iface) case types.FieldType_8byte: return toUint64(iface) case types.FieldType_16byte, types.FieldType_32byte, types.FieldType_64byte, types.FieldType_128byte, types.FieldType_256byte: return toFixedBytes(iface, int(types.GetSize(fd.FieldType))) case types.FieldType_Dynamicbyte: return toBytes(iface) default: return iface } } // setFieldFromValue 将 core 返回值设置到结构体字段 func setFieldFromValue(target reflect.Value, val interface{}, fd FieldDef) error { if val == nil { return nil } switch v := val.(type) { case uint64: setIntField(target, int64(v)) case int64: setIntField(target, v) case int32: setIntField(target, int64(v)) case int16: setIntField(target, int64(v)) case int8: setIntField(target, int64(v)) case float64: setFloatField(target, v) case float32: setFloatField(target, float64(v)) case []byte: setBytesField(target, v, fd) default: // 尝试直接设置 rv := reflect.ValueOf(val) if rv.Type().AssignableTo(target.Type()) { target.Set(rv) } } return nil } func setIntField(target reflect.Value, val int64) { switch target.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: target.SetInt(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: target.SetUint(uint64(val)) case reflect.Float32, reflect.Float64: target.SetFloat(float64(val)) } } func setFloatField(target reflect.Value, val float64) { switch target.Kind() { case reflect.Float32, reflect.Float64: target.SetFloat(val) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: target.SetInt(int64(val)) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: target.SetUint(uint64(val)) } } func setBytesField(target reflect.Value, val []byte, fd FieldDef) { switch target.Kind() { case reflect.String: // 截断到第一个 null 字节 s := string(val) for i, c := range s { if c == 0 { s = s[:i] break } } target.SetString(s) case reflect.Slice: if target.Type().Elem().Kind() == reflect.Uint8 { target.SetBytes(val) } } } // ===== 类型转换辅助函数 ===== func toUint64(v interface{}) uint64 { switch val := v.(type) { case uint64: return val case int64: return uint64(val) case int: return uint64(val) case int32: return uint64(val) case uint32: return uint64(val) case int16: return uint64(val) case uint16: return uint64(val) case int8: return uint64(val) case uint8: return uint64(val) case float64: return uint64(val) case float32: return uint64(val) default: rv := reflect.ValueOf(v) if rv.CanUint() { return rv.Uint() } if rv.CanInt() { return uint64(rv.Int()) } return 0 } } func toInt8(v interface{}) int8 { return int8(toUint64(v)) } func toInt16(v interface{}) int16 { return int16(toUint64(v)) } func toInt32(v interface{}) int32 { return int32(toUint64(v)) } func toFixedBytes(v interface{}, size int) []byte { buf := make([]byte, size) switch val := v.(type) { case string: copy(buf, val) case []byte: copy(buf, val) default: // 数值类型: BigEndian 编码 rv := reflect.ValueOf(v) if rv.CanUint() { binary.BigEndian.PutUint64(buf, rv.Uint()) } else if rv.CanInt() { binary.BigEndian.PutUint64(buf, uint64(rv.Int())) } } return buf } func toBytes(v interface{}) []byte { switch val := v.(type) { case []byte: return val case string: return []byte(val) default: return nil } } // getPKValue 从结构体中提取主键值 func getPKValue(obj interface{}, model *ModelInfo) uint64 { if !model.PKInStruct { return 0 // PK 不在结构体中,返回 0 让 core 自动分配 } v := reflect.ValueOf(obj) if v.Kind() == reflect.Ptr { v = v.Elem() } pkDef := model.AllFields[model.PKIndex] fv := findField(v, pkDef.Name, model.StructType) if !fv.IsValid() { return 0 } return toUint64(fv.Interface()) } // setPKValue 设置结构体的主键值 func setPKValue(obj interface{}, model *ModelInfo, pk uint64) { if !model.PKInStruct { return // PK 不在结构体中,无法回写 } v := reflect.ValueOf(obj) if v.Kind() == reflect.Ptr { v = v.Elem() } pkDef := model.AllFields[model.PKIndex] fv := findField(v, pkDef.Name, model.StructType) if fv.IsValid() && fv.CanSet() { fv.SetUint(pk) } } // zeroValue 返回字段类型的零值 func zeroValue(fd FieldDef) interface{} { switch fd.FieldType { case types.FieldType_1byte: return int8(0) case types.FieldType_2byte: return int16(0) case types.FieldType_4byte: return int32(0) case types.FieldType_8byte: return uint64(0) default: size := int(types.GetSize(fd.FieldType)) if size > 0 { return make([]byte, size) } return make([]byte, 12) // dynamic } }