162 lines
3.7 KiB
Go
162 lines
3.7 KiB
Go
package dborm
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"regexp"
|
|
"time"
|
|
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
// 数据库连接实例
|
|
var dbgEngine *gorm.DB
|
|
|
|
// 载入连接日志配置
|
|
func loadLogger() logger.Interface {
|
|
newLogger := logger.New(
|
|
log.New(os.Stdout, "[GORM] ", log.LstdFlags), // 将日志输出到控制台
|
|
logger.Config{
|
|
SlowThreshold: time.Second, // Slow SQL 阈值
|
|
LogLevel: logger.Info, // 日志级别 Silent不输出任何日志
|
|
ParameterizedQueries: false, // 参数化查询SQL 用实际值带入?的执行语句
|
|
Colorful: false, // 彩色日志输出
|
|
},
|
|
)
|
|
return newLogger
|
|
}
|
|
|
|
// 连接数据库实例
|
|
func InitGormConnect(dbType, dbUser, dbPassword, dbHost, dbPort, dbName, dbParam, dbLogging any) error {
|
|
var dialector gorm.Dialector
|
|
switch dbType {
|
|
case "mysql":
|
|
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s",
|
|
dbUser,
|
|
dbPassword,
|
|
dbHost,
|
|
dbPort,
|
|
dbName,
|
|
dbParam,
|
|
)
|
|
dialector = mysql.Open(dsn)
|
|
default:
|
|
err := fmt.Errorf("invalid type: %s", dbType)
|
|
return err
|
|
}
|
|
opts := &gorm.Config{}
|
|
// 是否需要日志输出
|
|
if dbLogging.(bool) {
|
|
opts.Logger = loadLogger()
|
|
}
|
|
// 创建连接
|
|
db, err := gorm.Open(dialector, opts)
|
|
if err != nil {
|
|
log.Fatalf("failed to open: %s", err)
|
|
return err
|
|
}
|
|
// 获取底层 SQL 数据库连接
|
|
sqlDB, err := db.DB()
|
|
if err != nil {
|
|
log.Fatalf("failed to connect DB pool: %v", err)
|
|
return err
|
|
}
|
|
// 测试数据库连接
|
|
err = sqlDB.Ping()
|
|
if err != nil {
|
|
log.Fatalf("failed to ping database: %v", err)
|
|
return err
|
|
}
|
|
dbgEngine = db
|
|
return nil
|
|
}
|
|
|
|
// 关闭数据库实例
|
|
func Close() {
|
|
sqlDB, err := dbgEngine.DB()
|
|
if err != nil {
|
|
log.Fatalf("failed to connect pool: %s", err)
|
|
}
|
|
if err := sqlDB.Close(); err != nil {
|
|
log.Fatalf("failed to close: %s", err)
|
|
}
|
|
}
|
|
|
|
// 获取默认数据源
|
|
func DefaultDB() *gorm.DB {
|
|
return dbgEngine
|
|
}
|
|
|
|
// RawSQL 原生查询语句
|
|
func RawSQL(sql string, parameters []any) ([]map[string]any, error) {
|
|
// 数据源
|
|
db := DefaultDB()
|
|
|
|
// 使用正则表达式替换连续的空白字符为单个空格
|
|
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
|
|
|
// logger.Infof("sql=> %v", fmtSql)
|
|
// logger.Infof("parameters=> %v", parameters)
|
|
|
|
// 查询结果
|
|
var rows []map[string]any
|
|
res := db.Raw(fmtSql, parameters...).Scan(&rows)
|
|
if res.Error != nil {
|
|
return nil, res.Error
|
|
}
|
|
return rows, nil
|
|
}
|
|
|
|
// ExecSQL 原生执行语句
|
|
func ExecSQL(sql string, parameters []any) (int64, error) {
|
|
// 数据源
|
|
db := DefaultDB()
|
|
|
|
// 使用正则表达式替换连续的空白字符为单个空格
|
|
fmtSql := regexp.MustCompile(`\s+`).ReplaceAllString(sql, " ")
|
|
// 执行结果
|
|
res := db.Exec(fmtSql, parameters...)
|
|
if res.Error != nil {
|
|
return 0, res.Error
|
|
}
|
|
return res.RowsAffected, nil
|
|
}
|
|
|
|
func CloneTable(srcTable, dstTable string) error {
|
|
// 获取表 A 的结构信息
|
|
var columns []gorm.ColumnType
|
|
dbMigrator := dbgEngine.Migrator()
|
|
columns, err := dbMigrator.ColumnTypes(srcTable)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to ColumnTypes, %v", err)
|
|
}
|
|
|
|
// 创建表 destination table
|
|
err = dbMigrator.CreateTable(dstTable)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to CreateTable, %v", err)
|
|
}
|
|
// 复制表 src 的字段到表 dst
|
|
for _, column := range columns {
|
|
err = dbMigrator.AddColumn(dstTable, column.Name())
|
|
if err != nil {
|
|
return fmt.Errorf("failed to AddColumn, %v", err)
|
|
}
|
|
}
|
|
|
|
// 复制表 src 的主键和索引到表 dst
|
|
err = dbMigrator.CreateConstraint(dstTable, "PRIMARY")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to AddColumn, %v", err)
|
|
}
|
|
|
|
err = dbMigrator.CreateConstraint(dstTable, "INDEX")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to AddColumn, %v", err)
|
|
}
|
|
return nil
|
|
}
|