163 lines
4.4 KiB
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) gdb.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.(gdb.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
|
|
}
|