Files
MyGoNavi/internal/app/methods_db.go
杨国锋 4099796c88 feat(connection): 增强连接管理与交互体验
- 新增测试连接功能,修复底层驱动假成功问题,确保密码/端口验证准确
- 支持导入/导出连接配置(JSON),便于迁移与备份
- 优化侧边栏:实现虚拟滚动解决卡顿,增加数据库筛选与断开连接重连机制
- 优化交互:改进右键菜单体验(全行触发/禁用选文),完善新建查询的上下文自动关联
- 界面调整:精简连接弹窗,移除冗余的默认数据库输入
2026-02-02 16:33:11 +08:00

283 lines
7.9 KiB
Go

package app
import (
"fmt"
"strings"
"GoNavi-Wails/internal/connection"
)
// Generic DB Methods
func (a *App) DBConnect(config connection.ConnectionConfig) connection.QueryResult {
key := getCacheKey(config)
// Use an anonymous function to scope the lock
func() {
a.mu.Lock()
defer a.mu.Unlock()
if oldDB, ok := a.dbCache[key]; ok {
oldDB.Close()
delete(a.dbCache, key)
}
}()
// getDatabase acquires the lock internally, so we must be unlocked here
_, err := a.getDatabase(config)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Message: "连接成功"}
}
func (a *App) TestConnection(config connection.ConnectionConfig) connection.QueryResult {
// Force close existing cached connection if any to ensure fresh test
key := getCacheKey(config)
func() {
a.mu.Lock()
defer a.mu.Unlock()
if oldDB, ok := a.dbCache[key]; ok {
oldDB.Close()
delete(a.dbCache, key)
}
}()
_, err := a.getDatabase(config)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Message: "连接成功"}
}
func (a *App) CreateDatabase(config connection.ConnectionConfig, dbName string) connection.QueryResult {
runConfig := config
runConfig.Database = ""
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
query := fmt.Sprintf("CREATE DATABASE `%%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", dbName)
if runConfig.Type == "postgres" {
query = fmt.Sprintf("CREATE DATABASE \"%%s\"", dbName)
}
_, err = dbInst.Exec(query)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Message: "Database created successfully"}
}
func (a *App) MySQLConnect(config connection.ConnectionConfig) connection.QueryResult {
config.Type = "mysql"
return a.DBConnect(config)
}
func (a *App) MySQLQuery(config connection.ConnectionConfig, dbName string, query string) connection.QueryResult {
config.Type = "mysql"
return a.DBQuery(config, dbName, query)
}
func (a *App) MySQLGetDatabases(config connection.ConnectionConfig) connection.QueryResult {
config.Type = "mysql"
return a.DBGetDatabases(config)
}
func (a *App) MySQLGetTables(config connection.ConnectionConfig, dbName string) connection.QueryResult {
config.Type = "mysql"
return a.DBGetTables(config, dbName)
}
func (a *App) MySQLShowCreateTable(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
config.Type = "mysql"
return a.DBShowCreateTable(config, dbName, tableName)
}
func (a *App) DBQuery(config connection.ConnectionConfig, dbName string, query string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
lowerQuery := strings.TrimSpace(strings.ToLower(query))
if strings.HasPrefix(lowerQuery, "select") || strings.HasPrefix(lowerQuery, "show") || strings.HasPrefix(lowerQuery, "describe") || strings.HasPrefix(lowerQuery, "explain") {
data, columns, err := dbInst.Query(query)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: data, Fields: columns}
} else {
affected, err := dbInst.Exec(query)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: map[string]int64{"affectedRows": affected}}
}
}
func (a *App) DBGetDatabases(config connection.ConnectionConfig) connection.QueryResult {
dbInst, err := a.getDatabase(config)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
dbs, err := dbInst.GetDatabases()
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
var resData []map[string]string
for _, name := range dbs {
resData = append(resData, map[string]string{"Database": name})
}
return connection.QueryResult{Success: true, Data: resData}
}
func (a *App) DBGetTables(config connection.ConnectionConfig, dbName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
tables, err := dbInst.GetTables(dbName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
var resData []map[string]string
for _, name := range tables {
resData = append(resData, map[string]string{"Table": name})
}
return connection.QueryResult{Success: true, Data: resData}
}
func (a *App) DBShowCreateTable(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
sqlStr, err := dbInst.GetCreateStatement(dbName, tableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: sqlStr}
}
func (a *App) DBGetColumns(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
columns, err := dbInst.GetColumns(dbName, tableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: columns}
}
func (a *App) DBGetIndexes(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
indexes, err := dbInst.GetIndexes(dbName, tableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: indexes}
}
func (a *App) DBGetForeignKeys(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
fks, err := dbInst.GetForeignKeys(dbName, tableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: fks}
}
func (a *App) DBGetTriggers(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
triggers, err := dbInst.GetTriggers(dbName, tableName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: triggers}
}
func (a *App) DBGetAllColumns(config connection.ConnectionConfig, dbName string) connection.QueryResult {
runConfig := config
if dbName != "" {
runConfig.Database = dbName
}
dbInst, err := a.getDatabase(runConfig)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
cols, err := dbInst.GetAllColumns(dbName)
if err != nil {
return connection.QueryResult{Success: false, Message: err.Error()}
}
return connection.QueryResult{Success: true, Data: cols}
}