mysql.go 12.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
package gva

import (
	"fmt"
	information "gin-vue-admin/cmd/information/extra"
	data "gin-vue-admin/cmd/information/system"
	"gin-vue-admin/global"
	"gin-vue-admin/model"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"github.com/gookit/color"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"os"
	"strings"
)

type DatabaseInfo struct {
	Value        string `gorm:"column:Value"`
	VariableName string `gorm:"column:Variable_name"`
}

var Mysql = &_mysql{_config: &gorm.Config{}}

type _mysql struct {
	db      *gorm.DB
	err     error
	_config *gorm.Config

	old       string // 配置文件第一次读取数据库数据
	input     string
	version   string
	character string
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: gorm连接mysql数据库
func (m *_mysql) Init() {
	if global.GVA_CONFIG.Mysql.LogMode {
		m._config.Logger = logger.Default.LogMode(logger.Info)
	} else {
		m._config.Logger = logger.Default.LogMode(logger.Silent)
	}
	m._config.DisableForeignKeyConstraintWhenMigrating = true
	m.db, m.err = gorm.Open(mysql.New(mysql.Config{
		DSN:                       global.GVA_CONFIG.Mysql.Dsn(), // DSN data source name
		DefaultStringSize:         256,                           // string 类型字段的默认长度
		DisableDatetimePrecision:  true,                          // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,                          // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,                          // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false,                         // 根据当前 MySQL 版本自动配置
	}), m._config)
	global.GVA_DB = m.db
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: gorm 同步模型 生成mysql表
func (m *_mysql) AutoMigrateTables() {
	if !global.GVA_DB.Migrator().HasTable("casbin_rule") {
		m.err = global.GVA_DB.Migrator().CreateTable(&gormadapter.CasbinRule{})
	}
	m.err = m.db.AutoMigrate(
		new(model.SysApi),
		new(model.SysUser),
		new(model.SysBaseMenu),
		new(model.SysAuthority),
		new(model.SysDictionary),
		new(model.JwtBlacklist),
		new(model.SysOperationRecord),
		new(model.SysDictionaryDetail),
		new(model.SysBaseMenuParameter),

		new(model.WorkflowNode),
		new(model.WorkflowEdge),
		new(model.WorkflowProcess),
		new(model.WorkflowEndPoint),
		new(model.WorkflowStartPoint),

		new(model.ExaFileUploadAndDownload),
		new(model.ExaFile),
		new(model.ExaFileChunk),
	)
	if m.err != nil {
		color.Warn.Printf("[Mysql] --> 初始化数据表失败, err: %v\n", m.err)
		os.Exit(0)
	}
	color.Info.Println("[Mysql] --> 初始化数据表成功! ")
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 初始化数据
func (m *_mysql) InitData() {
	if m.err = data.Api.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> sys_apis 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.Admin.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> sys_users 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.Casbin.Init(); m.err != nil {
		color.Error.Println("\n[Mysql] --> casbin_rule 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.BaseMenu.Init(); m.err != nil {
		color.Error.Println("\n[Mysql] --> sys_base_menus 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.Authority.Init(); m.err != nil {
		color.Error.Println("\n[Mysql] --> sys_authorities 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.AuthorityMenu.Init(); m.err != nil {
		color.Error.Println("\n[Mysql] --> authority_menu 视图创建失败!, err:%v", m.err)
		os.Exit(0)
	}
	if m.err = data.Dictionary.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> dictionaries 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.AuthoritiesMenus.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> sys_authority_menus 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.DataAuthorities.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> sys_data_authority_id 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.DictionaryDetail.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> sys_dictionary_details 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = data.Workflow.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> 工作流相关 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	if m.err = information.File.Init(); m.err != nil {
		color.Warn.Println("\n[Mysql] --> exa_file_upload_and_downloads 表初始数据失败, err: %v", m.err)
		os.Exit(0)
	}
	color.Info.Println("\n[Mysql] --> 初始化数据成功!\n")
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 检查数据库是否存在
func (m *_mysql) CheckDatabase() {
	var unknownDatabase = fmt.Sprintf("Unknown database '%v'", global.GVA_CONFIG.Mysql.Dbname)
	m.Init()
	if m.err != nil {
		if strings.Split(m.err.Error(), ": ")[1] == unknownDatabase {
			color.Debug.Print("\n[Mysql] -->配置文件的数据库名为:")
			color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
			color.Debug.Println("不存在!\n")
			color.Debug.Println("您的配置文件所配置的数据库不存在,请选择:")
			color.Debug.Print("0:请自行创建配置文件所配置的数据库名为:")
			color.LightGreen.Printf(" {%v} \n", global.GVA_CONFIG.Mysql.Dbname)
			color.Debug.Print("1:尝试使用sql为您创建配置文件所配置的数据库名为:")
			color.LightGreen.Printf(" {%v} \n", global.GVA_CONFIG.Mysql.Dbname)
			color.Debug.Println("2:忽略错误! 注意: 如果不修复, 将会退出初始化数据的进程!")
			color.Warn.Println("\n注意!!!!!!!")
			color.Warn.Println("输入1之后,如果配置文件的mysql用户名为root才会有百分百的权限去创建数据库,不是root的话就会跳过创建数据库步骤!\n")
			color.Debug.Println("请输入指令:")
			if n, _ := fmt.Scanln(&m.input); n != 0 {
				if m.input == "1" {
					if global.GVA_CONFIG.Mysql.Username == "root" {
						m.database()
					} else {
						color.Debug.Print("\n很抱歉,您的配置文件的mysql用户名配置不是root,不确定你有无权限创建数据库,为您跳过创建数据库操作,请自行创建配置文件所配置的数据库名为:")
						color.LightGreen.Printf(" {%v} \n", global.GVA_CONFIG.Mysql.Dbname)
					}
				} else if m.input == "2" {
					os.Exit(0)
				} else {
					color.Warn.Println("[Mysql] --> 请自行创建数据库!")
					os.Exit(0)
				}
			}
		}
	}
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 检查数据库编码是不是utf8mb4
func (m *_mysql) CheckUtf8mb4() {
	m.Character()
	if m.character != "utf8mb4" {
		color.Info.Println("您当前的数据库编码不是utf8mb4,请选择:")
		color.Info.Println("0:请自行修改数据的编码为utf8mb4!")
		color.Info.Println("1:尝试使用sql为您修改编码为utf8mb4!")
		color.Info.Println("2:忽略错误! 注意如果不修复,生成初始数据的时候也许或许可能有几率报错的喔!")
		color.Info.Println("请输入指令:")
		if n, _ := fmt.Scanln(&m.input); n != 0 {
			if m.input == "1" {
				m.utf8mb4()
			} else if m.input == "2" {
				return
			} else {
				color.Warn.Println("[Mysql] --> 请自行修改数据的编码为utf8mb4!")
				os.Exit(0)
			}
		}
	}
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 打印数据库基本信息
func (m *_mysql) Info() {
	m.Version()
	color.Debug.Print("\n您当前的数据库版本: ")
	color.LightGreen.Printf(" {%v} ", m.version)
	color.Debug.Print(", 使用的数据库是: ")
	color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
	color.Debug.Print(", 数据库编码是: ")
	color.LightGreen.Printf(" {%v} \n\n", m.character)
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 获取数据库版本
func (m *_mysql) Version() {
	color.Debug.Println("[Mysql] -->获取数据库版本中.......")
	if err := global.GVA_DB.Raw("SELECT VERSION() AS version;").Scan(&m.version).Error; err != nil {
		color.Info.Printf("[Mysql] -->获取数据库版本失败! err: %v", err)
		m.version = "未知版本~~~"
	}
	color.Debug.Printf("\n[Mysql] -->获取数据库版本成功!\n")
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 获取数据库编码
func (m *_mysql) Character() {
	var info DatabaseInfo
	color.Debug.Println("\n[Mysql] -->获取数据库编码中.......")
	if err := global.GVA_DB.Raw("show variables like 'character_set_database' ").Scan(&info).Error; err != nil {
		color.Error.Printf("[Mysql] -->获取数据库编码失败! err:%v\n", err)
		m.character = "未知编码~~~"
	}
	color.Debug.Println("\n[Mysql] -->获取数据库编码成功!\n")
	m.character = info.Value
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 设置配置文件的数据库编码为utf8mb4
func (m *_mysql) utf8mb4() {
	color.Debug.Print("\n[Mysql] --> 设置数据库名为:")
	color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
	color.Debug.Print("数据库的编码为utf8mb4中.......\n")
	if err := global.GVA_DB.Debug().Exec("ALTER DATABASE " + global.GVA_CONFIG.Mysql.Dbname + " CHARACTER SET `utf8mb4` COLLATE `utf8mb4_general_ci`").Error; err != nil {
		color.Debug.Print("\n[Mysql] --> 设置数据库名为:")
		color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
		color.Debug.Print("数据库的编码为utf8mb4失败!请手动修改数据库名为:")
		color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
		color.Debug.Println("的编码为utf8mb4\n")
		return
	}
	color.Info.Print("\n[Mysql] --> 设置数据库名为:")
	color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
	color.Debug.Print("的编码为utf8mb4成功!\n")
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 创建配置文件的数据库
func (m *_mysql) database() {
	m.old = global.GVA_CONFIG.Mysql.Dbname
	global.GVA_CONFIG.Mysql.Dbname = "mysql"
	color.Debug.Printf("\n[Mysql] --> 正在连接 mysql 数据库中.......\n")
	m.Init()
	if m.err != nil {
		color.Error.Printf("\n[Mysql] --> 链接 mysql 数据库失败!, err: %v\n", m.err)
		color.Error.Printf("[Mysql] --> 请自行创建配置文件所需的数据库!\n")
		os.Exit(0)
	}
	color.Debug.Printf("\n[Mysql] --> 连接 mysql 数据库成功\n")
	global.GVA_CONFIG.Mysql.Dbname = m.old
	color.Debug.Print("\n[Mysql] --> 正在为您创建数据库名为:")
	color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
	color.Debug.Print("中.......\n")
	if m.err = global.GVA_DB.Exec("CREATE DATABASE IF NOT EXISTS " + global.GVA_CONFIG.Mysql.Dbname + " DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;").Error; m.err != nil {
		color.Debug.Print("\n[Mysql] --> 创建数据库名为:")
		color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
		color.Debug.Print("失败!请手动修改数据库名为")
		color.LightGreen.Printf(" {%v} \n", global.GVA_CONFIG.Mysql.Dbname)
		os.Exit(0)
		return
	}
	color.Debug.Print("\n[Mysql] --> 正在为您创建数据库名为:")
	color.LightGreen.Printf(" {%v} ", global.GVA_CONFIG.Mysql.Dbname)
	color.Debug.Print("成功!\n")
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@description: 处理零值
func (m *_mysql) zero() {
	var info DatabaseInfo
	color.Info.Println("\n[Mysql]--> 获取数据库数据中.......")
	if err := global.GVA_DB.Raw("show variables like 'sql_mode';").Scan(&info).Error; err != nil {
		color.Error.Printf("\n[Mysql]-->获取数据库数据失败! err:%v\n", err)
	}
	color.Info.Println("\n[Mysql]--> 处理数据库返回数据.......")
	var values = strings.Split(info.Value, ",")
	info.Value = ""
	for i, value := range values {
		if value == "NO_ZERO_IN_DATE" || value == "NO_ZERO_DATE" {
		} else {
			if i == len(values)-1 {
				info.Value += value
			} else {
				info.Value += value + ","
			}
		}
	}
	if err := global.GVA_DB.Exec("set global sql_mode='" + info.Value + "';").Error; err != nil {
		color.Error.Printf("\n[Mysql]--> 设置数据库的零值失效失败! err:%v\n", err)
		return
	}
	color.Info.Println("\n[Mysql]--> 设置数据库零值失效成功")
}