2021-05-08 18:00:33 +08:00
|
|
|
|
package application
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2023-11-07 21:05:21 +08:00
|
|
|
|
"context"
|
2023-12-05 23:03:51 +08:00
|
|
|
|
"mayfly-go/internal/common/consts"
|
2023-10-27 17:41:45 +08:00
|
|
|
|
"mayfly-go/internal/db/dbm"
|
2024-01-12 13:15:30 +08:00
|
|
|
|
"mayfly-go/internal/db/dbm/dbi"
|
2022-09-09 18:26:08 +08:00
|
|
|
|
"mayfly-go/internal/db/domain/entity"
|
|
|
|
|
|
"mayfly-go/internal/db/domain/repository"
|
2023-12-05 23:03:51 +08:00
|
|
|
|
tagapp "mayfly-go/internal/tag/application"
|
2023-10-26 17:15:49 +08:00
|
|
|
|
"mayfly-go/pkg/base"
|
|
|
|
|
|
"mayfly-go/pkg/errorx"
|
2022-06-02 17:41:11 +08:00
|
|
|
|
"mayfly-go/pkg/model"
|
2023-07-21 17:07:04 +08:00
|
|
|
|
"mayfly-go/pkg/utils/collx"
|
2023-12-05 23:03:51 +08:00
|
|
|
|
"mayfly-go/pkg/utils/stringx"
|
2023-10-27 17:41:45 +08:00
|
|
|
|
"mayfly-go/pkg/utils/structx"
|
2021-07-28 18:03:19 +08:00
|
|
|
|
"strings"
|
2021-05-08 18:00:33 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2021-07-28 18:03:19 +08:00
|
|
|
|
type Db interface {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
base.App[*entity.Db]
|
|
|
|
|
|
|
2022-06-16 15:55:18 +08:00
|
|
|
|
// 分页获取
|
2023-10-26 17:15:49 +08:00
|
|
|
|
GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
2021-05-08 18:00:33 +08:00
|
|
|
|
|
2022-10-26 20:49:29 +08:00
|
|
|
|
Count(condition *entity.DbQuery) int64
|
2021-09-11 14:04:09 +08:00
|
|
|
|
|
2024-01-07 21:46:25 +08:00
|
|
|
|
SaveDb(ctx context.Context, entity *entity.Db, tagIds ...uint64) error
|
2021-05-08 18:00:33 +08:00
|
|
|
|
|
2021-07-28 18:03:19 +08:00
|
|
|
|
// 删除数据库信息
|
2023-11-07 21:05:21 +08:00
|
|
|
|
Delete(ctx context.Context, id uint64) error
|
2021-07-28 18:03:19 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取数据库连接实例
|
2023-10-27 17:41:45 +08:00
|
|
|
|
// @param id 数据库id
|
2023-12-20 17:29:16 +08:00
|
|
|
|
//
|
|
|
|
|
|
// @param dbName 数据库名
|
2024-01-12 13:15:30 +08:00
|
|
|
|
GetDbConn(dbId uint64, dbName string) (*dbi.DbConn, error)
|
2023-12-20 17:29:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 根据数据库实例id获取连接,随机返回该instanceId下已连接的conn,若不存在则是使用该instanceId关联的db进行连接并返回。
|
2024-01-12 13:15:30 +08:00
|
|
|
|
GetDbConnByInstanceId(instanceId uint64) (*dbi.DbConn, error)
|
2021-05-08 18:00:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-05 23:03:51 +08:00
|
|
|
|
func newDbApp(dbRepo repository.Db, dbSqlRepo repository.DbSql, dbInstanceApp Instance, tagApp tagapp.TagTree) Db {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
app := &dbAppImpl{
|
2023-09-05 14:41:12 +08:00
|
|
|
|
dbSqlRepo: dbSqlRepo,
|
|
|
|
|
|
dbInstanceApp: dbInstanceApp,
|
2023-12-05 23:03:51 +08:00
|
|
|
|
tagApp: tagApp,
|
2022-09-09 18:26:08 +08:00
|
|
|
|
}
|
2023-10-26 17:15:49 +08:00
|
|
|
|
app.Repo = dbRepo
|
|
|
|
|
|
return app
|
2022-09-09 18:26:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-28 18:03:19 +08:00
|
|
|
|
type dbAppImpl struct {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
base.AppImpl[*entity.Db, repository.Db]
|
|
|
|
|
|
|
2023-09-05 14:41:12 +08:00
|
|
|
|
dbSqlRepo repository.DbSql
|
|
|
|
|
|
dbInstanceApp Instance
|
2023-12-05 23:03:51 +08:00
|
|
|
|
tagApp tagapp.TagTree
|
2021-05-08 18:00:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 分页获取数据库信息列表
|
2023-10-26 17:15:49 +08:00
|
|
|
|
func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
|
|
|
|
|
return d.GetRepo().GetDbList(condition, pageParam, toEntity, orderBy...)
|
2021-05-08 18:00:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-26 20:49:29 +08:00
|
|
|
|
func (d *dbAppImpl) Count(condition *entity.DbQuery) int64 {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
return d.GetRepo().Count(condition)
|
2021-09-11 14:04:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-07 21:46:25 +08:00
|
|
|
|
func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db, tagIds ...uint64) error {
|
2023-09-27 17:19:58 +08:00
|
|
|
|
// 查找是否存在
|
|
|
|
|
|
oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId}
|
2023-10-26 17:15:49 +08:00
|
|
|
|
err := d.GetBy(oldDb)
|
2021-07-28 18:03:19 +08:00
|
|
|
|
|
|
|
|
|
|
if dbEntity.Id == 0 {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err == nil {
|
|
|
|
|
|
return errorx.NewBiz("该实例下数据库名已存在")
|
|
|
|
|
|
}
|
2023-12-05 23:03:51 +08:00
|
|
|
|
|
|
|
|
|
|
resouceCode := stringx.Rand(16)
|
|
|
|
|
|
dbEntity.Code = resouceCode
|
|
|
|
|
|
|
|
|
|
|
|
return d.Tx(ctx, func(ctx context.Context) error {
|
|
|
|
|
|
return d.Insert(ctx, dbEntity)
|
|
|
|
|
|
}, func(ctx context.Context) error {
|
|
|
|
|
|
return d.tagApp.RelateResource(ctx, resouceCode, consts.TagResourceTypeDb, tagIds)
|
|
|
|
|
|
})
|
2022-05-08 14:10:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果存在该库,则校验修改的库是否为该库
|
2023-10-26 17:15:49 +08:00
|
|
|
|
if err == nil && oldDb.Id != dbEntity.Id {
|
|
|
|
|
|
return errorx.NewBiz("该实例下数据库名已存在")
|
2022-05-08 14:10:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dbId := dbEntity.Id
|
2023-10-26 17:15:49 +08:00
|
|
|
|
old, err := d.GetById(new(entity.Db), dbId)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errorx.NewBiz("该数据库不存在")
|
|
|
|
|
|
}
|
2022-05-08 14:10:57 +08:00
|
|
|
|
|
2023-09-27 17:19:58 +08:00
|
|
|
|
oldDbs := strings.Split(old.Database, " ")
|
|
|
|
|
|
newDbs := strings.Split(dbEntity.Database, " ")
|
2022-05-08 14:10:57 +08:00
|
|
|
|
// 比较新旧数据库列表,需要将移除的数据库相关联的信息删除
|
2024-01-13 13:38:53 +08:00
|
|
|
|
_, delDb, _ := collx.ArrayCompare(newDbs, oldDbs)
|
2023-09-27 17:19:58 +08:00
|
|
|
|
|
2022-05-08 14:10:57 +08:00
|
|
|
|
for _, v := range delDb {
|
2023-09-27 17:19:58 +08:00
|
|
|
|
// 关闭数据库连接
|
2023-10-27 17:41:45 +08:00
|
|
|
|
dbm.CloseDb(dbEntity.Id, v)
|
2022-05-08 14:10:57 +08:00
|
|
|
|
// 删除该库关联的所有sql记录
|
2023-11-07 21:05:21 +08:00
|
|
|
|
d.dbSqlRepo.DeleteByCond(ctx, &entity.DbSql{DbId: dbId, Db: v})
|
2021-07-28 18:03:19 +08:00
|
|
|
|
}
|
2022-05-08 14:10:57 +08:00
|
|
|
|
|
2023-12-05 23:03:51 +08:00
|
|
|
|
return d.Tx(ctx, func(ctx context.Context) error {
|
|
|
|
|
|
return d.UpdateById(ctx, dbEntity)
|
|
|
|
|
|
}, func(ctx context.Context) error {
|
2024-01-17 12:13:18 +08:00
|
|
|
|
return d.tagApp.RelateResource(ctx, old.Code, consts.TagResourceTypeDb, tagIds)
|
2023-12-05 23:03:51 +08:00
|
|
|
|
})
|
2021-07-28 18:03:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-07 21:05:21 +08:00
|
|
|
|
func (d *dbAppImpl) Delete(ctx context.Context, id uint64) error {
|
2023-10-26 17:15:49 +08:00
|
|
|
|
db, err := d.GetById(new(entity.Db), id)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errorx.NewBiz("该数据库不存在")
|
|
|
|
|
|
}
|
2022-05-08 14:10:57 +08:00
|
|
|
|
dbs := strings.Split(db.Database, " ")
|
|
|
|
|
|
for _, v := range dbs {
|
|
|
|
|
|
// 关闭连接
|
2023-10-27 17:41:45 +08:00
|
|
|
|
dbm.CloseDb(id, v)
|
2022-05-08 14:10:57 +08:00
|
|
|
|
}
|
2023-12-13 14:01:13 +08:00
|
|
|
|
|
|
|
|
|
|
return d.Tx(ctx,
|
|
|
|
|
|
func(ctx context.Context) error {
|
|
|
|
|
|
return d.DeleteById(ctx, id)
|
|
|
|
|
|
},
|
|
|
|
|
|
func(ctx context.Context) error {
|
|
|
|
|
|
// 删除该库下用户保存的所有sql信息
|
|
|
|
|
|
return d.dbSqlRepo.DeleteByCond(ctx, &entity.DbSql{DbId: id})
|
|
|
|
|
|
}, func(ctx context.Context) error {
|
|
|
|
|
|
var tagIds []uint64
|
|
|
|
|
|
return d.tagApp.RelateResource(ctx, db.Code, consts.TagResourceTypeDb, tagIds)
|
|
|
|
|
|
})
|
2021-07-28 18:03:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-12 13:15:30 +08:00
|
|
|
|
func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbi.DbConn, error) {
|
|
|
|
|
|
return dbm.GetDbConn(dbId, dbName, func() (*dbi.DbInfo, error) {
|
2023-10-27 17:41:45 +08:00
|
|
|
|
db, err := d.GetById(new(entity.Db), dbId)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, errorx.NewBiz("数据库信息不存在")
|
2021-07-28 18:03:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-27 17:41:45 +08:00
|
|
|
|
instance, err := d.dbInstanceApp.GetById(new(entity.DbInstance), db.InstanceId)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, errorx.NewBiz("数据库实例不存在")
|
2022-07-23 16:41:04 +08:00
|
|
|
|
}
|
2023-11-12 20:14:44 +08:00
|
|
|
|
|
|
|
|
|
|
checkDb := dbName
|
2023-12-06 14:50:02 +08:00
|
|
|
|
// 兼容pgsql/dm db/schema模式
|
2024-01-15 11:55:59 +00:00
|
|
|
|
if dbi.DbTypePostgres.Equal(instance.Type) || dbi.DbTypeDM.Equal(instance.Type) || dbi.DbTypeOracle.Equal(instance.Type) {
|
2023-11-12 20:14:44 +08:00
|
|
|
|
ss := strings.Split(dbName, "/")
|
|
|
|
|
|
if len(ss) > 1 {
|
|
|
|
|
|
checkDb = ss[0]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if !strings.Contains(" "+db.Database+" ", " "+checkDb+" ") {
|
|
|
|
|
|
return nil, errorx.NewBiz("未配置数据库【%s】的操作权限", dbName)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-27 17:41:45 +08:00
|
|
|
|
// 密码解密
|
2024-01-05 08:55:34 +08:00
|
|
|
|
if err := instance.PwdDecrypt(); err != nil {
|
|
|
|
|
|
return nil, errorx.NewBiz(err.Error())
|
|
|
|
|
|
}
|
2023-12-05 23:03:51 +08:00
|
|
|
|
return toDbInfo(instance, dbId, dbName, d.tagApp.ListTagPathByResource(consts.TagResourceTypeDb, db.Code)...), nil
|
2022-07-23 16:41:04 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-12 13:15:30 +08:00
|
|
|
|
func (d *dbAppImpl) GetDbConnByInstanceId(instanceId uint64) (*dbi.DbConn, error) {
|
2023-12-20 17:29:16 +08:00
|
|
|
|
conn := dbm.GetDbConnByInstanceId(instanceId)
|
|
|
|
|
|
if conn != nil {
|
|
|
|
|
|
return conn, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var dbs []*entity.Db
|
2024-01-05 17:23:29 +08:00
|
|
|
|
if err := d.ListByCond(&entity.Db{InstanceId: instanceId}, &dbs, "id", "database"); err != nil {
|
2024-01-05 22:16:38 +08:00
|
|
|
|
return nil, errorx.NewBiz("获取数据库列表失败")
|
2024-01-05 17:23:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
if len(dbs) == 0 {
|
2023-12-20 17:29:16 +08:00
|
|
|
|
return nil, errorx.NewBiz("该实例未配置数据库, 请先进行配置")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用该实例关联的已配置数据库中的第一个库进行连接并返回
|
|
|
|
|
|
firstDb := dbs[0]
|
|
|
|
|
|
return d.GetDbConn(firstDb.Id, strings.Split(firstDb.Database, " ")[0])
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-12 13:15:30 +08:00
|
|
|
|
func toDbInfo(instance *entity.DbInstance, dbId uint64, database string, tagPath ...string) *dbi.DbInfo {
|
|
|
|
|
|
di := new(dbi.DbInfo)
|
2023-12-20 17:29:16 +08:00
|
|
|
|
di.InstanceId = instance.Id
|
2024-01-15 11:55:59 +00:00
|
|
|
|
di.Sid = instance.Sid
|
2023-10-27 17:41:45 +08:00
|
|
|
|
di.Id = dbId
|
|
|
|
|
|
di.Database = database
|
|
|
|
|
|
di.TagPath = tagPath
|
2022-10-16 11:01:45 +08:00
|
|
|
|
|
2023-10-27 17:41:45 +08:00
|
|
|
|
structx.Copy(di, instance)
|
|
|
|
|
|
return di
|
2022-10-16 11:01:45 +08:00
|
|
|
|
}
|