2024-01-12 13:15:30 +08:00
|
|
|
|
package dbi
|
2023-10-27 17:41:45 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
2024-01-05 22:16:38 +08:00
|
|
|
|
machineapp "mayfly-go/internal/machine/application"
|
2024-01-13 13:38:53 +08:00
|
|
|
|
"mayfly-go/internal/machine/mcm"
|
2023-10-27 17:41:45 +08:00
|
|
|
|
"mayfly-go/pkg/errorx"
|
|
|
|
|
|
"mayfly-go/pkg/logx"
|
2024-03-11 20:04:20 +08:00
|
|
|
|
"strings"
|
2023-10-27 17:41:45 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2024-03-15 13:31:53 +08:00
|
|
|
|
type DbType string
|
|
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
|
DbTypeMysql DbType = "mysql"
|
|
|
|
|
|
DbTypeMariadb DbType = "mariadb"
|
|
|
|
|
|
DbTypePostgres DbType = "postgres"
|
|
|
|
|
|
DbTypeGauss DbType = "gauss"
|
|
|
|
|
|
DbTypeDM DbType = "dm"
|
|
|
|
|
|
DbTypeOracle DbType = "oracle"
|
|
|
|
|
|
DbTypeSqlite DbType = "sqlite"
|
|
|
|
|
|
DbTypeMssql DbType = "mssql"
|
|
|
|
|
|
DbTypeKingbaseEs DbType = "kingbaseEs"
|
|
|
|
|
|
DbTypeVastbase DbType = "vastbase"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func ToDbType(dbType string) DbType {
|
|
|
|
|
|
return DbType(dbType)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (dbType DbType) Equal(typ string) bool {
|
|
|
|
|
|
return ToDbType(typ) == dbType
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-27 17:41:45 +08:00
|
|
|
|
type DbInfo struct {
|
2023-12-20 17:29:16 +08:00
|
|
|
|
InstanceId uint64 // 实例id
|
|
|
|
|
|
Id uint64 // dbId
|
|
|
|
|
|
Name string
|
2023-10-27 17:41:45 +08:00
|
|
|
|
|
|
|
|
|
|
Type DbType // 类型,mysql postgres等
|
|
|
|
|
|
Host string
|
|
|
|
|
|
Port int
|
2024-03-15 13:31:53 +08:00
|
|
|
|
Extra string // 连接需要的其他额外参数(json字符串),如oracle数据库需要指定sid等
|
2023-10-27 17:41:45 +08:00
|
|
|
|
Network string
|
|
|
|
|
|
Username string
|
|
|
|
|
|
Password string
|
|
|
|
|
|
Params string
|
2024-03-15 13:31:53 +08:00
|
|
|
|
Database string // 若有schema的库则为'database/scheam'格式
|
2023-10-27 17:41:45 +08:00
|
|
|
|
|
2024-10-20 03:52:23 +00:00
|
|
|
|
Version DbVersion // 数据库版本信息,用于语法兼容
|
|
|
|
|
|
DefaultVersion bool // 经过查询数据库版本信息后,是否仍然使用默认版本
|
|
|
|
|
|
|
2024-05-08 21:04:25 +08:00
|
|
|
|
CodePath []string
|
2023-10-27 17:41:45 +08:00
|
|
|
|
SshTunnelMachineId int
|
2024-01-12 13:15:30 +08:00
|
|
|
|
|
|
|
|
|
|
Meta Meta
|
2023-10-27 17:41:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取记录日志的描述
|
|
|
|
|
|
func (d *DbInfo) GetLogDesc() string {
|
2024-05-08 21:04:25 +08:00
|
|
|
|
return fmt.Sprintf("DB[id=%d, tag=%s, name=%s, ip=%s:%d, database=%s]", d.Id, d.CodePath, d.Name, d.Host, d.Port, d.Database)
|
2023-10-27 17:41:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 连接数据库
|
2024-01-12 13:15:30 +08:00
|
|
|
|
func (dbInfo *DbInfo) Conn(meta Meta) (*DbConn, error) {
|
|
|
|
|
|
if meta == nil {
|
|
|
|
|
|
return nil, errorx.NewBiz("数据库元信息接口不能为空")
|
2023-10-27 17:41:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-12 13:15:30 +08:00
|
|
|
|
// 赋值Meta,方便后续获取dialect等
|
|
|
|
|
|
dbInfo.Meta = meta
|
|
|
|
|
|
database := dbInfo.Database
|
2024-03-15 13:31:53 +08:00
|
|
|
|
// 如果数据库为空,则使用默认数据库进行连接
|
|
|
|
|
|
if database == "" {
|
2024-11-01 17:27:22 +08:00
|
|
|
|
database = meta.GetMetadata(&DbConn{Info: dbInfo}).GetDefaultDb()
|
2024-03-15 13:31:53 +08:00
|
|
|
|
dbInfo.Database = database
|
|
|
|
|
|
}
|
2024-01-12 13:15:30 +08:00
|
|
|
|
|
|
|
|
|
|
conn, err := meta.GetSqlDb(dbInfo)
|
2023-10-27 17:41:45 +08:00
|
|
|
|
if err != nil {
|
2023-11-27 17:40:47 +08:00
|
|
|
|
logx.Errorf("连接db失败: %s:%d/%s, err:%s", dbInfo.Host, dbInfo.Port, database, err.Error())
|
2023-10-27 17:41:45 +08:00
|
|
|
|
return nil, errorx.NewBiz(fmt.Sprintf("数据库连接失败: %s", err.Error()))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = conn.Ping()
|
|
|
|
|
|
if err != nil {
|
2023-11-27 17:40:47 +08:00
|
|
|
|
logx.Errorf("db ping失败: %s:%d/%s, err:%s", dbInfo.Host, dbInfo.Port, database, err.Error())
|
2023-10-27 17:41:45 +08:00
|
|
|
|
return nil, errorx.NewBiz(fmt.Sprintf("数据库连接失败: %s", err.Error()))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dbc := &DbConn{Id: GetDbConnId(dbInfo.Id, database), Info: dbInfo}
|
|
|
|
|
|
|
|
|
|
|
|
// 最大连接周期,超过时间的连接就close
|
|
|
|
|
|
// conn.SetConnMaxLifetime(100 * time.Second)
|
|
|
|
|
|
// 设置最大连接数
|
|
|
|
|
|
conn.SetMaxOpenConns(5)
|
|
|
|
|
|
// 设置闲置连接数
|
|
|
|
|
|
conn.SetMaxIdleConns(1)
|
|
|
|
|
|
dbc.db = conn
|
|
|
|
|
|
logx.Infof("连接db: %s:%d/%s", dbInfo.Host, dbInfo.Port, database)
|
|
|
|
|
|
|
|
|
|
|
|
return dbc, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-05 22:16:38 +08:00
|
|
|
|
// 如果使用了ssh隧道,将其host port改变其本地映射host port
|
|
|
|
|
|
func (di *DbInfo) IfUseSshTunnelChangeIpPort() error {
|
|
|
|
|
|
// 开启ssh隧道
|
|
|
|
|
|
if di.SshTunnelMachineId > 0 {
|
2024-01-13 13:38:53 +08:00
|
|
|
|
sshTunnelMachine, err := GetSshTunnel(di.SshTunnelMachineId)
|
2024-01-05 22:16:38 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
exposedIp, exposedPort, err := sshTunnelMachine.OpenSshTunnel(fmt.Sprintf("db:%d", di.Id), di.Host, di.Port)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
di.Host = exposedIp
|
|
|
|
|
|
di.Port = exposedPort
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-15 13:31:53 +08:00
|
|
|
|
// 获取当前库的schema(兼容 database/schema模式)
|
2024-03-11 20:04:20 +08:00
|
|
|
|
func (di *DbInfo) CurrentSchema() string {
|
|
|
|
|
|
dbName := di.Database
|
|
|
|
|
|
schema := ""
|
|
|
|
|
|
arr := strings.Split(dbName, "/")
|
|
|
|
|
|
if len(arr) == 2 {
|
|
|
|
|
|
schema = arr[1]
|
|
|
|
|
|
}
|
|
|
|
|
|
return schema
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-15 13:31:53 +08:00
|
|
|
|
// 获取当前数据库(兼容 database/schema模式)
|
|
|
|
|
|
func (di *DbInfo) GetDatabase() string {
|
|
|
|
|
|
dbName := di.Database
|
|
|
|
|
|
ss := strings.Split(dbName, "/")
|
|
|
|
|
|
if len(ss) > 1 {
|
|
|
|
|
|
return ss[0]
|
|
|
|
|
|
}
|
|
|
|
|
|
return dbName
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-13 13:38:53 +08:00
|
|
|
|
// 根据ssh tunnel机器id返回ssh tunnel
|
|
|
|
|
|
func GetSshTunnel(sshTunnelMachineId int) (*mcm.SshTunnelMachine, error) {
|
|
|
|
|
|
return machineapp.GetMachineApp().GetSshTunnelMachine(sshTunnelMachineId)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-27 17:41:45 +08:00
|
|
|
|
// 获取连接id
|
|
|
|
|
|
func GetDbConnId(dbId uint64, db string) string {
|
|
|
|
|
|
if dbId == 0 {
|
|
|
|
|
|
return ""
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return fmt.Sprintf("%d:%s", dbId, db)
|
|
|
|
|
|
}
|