代码拉取完成,页面将自动刷新
package handler
import (
"database/sql"
"fmt"
"gitee.com/scottq/go-framework/src/utils"
"io/ioutil"
"strings"
)
const VERSION_MAG_TABLE = "migrate_version"
var CREATE_VERSION_TABLE_SQL = fmt.Sprintf(`
CREATE TABLE IF NOT EXISTS %s
(
id bigint unsigned NOT NULL AUTO_INCREMENT,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
label varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'label',
version varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '版本号',
upgrade_file varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '升级文件',
PRIMARY KEY (id),
UNIQUE KEY idx_version (label,version)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT ='升级表'
`, VERSION_MAG_TABLE)
type logFunc = func(info string, err error)
type ILogger interface {
AddLogger(logger logFunc)
}
type IVersionMag interface {
Upgrade(version string) error
UpgradeOne(version string, sqlFile string) error
Version() (string, error)
SetLabel(label string)
Label() string
ILogger
}
type VersionMag struct {
versionDir string
db *sql.DB
label string
optLock IOptimisticLock
_logger logFunc
}
func NewDBVersionMag(sqlDir string, db *sql.DB) (IVersionMag, error) {
lock, err := NewOptimisticLock(db, 60)
if err != nil {
return nil, err
}
mag := &VersionMag{
db: db,
versionDir: sqlDir,
optLock: lock,
}
if err := mag.init(); err != nil {
return nil, err
}
return mag, nil
}
func (this *VersionMag) AddLogger(logger logFunc) {
this._logger = logger
}
func (this *VersionMag) SetLabel(label string) {
this.label = label
}
func (this *VersionMag) Label() string {
return this.label
}
func (this *VersionMag) lockName() string {
return "sql_upgrade." + this.label
}
func (this *VersionMag) logInfo(info string) {
if this._logger == nil {
fmt.Println(info)
return
}
this._logger(info, nil)
}
func (this *VersionMag) logError(err error) {
if this._logger == nil {
fmt.Println(err.Error())
return
}
this._logger("", err)
}
//升级版本
func (this VersionMag) Upgrade(version string) error {
this.logInfo("version upgrade to " + version)
lockName := this.lockName()
if !this.optLock.Lock(lockName) {
this.logInfo("upgrade job has locked: " + lockName)
return nil
}
defer this.optLock.UnLock(lockName)
sqlDir := this.versionDir
files, err := ioutil.ReadDir(sqlDir)
if err != nil {
this.logError(err)
panic(err.Error())
}
//
for _, x := range files {
if x.IsDir() {
continue
}
sqlFile := x.Name()
sqlFileFull := sqlDir + "/" + sqlFile
upVersion := strings.ReplaceAll(sqlFile, ".sql", "")
upVersion = strings.TrimLeft(upVersion, "v")
if utils.CompareVersion(upVersion, version) > 0 {
continue
}
err := this.UpgradeOne(upVersion, sqlFileFull)
if err != nil {
panic(err.Error())
return err
}
}
return nil
}
//升级一次版本
func (this *VersionMag) UpgradeOne(upVersion string, sqlFile string) error {
var err error
version, err := this.Version()
if err != nil {
return err
}
//无需处理
if utils.CompareVersion(upVersion, version) <= 0 {
this.logInfo("no need upgrade: v" + upVersion)
return nil
}
//执行升级文件
bytes, err := ioutil.ReadFile(sqlFile)
if err != nil {
this.logError(err)
return err
}
execSql := string(bytes)
err = this.upgradeSql(upVersion, execSql, sqlFile)
if err != nil {
return err
}
this.logInfo(fmt.Sprintf("upgrade success v%s => v%s", version, upVersion))
return nil
}
func (this *VersionMag) upgradeSql(upVersion string, sqlContent string, comment string) error {
var err error
_, err = this.db.Exec(sqlContent)
if err != nil {
this.logError(err)
return err
}
//保存version信息
err = this.addVersionRecord(this.label, upVersion, comment)
if err != nil {
this.logError(err)
return err
}
return nil
}
func (this *VersionMag) addVersionRecord(label, version, sqlFile string) error {
//保存version信息
insertSql := fmt.Sprintf("INSERT INTO %s SET `label`=?,`version`=?,`upgrade_file`=?", VERSION_MAG_TABLE)
stmt, err := this.db.Prepare(insertSql)
if err != nil {
this.logError(err)
return err
}
_, err = stmt.Exec(label, version, sqlFile)
if err != nil {
this.logError(err)
return err
}
return nil
}
func (this VersionMag) init() error {
var err error
_, err = this.db.Exec(CREATE_VERSION_TABLE_SQL)
if err != nil {
this.logError(err)
return err
}
return nil
}
//获取当前版本信息
func (this VersionMag) Version() (string, error) {
var err error
querySql := fmt.Sprintf("SELECT version FROM %s WHERE label=? ORDER BY id DESC LIMIT 1", VERSION_MAG_TABLE)
row := this.db.QueryRow(querySql, this.label)
var version string
err = row.Scan(&version)
switch err {
case nil:
case sql.ErrNoRows:
default:
this.logError(err)
return "", err
}
if version == "" {
version = "0.0.0"
}
return version, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。