feat: 调整单个数据库资源可配置多个数据库

This commit is contained in:
meilin.huang
2022-05-08 14:10:57 +08:00
parent 483f5b7604
commit 9db3db31be
26 changed files with 329 additions and 143 deletions

View File

@@ -31,7 +31,6 @@ func (d *Db) Dbs(rc *ctx.ReqCtx) {
g := rc.GinCtx
m := &entity.Db{EnvId: uint64(ginx.QueryInt(g, "envId", 0)),
ProjectId: uint64(ginx.QueryInt(g, "projectId", 0)),
Database: g.Query("database"),
}
m.CreatorId = rc.LoginAccount.Id
rc.ResData = d.DbApp.GetPageList(m, ginx.GetPageParam(rc.GinCtx), new([]vo.SelectDataDbVO))
@@ -54,37 +53,38 @@ func (d *Db) DeleteDb(rc *ctx.ReqCtx) {
}
func (d *Db) TableInfos(rc *ctx.ReqCtx) {
rc.ResData = d.DbApp.GetDbInstance(GetDbId(rc.GinCtx)).GetTableInfos()
rc.ResData = d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx)).GetTableInfos()
}
func (d *Db) TableIndex(rc *ctx.ReqCtx) {
tn := rc.GinCtx.Query("tableName")
biz.NotEmpty(tn, "tableName不能为空")
rc.ResData = d.DbApp.GetDbInstance(GetDbId(rc.GinCtx)).GetTableIndex(tn)
rc.ResData = d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx)).GetTableIndex(tn)
}
func (d *Db) GetCreateTableDdl(rc *ctx.ReqCtx) {
tn := rc.GinCtx.Query("tableName")
biz.NotEmpty(tn, "tableName不能为空")
rc.ResData = d.DbApp.GetDbInstance(GetDbId(rc.GinCtx)).GetCreateTableDdl(tn)
rc.ResData = d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx)).GetCreateTableDdl(tn)
}
// @router /api/db/:dbId/exec-sql [get]
func (d *Db) ExecSql(rc *ctx.ReqCtx) {
g := rc.GinCtx
dbInstance := d.DbApp.GetDbInstance(GetDbId(g))
biz.IsTrue(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbInstance.ProjectId), "您无权操作该资源")
id, db := GetIdAndDb(g)
dbInstance := d.DbApp.GetDbInstance(id, db)
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbInstance.ProjectId), "%s")
// 去除前后空格及换行符
sql := strings.TrimFunc(g.Query("sql"), func(r rune) bool {
s := string(r)
return s == " " || s == "\n"
})
rc.ReqParam = sql
rc.ReqParam = fmt.Sprintf("db: %d:%s | sql: %s", id, db, sql)
biz.NotEmpty(sql, "sql不能为空")
if strings.HasPrefix(sql, "SELECT") || strings.HasPrefix(sql, "select") {
if strings.HasPrefix(sql, "SELECT") || strings.HasPrefix(sql, "select") || strings.HasPrefix(sql, "show") {
colNames, res, err := dbInstance.SelectData(sql)
biz.ErrIsNilAppendErr(err, "查询失败: %s")
colAndRes := make(map[string]interface{})
@@ -119,10 +119,10 @@ func (d *Db) ExecSqlFile(rc *ctx.ReqCtx) {
bytes, _ := ioutil.ReadAll(file)
sqlContent := string(bytes)
sqls := strings.Split(sqlContent, ";")
dbId := GetDbId(g)
dbId, db := GetIdAndDb(g)
go func() {
db := d.DbApp.GetDbInstance(dbId)
db := d.DbApp.GetDbInstance(dbId, db)
dbEntity := d.DbApp.GetById(dbId)
dbInfo := fmt.Sprintf("于%s的%s环境", dbEntity.Name, dbEntity.Env)
@@ -136,7 +136,7 @@ func (d *Db) ExecSqlFile(rc *ctx.ReqCtx) {
}
}()
biz.IsTrue(d.ProjectApp.CanAccess(rc.LoginAccount.Id, db.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, db.ProjectId), "%s")
for _, sql := range sqls {
sql = strings.Trim(sql, " ")
@@ -155,8 +155,8 @@ func (d *Db) ExecSqlFile(rc *ctx.ReqCtx) {
// @router /api/db/:dbId/t-metadata [get]
func (d *Db) TableMA(rc *ctx.ReqCtx) {
dbi := d.DbApp.GetDbInstance(GetDbId(rc.GinCtx))
biz.IsTrue(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "您无权操作该资源")
dbi := d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx))
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "%s")
rc.ResData = dbi.GetTableMetedatas()
}
@@ -166,15 +166,15 @@ func (d *Db) ColumnMA(rc *ctx.ReqCtx) {
tn := g.Query("tableName")
biz.NotEmpty(tn, "tableName不能为空")
dbi := d.DbApp.GetDbInstance(GetDbId(rc.GinCtx))
biz.IsTrue(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "您无权操作该资源")
dbi := d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx))
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "%s")
rc.ResData = dbi.GetColumnMetadatas(tn)
}
// @router /api/db/:dbId/hint-tables [get]
func (d *Db) HintTables(rc *ctx.ReqCtx) {
dbi := d.DbApp.GetDbInstance(GetDbId(rc.GinCtx))
biz.IsTrue(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "您无权操作该资源")
dbi := d.DbApp.GetDbInstance(GetIdAndDb(rc.GinCtx))
biz.ErrIsNilAppendErr(d.ProjectApp.CanAccess(rc.LoginAccount.Id, dbi.ProjectId), "%s")
// 获取所有表
tables := dbi.GetTableMetedatas()
@@ -225,7 +225,7 @@ func (d *Db) SaveSql(rc *ctx.ReqCtx) {
biz.ErrIsNil(err, "该数据库信息不存在")
// 获取用于是否有该dbsql的保存记录有则更改否则新增
dbSql := &entity.DbSql{Type: dbSqlForm.Type, DbId: dbId, Name: dbSqlForm.Name}
dbSql := &entity.DbSql{Type: dbSqlForm.Type, DbId: dbId, Name: dbSqlForm.Name, Db: dbSqlForm.Db}
dbSql.CreatorId = account.Id
e := model.GetBy(dbSql)
@@ -241,8 +241,9 @@ func (d *Db) SaveSql(rc *ctx.ReqCtx) {
// 获取所有保存的sql names
func (d *Db) GetSqlNames(rc *ctx.ReqCtx) {
id, db := GetIdAndDb(rc.GinCtx)
// 获取用于是否有该dbsql的保存记录有则更改否则新增
dbSql := &entity.DbSql{Type: 1, DbId: GetDbId(rc.GinCtx)}
dbSql := &entity.DbSql{Type: 1, DbId: id, Db: db}
dbSql.CreatorId = rc.LoginAccount.Id
var sqls []entity.DbSql
model.ListBy(dbSql, &sqls, "id", "name")
@@ -262,8 +263,9 @@ func (d *Db) DeleteSql(rc *ctx.ReqCtx) {
// @router /api/db/:dbId/sql [get]
func (d *Db) GetSql(rc *ctx.ReqCtx) {
id, db := GetIdAndDb(rc.GinCtx)
// 根据创建者id 数据库id以及sql模板名称查询保存的sql信息
dbSql := &entity.DbSql{Type: 1, DbId: GetDbId(rc.GinCtx)}
dbSql := &entity.DbSql{Type: 1, DbId: id, Db: db}
dbSql.CreatorId = rc.LoginAccount.Id
dbSql.Name = rc.GinCtx.Query("name")
@@ -279,3 +281,9 @@ func GetDbId(g *gin.Context) uint64 {
biz.IsTrue(dbId > 0, "dbId错误")
return uint64(dbId)
}
func GetIdAndDb(g *gin.Context) (uint64, string) {
db := g.Query("db")
biz.NotEmpty(db, "db不能为空")
return GetDbId(g), db
}

View File

@@ -7,7 +7,7 @@ type DbForm struct {
Host string `binding:"required" json:"host"`
Port int `binding:"required" json:"port"`
Username string `binding:"required" json:"username"`
Password string `binding:"required" json:"password"`
Password string `json:"password"`
Database string `binding:"required" json:"database"`
ProjectId uint64 `binding:"required" json:"projectId"`
Project string `json:"project"`

View File

@@ -41,6 +41,7 @@ type DbSqlSaveForm struct {
Name string
Sql string `binding:"required"`
Type int `binding:"required"`
Db string `binding:"required"`
}
type MachineFileUpdateForm struct {

View File

@@ -104,7 +104,7 @@ func (m *Machine) GetProcess(rc *ctx.ReqCtx) {
cmd += "| head -n " + count
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.IsTrue(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
res, err := cli.Run(cmd)
biz.ErrIsNilAppendErr(err, "获取进程信息失败: %s")
@@ -117,7 +117,7 @@ func (m *Machine) KillProcess(rc *ctx.ReqCtx) {
biz.NotEmpty(pid, "进程id不能为空")
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.IsTrue(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
_, err := cli.Run("kill -9 " + pid)
biz.ErrIsNilAppendErr(err, "终止进程失败: %s")
@@ -145,7 +145,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
rows := ginx.QueryInt(g, "rows", 40)
cli := m.MachineApp.GetCli(GetMachineId(g))
biz.IsTrue(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
sws, err := machine.NewLogicSshWsSession(cols, rows, cli, wsConn)
biz.ErrIsNilAppendErr(err, "连接失败:%s")

View File

@@ -64,7 +64,7 @@ func (m *MachineScript) RunMachineScript(rc *ctx.ReqCtx) {
script = utils.TemplateParse(ms.Script, utils.Json2Map(params))
}
cli := m.MachineApp.GetCli(machineId)
biz.IsTrue(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(m.ProjectApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().ProjectId), "%s")
res, err := cli.Run(script)
// 记录请求参数

View File

@@ -86,7 +86,7 @@ func (r *Redis) Scan(rc *ctx.ReqCtx) {
g := rc.GinCtx
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
biz.IsTrue(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
keys, cursor := ri.Scan(uint64(ginx.PathParamInt(g, "cursor")), g.Query("match"), int64(ginx.PathParamInt(g, "count")))
@@ -126,7 +126,7 @@ func (r *Redis) DeleteKey(rc *ctx.ReqCtx) {
biz.NotEmpty(key, "key不能为空")
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
biz.IsTrue(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
rc.ReqParam = key
ri.Cli.Del(key)
@@ -138,7 +138,7 @@ func (r *Redis) checkKey(rc *ctx.ReqCtx) (*application.RedisInstance, string) {
biz.NotEmpty(key, "key不能为空")
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
biz.IsTrue(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
return ri, key
}
@@ -163,7 +163,7 @@ func (r *Redis) SetStringValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, keyValue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
biz.IsTrue(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
str, err := ri.Cli.Set(keyValue.Key, keyValue.Value, time.Second*time.Duration(keyValue.Timed)).Result()
biz.ErrIsNilAppendErr(err, "保存字符串值失败: %s")
@@ -176,7 +176,7 @@ func (r *Redis) SetHashValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, hashValue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
biz.IsTrue(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
key := hashValue.Key
// 简单处理->先删除,后新增
@@ -203,7 +203,7 @@ func (r *Redis) SetSetValue(rc *ctx.ReqCtx) {
ginx.BindJsonAndValid(g, keyvalue)
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
biz.IsTrue(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "您无权操作该资源")
biz.ErrIsNilAppendErr(r.ProjectApp.CanAccess(rc.LoginAccount.Id, ri.ProjectId), "%s")
key := keyvalue.Key
// 简单处理->先删除,后新增

View File

@@ -8,6 +8,7 @@ import (
"mayfly-go/base/cache"
"mayfly-go/base/global"
"mayfly-go/base/model"
"mayfly-go/base/utils"
"mayfly-go/server/devops/domain/entity"
"mayfly-go/server/devops/domain/repository"
"mayfly-go/server/devops/infrastructure/persistence"
@@ -35,7 +36,9 @@ type Db interface {
Delete(id uint64)
// 获取数据库连接实例
GetDbInstance(id uint64) *DbInstance
// @param id 数据库实例id
// @param db 数据库
GetDbInstance(id uint64, db string) *DbInstance
}
type dbAppImpl struct {
@@ -71,29 +74,60 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) {
// 默认tcp连接
dbEntity.Network = "tcp"
// 测试连接
TestConnection(dbEntity)
if dbEntity.Password != "" {
TestConnection(*dbEntity)
}
// 查找是否存在该库
oldDb := &entity.Db{Host: dbEntity.Host, Port: dbEntity.Port, Database: dbEntity.Database}
oldDb := &entity.Db{Host: dbEntity.Host, Port: dbEntity.Port, EnvId: dbEntity.EnvId}
err := d.GetDbBy(oldDb)
if dbEntity.Id == 0 {
biz.IsTrue(err != nil, "该库已存在")
biz.NotEmpty(dbEntity.Password, "密码不能为空")
biz.IsTrue(err != nil, "该数据库实例已存在")
d.dbRepo.Insert(dbEntity)
} else {
// 如果存在该库,则校验修改的库是否为该库
if err == nil {
biz.IsTrue(oldDb.Id == dbEntity.Id, "该库已存在")
}
// 先关闭数据库连接
CloseDb(dbEntity.Id)
d.dbRepo.Update(dbEntity)
return
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil {
biz.IsTrue(oldDb.Id == dbEntity.Id, "该数据库实例已存在")
}
dbId := dbEntity.Id
old := d.GetById(dbId)
var oldDbs []interface{}
for _, v := range strings.Split(old.Database, " ") {
oldDbs = append(oldDbs, v)
}
var newDbs []interface{}
for _, v := range strings.Split(dbEntity.Database, " ") {
newDbs = append(newDbs, v)
}
// 比较新旧数据库列表,需要将移除的数据库相关联的信息删除
_, delDb, _ := utils.ArrayCompare(newDbs, oldDbs, func(i1, i2 interface{}) bool {
return i1.(string) == i2.(string)
})
for _, v := range delDb {
// 先关闭数据库连接
CloseDb(dbEntity.Id, v.(string))
// 删除该库关联的所有sql记录
d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: dbId, Db: v.(string)})
}
d.dbRepo.Update(dbEntity)
}
func (d *dbAppImpl) Delete(id uint64) {
// 关闭连接
CloseDb(id)
db := d.GetById(id)
dbs := strings.Split(db.Database, " ")
for _, v := range dbs {
// 关闭连接
CloseDb(id, v)
}
d.dbRepo.Delete(id)
// 删除该库下用户保存的所有sql信息
d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: id})
@@ -101,13 +135,13 @@ func (d *dbAppImpl) Delete(id uint64) {
var mutex sync.Mutex
func (da *dbAppImpl) GetDbInstance(id uint64) *DbInstance {
func (da *dbAppImpl) GetDbInstance(id uint64, db string) *DbInstance {
mutex.Lock()
defer mutex.Unlock()
// Id不为0则为需要缓存
needCache := id != 0
if needCache {
load, ok := dbCache.Get(id)
load, ok := dbCache.Get(GetDbCacheKey(id, db))
if ok {
return load.(*DbInstance)
}
@@ -115,8 +149,11 @@ func (da *dbAppImpl) GetDbInstance(id uint64) *DbInstance {
d := da.GetById(id)
biz.NotNil(d, "数据库信息不存在")
global.Log.Infof("连接db: %s:%d/%s", d.Host, d.Port, d.Database)
biz.IsTrue(strings.Contains(d.Database, db), "未配置该库的操作权限")
global.Log.Infof("连接db: %s:%d/%s", d.Host, d.Port, db)
// 将数据库替换为要访问的数据库,原本数据库为空格拼接的所有库
d.Database = db
DB, err := sql.Open(d.Type, getDsn(d))
biz.ErrIsNil(err, fmt.Sprintf("Open %s failed, err:%v\n", d.Type, err))
perr := DB.Ping()
@@ -131,33 +168,39 @@ func (da *dbAppImpl) GetDbInstance(id uint64) *DbInstance {
// 设置闲置连接数
DB.SetMaxIdleConns(1)
dbi := &DbInstance{Id: id, Type: d.Type, ProjectId: d.ProjectId, db: DB}
cacheKey := GetDbCacheKey(id, db)
dbi := &DbInstance{Id: cacheKey, Type: d.Type, ProjectId: d.ProjectId, db: DB}
if needCache {
dbCache.Put(id, dbi)
dbCache.Put(cacheKey, dbi)
}
return dbi
}
//------------------------------------------------------------------------------
// 客户端连接缓存30分钟内没有访问则会被关闭
// 客户端连接缓存30分钟内没有访问则会被关闭, key为数据库实例id:数据库
var dbCache = cache.NewTimedCache(30*time.Minute, 5*time.Second).
WithUpdateAccessTime(true).
OnEvicted(func(key interface{}, value interface{}) {
global.Log.Info(fmt.Sprintf("删除db连接缓存 id: %d", key))
global.Log.Info(fmt.Sprintf("删除db连接缓存 id: %s", key))
value.(*DbInstance).Close()
})
func GetDbInstanceByCache(id uint64) *DbInstance {
if load, ok := dbCache.Get(fmt.Sprint(id)); ok {
func GetDbCacheKey(dbId uint64, db string) string {
return fmt.Sprintf("%d:%s", dbId, db)
}
func GetDbInstanceByCache(id string) *DbInstance {
if load, ok := dbCache.Get(id); ok {
return load.(*DbInstance)
}
return nil
}
func TestConnection(d *entity.Db) {
biz.NotNil(d, "数据库信息不存在")
DB, err := sql.Open(d.Type, getDsn(d))
func TestConnection(d entity.Db) {
// 验证第一个库是否可以连接即可
d.Database = strings.Split(d.Database, " ")[0]
DB, err := sql.Open(d.Type, getDsn(&d))
biz.ErrIsNil(err, "Open %s failed, err:%v\n", d.Type, err)
defer DB.Close()
perr := DB.Ping()
@@ -166,7 +209,7 @@ func TestConnection(d *entity.Db) {
// db实例
type DbInstance struct {
Id uint64
Id string
Type string
ProjectId uint64
db *sql.DB
@@ -264,7 +307,9 @@ func getDsn(d *entity.Db) string {
return ""
}
func CloseDb(id uint64) {
// 关闭该数据库所有连接
func CloseDb(dbId uint64, db string) {
id := GetDbCacheKey(dbId, db)
if di := GetDbInstanceByCache(id); di != nil {
di.Close()
dbCache.Delete(id)

View File

@@ -37,7 +37,7 @@ type Project interface {
DeleteMember(projectId, accountId uint64)
// 账号是否有权限访问该项目关联的资源信息
CanAccess(accountId, projectId uint64) bool
CanAccess(accountId, projectId uint64) error
}
type projectAppImpl struct {
@@ -120,6 +120,9 @@ func (p *projectAppImpl) DeleteMember(projectId, accountId uint64) {
p.projectMemberRepo.DeleteByPidMid(projectId, accountId)
}
func (p *projectAppImpl) CanAccess(accountId, projectId uint64) bool {
return p.projectMemberRepo.IsExist(projectId, accountId)
func (p *projectAppImpl) CanAccess(accountId, projectId uint64) error {
if p.projectMemberRepo.IsExist(projectId, accountId) {
return nil
}
return biz.NewBizErr("您无权操作该资源")
}

View File

@@ -8,6 +8,7 @@ type DbSql struct {
model.Model `orm:"-"`
DbId uint64 `json:"dbId"`
Db string `json:"db"`
Type int `json:"type"` // 类型
Sql string `json:"sql"`
Name string `json:"name"`

View File

@@ -21,13 +21,13 @@ SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `t_db`;
CREATE TABLE `t_db` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '数据库名称',
`name` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '数据库实例名称',
`host` varchar(20) COLLATE utf8mb4_bin NOT NULL,
`port` int(8) NOT NULL,
`username` varchar(255) COLLATE utf8mb4_bin NOT NULL,
`password` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`type` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '数据库类型(mysql...)',
`database` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
`type` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '数据库实例类型(mysql...)',
`database` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '数据库,空格分割多个数据库',
`network` varchar(8) COLLATE utf8mb4_bin DEFAULT NULL,
`project_id` bigint(20) DEFAULT NULL,
`project` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL,
@@ -41,7 +41,7 @@ CREATE TABLE `t_db` (
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='数据库信息表';
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='数据库资源信息表';
-- ----------------------------
-- Records of t_db
@@ -55,7 +55,8 @@ COMMIT;
DROP TABLE IF EXISTS `t_db_sql`;
CREATE TABLE `t_db_sql` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`db_id` bigint(20) NOT NULL COMMENT '数据库id',
`db_id` bigint(20) NOT NULL COMMENT '数据库实例id',
`db` varchar(125) NOT NULL COMMENT '数据库',
`name` varchar(60) COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'sql模板名',
`sql` text COLLATE utf8mb4_bin,
`type` tinyint(8) NOT NULL,