github.com/wangyougui/gf/v2@v2.6.5/frame/gins/gins_database.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package gins 8 9 import ( 10 "context" 11 "fmt" 12 13 "github.com/wangyougui/gf/v2/database/gdb" 14 "github.com/wangyougui/gf/v2/errors/gcode" 15 "github.com/wangyougui/gf/v2/errors/gerror" 16 "github.com/wangyougui/gf/v2/internal/consts" 17 "github.com/wangyougui/gf/v2/internal/instance" 18 "github.com/wangyougui/gf/v2/internal/intlog" 19 "github.com/wangyougui/gf/v2/os/gcfg" 20 "github.com/wangyougui/gf/v2/os/glog" 21 "github.com/wangyougui/gf/v2/util/gconv" 22 "github.com/wangyougui/gf/v2/util/gutil" 23 ) 24 25 // Database returns an instance of database ORM object with specified configuration group name. 26 // Note that it panics if any error occurs duration instance creating. 27 func Database(name ...string) gdb.DB { 28 var ( 29 ctx = context.Background() 30 group = gdb.DefaultGroupName 31 ) 32 33 if len(name) > 0 && name[0] != "" { 34 group = name[0] 35 } 36 instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameDatabase, group) 37 db := instance.GetOrSetFuncLock(instanceKey, func() interface{} { 38 // It ignores returned error to avoid file no found error while it's not necessary. 39 var ( 40 configMap map[string]interface{} 41 configNodeKey = consts.ConfigNodeNameDatabase 42 ) 43 // It firstly searches the configuration of the instance name. 44 if configData, _ := Config().Data(ctx); len(configData) > 0 { 45 if v, _ := gutil.MapPossibleItemByKey(configData, consts.ConfigNodeNameDatabase); v != "" { 46 configNodeKey = v 47 } 48 } 49 if v, _ := Config().Get(ctx, configNodeKey); !v.IsEmpty() { 50 configMap = v.Map() 51 } 52 // No configuration found, it formats and panics error. 53 if len(configMap) == 0 && !gdb.IsConfigured() { 54 // File configuration object checks. 55 var err error 56 if fileConfig, ok := Config().GetAdapter().(*gcfg.AdapterFile); ok { 57 if _, err = fileConfig.GetFilePath(); err != nil { 58 panic(gerror.WrapCode(gcode.CodeMissingConfiguration, err, 59 `configuration not found, did you miss the configuration file or misspell the configuration file name`, 60 )) 61 } 62 } 63 // Panic if nothing found in Config object or in gdb configuration. 64 if len(configMap) == 0 && !gdb.IsConfigured() { 65 panic(gerror.NewCodef( 66 gcode.CodeMissingConfiguration, 67 `database initialization failed: configuration missing for database node "%s"`, 68 consts.ConfigNodeNameDatabase, 69 )) 70 } 71 } 72 73 if len(configMap) == 0 { 74 configMap = make(map[string]interface{}) 75 } 76 // Parse `m` as map-slice and adds it to global configurations for package gdb. 77 for g, groupConfig := range configMap { 78 cg := gdb.ConfigGroup{} 79 switch value := groupConfig.(type) { 80 case []interface{}: 81 for _, v := range value { 82 if node := parseDBConfigNode(v); node != nil { 83 cg = append(cg, *node) 84 } 85 } 86 case map[string]interface{}: 87 if node := parseDBConfigNode(value); node != nil { 88 cg = append(cg, *node) 89 } 90 } 91 if len(cg) > 0 { 92 if gdb.GetConfig(group) == nil { 93 intlog.Printf(ctx, "add configuration for group: %s, %#v", g, cg) 94 gdb.SetConfigGroup(g, cg) 95 } else { 96 intlog.Printf(ctx, "ignore configuration as it already exists for group: %s, %#v", g, cg) 97 intlog.Printf(ctx, "%s, %#v", g, cg) 98 } 99 } 100 } 101 // Parse `m` as a single node configuration, 102 // which is the default group configuration. 103 if node := parseDBConfigNode(configMap); node != nil { 104 cg := gdb.ConfigGroup{} 105 if node.Link != "" || node.Host != "" { 106 cg = append(cg, *node) 107 } 108 if len(cg) > 0 { 109 if gdb.GetConfig(group) == nil { 110 intlog.Printf(ctx, "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg) 111 gdb.SetConfigGroup(gdb.DefaultGroupName, cg) 112 } else { 113 intlog.Printf( 114 ctx, 115 "ignore configuration as it already exists for group: %s, %#v", 116 gdb.DefaultGroupName, cg, 117 ) 118 intlog.Printf(ctx, "%s, %#v", gdb.DefaultGroupName, cg) 119 } 120 } 121 } 122 123 // Create a new ORM object with given configurations. 124 if db, err := gdb.NewByGroup(name...); err == nil { 125 // Initialize logger for ORM. 126 var ( 127 loggerConfigMap map[string]interface{} 128 loggerNodeName = fmt.Sprintf("%s.%s", configNodeKey, consts.ConfigNodeNameLogger) 129 ) 130 if v, _ := Config().Get(ctx, loggerNodeName); !v.IsEmpty() { 131 loggerConfigMap = v.Map() 132 } 133 if len(loggerConfigMap) == 0 { 134 if v, _ := Config().Get(ctx, configNodeKey); !v.IsEmpty() { 135 loggerConfigMap = v.Map() 136 } 137 } 138 if len(loggerConfigMap) > 0 { 139 if logger, ok := db.GetLogger().(*glog.Logger); ok { 140 if err = logger.SetConfigWithMap(loggerConfigMap); err != nil { 141 panic(err) 142 } 143 } 144 } 145 return db 146 } else { 147 // If panics, often because it does not find its configuration for given group. 148 panic(err) 149 } 150 return nil 151 }) 152 if db != nil { 153 return db.(gdb.DB) 154 } 155 return nil 156 } 157 158 func parseDBConfigNode(value interface{}) *gdb.ConfigNode { 159 nodeMap, ok := value.(map[string]interface{}) 160 if !ok { 161 return nil 162 } 163 var ( 164 node = &gdb.ConfigNode{} 165 err = gconv.Struct(nodeMap, node) 166 ) 167 if err != nil { 168 panic(err) 169 } 170 // Find possible `Link` configuration content. 171 if _, v := gutil.MapPossibleItemByKey(nodeMap, "Link"); v != nil { 172 node.Link = gconv.String(v) 173 } 174 return node 175 }