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" "reflect" "strings" "time" ) const ( sqlResultTimeMicroFormat = "2006-01-02T15:04:05.000000+08:00" sqlResultTimeMilliFormat = "2006-01-02T15:04:05.000+08:00" sqlResultTimeSecFormat = "2006-01-02T15:04:05+08:00" ) func parseSqlTableRowTimeStr(timeStr string) (time.Time, error) { var layout string if strings.HasSuffix(timeStr, ".000000+08:00") { layout = sqlResultTimeMicroFormat } else if strings.HasSuffix(timeStr, ".000+08:00") { layout = sqlResultTimeMilliFormat } else { layout = sqlResultTimeSecFormat } return time.ParseInLocation(layout, timeStr, time.Local) } func ParseSqlTableRow(input any, output any) error { if input == nil || output == nil { return nil } outputType := reflect.TypeOf(output) if outputType.Kind() != reflect.Ptr { return errors.New("输出实体应该为结构的slice或者是结构的指针") } if outputType.Kind() == reflect.Ptr { outputType = outputType.Elem() } if outputType.Kind() != reflect.Slice && outputType.Kind() != reflect.Struct { return errors.New("输出实体应该为结构的slice或者是结构的指针") } outputElemType := outputType if outputType.Kind() == reflect.Slice { outputElemType = outputType.Elem() } fmt.Println(outputElemType.String()) tableRows, ok := input.([]map[string]any) if !ok { tableRow, ok := input.(map[string]any) if !ok { return errors.New("输入数据应该为[]map[string]any或[]map[string]any") } tableRows = []map[string]any{tableRow} } outputEntities := reflect.MakeSlice(reflect.SliceOf(outputElemType), 0, 0) for _, tableRow := range tableRows { outputEntityValue := reflect.New(outputElemType).Elem().Addr() outputEntity := outputEntityValue.Interface() sqlResult, err := ParseSqlResult(outputEntity) if err != nil { return err } for fieldName, sqlColumn := range sqlResult.ColumnMap { tableRowValue, ok := tableRow[sqlColumn.Name] if !ok { continue } fieldValue := sqlColumn.OriginFieldValue if fieldValue.Type().Kind() == reflect.Ptr { if fieldValue.IsValid() { fieldValue.Set(reflect.New(sqlColumn.FieldTypeElem)) } fieldValue = fieldValue.Elem() } outputKind := reflectutils.GroupValueKind(fieldValue) switch outputKind { case reflect.Bool: err := reflectutils.AssignBoolValue(tableRowValue, fieldValue) if err != nil { return err } case reflect.String: strValue := tableRowValue.(string) if strutils.IsStringNotEmpty(sqlColumn.ParseTime) { parsedTime, err := parseSqlTableRowTimeStr(strValue) if err != nil { return err } strValue = parsedTime.Format(sqlColumn.ParseTime) } else if strutils.IsStringNotEmpty(sqlColumn.AESKey) { decryptedValue, err := encoding.AESDecrypt(strValue, sqlColumn.AESKey) if err != nil { return err } strValue = decryptedValue } err = reflectutils.AssignStringValue(strValue, fieldValue) if err != nil { return err } case reflect.Int64: err := reflectutils.AssignIntValue(tableRowValue, fieldValue) if err != nil { return err } case reflect.Uint64: err := reflectutils.AssignUintValue(tableRowValue, fieldValue) if err != nil { return err } case reflect.Float64: err := reflectutils.AssignFloatValue(tableRowValue, fieldValue) if err != nil { return err } case reflect.Struct: if fieldValue.Type() == reflect.TypeOf(time.Time{}) { parsedTime, err := parseSqlTableRowTimeStr(tableRowValue.(string)) if err != nil { return err } fieldValue.Set(reflect.ValueOf(parsedTime)) continue } return fmt.Errorf("字段: %s 列: %s 不支持的类型: %s", fieldName, sqlColumn.Name, reflect.TypeOf(tableRowValue).String()) default: return fmt.Errorf("字段: %s 列: %s 不支持的类型: %s", fieldName, sqlColumn.Name, reflect.TypeOf(tableRowValue).String()) } } outputEntities = reflect.Append(outputEntities, outputEntityValue.Elem()) } outputValue := reflect.Indirect(reflect.ValueOf(output)) if outputType.Kind() == reflect.Slice { outputValue.Set(outputEntities) } else { fmt.Println(outputValue.Type().String()) outputValue.Set(outputEntities.Index(0)) } return nil }