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