handler.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Package handler 提供数据查询模块的HTTP请求处理器
  2. // 负责处理数据查询、SQL执行等相关API请求,协调前端请求与后端服务层的交互
  3. package handler
  4. import (
  5. "net/http"
  6. "dbview/service/internal/common/databases/meta"
  7. "dbview/service/internal/common/response"
  8. api "dbview/service/internal/modules/data_query/api"
  9. svc "dbview/service/internal/modules/data_query/service"
  10. "github.com/gin-gonic/gin"
  11. )
  12. // Handler 数据查询处理器结构体
  13. // 封装了数据查询服务层的调用逻辑,处理HTTP请求和响应
  14. type Handler struct {
  15. svc *svc.DataService // 数据查询服务实例
  16. }
  17. // NewHandler 创建新的数据查询处理器
  18. // 参数:
  19. // - s: 数据查询服务实例
  20. //
  21. // 返回:
  22. // - *Handler: 初始化后的处理器实例
  23. func NewHandler(s *svc.DataService) *Handler {
  24. return &Handler{svc: s}
  25. }
  26. // QueryDataHandler 处理数据查询请求 POST /data/query
  27. // 支持同步和异步两种查询模式,根据请求参数决定执行方式
  28. // 请求体:api.QueryDataRequest 包含连接信息、查询路径、查询条件等
  29. // 响应:统一的数据操作响应格式,包含查询结果或异步任务ID
  30. func (h *Handler) QueryDataHandler(c *gin.Context) {
  31. // 解析请求参数,验证必填字段
  32. var req api.QueryDataRequest
  33. if err := c.ShouldBindJSON(&req); err != nil {
  34. // 参数绑定失败,返回客户端错误
  35. c.JSON(http.StatusBadRequest, response.Response{Code: 1, Msg: "请求参数错误", Error: err.Error()})
  36. return
  37. }
  38. // 调用服务层执行数据查询操作
  39. // 支持根据路径定位数据库对象,并应用查询条件进行数据筛选
  40. result, err := h.svc.QueryData(c.Request.Context(), req.ConnID, req.ConnInfo, req.Path, req.Query, req.Async)
  41. if err != nil {
  42. // 服务层调用失败,返回服务器内部错误
  43. c.JSON(http.StatusInternalServerError, response.Response{Code: 2, Msg: "查询数据失败", Error: err.Error()})
  44. return
  45. }
  46. // 根据查询模式处理不同的返回结果
  47. // 异步模式返回任务ID,同步模式返回查询结果
  48. if taskId, ok := result.(string); ok {
  49. // 异步查询:任务已提交到后台队列,返回任务ID供后续查询状态
  50. asyncResp := api.AsyncQueryResponse{
  51. Success: true,
  52. TaskID: taskId,
  53. Message: "查询已提交到任务队列",
  54. }
  55. c.JSON(http.StatusOK, response.Response{Code: 0, Msg: "ok", Data: asyncResp})
  56. return
  57. }
  58. // 同步查询:直接返回查询结果数据
  59. if queryResult, ok := result.(meta.QueryResult); ok {
  60. // 构建统一的数据操作响应,包含查询结果和成功状态
  61. resp := api.DataOperationResponse{
  62. Success: true,
  63. Data: queryResult,
  64. Message: "查询完成",
  65. }
  66. c.JSON(http.StatusOK, response.Response{Code: 0, Msg: "ok", Data: resp})
  67. return
  68. }
  69. // 理论上不会到达这里,但为了代码健壮性保留错误处理
  70. c.JSON(http.StatusInternalServerError, response.Response{Code: 2, Msg: "未知的返回类型", Error: "service returned unexpected type"})
  71. }
  72. // GetTaskResultHandler 处理异步查询任务结果获取请求 GET /data/task/result
  73. // 用于查询异步数据查询任务的执行状态和结果
  74. // 当任务完成时返回查询结果数据,当任务进行中时只返回状态信息
  75. // 请求体:api.GetTaskResultRequest 包含任务ID
  76. // 响应:包含任务状态和可能的查询结果数据
  77. func (h *Handler) GetTaskResultHandler(c *gin.Context) {
  78. // 解析请求参数,获取要查询的任务ID
  79. var req api.GetTaskResultRequest
  80. if err := c.ShouldBindJSON(&req); err != nil {
  81. // 参数验证失败,返回客户端错误
  82. c.JSON(http.StatusBadRequest, response.Response{Code: 1, Msg: "请求参数错误", Error: err.Error()})
  83. return
  84. }
  85. // 调用服务层查询指定任务的执行结果和状态
  86. // 返回查询结果数据、任务状态和可能的错误信息
  87. result, status, err := h.svc.GetTaskResult(c.Request.Context(), req.TaskID)
  88. if err != nil {
  89. // 获取任务结果失败,返回服务器内部错误
  90. c.JSON(http.StatusInternalServerError, response.Response{Code: 2, Msg: "获取任务结果失败", Error: err.Error()})
  91. return
  92. }
  93. // 构建基础响应结构,包含任务状态信息
  94. resp := api.GetTaskResultResponse{
  95. Success: true,
  96. Status: status,
  97. Message: "获取任务结果成功",
  98. }
  99. // 如果任务已完成,填充查询结果数据
  100. // 只有在任务完成状态下才有实际的查询结果
  101. if status == "completed" {
  102. resp.Data = api.DataOperationResponse{
  103. Success: true,
  104. Data: result,
  105. Message: "查询完成",
  106. }
  107. }
  108. // 返回任务状态和可能的查询结果
  109. c.JSON(http.StatusOK, response.Response{Code: 0, Msg: "ok", Data: resp})
  110. }
  111. // ExecuteSQLHandler 处理SQL执行请求 POST /data/execute
  112. // 支持执行各种类型的SQL语句(SELECT、INSERT、UPDATE、DELETE、CREATE、DROP等)
  113. // 支持同步和异步两种执行模式,根据SQL复杂度和数据量自动选择或由客户端指定
  114. // 请求体:api.ExecuteSQLRequest 包含连接信息、SQL语句、参数等
  115. // 响应:统一的执行结果,包含执行状态、影响行数、可能的查询结果等信息
  116. func (h *Handler) ExecuteSQLHandler(c *gin.Context) {
  117. // 解析请求参数,验证SQL语句和连接信息
  118. var req api.ExecuteSQLRequest
  119. if err := c.ShouldBindJSON(&req); err != nil {
  120. // 参数绑定失败,返回客户端错误
  121. c.JSON(http.StatusBadRequest, response.Response{Code: 1, Msg: "请求参数错误", Error: err.Error()})
  122. return
  123. }
  124. // 调用服务层执行SQL语句
  125. // 支持参数化查询防止SQL注入,根据路径定位数据库对象
  126. result, err := h.svc.ExecuteSQL(c.Request.Context(), req.ConnID, req.ConnInfo, req.Path, req.SQL, req.Params, req.Async)
  127. if err != nil {
  128. // SQL执行失败,返回服务器内部错误
  129. c.JSON(http.StatusInternalServerError, response.Response{Code: 2, Msg: "执行SQL失败", Error: err.Error()})
  130. return
  131. }
  132. // 根据执行模式处理不同的返回结果
  133. // 异步模式返回任务ID,同步模式返回执行结果
  134. if taskId, ok := result.(string); ok {
  135. // 异步执行:SQL已提交到后台队列,返回任务ID供后续查询执行状态
  136. asyncResp := api.AsyncExecuteResponse{
  137. Success: true,
  138. TaskID: taskId,
  139. Message: "SQL已提交到任务队列",
  140. }
  141. c.JSON(http.StatusOK, response.Response{Code: 0, Msg: "ok", Data: asyncResp})
  142. return
  143. }
  144. // 同步执行:直接返回SQL执行结果
  145. if executeResult, ok := result.(meta.ExecuteResult); ok {
  146. // 将内部的ExecuteResult转换为统一的DataOperationResponse格式
  147. // 便于前端统一处理不同类型的数据库操作结果
  148. resp := api.DataOperationResponse{
  149. Success: executeResult.Success,
  150. SQLType: executeResult.SQLType, // SQL语句类型(SELECT/INSERT/UPDATE等)
  151. AffectedRows: executeResult.AffectedRows, // 受影响的行数
  152. LastInsertID: executeResult.LastInsertID, // 自增主键值(INSERT语句)
  153. ErrorMessage: executeResult.ErrorMessage, // 执行错误信息
  154. ExecutionTime: executeResult.ExecutionTime, // 执行耗时(毫秒)
  155. RowsReturned: executeResult.RowsReturned, // 返回的行数(SELECT语句)
  156. Message: "SQL执行完成",
  157. }
  158. // 只有SELECT语句才包含查询结果数据,其他语句(如INSERT/UPDATE)没有Data字段
  159. if executeResult.Data != nil {
  160. resp.Data = *executeResult.Data
  161. }
  162. c.JSON(http.StatusOK, response.Response{Code: 0, Msg: "ok", Data: resp})
  163. return
  164. }
  165. // 理论上不会到达这里,但为了代码健壮性保留错误处理
  166. c.JSON(http.StatusInternalServerError, response.Response{Code: 2, Msg: "未知的返回类型", Error: "service returned unexpected type"})
  167. }
  168. // GetExecuteTaskResultHandler 处理异步SQL执行任务结果获取请求 GET /data/execute/task/result
  169. // 用于查询异步SQL执行任务的执行状态和结果
  170. // 当任务完成时返回SQL执行结果(包括影响行数、可能的查询数据等)
  171. // 当任务失败时返回错误信息,当任务进行中时只返回状态信息
  172. // 请求体:api.GetExecuteTaskResultRequest 包含任务ID
  173. // 响应:包含任务状态和可能的SQL执行结果数据
  174. func (h *Handler) GetExecuteTaskResultHandler(c *gin.Context) {
  175. // 解析请求参数,获取要查询的任务ID
  176. var req api.GetExecuteTaskResultRequest
  177. if err := c.ShouldBindJSON(&req); err != nil {
  178. // 参数验证失败,返回客户端错误
  179. c.JSON(http.StatusBadRequest, response.Response{Code: 1, Msg: "请求参数错误", Error: err.Error()})
  180. return
  181. }
  182. // 调用服务层查询指定SQL执行任务的结果和状态
  183. // 返回执行结果数据、任务状态和可能的错误信息
  184. result, status, err := h.svc.GetExecuteTaskResult(c.Request.Context(), req.TaskID)
  185. if err != nil {
  186. // 获取任务结果失败,返回服务器内部错误
  187. c.JSON(http.StatusInternalServerError, response.Response{Code: 2, Msg: "获取任务结果失败", Error: err.Error()})
  188. return
  189. }
  190. // 构建基础响应结构,包含任务状态信息
  191. resp := api.GetExecuteTaskResultResponse{
  192. Success: true,
  193. Status: status,
  194. Message: "获取任务结果成功",
  195. }
  196. // 如果任务已完成,填充SQL执行结果数据
  197. // 包含执行成功状态、影响行数、执行时间等详细信息
  198. if status == "completed" {
  199. // 将内部的ExecuteResult转换为统一的DataOperationResponse格式
  200. // 便于前端统一处理不同类型的数据库操作结果
  201. resp.Data = api.DataOperationResponse{
  202. Success: result.Success, // SQL执行是否成功
  203. SQLType: result.SQLType, // SQL语句类型(SELECT/INSERT/UPDATE等)
  204. AffectedRows: result.AffectedRows, // 受影响的行数
  205. LastInsertID: result.LastInsertID, // 自增主键值(INSERT语句)
  206. ErrorMessage: result.ErrorMessage, // 执行错误信息
  207. ExecutionTime: result.ExecutionTime, // 执行耗时(毫秒)
  208. RowsReturned: result.RowsReturned, // 返回的行数(SELECT语句)
  209. }
  210. // 只有SELECT语句才包含查询结果数据,其他语句(如INSERT/UPDATE)没有Data字段
  211. if result.Data != nil {
  212. resp.Data.Data = *result.Data
  213. }
  214. }
  215. // 返回任务状态和可能的SQL执行结果
  216. c.JSON(http.StatusOK, response.Response{Code: 0, Msg: "ok", Data: resp})
  217. }