package service import ( "fmt" "strconv" "strings" "time" "git.x2erp.com/qdy/go-base/ctx" "git.x2erp.com/qdy/go-base/logger" "git.x2erp.com/qdy/go-base/model/request" "git.x2erp.com/qdy/go-base/model/response" "git.x2erp.com/qdy/go-base/util" "git.x2erp.com/qdy/go-db/factory/database" "github.com/jmoiron/sqlx" ) func QueryYamlConfigure(dbFactory *database.DBFactory, req request.QueryRequest, reqCtx *ctx.RequestContext) *response.QueryResult[map[string]interface{}] { return query(dbFactory.GetDB(), req, reqCtx) } // QueryYamlConfigure 执行带位置参数的查询 func query(db *sqlx.DB, req request.QueryRequest, reqCtx *ctx.RequestContext) *response.QueryResult[map[string]interface{}] { startTime := time.Now() // 安全检查 if db == nil { return util.CreateErrorResult[map[string]interface{}]("database connection is nil", reqCtx) } sqlStr := ` SELECT b.config_startup_detail_id, b.config_key, b.config_value FROM config_startup a JOIN config_startup_detail b ON a.config_startup_id = b.config_startup_id WHERE a.config_environment_id = $1 AND a.config_service_id = $2;` params := req.PositionalParams logger.DebugC(reqCtx, sqlStr) logger.DebugC(reqCtx, fmt.Sprintf("PositionalParams: %v", params)) // 执行查询 rows, err := db.Queryx(sqlStr, params...) if err != nil { return util.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Query execution failed: %v", err), reqCtx) } defer rows.Close() // 处理结果集 return processQueryResult(rows, startTime, reqCtx) } func processQueryResult(rows *sqlx.Rows, startTime time.Time, reqCtx *ctx.RequestContext) *response.QueryResult[map[string]interface{}] { // 初始化结果结构体 result := &response.QueryResult[map[string]interface{}]{ Metadata: reqCtx, } // 获取列信息 columns, err := rows.Columns() if err != nil { return util.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Failed to get columns: %v", err), reqCtx) } // 存储最终结果:根key -> 内层配置map results := make(map[string]interface{}) count := 0 // 记录已经出现的内层key,用于检测重复 // outerKey -> innerKey -> rowNumber //keyTracker := make(map[string]map[string]int) // 遍历行数据 for rows.Next() { count++ values := make([]interface{}, len(columns)) valuePtrs := make([]interface{}, len(columns)) for i := range columns { valuePtrs[i] = &values[i] } // 扫描行数据 if err := rows.Scan(valuePtrs...); err != nil { return util.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Scan row %d failed: %v", count, err), reqCtx) } // 提取当前行的三个核心字段 var detailID, configKey string var configValue interface{} for i, col := range columns { v := values[i] if v == nil { continue } switch col { case "config_startup_detail_id": detailID = toString(v) // detailID 需要字符串 case "config_key": configKey = toString(v) // config_key 需要字符串 case "config_value": configValue = convertValue(v) // config_value 需要带类型转换 } } //logger.DebugC(reqCtx, fmt.Sprintf("Row %d - detailID: %s, configKey: %s", count, detailID, configKey)) // 解析 detailID 获取根key(倒数第3段) parts := strings.Split(detailID, ".") if len(parts) < 3 { return util.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Row %d detailID format error: %s", count, detailID), reqCtx) } rootKey := parts[len(parts)-3] // 取倒数第3段,例如 "database" // 获取或创建外层key对应的map configMap, exists := results[rootKey] if !exists { // 不存在则创建 configMap = make(map[string]interface{}) results[rootKey] = configMap } // 添加或覆盖内层配置 configMap.(map[string]interface{})[configKey] = configValue } // 检查行遍历错误 if err := rows.Err(); err != nil { return util.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Row iteration error: %v", err), reqCtx) } // 构建成功结果 result.Success = true result.Data = results result.Count = count result.Time = time.Since(startTime).String() result.Message = "Query success" return result } // 辅助函数:转换为字符串 func toString(v interface{}) string { switch val := v.(type) { case string: return val case []byte: return string(val) case int64: return strconv.FormatInt(val, 10) case int32: return strconv.FormatInt(int64(val), 10) case int: return strconv.Itoa(val) case float64: return strconv.FormatFloat(val, 'f', -1, 64) case float32: return strconv.FormatFloat(float64(val), 'f', -1, 32) case bool: return strconv.FormatBool(val) default: return fmt.Sprintf("%v", val) } } // 辅助函数:转换值,保持合适的数据类型 func convertValue(v interface{}) interface{} { switch val := v.(type) { case []byte: // 尝试解析为合适的数据类型 strVal := string(val) return parseStringValue(strVal) case string: return parseStringValue(val) case int64, int32, int: return val case float64, float32: return val case bool: return val default: // 其他类型转换为字符串 return toString(val) } } // 辅助函数:解析字符串值为合适的数据类型 func parseStringValue(strVal string) interface{} { // 1. 尝试布尔值 (支持 true/false, yes/no, on/off, 1/0) lowerVal := strings.ToLower(strings.TrimSpace(strVal)) if lowerVal == "true" || lowerVal == "yes" || lowerVal == "on" || lowerVal == "1" { return true } if lowerVal == "false" || lowerVal == "no" || lowerVal == "off" || lowerVal == "0" { return false } // 2. 尝试整数 if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { return intVal } // 3. 尝试浮点数 if floatVal, err := strconv.ParseFloat(strVal, 64); err == nil { return floatVal } // 4. 保持为字符串 return strVal }