gin-base/database/gdb_database.go

163 lines
4.4 KiB
Go

package database
import (
"context"
"fmt"
"git.magicany.cc/black1552/gin-base/config"
"git.magicany.cc/black1552/gin-base/database/instance"
"git.magicany.cc/black1552/gin-base/database/intlog"
customLog "git.magicany.cc/black1552/gin-base/log"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gutil"
)
const (
frameCoreComponentNameDatabase = "core.component.database"
ConfigNodeNameDatabase = "database"
)
func Database(name ...string) DB {
var (
ctx = context.Background()
group = gdb.DefaultGroupName
)
if len(name) > 0 && name[0] != "" {
group = name[0]
}
instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameDatabase, group)
db := instance.GetOrSetFuncLock(instanceKey, func() interface{} {
// It ignores returned error to avoid file no found error while it's not necessary.
var (
configMap map[string]interface{}
configNodeKey = ConfigNodeNameDatabase
)
// It firstly searches the configuration of the instance name.
if configData := config.GetAllConfig(); len(configData) > 0 {
if v, _ := gutil.MapPossibleItemByKey(configData, ConfigNodeNameDatabase); v != "" {
configNodeKey = v
}
}
if v := config.GetConfigValue(configNodeKey); !v.IsEmpty() {
configMap = v.Map()
}
// 检查配置是否存在
if len(configMap) == 0 {
// 从 config 包获取所有配置,检查是否包含数据库配置
allConfig := config.GetAllConfig()
if len(allConfig) == 0 {
panic(gerror.NewCodef(
gcode.CodeMissingConfiguration,
`database initialization failed: configuration file is empty or invalid`,
))
}
// 检查是否配置了数据库节点
if _, exists := allConfig["database"]; !exists {
// 尝试其他可能的键名
found := false
for key := range allConfig {
if key == "DATABASE" || key == "Database" {
found = true
break
}
}
if !found {
panic(gerror.NewCodef(
gcode.CodeMissingConfiguration,
`database initialization failed: configuration missing for database node "%s"`,
ConfigNodeNameDatabase,
))
}
}
}
if len(configMap) == 0 {
configMap = make(map[string]interface{})
}
// Parse `m` as map-slice and adds it to global configurations for package gdb.
for g, groupConfig := range configMap {
cg := ConfigGroup{}
switch value := groupConfig.(type) {
case []interface{}:
for _, v := range value {
if node := parseDBConfigNode(v); node != nil {
cg = append(cg, *node)
}
}
case map[string]interface{}:
if node := parseDBConfigNode(value); node != nil {
cg = append(cg, *node)
}
}
if len(cg) > 0 {
if GetConfig(group) == nil {
intlog.Printf(ctx, "add configuration for group: %s, %#v", g, cg)
SetConfigGroup(g, cg)
} else {
intlog.Printf(ctx, "ignore configuration as it already exists for group: %s, %#v", g, cg)
intlog.Printf(ctx, "%s, %#v", g, cg)
}
}
}
// Parse `m` as a single node configuration,
// which is the default group configuration.
if node := parseDBConfigNode(configMap); node != nil {
cg := ConfigGroup{}
if node.Link != "" || node.Host != "" {
cg = append(cg, *node)
}
if len(cg) > 0 {
if GetConfig(group) == nil {
intlog.Printf(ctx, "add configuration for group: %s, %#v", DefaultGroupName, cg)
SetConfigGroup(DefaultGroupName, cg)
} else {
intlog.Printf(
ctx,
"ignore configuration as it already exists for group: %s, %#v",
DefaultGroupName, cg,
)
intlog.Printf(ctx, "%s, %#v", DefaultGroupName, cg)
}
}
}
// Create a new ORM object with given configurations.
if db, err := NewByGroup(name...); err == nil {
// 自动初始化自定义日志器并设置到数据库
db.SetLogger(customLog.GetLogger())
return db
} else {
// If panics, often because it does not find its configuration for given group.
panic(err)
}
return nil
})
if db != nil {
return db.(DB)
}
return nil
}
func parseDBConfigNode(value interface{}) *ConfigNode {
nodeMap, ok := value.(map[string]interface{})
if !ok {
return nil
}
var (
node = &ConfigNode{}
err = gconv.Struct(nodeMap, node)
)
if err != nil {
panic(err)
}
// Find possible `Link` configuration content.
if _, v := gutil.MapPossibleItemByKey(nodeMap, "Link"); v != nil {
node.Link = gconv.String(v)
}
return node
}