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