fix: 解决数据冲突导致的升级失败问题 (#2306)

Refs #2290
pull/2311/head
ssongliu 1 year ago committed by GitHub
parent 0e158ffa2b
commit b6055eb058
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -233,11 +233,11 @@ func (b *BaseApi) ListDBName(c *gin.Context) {
// @Summary Load mysql database from remote
// @Description 从服务器获取
// @Accept json
// @Param request body dto.MysqlLoadDB true "request"
// @Param request body dto.OperateByID true "request"
// @Security ApiKeyAuth
// @Router /databases/load [post]
func (b *BaseApi) LoadDBFromRemote(c *gin.Context) {
var req dto.MysqlLoadDB
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
@ -315,12 +315,12 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) {
// @Summary Load mysql base info
// @Description 获取 mysql 基础信息
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Param request body dto.OperateByID true "request"
// @Success 200 {object} dto.DBBaseInfo
// @Security ApiKeyAuth
// @Router /databases/baseinfo [post]
func (b *BaseApi) LoadBaseinfo(c *gin.Context) {
var req dto.OperationWithNameAndType
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
@ -360,12 +360,12 @@ func (b *BaseApi) LoadDatabaseFile(c *gin.Context) {
// @Summary Load mysql remote access
// @Description 获取 mysql 远程访问权限
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Param request body dto.OperateByID true "request"
// @Success 200 {boolean} isRemote
// @Security ApiKeyAuth
// @Router /databases/remote [post]
func (b *BaseApi) LoadRemoteAccess(c *gin.Context) {
var req dto.OperationWithNameAndType
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
@ -383,12 +383,12 @@ func (b *BaseApi) LoadRemoteAccess(c *gin.Context) {
// @Summary Load mysql status info
// @Description 获取 mysql 状态信息
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Param request body dto.OperateByID true "request"
// @Success 200 {object} dto.MysqlStatus
// @Security ApiKeyAuth
// @Router /databases/status [post]
func (b *BaseApi) LoadStatus(c *gin.Context) {
var req dto.OperationWithNameAndType
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
@ -406,12 +406,12 @@ func (b *BaseApi) LoadStatus(c *gin.Context) {
// @Summary Load mysql variables info
// @Description 获取 mysql 性能参数信息
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Param request body dto.OperateByID true "request"
// @Success 200 {object} dto.MysqlVariables
// @Security ApiKeyAuth
// @Router /databases/variables [post]
func (b *BaseApi) LoadVariables(c *gin.Context) {
var req dto.OperationWithNameAndType
var req dto.OperateByID
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return

@ -4,10 +4,10 @@ import "time"
type MysqlDBSearch struct {
PageInfo
Info string `json:"info"`
Database string `json:"database" validate:"required"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
Info string `json:"info"`
DatabaseID uint `json:"databaseID" validate:"required"`
OrderBy string `json:"orderBy"`
Order string `json:"order"`
}
type MysqlDBInfo struct {
@ -15,7 +15,7 @@ type MysqlDBInfo struct {
CreatedAt time.Time `json:"createdAt"`
Name string `json:"name"`
From string `json:"from"`
MysqlName string `json:"mysqlName"`
DatabaseID uint `json:"databaseID"`
Format string `json:"format"`
Username string `json:"username"`
Password string `json:"password"`
@ -25,17 +25,18 @@ type MysqlDBInfo struct {
}
type MysqlOption struct {
ID uint `json:"id"`
From string `json:"from"`
Type string `json:"type"`
Database string `json:"database"`
Name string `json:"name"`
ID uint `json:"id"`
From string `json:"from"`
Type string `json:"type"`
DatabaseID uint `json:"databaseID"`
Database string `json:"database"`
Name string `json:"name"`
}
type MysqlDBCreate struct {
Name string `json:"name" validate:"required"`
From string `json:"from" validate:"required,oneof=local remote"`
Database string `json:"database" validate:"required"`
DatabaseID uint `json:"databaseID" validate:"required"`
Format string `json:"format" validate:"required,oneof=utf8mb4 utf8 gbk big5"`
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
@ -43,22 +44,15 @@ type MysqlDBCreate struct {
Description string `json:"description"`
}
type MysqlLoadDB struct {
From string `json:"from" validate:"required,oneof=local remote"`
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
Database string `json:"database" validate:"required"`
}
type MysqlDBDeleteCheck struct {
ID uint `json:"id" validate:"required"`
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
Database string `json:"database" validate:"required"`
ID uint `json:"id" validate:"required"`
DatabaseID uint `json:"databaseID" validate:"required"`
}
type MysqlDBDelete struct {
ID uint `json:"id" validate:"required"`
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
Database string `json:"database" validate:"required"`
DatabaseID uint `json:"databaseID" validate:"required"`
ForceDelete bool `json:"forceDelete"`
DeleteBackup bool `json:"deleteBackup"`
}
@ -124,9 +118,8 @@ type MysqlVariables struct {
}
type MysqlVariablesUpdate struct {
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
Database string `json:"database" validate:"required"`
Variables []MysqlVariablesUpdateHelper `json:"variables"`
DatabaseID uint `json:"databaseID" validate:"required"`
Variables []MysqlVariablesUpdateHelper `json:"variables"`
}
type MysqlVariablesUpdateHelper struct {
@ -134,17 +127,16 @@ type MysqlVariablesUpdateHelper struct {
Value interface{} `json:"value"`
}
type MysqlConfUpdateByFile struct {
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
Database string `json:"database" validate:"required"`
File string `json:"file"`
DatabaseID uint `json:"databaseID" validate:"required"`
File string `json:"file"`
}
type ChangeDBInfo struct {
ID uint `json:"id"`
From string `json:"from" validate:"required,oneof=local remote"`
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
Database string `json:"database" validate:"required"`
Value string `json:"value" validate:"required"`
ID uint `json:"id"`
From string `json:"from" validate:"required,oneof=local remote"`
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
DatabaseID uint `json:"databaseID" validate:"required"`
Value string `json:"value" validate:"required"`
}
type DBBaseInfo struct {
@ -153,24 +145,6 @@ type DBBaseInfo struct {
Port int64 `json:"port"`
}
type BackupDB struct {
MysqlName string `json:"mysqlName" validate:"required"`
DBName string `json:"dbName" validate:"required"`
}
type RecoverDB struct {
MysqlName string `json:"mysqlName" validate:"required"`
DBName string `json:"dbName" validate:"required"`
BackupName string `json:"backupName" validate:"required"`
}
type UploadRecover struct {
MysqlName string `json:"mysqlName" validate:"required"`
DBName string `json:"dbName" validate:"required"`
FileName string `json:"fileName"`
FileDir string `json:"fileDir"`
}
// redis
type ChangeRedisPass struct {
Value string `json:"value" validate:"required"`

@ -3,7 +3,7 @@ package model
type Database struct {
BaseModel
AppInstallID uint `json:"appInstallID" gorm:"type:decimal"`
Name string `json:"name" gorm:"type:varchar(64);not null;unique"`
Name string `json:"name" gorm:"type:varchar(64);not null"`
Type string `json:"type" gorm:"type:varchar(64);not null"`
Version string `json:"version" gorm:"type:varchar(64);not null"`
From string `json:"from" gorm:"type:varchar(64);not null"`

@ -4,10 +4,12 @@ type DatabaseMysql struct {
BaseModel
Name string `json:"name" gorm:"type:varchar(256);not null"`
From string `json:"from" gorm:"type:varchar(256);not null;default:local"`
MysqlName string `json:"mysqlName" gorm:"type:varchar(64);not null"`
MysqlName string `json:"mysqlName" gorm:"type:varchar(64);not null"` // 已废弃
Format string `json:"format" gorm:"type:varchar(64);not null"`
Username string `json:"username" gorm:"type:varchar(256);not null"`
Password string `json:"password" gorm:"type:varchar(256);not null"`
Permission string `json:"permission" gorm:"type:varchar(256);not null"`
Description string `json:"description" gorm:"type:varchar(256);"`
DatabaseID uint `json:"databaseID" gorm:"type:decimal"`
}

@ -14,7 +14,7 @@ type MysqlRepo struct{}
type IMysqlRepo interface {
Get(opts ...DBOption) (model.DatabaseMysql, error)
WithByMysqlName(mysqlName string) DBOption
WithByDatabase(databaseID uint) DBOption
WithByFrom(from string) DBOption
List(opts ...DBOption) ([]model.DatabaseMysql, error)
Page(limit, offset int, opts ...DBOption) (int64, []model.DatabaseMysql, error)
@ -107,9 +107,9 @@ func (u *MysqlRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.DatabaseMysql{}).Where("id = ?", id).Updates(vars).Error
}
func (u *MysqlRepo) WithByMysqlName(mysqlName string) DBOption {
func (u *MysqlRepo) WithByDatabase(databaseID uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("mysql_name = ?", mysqlName)
return g.Where("database_id = ?", databaseID)
}
}

@ -190,7 +190,7 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
var createMysql dto.MysqlDBCreate
createMysql.Name = dbConfig.DbName
createMysql.Username = dbConfig.DbUser
createMysql.Database = dbInstall.Name
// createMysql.Database = dbInstall.Name
createMysql.Format = "utf8mb4"
createMysql.Permission = "%"
createMysql.Password = dbConfig.Password
@ -253,16 +253,16 @@ func deleteAppInstall(install model.AppInstall, deleteBackup bool, forceDelete b
return err
}
if DatabaseKeys[install.App.Key] > 0 {
_ = databaseRepo.Delete(ctx, databaseRepo.WithAppInstallID(install.ID))
}
// if DatabaseKeys[install.App.Key] > 0 {
// _ = databaseRepo.Delete(ctx, databaseRepo.WithAppInstallID(install.ID))
// }
switch install.App.Key {
case constant.AppOpenresty:
_ = websiteRepo.DeleteAll(ctx)
_ = websiteDomainRepo.DeleteAll(ctx)
case constant.AppMysql, constant.AppMariaDB:
_ = mysqlRepo.Delete(ctx, mysqlRepo.WithByMysqlName(install.Name))
// _ = mysqlRepo.Delete(ctx, mysqlRepo.WithByMysqlName(install.Name))
}
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("app"), commonRepo.WithByName(install.App.Key), backupRepo.WithByDetailName(install.Name))
@ -301,7 +301,7 @@ func deleteLink(ctx context.Context, install *model.AppInstall, deleteDB bool, f
ForceDelete: forceDelete,
DeleteBackup: deleteBackup,
Type: re.Key,
Database: database.MysqlName,
// Database: database.MysqlName,
}); err != nil && !forceDelete {
return err
}

@ -111,7 +111,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro
if err != nil {
return err
}
if err := handleMysqlBackup(db.MysqlName, db.Name, tmpDir, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil {
if err := handleMysqlBackup(db.DatabaseID, db.Name, tmpDir, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil {
return err
}
}
@ -190,7 +190,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
return err
}
newDB, envMap, err := reCreateDB(db.ID, resourceApp, oldInstall.Env)
newDB, envMap, err := reCreateDB(db, resourceApp, oldInstall.Env)
if err != nil {
return err
}
@ -205,7 +205,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
_ = appInstallResourceRepo.BatchUpdateBy(map[string]interface{}{"resource_id": newDB.ID}, commonRepo.WithByID(resource.ID))
if err := handleMysqlRecover(dto.CommonRecover{
Name: newDB.MysqlName,
Name: fmt.Sprintf("%d", newDB.DatabaseID),
DetailName: newDB.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
}, true); err != nil {
@ -252,10 +252,10 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
return nil
}
func reCreateDB(dbID uint, app model.AppInstall, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
func reCreateDB(db model.DatabaseMysql, app model.AppInstall, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
mysqlService := NewIMysqlService()
ctx := context.Background()
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: app.Name, Type: app.App.Key, DeleteBackup: true, ForceDelete: true})
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: db.ID, DatabaseID: db.DatabaseID, Type: app.App.Key, DeleteBackup: true, ForceDelete: true})
envMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil {
@ -267,7 +267,7 @@ func reCreateDB(dbID uint, app model.AppInstall, oldEnv string) (*model.Database
createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{
Name: oldName,
From: "local",
Database: app.Name,
DatabaseID: db.DatabaseID,
Format: "utf8mb4",
Username: oldUser,
Password: oldPassword,

@ -5,6 +5,7 @@ import (
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
@ -23,16 +24,25 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
}
timeNow := time.Now().Format("20060102150405")
targetDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, req.Name, req.DetailName))
databaseID, err := strconv.Atoi(req.Name)
if err != nil {
return err
}
database, err := databaseRepo.Get(commonRepo.WithByID(uint(databaseID)))
if err != nil {
return err
}
dirName := fmt.Sprintf("%s-%s", database.From, database.Name)
targetDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, dirName, req.DetailName))
fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow)
if err := handleMysqlBackup(req.Name, req.DetailName, targetDir, fileName); err != nil {
if err := handleMysqlBackup(uint(databaseID), req.DetailName, targetDir, fileName); err != nil {
return err
}
record := &model.BackupRecord{
Type: req.Type,
Name: req.Name,
Name: dirName,
DetailName: req.DetailName,
Source: "LOCAL",
BackupType: "LOCAL",
@ -97,12 +107,12 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
return nil
}
func handleMysqlBackup(database, dbName, targetDir, fileName string) error {
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName), mysqlRepo.WithByMysqlName(database))
func handleMysqlBackup(databaseID uint, dbName, targetDir, fileName string) error {
cli, _, _, err := LoadMysqlClientByFrom(databaseID)
if err != nil {
return err
}
cli, _, err := LoadMysqlClientByFrom(database)
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName), mysqlRepo.WithByDatabase(databaseID))
if err != nil {
return err
}
@ -127,11 +137,15 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
if !fileOp.Stat(req.File) {
return errors.New(fmt.Sprintf("%s file is not exist", req.File))
}
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(req.DetailName), mysqlRepo.WithByMysqlName(req.Name))
databaseID, err := strconv.Atoi(req.Name)
if err != nil {
return err
}
cli, _, _, err := LoadMysqlClientByFrom(uint(databaseID))
if err != nil {
return err
}
cli, _, err := LoadMysqlClientByFrom(req.Name)
dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(req.DetailName), mysqlRepo.WithByDatabase(uint(databaseID)))
if err != nil {
return err
}

@ -292,16 +292,16 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, backup model.Back
for _, dbInfo := range dbs {
var record model.BackupRecord
database, _ := databaseRepo.Get(commonRepo.WithByName(dbInfo.MysqlName))
database, _ := databaseRepo.Get(commonRepo.WithByID(dbInfo.DatabaseID))
record.Type = database.Type
record.Source = "LOCAL"
record.BackupType = backup.Type
record.Name = dbInfo.MysqlName
backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", database.Type, record.Name, dbInfo.Name))
dirName := fmt.Sprintf("%s-%s", database.From, database.Name)
record.Name = dirName
backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", database.Type, dirName, dbInfo.Name))
record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format("20060102150405"))
if err = handleMysqlBackup(dbInfo.MysqlName, dbInfo.Name, backupDir, record.FileName); err != nil {
if err = handleMysqlBackup(dbInfo.DatabaseID, dbInfo.Name, backupDir, record.FileName); err != nil {
return paths, err
}

@ -5,7 +5,6 @@ import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
"github.com/1Panel-dev/1Panel/backend/utils/mysql"
@ -88,15 +87,12 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
}
func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
db, _ := databaseRepo.Get(commonRepo.WithByName(req.Name))
db, _ := databaseRepo.Get(commonRepo.WithByName(req.Name), commonRepo.WithByType(req.Type), databaseRepo.WithByFrom(req.From))
if db.ID != 0 {
if db.From == "local" {
return buserr.New(constant.ErrLocalExist)
}
return constant.ErrRecordExist
}
if _, err := mysql.NewMysqlClient(client.DBInfo{
From: "remote",
From: req.From,
Address: req.Address,
Port: req.Port,
Username: req.Username,
@ -123,7 +119,7 @@ func (u *DatabaseService) Delete(id uint) error {
return err
}
if db.From != "local" {
if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByMysqlName(db.Name)); err != nil {
if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByDatabase(db.ID)); err != nil {
return err
}
}

@ -35,7 +35,6 @@ type IMysqlService interface {
SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error)
ListDBOption() ([]dto.MysqlOption, error)
Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error)
LoadFromRemote(req dto.MysqlLoadDB) error
ChangeAccess(info dto.ChangeDBInfo) error
ChangePassword(info dto.ChangeDBInfo) error
UpdateVariables(req dto.MysqlVariablesUpdate) error
@ -44,10 +43,11 @@ type IMysqlService interface {
DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error)
Delete(ctx context.Context, req dto.MysqlDBDelete) error
LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error)
LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error)
LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error)
LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error)
LoadFromRemote(req dto.OperateByID) error
LoadStatus(req dto.OperateByID) (*dto.MysqlStatus, error)
LoadVariables(req dto.OperateByID) (*dto.MysqlVariables, error)
LoadBaseInfo(req dto.OperateByID) (*dto.DBBaseInfo, error)
LoadRemoteAccess(req dto.OperateByID) (bool, error)
LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error)
}
@ -58,10 +58,11 @@ func NewIMysqlService() IMysqlService {
func (u *MysqlService) SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error) {
total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize,
mysqlRepo.WithByMysqlName(search.Database),
mysqlRepo.WithByDatabase(search.DatabaseID),
commonRepo.WithLikeName(search.Info),
commonRepo.WithOrderRuleBy(search.OrderBy, search.Order),
)
var dtoMysqls []dto.MysqlDBInfo
for _, mysql := range mysqls {
var item dto.MysqlDBInfo
@ -89,10 +90,10 @@ func (u *MysqlService) ListDBOption() ([]dto.MysqlOption, error) {
if err := copier.Copy(&item, &mysql); err != nil {
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
item.Database = mysql.MysqlName
for _, database := range databases {
if database.Name == item.Database {
if database.ID == item.DatabaseID {
item.Type = database.Type
item.Database = database.Name
}
}
dbs = append(dbs, item)
@ -105,7 +106,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
return nil, buserr.New(constant.ErrCmdIllegal)
}
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name), mysqlRepo.WithByMysqlName(req.Database), databaseRepo.WithByFrom(req.From))
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name), mysqlRepo.WithByDatabase(req.DatabaseID))
if mysql.ID != 0 {
return nil, constant.ErrRecordExist
}
@ -115,15 +116,14 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if req.From == "local" && req.Username == "root" {
if req.Username == "root" {
return nil, errors.New("Cannot set root as user name")
}
cli, version, err := LoadMysqlClientByFrom(req.Database)
cli, version, _, err := LoadMysqlClientByFrom(req.DatabaseID)
if err != nil {
return nil, err
}
createItem.MysqlName = req.Database
defer cli.Close()
if err := cli.Create(client.CreateInfo{
Name: req.Name,
@ -144,13 +144,13 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
return &createItem, nil
}
func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error {
client, version, err := LoadMysqlClientByFrom(req.Database)
func (u *MysqlService) LoadFromRemote(req dto.OperateByID) error {
client, version, _, err := LoadMysqlClientByFrom(req.ID)
if err != nil {
return err
}
databases, err := mysqlRepo.List(databaseRepo.WithByFrom(req.From))
dbs, err := mysqlRepo.List(mysqlRepo.WithByDatabase(req.ID))
if err != nil {
return err
}
@ -160,8 +160,8 @@ func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error {
}
for _, data := range datas {
hasOld := false
for _, oldData := range databases {
if strings.EqualFold(oldData.Name, data.Name) && strings.EqualFold(oldData.MysqlName, data.MysqlName) {
for _, oldData := range dbs {
if strings.EqualFold(oldData.Name, data.Name) {
hasOld = true
break
}
@ -171,6 +171,7 @@ func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error {
if err := copier.Copy(&createItem, &data); err != nil {
return errors.WithMessage(constant.ErrStructTransform, err.Error())
}
createItem.DatabaseID = req.ID
if err := mysqlRepo.Create(context.Background(), &createItem); err != nil {
return err
}
@ -189,9 +190,12 @@ func (u *MysqlService) DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error)
if err != nil {
return appInUsed, err
}
database, err := databaseRepo.Get(commonRepo.WithByID(req.DatabaseID))
if err != nil {
return appInUsed, err
}
if db.From == "local" {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
app, err := appInstallRepo.LoadBaseInfo(database.Type, database.Name)
if err != nil {
return appInUsed, err
}
@ -220,7 +224,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
if err != nil && !req.ForceDelete {
return err
}
cli, version, err := LoadMysqlClientByFrom(req.Database)
cli, version, database, err := LoadMysqlClientByFrom(req.DatabaseID)
if err != nil {
return err
}
@ -235,7 +239,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
return err
}
uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, req.Database, db.Name))
uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, database, db.Name))
if _, err := os.Stat(uploadDir); err == nil {
_ = os.RemoveAll(uploadDir)
}
@ -244,13 +248,17 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
if err != nil && !req.ForceDelete {
return err
}
backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, db.MysqlName, db.Name))
backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s-%s/%s", req.Type, db.From, database, db.Name))
if _, err := os.Stat(backupDir); err == nil {
_ = os.RemoveAll(backupDir)
}
global.LOG.Infof("delete database %s-%s backups successful", req.Database, db.Name)
backupDir2 := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, database, db.Name))
if _, err := os.Stat(backupDir2); err == nil {
_ = os.RemoveAll(backupDir2)
}
global.LOG.Infof("delete database %s-%s backups successful", database, db.Name)
}
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(req.Database), backupRepo.WithByDetailName(db.Name))
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(database), backupRepo.WithByDetailName(db.Name))
_ = mysqlRepo.Delete(ctx, commonRepo.WithByID(db.ID))
return nil
@ -260,7 +268,7 @@ func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error {
if cmd.CheckIllegal(req.Value) {
return buserr.New(constant.ErrCmdIllegal)
}
cli, version, err := LoadMysqlClientByFrom(req.Database)
cli, version, database, err := LoadMysqlClientByFrom(req.DatabaseID)
if err != nil {
return err
}
@ -291,7 +299,7 @@ func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error {
if req.ID != 0 {
var appRess []model.AppInstallResource
if req.From == "local" {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
app, err := appInstallRepo.LoadBaseInfo(req.Type, database)
if err != nil {
return err
}
@ -323,7 +331,7 @@ func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error {
return nil
}
if err := updateInstallInfoInDB(req.Type, req.Database, "password", false, req.Value); err != nil {
if err := updateInstallInfoInDB(req.Type, database, "password", false, req.Value); err != nil {
return err
}
return nil
@ -333,7 +341,7 @@ func (u *MysqlService) ChangeAccess(req dto.ChangeDBInfo) error {
if cmd.CheckIllegal(req.Value) {
return buserr.New(constant.ErrCmdIllegal)
}
cli, version, err := LoadMysqlClientByFrom(req.Database)
cli, version, _, err := LoadMysqlClientByFrom(req.DatabaseID)
if err != nil {
return err
}
@ -370,11 +378,11 @@ func (u *MysqlService) ChangeAccess(req dto.ChangeDBInfo) error {
}
func (u *MysqlService) UpdateConfByFile(req dto.MysqlConfUpdateByFile) error {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
database, err := databaseRepo.Get(commonRepo.WithByID(req.DatabaseID))
if err != nil {
return err
}
path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name)
path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, database.Type, database.Name)
file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
return err
@ -383,20 +391,20 @@ func (u *MysqlService) UpdateConfByFile(req dto.MysqlConfUpdateByFile) error {
write := bufio.NewWriter(file)
_, _ = write.WriteString(req.File)
write.Flush()
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil {
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, database.Type, database.Name)); err != nil {
return err
}
return nil
}
func (u *MysqlService) UpdateVariables(req dto.MysqlVariablesUpdate) error {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
database, err := databaseRepo.Get(commonRepo.WithByID(req.DatabaseID))
if err != nil {
return err
}
var files []string
path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name)
path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, database.Type, database.Name)
lineBytes, err := os.ReadFile(path)
if err != nil {
return err
@ -405,7 +413,7 @@ func (u *MysqlService) UpdateVariables(req dto.MysqlVariablesUpdate) error {
group := "[mysqld]"
for _, info := range req.Variables {
if !strings.HasPrefix(app.Version, "5.7") && !strings.HasPrefix(app.Version, "5.6") {
if !strings.HasPrefix(database.Version, "5.7") && !strings.HasPrefix(database.Version, "5.6") {
if info.Param == "query_cache_size" {
continue
}
@ -427,16 +435,20 @@ func (u *MysqlService) UpdateVariables(req dto.MysqlVariablesUpdate) error {
return err
}
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil {
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, database.Type, database.Name)); err != nil {
return err
}
return nil
}
func (u *MysqlService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) {
func (u *MysqlService) LoadBaseInfo(req dto.OperateByID) (*dto.DBBaseInfo, error) {
database, err := databaseRepo.Get(commonRepo.WithByID(req.ID))
if err != nil {
return nil, err
}
var data dto.DBBaseInfo
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
app, err := appInstallRepo.LoadBaseInfo(database.Type, database.Name)
if err != nil {
return nil, err
}
@ -447,8 +459,12 @@ func (u *MysqlService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBa
return &data, nil
}
func (u *MysqlService) LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error) {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
func (u *MysqlService) LoadRemoteAccess(req dto.OperateByID) (bool, error) {
database, err := databaseRepo.Get(commonRepo.WithByID(req.ID))
if err != nil {
return false, err
}
app, err := appInstallRepo.LoadBaseInfo(database.Type, database.Name)
if err != nil {
return false, err
}
@ -465,8 +481,12 @@ func (u *MysqlService) LoadRemoteAccess(req dto.OperationWithNameAndType) (bool,
return false, nil
}
func (u *MysqlService) LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error) {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
func (u *MysqlService) LoadVariables(req dto.OperateByID) (*dto.MysqlVariables, error) {
database, err := databaseRepo.Get(commonRepo.WithByID(req.ID))
if err != nil {
return nil, err
}
app, err := appInstallRepo.LoadBaseInfo(database.Type, database.Name)
if err != nil {
return nil, err
}
@ -483,8 +503,12 @@ func (u *MysqlService) LoadVariables(req dto.OperationWithNameAndType) (*dto.Mys
return &info, nil
}
func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error) {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
func (u *MysqlService) LoadStatus(req dto.OperateByID) (*dto.MysqlStatus, error) {
database, err := databaseRepo.Get(commonRepo.WithByID(req.ID))
if err != nil {
return nil, err
}
app, err := appInstallRepo.LoadBaseInfo(database.Type, database.Name)
if err != nil {
return nil, err
}
@ -622,7 +646,7 @@ func updateMyCnf(oldFiles []string, group string, param string, value interface{
return newFiles
}
func LoadMysqlClientByFrom(database string) (mysql.MysqlClient, string, error) {
func LoadMysqlClientByFrom(databaseID uint) (mysql.MysqlClient, string, string, error) {
var (
dbInfo client.DBInfo
version string
@ -630,12 +654,12 @@ func LoadMysqlClientByFrom(database string) (mysql.MysqlClient, string, error) {
)
dbInfo.Timeout = 300
databaseItem, err := databaseRepo.Get(commonRepo.WithByName(database))
databaseItem, err := databaseRepo.Get(commonRepo.WithByID(databaseID))
if err != nil {
return nil, "", err
return nil, "", databaseItem.Name, err
}
dbInfo.From = databaseItem.From
dbInfo.Database = database
dbInfo.Database = databaseItem.Name
if dbInfo.From != "local" {
dbInfo.Address = databaseItem.Address
dbInfo.Port = databaseItem.Port
@ -644,9 +668,9 @@ func LoadMysqlClientByFrom(database string) (mysql.MysqlClient, string, error) {
version = databaseItem.Version
} else {
app, err := appInstallRepo.LoadBaseInfo(databaseItem.Type, database)
app, err := appInstallRepo.LoadBaseInfo(databaseItem.Type, databaseItem.Name)
if err != nil {
return nil, "", err
return nil, "", databaseItem.Name, err
}
dbInfo.Address = app.ContainerName
dbInfo.Username = "root"
@ -656,7 +680,7 @@ func LoadMysqlClientByFrom(database string) (mysql.MysqlClient, string, error) {
cli, err := mysql.NewMysqlClient(dbInfo)
if err != nil {
return nil, "", err
return nil, "", databaseItem.Name, err
}
return cli, version, nil
return cli, version, databaseItem.Name, nil
}

@ -43,6 +43,7 @@ func Init() {
migrations.UpdateDatabase,
migrations.UpdateAppInstallResource,
migrations.DropDatabaseLocal,
migrations.AddDatabaseID,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)

@ -572,103 +572,39 @@ var AddDatabases = &gormigrate.Migration{
ID: "20230831-add-databases",
Migrate: func(tx *gorm.DB) error {
installRepo := repo.NewIAppInstallRepo()
mysqlInfo, err := installRepo.LoadBaseInfo("mysql", "")
if err == nil {
var mysqlDb model.Database
_ = tx.Where("name = ?", mysqlInfo.Name).First(&mysqlDb).Error
if mysqlDb.ID == 0 {
if err := tx.Create(&model.Database{
AppInstallID: mysqlInfo.ID,
Name: mysqlInfo.Name,
Type: "mysql",
Version: mysqlInfo.Version,
From: "local",
Address: mysqlInfo.ServiceName,
Port: service.DatabaseKeys["mysql"],
Username: "root",
Password: mysqlInfo.Password,
}).Error; err != nil {
return err
}
mysql := addDatabaseData("mysql", installRepo)
if mysql.AppInstallID != 0 {
if err := tx.Create(mysql).Error; err != nil {
return err
}
}
mariadbInfo, err := installRepo.LoadBaseInfo("mariadb", "")
if err == nil {
if err := tx.Create(&model.Database{
AppInstallID: mariadbInfo.ID,
Name: mariadbInfo.Name,
Type: "mariadb",
Version: mariadbInfo.Version,
From: "local",
Address: mariadbInfo.ServiceName,
Port: service.DatabaseKeys["mariadb"],
Username: "root",
Password: mariadbInfo.Password,
}).Error; err != nil {
mariadb := addDatabaseData("mariadb", installRepo)
if mariadb.AppInstallID != 0 {
if err := tx.Create(mariadb).Error; err != nil {
return err
}
}
redisInfo, err := installRepo.LoadBaseInfo("redis", "")
if err == nil {
if err := tx.Create(&model.Database{
AppInstallID: redisInfo.ID,
Name: redisInfo.Name,
Type: "redis",
Version: redisInfo.Version,
From: "local",
Address: redisInfo.ServiceName,
Port: service.DatabaseKeys["redis"],
Username: "root",
Password: redisInfo.Password,
}).Error; err != nil {
redis := addDatabaseData("redis", installRepo)
if redis.AppInstallID != 0 {
if err := tx.Create(redis).Error; err != nil {
return err
}
}
pgInfo, err := installRepo.LoadBaseInfo("postgresql", "")
if err == nil {
if err := tx.Create(&model.Database{
AppInstallID: pgInfo.ID,
Name: pgInfo.Name,
Type: "postgresql",
Version: pgInfo.Version,
From: "local",
Address: pgInfo.ServiceName,
Port: service.DatabaseKeys["postgresql"],
Username: pgInfo.UserName,
Password: pgInfo.Password,
}).Error; err != nil {
postgresql := addDatabaseData("postgresql", installRepo)
if postgresql.AppInstallID != 0 {
if err := tx.Create(postgresql).Error; err != nil {
return err
}
}
mongodbInfo, err := installRepo.LoadBaseInfo("mongodb", "")
if err == nil {
if err := tx.Create(&model.Database{
AppInstallID: mongodbInfo.ID,
Name: mongodbInfo.Name,
Type: "mongodb",
Version: mongodbInfo.Version,
From: "local",
Address: mongodbInfo.ServiceName,
Port: service.DatabaseKeys["mongodb"],
Username: mongodbInfo.UserName,
Password: mongodbInfo.Password,
}).Error; err != nil {
mongodb := addDatabaseData("mongodb", installRepo)
if mongodb.AppInstallID != 0 {
if err := tx.Create(mongodb).Error; err != nil {
return err
}
}
memcachedInfo, err := installRepo.LoadBaseInfo("memcached", "")
if err == nil {
if err := tx.Create(&model.Database{
AppInstallID: memcachedInfo.ID,
Name: memcachedInfo.Name,
Type: "memcached",
Version: memcachedInfo.Version,
From: "local",
Address: memcachedInfo.ServiceName,
Port: service.DatabaseKeys["memcached"],
Username: "root",
Password: memcachedInfo.Password,
}).Error; err != nil {
memcached := addDatabaseData("memcached", installRepo)
if memcached.AppInstallID != 0 {
if err := tx.Create(memcached).Error; err != nil {
return err
}
}
@ -767,3 +703,55 @@ var DropDatabaseLocal = &gormigrate.Migration{
return nil
},
}
var AddDatabaseID = &gormigrate.Migration{
ID: "20230914-add-database-id",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.DatabaseMysql{}); err != nil {
return err
}
var (
mysqls []model.DatabaseMysql
databases []model.Database
)
_ = tx.Find(&mysqls).Error
if len(mysqls) == 0 {
return nil
}
_ = tx.Find(&databases).Error
for _, mysql := range mysqls {
for _, database := range databases {
if mysql.MysqlName == database.Name && mysql.From == database.From {
if err := tx.Model(&model.DatabaseMysql{}).Where("id = ?", mysql.ID).Updates(map[string]interface{}{
"database_id": database.ID,
}).Error; err != nil {
return err
}
break
}
}
}
return nil
},
}
func addDatabaseData(appType string, installRepo repo.IAppInstallRepo) *model.Database {
dbInfo, err := installRepo.LoadBaseInfo(appType, "")
if err == nil {
if appType == "mysql" || appType == "redis" || appType == "mariadb" || appType == "memcached" {
dbInfo.UserName = "root"
}
return &model.Database{
AppInstallID: dbInfo.ID,
Name: dbInfo.Name,
Type: appType,
Version: dbInfo.Version,
From: "local",
Address: dbInfo.ServiceName,
Port: service.DatabaseKeys[appType],
Username: dbInfo.UserName,
Password: dbInfo.Password,
}
}
return &model.Database{}
}

@ -80,7 +80,6 @@ type RecoverInfo struct {
type SyncDBInfo struct {
Name string `json:"name"`
From string `json:"from"`
MysqlName string `json:"mysqlName"`
Format string `json:"format"`
Username string `json:"username"`
Password string `json:"password"`

@ -273,10 +273,9 @@ func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) {
continue
}
dataItem := SyncDBInfo{
Name: parts[0],
From: "local",
MysqlName: r.Database,
Format: parts[1],
Name: parts[0],
From: "local",
Format: parts[1],
}
userLines, err := r.ExecSQLForRows(fmt.Sprintf("select user,host from mysql.db where db = '%s'", parts[0]), 300)
if err != nil {

@ -283,10 +283,9 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) {
continue
}
dataItem := SyncDBInfo{
Name: dbName,
From: "remote",
MysqlName: r.Database,
Format: charsetName,
Name: dbName,
From: "remote",
Format: charsetName,
}
userRows, err := r.Client.Query("select user,host from mysql.db where db = ?", dbName)
if err != nil {

@ -3740,7 +3740,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4322,7 +4322,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.MysqlLoadDB"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4685,7 +4685,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4757,7 +4757,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4793,7 +4793,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -11900,14 +11900,14 @@ const docTemplate = `{
"dto.ChangeDBInfo": {
"type": "object",
"required": [
"database",
"databaseID",
"from",
"type",
"value"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"from": {
"type": "string",
@ -13543,29 +13543,21 @@ const docTemplate = `{
"dto.MysqlConfUpdateByFile": {
"type": "object",
"required": [
"database",
"type"
"databaseID"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"file": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlDBCreate": {
"type": "object",
"required": [
"database",
"databaseID",
"format",
"from",
"name",
@ -13574,8 +13566,8 @@ const docTemplate = `{
"username"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"description": {
"type": "string"
@ -13613,13 +13605,13 @@ const docTemplate = `{
"dto.MysqlDBDelete": {
"type": "object",
"required": [
"database",
"databaseID",
"id",
"type"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"deleteBackup": {
"type": "boolean"
@ -13642,36 +13634,28 @@ const docTemplate = `{
"dto.MysqlDBDeleteCheck": {
"type": "object",
"required": [
"database",
"id",
"type"
"databaseID",
"id"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"id": {
"type": "integer"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlDBSearch": {
"type": "object",
"required": [
"database",
"databaseID",
"page",
"pageSize"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"info": {
"type": "string"
@ -13690,39 +13674,15 @@ const docTemplate = `{
}
}
},
"dto.MysqlLoadDB": {
"type": "object",
"required": [
"database",
"from",
"type"
],
"properties": {
"database": {
"type": "string"
},
"from": {
"type": "string",
"enum": [
"local",
"remote"
]
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlOption": {
"type": "object",
"properties": {
"database": {
"type": "string"
},
"databaseID": {
"type": "integer"
},
"from": {
"type": "string"
},
@ -13909,19 +13869,11 @@ const docTemplate = `{
"dto.MysqlVariablesUpdate": {
"type": "object",
"required": [
"database",
"type"
"databaseID"
],
"properties": {
"database": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
"databaseID": {
"type": "integer"
},
"variables": {
"type": "array",

@ -3733,7 +3733,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4315,7 +4315,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.MysqlLoadDB"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4678,7 +4678,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4750,7 +4750,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -4786,7 +4786,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.OperateByID"
}
}
],
@ -11893,14 +11893,14 @@
"dto.ChangeDBInfo": {
"type": "object",
"required": [
"database",
"databaseID",
"from",
"type",
"value"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"from": {
"type": "string",
@ -13536,29 +13536,21 @@
"dto.MysqlConfUpdateByFile": {
"type": "object",
"required": [
"database",
"type"
"databaseID"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"file": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlDBCreate": {
"type": "object",
"required": [
"database",
"databaseID",
"format",
"from",
"name",
@ -13567,8 +13559,8 @@
"username"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"description": {
"type": "string"
@ -13606,13 +13598,13 @@
"dto.MysqlDBDelete": {
"type": "object",
"required": [
"database",
"databaseID",
"id",
"type"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"deleteBackup": {
"type": "boolean"
@ -13635,36 +13627,28 @@
"dto.MysqlDBDeleteCheck": {
"type": "object",
"required": [
"database",
"id",
"type"
"databaseID",
"id"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"id": {
"type": "integer"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlDBSearch": {
"type": "object",
"required": [
"database",
"databaseID",
"page",
"pageSize"
],
"properties": {
"database": {
"type": "string"
"databaseID": {
"type": "integer"
},
"info": {
"type": "string"
@ -13683,39 +13667,15 @@
}
}
},
"dto.MysqlLoadDB": {
"type": "object",
"required": [
"database",
"from",
"type"
],
"properties": {
"database": {
"type": "string"
},
"from": {
"type": "string",
"enum": [
"local",
"remote"
]
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlOption": {
"type": "object",
"properties": {
"database": {
"type": "string"
},
"databaseID": {
"type": "integer"
},
"from": {
"type": "string"
},
@ -13902,19 +13862,11 @@
"dto.MysqlVariablesUpdate": {
"type": "object",
"required": [
"database",
"type"
"databaseID"
],
"properties": {
"database": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
"databaseID": {
"type": "integer"
},
"variables": {
"type": "array",

@ -131,8 +131,8 @@ definitions:
type: object
dto.ChangeDBInfo:
properties:
database:
type: string
databaseID:
type: integer
from:
enum:
- local
@ -148,7 +148,7 @@ definitions:
value:
type: string
required:
- database
- databaseID
- from
- type
- value
@ -1241,23 +1241,17 @@ definitions:
type: object
dto.MysqlConfUpdateByFile:
properties:
database:
type: string
databaseID:
type: integer
file:
type: string
type:
enum:
- mysql
- mariadb
type: string
required:
- database
- type
- databaseID
type: object
dto.MysqlDBCreate:
properties:
database:
type: string
databaseID:
type: integer
description:
type: string
format:
@ -1281,7 +1275,7 @@ definitions:
username:
type: string
required:
- database
- databaseID
- format
- from
- name
@ -1291,8 +1285,8 @@ definitions:
type: object
dto.MysqlDBDelete:
properties:
database:
type: string
databaseID:
type: integer
deleteBackup:
type: boolean
forceDelete:
@ -1305,30 +1299,24 @@ definitions:
- mariadb
type: string
required:
- database
- databaseID
- id
- type
type: object
dto.MysqlDBDeleteCheck:
properties:
database:
type: string
databaseID:
type: integer
id:
type: integer
type:
enum:
- mysql
- mariadb
type: string
required:
- database
- databaseID
- id
- type
type: object
dto.MysqlDBSearch:
properties:
database:
type: string
databaseID:
type: integer
info:
type: string
order:
@ -1340,33 +1328,16 @@ definitions:
pageSize:
type: integer
required:
- database
- databaseID
- page
- pageSize
type: object
dto.MysqlLoadDB:
properties:
database:
type: string
from:
enum:
- local
- remote
type: string
type:
enum:
- mysql
- mariadb
type: string
required:
- database
- from
- type
type: object
dto.MysqlOption:
properties:
database:
type: string
databaseID:
type: integer
from:
type: string
id:
@ -1490,20 +1461,14 @@ definitions:
type: object
dto.MysqlVariablesUpdate:
properties:
database:
type: string
type:
enum:
- mysql
- mariadb
type: string
databaseID:
type: integer
variables:
items:
$ref: '#/definitions/dto.MysqlVariablesUpdateHelper'
type: array
required:
- database
- type
- databaseID
type: object
dto.MysqlVariablesUpdateHelper:
properties:
@ -6412,7 +6377,7 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
$ref: '#/definitions/dto.OperateByID'
responses:
"200":
description: OK
@ -6783,7 +6748,7 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/dto.MysqlLoadDB'
$ref: '#/definitions/dto.OperateByID'
responses: {}
security:
- ApiKeyAuth: []
@ -7010,7 +6975,7 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
$ref: '#/definitions/dto.OperateByID'
responses:
"200":
description: OK
@ -7054,7 +7019,7 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
$ref: '#/definitions/dto.OperateByID'
responses:
"200":
description: OK
@ -7076,7 +7041,7 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
$ref: '#/definitions/dto.OperateByID'
responses:
"200":
description: OK

@ -1,23 +1,17 @@
import { ReqPage } from '.';
export namespace Database {
export interface SearchDBWithPage {
info: string;
database: string;
databaseID: number;
page: number;
pageSize: number;
orderBy?: string;
order?: string;
}
export interface SearchBackupRecord extends ReqPage {
mysqlName: string;
dbName: string;
}
export interface MysqlDBInfo {
id: number;
createdAt: Date;
name: string;
mysqlName: string;
databaseID: number;
from: string;
format: string;
username: string;
@ -34,34 +28,27 @@ export namespace Database {
containerName: string;
}
export interface MysqlConfUpdateByFile {
type: string;
database: string;
databaseID: number;
file: string;
}
export interface MysqlDBCreate {
name: string;
from: string;
database: string;
databaseID: number;
format: string;
username: string;
password: string;
permission: string;
description: string;
}
export interface MysqlLoadDB {
from: string;
type: string;
database: string;
}
export interface MysqlDBDeleteCheck {
id: number;
type: string;
database: string;
databaseID: number;
}
export interface MysqlDBDelete {
id: number;
type: string;
database: string;
databaseID: number;
forceDelete: boolean;
deleteBackup: boolean;
}
@ -86,8 +73,7 @@ export namespace Database {
long_query_time: number;
}
export interface VariablesUpdate {
type: string;
database: string;
databaseID: number;
variables: Array<VariablesUpdateHelper>;
}
export interface VariablesUpdateHelper {
@ -135,6 +121,7 @@ export namespace Database {
id: number;
from: string;
type: string;
databaseID: number;
database: string;
name: string;
}
@ -142,7 +129,7 @@ export namespace Database {
id: number;
from: string;
type: string;
database: string;
databaseID: number;
value: string;
}

@ -19,9 +19,6 @@ export const addMysqlDB = (params: Database.MysqlDBCreate) => {
}
return http.post(`/databases`, request);
};
export const loadDBFromRemote = (params: Database.MysqlLoadDB) => {
return http.post(`/databases/load`, params);
};
export const updateMysqlAccess = (params: Database.ChangeInfo) => {
return http.post(`/databases/change/access`, params);
};
@ -48,17 +45,20 @@ export const deleteMysqlDB = (params: Database.MysqlDBDelete) => {
return http.post(`/databases/del`, params);
};
export const loadMysqlBaseInfo = (type: string, database: string) => {
return http.post<Database.BaseInfo>(`/databases/baseinfo`, { type: type, name: database });
export const loadDBFromRemote = (id: number) => {
return http.post(`/databases/load`, { id: id });
};
export const loadMysqlBaseInfo = (id: number) => {
return http.post<Database.BaseInfo>(`/databases/baseinfo`, { id: id });
};
export const loadMysqlVariables = (type: string, database: string) => {
return http.post<Database.MysqlVariables>(`/databases/variables`, { type: type, name: database });
export const loadMysqlVariables = (id: number) => {
return http.post<Database.MysqlVariables>(`/databases/variables`, { id: id });
};
export const loadMysqlStatus = (type: string, database: string) => {
return http.post<Database.MysqlStatus>(`/databases/status`, { type: type, name: database });
export const loadMysqlStatus = (id: number) => {
return http.post<Database.MysqlStatus>(`/databases/status`, { id: id });
};
export const loadRemoteAccess = (type: string, database: string) => {
return http.post<boolean>(`/databases/remote`, { type: type, name: database });
export const loadRemoteAccess = (id: number) => {
return http.post<boolean>(`/databases/remote`, { id: id });
};
export const loadDBOptions = () => {
return http.get<Array<Database.MysqlOption>>(`/databases/options`);

@ -72,15 +72,18 @@ const backupVisiable = ref(false);
const type = ref();
const name = ref();
const detailName = ref();
const databaseID = ref();
interface DialogProps {
type: string;
name: string;
databaseID: string;
detailName: string;
}
const acceptParams = (params: DialogProps): void => {
type.value = params.type;
name.value = params.name;
databaseID.value = params.databaseID;
detailName.value = params.detailName;
backupVisiable.value = true;
search();
@ -103,9 +106,10 @@ const search = async () => {
};
const onBackup = async () => {
let nameItem = type.value === 'mysql' || type.value === 'mariadb' ? databaseID.value : name.value;
let params = {
type: type.value,
name: name.value,
name: nameItem,
detailName: detailName.value,
};
loading.value = true;
@ -121,10 +125,11 @@ const onBackup = async () => {
};
const onRecover = async (row: Backup.RecordInfo) => {
let nameItem = type.value === 'mysql' || type.value === 'mariadb' ? databaseID.value : name.value;
let params = {
source: row.source,
type: type.value,
name: name.value,
name: nameItem,
detailName: detailName.value,
file: row.fileDir + '/' + row.fileName,
};

@ -109,14 +109,17 @@ const upVisiable = ref(false);
const type = ref();
const name = ref();
const detailName = ref();
const databaseID = ref();
interface DialogProps {
type: string;
name: string;
databaseID: string;
detailName: string;
}
const acceptParams = async (params: DialogProps): Promise<void> => {
type.value = params.type;
name.value = params.name;
databaseID.value = params.databaseID;
detailName.value = params.detailName;
const pathRes = await loadBaseDir();
@ -148,10 +151,11 @@ const search = async () => {
};
const onRecover = async (row: File.File) => {
let nameItem = type.value === 'mysql' || type.value === 'mariadb' ? databaseID.value : name.value;
let params = {
source: 'LOCAL',
type: type.value,
name: name.value,
name: nameItem,
detailName: detailName.value,
file: baseDir.value + row.name,
};

@ -28,7 +28,7 @@ const databaseRouter = {
},
},
{
path: 'mysql/setting/:type/:database',
path: 'mysql/setting/:type/:database/:databaseID',
name: 'MySQL-Setting',
component: () => import('@/views/database/mysql/setting/index.vue'),
props: true,

@ -120,6 +120,7 @@ const form = reactive({
from: '',
type: '',
database: '',
databaseID: 0,
username: '',
remoteIP: '',
});
@ -134,6 +135,7 @@ interface DialogProps {
from: string;
type: string;
database: string;
databaseID: number;
}
const acceptParams = (param: DialogProps): void => {
@ -141,6 +143,7 @@ const acceptParams = (param: DialogProps): void => {
form.from = param.from;
form.type = param.type;
form.database = param.database;
form.databaseID = param.databaseID;
loadAccess();
loadPassword();
dialogVisiable.value = true;
@ -171,7 +174,7 @@ const handleClose = () => {
const loadAccess = async () => {
if (form.from === 'local') {
const res = await loadRemoteAccess(form.type, form.database);
const res = await loadRemoteAccess(form.databaseID);
form.privilege = res.data;
}
};
@ -203,7 +206,7 @@ const onSubmit = async () => {
id: 0,
from: form.from,
type: form.type,
database: form.database,
databaseID: form.databaseID,
value: form.password,
};
loading.value = true;
@ -236,7 +239,7 @@ const onSubmitAccess = async () => {
id: 0,
from: form.from,
type: form.type,
database: form.database,
databaseID: form.databaseID,
value: form.privilege ? '%' : 'localhost',
};
loading.value = true;

@ -93,6 +93,7 @@ const form = reactive({
from: 'local',
type: '',
database: '',
databaseID: 0,
format: '',
username: '',
password: '',
@ -124,12 +125,14 @@ interface DialogProps {
from: string;
type: string;
database: string;
databaseID: number;
}
const acceptParams = (params: DialogProps): void => {
form.name = '';
form.from = params.from;
form.type = params.type;
form.database = params.database;
form.databaseID = params.databaseID;
form.format = 'utf8mb4';
form.username = '';
form.permission = '%';

@ -49,7 +49,7 @@ import { MsgSuccess } from '@/utils/message';
let deleteReq = ref({
id: 0,
type: '',
database: '',
databaseID: 0,
deleteBackup: false,
forceDelete: false,
});
@ -64,7 +64,7 @@ interface DialogProps {
id: number;
type: string;
name: string;
database: string;
databaseID: number;
}
const emit = defineEmits<{ (e: 'search'): void }>();
@ -72,7 +72,7 @@ const acceptParams = async (prop: DialogProps) => {
deleteReq.value = {
id: prop.id,
type: prop.type,
database: prop.database,
databaseID: prop.databaseID,
deleteBackup: false,
forceDelete: false,
};

@ -285,6 +285,7 @@ const onOpenDialog = async () => {
from: currentDB.value.from,
type: currentDB.value.type,
database: currentDBName.value,
databaseID: currentDB.value.id,
};
dialogRef.value!.acceptParams(params);
};
@ -298,7 +299,8 @@ const onChangeConn = async () => {
connRef.value!.acceptParams({
from: currentDB.value.from,
type: currentDB.value.type,
database: currentDBName.value,
databaseID: currentDB.value.id,
database: currentDB.value.database,
});
};
@ -315,7 +317,10 @@ const onSetting = async () => {
if (currentDB.value) {
globalStore.setCurrentDB(currentDB.value.database);
}
router.push({ name: 'MySQL-Setting', params: { type: currentDB.value.type, database: currentDB.value.database } });
router.push({
name: 'MySQL-Setting',
params: { type: currentDB.value.type, database: currentDB.value.database, databaseID: currentDB.value.id },
});
};
const changeDatabase = async () => {
@ -344,7 +349,7 @@ const search = async (column?: any) => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
info: searchName.value,
database: currentDB.value.database,
databaseID: currentDB.value.id,
orderBy: paginationConfig.orderBy,
order: paginationConfig.order,
};
@ -360,12 +365,7 @@ const loadDB = async () => {
type: 'info',
}).then(async () => {
loading.value = true;
let params = {
from: currentDB.value.from,
type: currentDB.value.type,
database: currentDBName.value,
};
await loadDBFromRemote(params)
await loadDBFromRemote(currentDB.value.id)
.then(() => {
loading.value = false;
search();
@ -464,8 +464,7 @@ const onCopy = async (row: any) => {
const onDelete = async (row: Database.MysqlDBInfo) => {
let param = {
id: row.id,
type: currentDB.value.type,
database: currentDBName.value,
databaseID: currentDB.value.id,
};
const res = await deleteCheckMysqlDB(param);
if (res.data && res.data.length > 0) {
@ -474,8 +473,8 @@ const onDelete = async (row: Database.MysqlDBInfo) => {
deleteRef.value.acceptParams({
id: row.id,
type: currentDB.value.type,
database: currentDBName.value,
name: row.name,
databaseID: currentDB.value.id,
});
}
};
@ -485,8 +484,7 @@ const onChangePassword = async (row: Database.MysqlDBInfo) => {
id: row.id,
from: row.from,
type: currentDB.value.type,
database: currentDBName.value,
mysqlName: row.name,
databaseID: currentDB.value.id,
operation: 'password',
username: row.username,
password: row.password,
@ -511,8 +509,7 @@ const buttons = [
id: row.id,
from: row.from,
type: currentDB.value.type,
database: currentDBName.value,
mysqlName: row.name,
databaseID: currentDB.value.id,
operation: 'privilege',
privilege: '',
privilegeIPs: '',
@ -532,7 +529,8 @@ const buttons = [
click: (row: Database.MysqlDBInfo) => {
let params = {
type: currentDB.value.type,
name: currentDBName.value,
name: currentDB.value.from + '-' + currentDB.value.database,
databaseID: currentDB.value.id + '',
detailName: row.name,
};
dialogBackupRef.value!.acceptParams(params);
@ -543,7 +541,8 @@ const buttons = [
click: (row: Database.MysqlDBInfo) => {
let params = {
type: currentDB.value.type,
name: currentDBName.value,
name: currentDB.value.from + '-' + currentDB.value.database,
databaseID: currentDB.value.id + '',
detailName: row.name,
};
uploadRef.value!.acceptParams(params);

@ -79,7 +79,7 @@ const changeForm = reactive({
id: 0,
from: '',
type: '',
database: '',
databaseID: 0,
mysqlName: '',
userName: '',
password: '',
@ -109,7 +109,7 @@ interface DialogProps {
id: number;
from: string;
type: string;
database: string;
databaseID: number;
mysqlName: string;
username: string;
password: string;
@ -126,7 +126,7 @@ const acceptParams = (params: DialogProps): void => {
changeForm.id = params.id;
changeForm.from = params.from;
changeForm.type = params.type;
changeForm.database = params.database;
changeForm.databaseID = params.databaseID;
changeForm.mysqlName = params.mysqlName;
changeForm.userName = params.username;
changeForm.password = params.password;
@ -150,7 +150,7 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
id: changeForm.id,
from: changeForm.from,
type: changeForm.type,
database: changeForm.database,
databaseID: changeForm.databaseID,
value: '',
};
if (changeForm.operation === 'password') {
@ -202,7 +202,7 @@ const onSubmit = async () => {
id: changeForm.id,
from: changeForm.from,
type: changeForm.type,
database: changeForm.database,
databaseID: changeForm.databaseID,
value: changeForm.password,
};
loading.value = true;

@ -188,10 +188,12 @@ const variables = ref();
interface DBProps {
type: string;
database: string;
databaseID: string;
}
const props = withDefaults(defineProps<DBProps>(), {
type: '',
database: '',
databaseID: '',
});
const dialogContainerLogRef = ref();
@ -259,8 +261,7 @@ const getDefaultConfig = async () => {
const onSubmitChangeConf = async () => {
let param = {
type: props.type,
database: props.database,
databaseID: Number(props.databaseID),
file: mysqlConf.value,
};
loading.value = true;
@ -290,7 +291,7 @@ const loadContainerLog = async (containerID: string) => {
};
const loadBaseInfo = async () => {
const res = await loadMysqlBaseInfo(props.type, props.database);
const res = await loadMysqlBaseInfo(Number(props.databaseID));
mysqlName.value = res.data?.name;
baseInfo.port = res.data?.port;
baseInfo.containerID = res.data?.containerName;
@ -303,23 +304,22 @@ const changeLoading = (status: boolean) => {
};
const loadVariables = async () => {
const res = await loadMysqlVariables(props.type, props.database);
const res = await loadMysqlVariables(Number(props.databaseID));
variables.value = res.data;
variablesRef.value!.acceptParams({
type: props.type,
database: props.database,
databaseID: Number(props.databaseID),
mysqlVersion: mysqlVersion.value,
variables: res.data,
});
};
const loadSlowLogs = async () => {
const res = await loadMysqlVariables(props.type, props.database);
const res = await loadMysqlVariables(Number(props.databaseID));
variables.value = res.data;
let param = {
type: props.type,
database: props.database,
databaseID: Number(props.databaseID),
variables: variables.value,
};
slowLogRef.value!.acceptParams(param);
@ -351,7 +351,7 @@ const onLoadInfo = async () => {
if (mysqlStatus.value === 'Running') {
loadVariables();
loadSlowLogs();
statusRef.value!.acceptParams({ type: props.type, database: props.database });
statusRef.value!.acceptParams({ databaseID: Number(props.databaseID) });
}
});
};

@ -79,15 +79,18 @@ const variables = reactive({
const currentDB = reactive({
type: '',
database: '',
databaseID: 0,
});
interface DialogProps {
type: string;
database: string;
databaseID: number;
variables: Database.MysqlVariables;
}
const acceptParams = async (params: DialogProps): Promise<void> => {
currentDB.type = params.type;
currentDB.database = params.database;
currentDB.databaseID = params.databaseID;
variables.slow_query_log = params.variables.slow_query_log;
variables.long_query_time = Number(params.variables.long_query_time);
@ -149,8 +152,7 @@ const onSave = async () => {
param.push({ param: 'slow_query_log_file', value: '/var/lib/mysql/1Panel-slow.log' });
}
let params = {
type: currentDB.type,
database: currentDB.database,
databaseID: currentDB.databaseID,
variables: param,
};
emit('loading', true);

@ -209,23 +209,20 @@ let mysqlStatus = reactive({
});
const currentDB = reactive({
type: '',
database: '',
databaseID: 0,
});
interface DialogProps {
type: string;
database: string;
databaseID: number;
}
const acceptParams = (params: DialogProps): void => {
currentDB.type = params.type;
currentDB.database = params.database;
currentDB.databaseID = params.databaseID;
loadStatus();
};
const loadStatus = async () => {
const res = await loadMysqlStatus(currentDB.type, currentDB.database);
const res = await loadMysqlStatus(currentDB.databaseID);
let queryPerSecond = res.data.Questions / res.data.Uptime;
let txPerSecond = (res.data!.Com_commit + res.data.Com_rollback) / res.data.Uptime;

@ -170,19 +170,16 @@ const variablesRules = reactive({
});
const currentDB = reactive({
type: '',
database: '',
databaseID: 0,
version: '',
});
interface DialogProps {
type: string;
database: string;
databaseID: number;
version: string;
variables: Database.MysqlVariables;
}
const acceptParams = (params: DialogProps): void => {
currentDB.type = params.type;
currentDB.database = params.database;
currentDB.databaseID = params.databaseID;
currentDB.version = params.version;
mysqlVariables.key_buffer_size = Number(params.variables.key_buffer_size) / 1024 / 1024;
mysqlVariables.query_cache_size = Number(params.variables.query_cache_size) / 1024 / 1024;
@ -288,8 +285,7 @@ const onSaveVariables = async () => {
}
emit('loading', true);
let params = {
type: currentDB.type,
database: currentDB.database,
databaseID: currentDB.databaseID,
variables: param,
};
await updateMysqlVariables(params)

Loading…
Cancel
Save