Няма описание
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

query_yaml_configure.go 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package service
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "time"
  7. "git.x2erp.com/qdy/go-base/ctx"
  8. "git.x2erp.com/qdy/go-base/logger"
  9. "git.x2erp.com/qdy/go-base/myservice"
  10. "git.x2erp.com/qdy/go-base/types"
  11. "git.x2erp.com/qdy/go-db/factory/database"
  12. "github.com/jmoiron/sqlx"
  13. )
  14. func QueryYamlConfigure(dbFactory *database.DBFactory, req types.QueryRequest, reqCtx *ctx.RequestContext) *types.QueryResult[map[string]interface{}] {
  15. return query(dbFactory.GetDB(), req, reqCtx)
  16. }
  17. // QueryYamlConfigure 执行带位置参数的查询
  18. func query(db *sqlx.DB, req types.QueryRequest, reqCtx *ctx.RequestContext) *types.QueryResult[map[string]interface{}] {
  19. startTime := time.Now()
  20. // 安全检查
  21. if db == nil {
  22. return myservice.CreateErrorResult[map[string]interface{}]("database connection is nil", startTime, reqCtx)
  23. }
  24. sqlStr := `
  25. SELECT b.config_startup_detail_id, b.config_key, b.config_value
  26. FROM config_startup a
  27. JOIN config_startup_detail b ON a.config_startup_id = b.config_startup_id
  28. WHERE a.config_environment_id = $1
  29. AND a.config_service_id = $2;`
  30. params := req.PositionalParams
  31. logger.DebugC(reqCtx, sqlStr)
  32. logger.DebugC(reqCtx, fmt.Sprintf("PositionalParams: %v", params))
  33. // 执行查询
  34. rows, err := db.Queryx(sqlStr, params...)
  35. if err != nil {
  36. return myservice.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Query execution failed: %v", err), startTime, reqCtx)
  37. }
  38. defer rows.Close()
  39. // 处理结果集
  40. return processQueryResult(rows, startTime, reqCtx)
  41. }
  42. func processQueryResult(rows *sqlx.Rows, startTime time.Time, reqCtx *ctx.RequestContext) *types.QueryResult[map[string]interface{}] {
  43. // 初始化结果结构体
  44. result := &types.QueryResult[map[string]interface{}]{
  45. Metadata: reqCtx,
  46. }
  47. // 获取列信息
  48. columns, err := rows.Columns()
  49. if err != nil {
  50. return myservice.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Failed to get columns: %v", err), startTime, reqCtx)
  51. }
  52. // 存储最终结果:根key -> 内层配置map
  53. results := make(map[string]interface{})
  54. count := 0
  55. // 记录已经出现的内层key,用于检测重复
  56. // outerKey -> innerKey -> rowNumber
  57. //keyTracker := make(map[string]map[string]int)
  58. // 遍历行数据
  59. for rows.Next() {
  60. count++
  61. values := make([]interface{}, len(columns))
  62. valuePtrs := make([]interface{}, len(columns))
  63. for i := range columns {
  64. valuePtrs[i] = &values[i]
  65. }
  66. // 扫描行数据
  67. if err := rows.Scan(valuePtrs...); err != nil {
  68. return myservice.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Scan row %d failed: %v", count, err), startTime, reqCtx)
  69. }
  70. // 提取当前行的三个核心字段
  71. var detailID, configKey string
  72. var configValue interface{}
  73. for i, col := range columns {
  74. v := values[i]
  75. if v == nil {
  76. continue
  77. }
  78. switch col {
  79. case "config_startup_detail_id":
  80. detailID = toString(v) // detailID 需要字符串
  81. case "config_key":
  82. configKey = toString(v) // config_key 需要字符串
  83. case "config_value":
  84. configValue = convertValue(v) // config_value 需要带类型转换
  85. }
  86. }
  87. //logger.DebugC(reqCtx, fmt.Sprintf("Row %d - detailID: %s, configKey: %s", count, detailID, configKey))
  88. // 解析 detailID 获取根key(倒数第3段)
  89. parts := strings.Split(detailID, ".")
  90. if len(parts) < 3 {
  91. return myservice.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Row %d detailID format error: %s", count, detailID), startTime, reqCtx)
  92. }
  93. rootKey := parts[len(parts)-3] // 取倒数第3段,例如 "database"
  94. // 获取或创建外层key对应的map
  95. configMap, exists := results[rootKey]
  96. if !exists {
  97. // 不存在则创建
  98. configMap = make(map[string]interface{})
  99. results[rootKey] = configMap
  100. }
  101. // 添加或覆盖内层配置
  102. configMap.(map[string]interface{})[configKey] = configValue
  103. }
  104. // 检查行遍历错误
  105. if err := rows.Err(); err != nil {
  106. return myservice.CreateErrorResult[map[string]interface{}](fmt.Sprintf("Row iteration error: %v", err), startTime, reqCtx)
  107. }
  108. // 构建成功结果
  109. result.Success = true
  110. result.Data = results
  111. result.Count = count
  112. result.Time = time.Since(startTime).String()
  113. result.Message = "Query success"
  114. return result
  115. }
  116. // 辅助函数:转换为字符串
  117. func toString(v interface{}) string {
  118. switch val := v.(type) {
  119. case string:
  120. return val
  121. case []byte:
  122. return string(val)
  123. case int64:
  124. return strconv.FormatInt(val, 10)
  125. case int32:
  126. return strconv.FormatInt(int64(val), 10)
  127. case int:
  128. return strconv.Itoa(val)
  129. case float64:
  130. return strconv.FormatFloat(val, 'f', -1, 64)
  131. case float32:
  132. return strconv.FormatFloat(float64(val), 'f', -1, 32)
  133. case bool:
  134. return strconv.FormatBool(val)
  135. default:
  136. return fmt.Sprintf("%v", val)
  137. }
  138. }
  139. // 辅助函数:转换值,保持合适的数据类型
  140. func convertValue(v interface{}) interface{} {
  141. switch val := v.(type) {
  142. case []byte:
  143. // 尝试解析为合适的数据类型
  144. strVal := string(val)
  145. return parseStringValue(strVal)
  146. case string:
  147. return parseStringValue(val)
  148. case int64, int32, int:
  149. return val
  150. case float64, float32:
  151. return val
  152. case bool:
  153. return val
  154. default:
  155. // 其他类型转换为字符串
  156. return toString(val)
  157. }
  158. }
  159. // 辅助函数:解析字符串值为合适的数据类型
  160. func parseStringValue(strVal string) interface{} {
  161. // 1. 尝试布尔值 (支持 true/false, yes/no, on/off, 1/0)
  162. lowerVal := strings.ToLower(strings.TrimSpace(strVal))
  163. if lowerVal == "true" || lowerVal == "yes" || lowerVal == "on" || lowerVal == "1" {
  164. return true
  165. }
  166. if lowerVal == "false" || lowerVal == "no" || lowerVal == "off" || lowerVal == "0" {
  167. return false
  168. }
  169. // 2. 尝试整数
  170. if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
  171. return intVal
  172. }
  173. // 3. 尝试浮点数
  174. if floatVal, err := strconv.ParseFloat(strVal, 64); err == nil {
  175. return floatVal
  176. }
  177. // 4. 保持为字符串
  178. return strVal
  179. }