package api import ( "encoding/json" "u-desk/internal/service" "u-desk/internal/storage/models" "u-desk/internal/storage/repository" ) type SqlAPI struct { sqlService *service.SqlExecService resultRepo repository.ResultRepository } func NewSqlAPI() (*SqlAPI, error) { sqlService, err := service.NewSqlExecService() if err != nil { return nil, err } resultRepo, err := repository.NewResultRepository() if err != nil { return nil, err } return &SqlAPI{sqlService, resultRepo}, nil } // ExecuteSQL 执行SQL语句 // 注意:SQL 语句应该已经包含分页信息(LIMIT 和 OFFSET),由客户端添加 func (api *SqlAPI) ExecuteSQL(connectionID uint, sqlStr string, database string) (map[string]interface{}, error) { result, err := api.sqlService.ExecuteSQL(connectionID, sqlStr, database) if err != nil { return nil, err } response := map[string]interface{}{ "type": result.Type, "data": result.Data, "rowsAffected": result.RowsAffected, "executionTime": result.ExecutionTime, } // 如果是查询,添加列顺序信息 if result.Type == "query" && len(result.Columns) > 0 { response["columns"] = result.Columns } // 自动保存结果到历史记录(异步执行) go func() { api.resultRepo.Save(connectionID, database, sqlStr, result.Type, result.Data, result.Columns, result.RowsAffected, result.ExecutionTime) }() return response, nil } func (api *SqlAPI) GetDatabases(connectionID uint) ([]string, error) { return api.sqlService.GetDatabases(connectionID) } func (api *SqlAPI) GetTables(connectionID uint, database string) ([]string, error) { return api.sqlService.GetTables(connectionID, database) } func (api *SqlAPI) GetTableStructure(connectionID uint, database, tableName string) (map[string]interface{}, error) { return api.sqlService.GetTableStructure(connectionID, database, tableName) } func (api *SqlAPI) GetIndexes(connectionID uint, database, tableName string) ([]map[string]interface{}, error) { return api.sqlService.GetIndexes(connectionID, database, tableName) } func (api *SqlAPI) PreviewTableStructure(connectionID uint, database, tableName string, structure map[string]interface{}) ([]string, error) { return api.sqlService.PreviewTableStructure(connectionID, database, tableName, structure) } func (api *SqlAPI) UpdateTableStructure(connectionID uint, database, tableName string, structure map[string]interface{}) ([]string, error) { return api.sqlService.UpdateTableStructure(connectionID, database, tableName, structure) } func (api *SqlAPI) SaveResult(connectionID uint, database, sql string, resultType string, data interface{}, columns []string, rowsAffected int, executionTime int64) (map[string]interface{}, error) { history, err := api.resultRepo.Save(connectionID, database, sql, resultType, data, columns, rowsAffected, executionTime) if err != nil { return nil, err } return historyToMap(history), nil } func (api *SqlAPI) GetResultHistory(connectionID *uint, keyword string, limit, offset int) (map[string]interface{}, error) { histories, total, err := api.resultRepo.Search(connectionID, keyword, limit, offset) if err != nil { return nil, err } items := make([]map[string]interface{}, len(histories)) for i, h := range histories { items[i] = historyToMap(&h) } return map[string]interface{}{"items": items, "total": total}, nil } func (api *SqlAPI) GetResultHistoryByID(id uint) (map[string]interface{}, error) { history, err := api.resultRepo.FindByID(id) if err != nil || history == nil { return nil, err } return historyToMap(history), nil } func (api *SqlAPI) DeleteResultHistory(id uint) error { return api.resultRepo.Delete(id) } func historyToMap(history *models.SqlResultHistory) map[string]interface{} { result := map[string]interface{}{ "id": history.ID, "connection_id": history.ConnectionID, "database": history.Database, "sql": history.Sql, "type": history.Type, "rows_affected": history.RowsAffected, "execution_time": history.ExecutionTime, "created_at": history.CreatedAt, } if history.Data != "" { var data interface{} json.Unmarshal([]byte(history.Data), &data) result["data"] = data } if history.Columns != "" { var columns []string json.Unmarshal([]byte(history.Columns), &columns) result["columns"] = columns } return result }