package sql import ( "errors" "fmt" "git.sxidc.com/go-tools/utils/encoding" "git.sxidc.com/go-tools/utils/reflectutils" "git.sxidc.com/go-tools/utils/strutils" "git.sxidc.com/service-supports/ds-sdk/sdk" "reflect" "strings" "time" ) func ParseSqlResult(input any, output any) error { if input == nil || output == nil { return nil } // 输出的Type,可以是slice的指针或者是结构的指针 outputType := reflect.TypeOf(output) if outputType.Kind() != reflect.Ptr { return errors.New("输出实体应该为结构的slice或者是结构的指针") } // 取元素类型 if outputType.Kind() == reflect.Ptr { outputType = outputType.Elem() } // 检查元素类型是否为slice或者结构 if outputType.Kind() != reflect.Slice && outputType.Kind() != reflect.Struct { return errors.New("输出实体应该为结构的slice或者是结构的指针") } // 如果输出类型为slice,则取slice元素类型 outputElemType := outputType if outputElemType.Kind() == reflect.Slice { outputElemType = outputElemType.Elem() } // 校验元素类型是否为结构类型 if outputElemType.Kind() != reflect.Struct { return errors.New("输出实体slice应该为结构的slice指针") } // 构造需要遍历的tableRows tableRows, ok := input.([]sdk.SqlResult) if !ok { tableRow, ok := input.(sdk.SqlResult) if !ok { return errors.New("输入数据应该为[]sdk.SqlResult或[]sdk.SqlResult") } tableRows = []sdk.SqlResult{tableRow} } // 构造输出实体slice outputEntities := reflect.MakeSlice(reflect.SliceOf(outputElemType), 0, 0) for _, tableRow := range tableRows { // 构造输出实体 outputEntityValue := reflect.New(outputElemType).Elem().Addr() outputEntity := outputEntityValue.Interface() err := formOutputEntity(tableRow, outputEntity) if err != nil { return err } // 保存输出实体 outputEntities = reflect.Append(outputEntities, outputEntityValue.Elem()) } // 将输出实体赋值给输出指针变量 outputValue := reflect.Indirect(reflect.ValueOf(output)) if !outputValue.CanSet() { return nil } if outputType.Kind() == reflect.Slice { outputValue.Set(outputEntities) } else { outputValue.Set(outputEntities.Index(0)) } return nil } func formOutputEntity(tableRow sdk.SqlResult, outputEntity any) error { sqlResult, err := ParseSqlResultTag(outputEntity) if err != nil { return err } for fieldName, resultElement := range sqlResult.ResultElement { switch element := resultElement.(type) { case *ResultStruct: err := formOutputEntity(tableRow, element.FieldValueElem.Addr().Interface()) if err != nil { return err } case *ResultColumn: tableRowValue, ok := tableRow[element.Name] if !ok { continue } // 构造结构字段,如果结构字段是指针且为nil,需要构造元素 fieldTypeElem := element.FieldTypeElem fieldValueElem := element.FieldValueElem outputKind := reflectutils.GroupValueKind(fieldValueElem) if !fieldValueElem.CanSet() { continue } switch outputKind { case reflect.Bool: err := reflectutils.AssignBoolValue(tableRowValue, fieldValueElem) if err != nil { return err } case reflect.String: strValue := tableRowValue.(string) if strutils.IsStringNotEmpty(element.ParseTime) { parsedTime, err := sdk.ParseSqlResultTimeStr(strValue) if err != nil { return err } strValue = parsedTime.Format(element.ParseTime) } else if strutils.IsStringNotEmpty(element.AESKey) { if strutils.IsStringNotEmpty(strValue) { decryptedValue, err := encoding.AESDecrypt(strValue, element.AESKey) if err != nil { return err } strValue = decryptedValue } } err = reflectutils.AssignStringValue(strValue, fieldValueElem) if err != nil { return err } case reflect.Int64: err := reflectutils.AssignInt64Value(tableRowValue, fieldValueElem) if err != nil { return err } case reflect.Uint64: err := reflectutils.AssignUint64Value(tableRowValue, fieldValueElem) if err != nil { return err } case reflect.Float64: err := reflectutils.AssignFloat64Value(tableRowValue, fieldValueElem) if err != nil { return err } case reflect.Struct: if fieldValueElem.Type() == reflect.TypeOf(time.Time{}) { parsedTime, err := sdk.ParseSqlResultTimeStr(tableRowValue.(string)) if err != nil { return err } fieldValueElem.Set(reflect.ValueOf(parsedTime)) continue } return fmt.Errorf("字段: %s 列: %s 不支持的类型: %s", fieldName, element.Name, fieldTypeElem.String()) case reflect.Slice: if fieldTypeElem.Elem().Kind() != reflect.String { return errors.New("slice仅支持[]string") } strValue, ok := tableRowValue.(string) if !ok { return errors.New("slice仅支持[]string") } strParts := strings.Split(strValue, element.SplitWith) if strParts == nil || len(strParts) == 0 { return nil } valSlice := fieldValueElem if valSlice.IsNil() { valSlice = reflect.MakeSlice(fieldTypeElem, 0, 0) } for _, strPart := range strParts { valSlice = reflect.Append(valSlice, reflect.ValueOf(strPart)) } fieldValueElem.Set(valSlice) default: return fmt.Errorf("字段: %s 列: %s 不支持的类型: %s", fieldName, element.Name, fieldTypeElem.String()) } default: return errors.New("不支持的元素类型") } } return nil }