github.com/gogf/gf@v1.16.9/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/gogf/gf. 6 7 package gins 8 9 import ( 10 "context" 11 "fmt" 12 "github.com/gogf/gf/errors/gcode" 13 "github.com/gogf/gf/errors/gerror" 14 "github.com/gogf/gf/internal/intlog" 15 "github.com/gogf/gf/text/gstr" 16 "github.com/gogf/gf/util/gutil" 17 18 "github.com/gogf/gf/database/gdb" 19 "github.com/gogf/gf/text/gregex" 20 "github.com/gogf/gf/util/gconv" 21 ) 22 23 const ( 24 frameCoreComponentNameDatabase = "gf.core.component.database" 25 configNodeNameDatabase = "database" 26 ) 27 28 // Database returns an instance of database ORM object 29 // with specified configuration group name. 30 func Database(name ...string) gdb.DB { 31 group := gdb.DefaultGroupName 32 if len(name) > 0 && name[0] != "" { 33 group = name[0] 34 } 35 instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameDatabase, group) 36 db := instances.GetOrSetFuncLock(instanceKey, func() interface{} { 37 var ( 38 configMap map[string]interface{} 39 configNodeKey string 40 ) 41 // It firstly searches the configuration of the instance name. 42 if Config().Available() { 43 configNodeKey, _ = gutil.MapPossibleItemByKey( 44 Config().GetMap("."), 45 configNodeNameDatabase, 46 ) 47 if configNodeKey == "" { 48 configNodeKey = configNodeNameDatabase 49 } 50 configMap = Config().GetMap(configNodeKey) 51 } 52 if len(configMap) == 0 && !gdb.IsConfigured() { 53 configFilePath, _ := Config().GetFilePath() 54 if configFilePath == "" { 55 exampleFileName := "config.example.toml" 56 if exampleConfigFilePath, _ := Config().GetFilePath(exampleFileName); exampleConfigFilePath != "" { 57 panic(gerror.NewCodef( 58 gcode.CodeMissingConfiguration, 59 `configuration file "%s" not found, but found "%s", did you miss renaming the example configuration file?`, 60 Config().GetFileName(), 61 exampleFileName, 62 )) 63 } else { 64 panic(gerror.NewCodef( 65 gcode.CodeMissingConfiguration, 66 `configuration file "%s" not found, did you miss the configuration file or the misspell the configuration file name?`, 67 Config().GetFileName(), 68 )) 69 } 70 } 71 panic(gerror.NewCodef( 72 gcode.CodeMissingConfiguration, 73 `database initialization failed: "%s" node not found, is configuration file or configuration node missing?`, 74 configNodeNameDatabase, 75 )) 76 } 77 if len(configMap) == 0 { 78 configMap = make(map[string]interface{}) 79 } 80 // Parse <m> as map-slice and adds it to gdb's global configurations. 81 for g, groupConfig := range configMap { 82 cg := gdb.ConfigGroup{} 83 switch value := groupConfig.(type) { 84 case []interface{}: 85 for _, v := range value { 86 if node := parseDBConfigNode(v); node != nil { 87 cg = append(cg, *node) 88 } 89 } 90 case map[string]interface{}: 91 if node := parseDBConfigNode(value); node != nil { 92 cg = append(cg, *node) 93 } 94 } 95 if len(cg) > 0 { 96 if gdb.GetConfig(group) == nil { 97 intlog.Printf(context.TODO(), "add configuration for group: %s, %#v", g, cg) 98 gdb.SetConfigGroup(g, cg) 99 } else { 100 intlog.Printf(context.TODO(), "ignore configuration as it already exists for group: %s, %#v", g, cg) 101 intlog.Printf(context.TODO(), "%s, %#v", g, cg) 102 } 103 } 104 } 105 // Parse <m> as a single node configuration, 106 // which is the default group configuration. 107 if node := parseDBConfigNode(configMap); node != nil { 108 cg := gdb.ConfigGroup{} 109 if node.Link != "" || node.Host != "" { 110 cg = append(cg, *node) 111 } 112 113 if len(cg) > 0 { 114 if gdb.GetConfig(group) == nil { 115 intlog.Printf(context.TODO(), "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg) 116 gdb.SetConfigGroup(gdb.DefaultGroupName, cg) 117 } else { 118 intlog.Printf(context.TODO(), "ignore configuration as it already exists for group: %s, %#v", gdb.DefaultGroupName, cg) 119 intlog.Printf(context.TODO(), "%s, %#v", gdb.DefaultGroupName, cg) 120 } 121 } 122 } 123 // Create a new ORM object with given configurations. 124 if db, err := gdb.New(name...); err == nil { 125 if Config().Available() { 126 // Initialize logger for ORM. 127 var loggerConfigMap map[string]interface{} 128 loggerConfigMap = Config().GetMap(fmt.Sprintf("%s.%s", configNodeKey, configNodeNameLogger)) 129 if len(loggerConfigMap) == 0 { 130 loggerConfigMap = Config().GetMap(configNodeKey) 131 } 132 if len(loggerConfigMap) > 0 { 133 if err := db.GetLogger().SetConfigWithMap(loggerConfigMap); err != nil { 134 panic(err) 135 } 136 } 137 } 138 return db 139 } else { 140 // If panics, often because it does not find its configuration for given group. 141 panic(err) 142 } 143 return nil 144 }) 145 if db != nil { 146 return db.(gdb.DB) 147 } 148 return nil 149 } 150 151 func parseDBConfigNode(value interface{}) *gdb.ConfigNode { 152 nodeMap, ok := value.(map[string]interface{}) 153 if !ok { 154 return nil 155 } 156 node := &gdb.ConfigNode{} 157 err := gconv.Struct(nodeMap, node) 158 if err != nil { 159 panic(err) 160 } 161 // To be compatible with old version. 162 if _, v := gutil.MapPossibleItemByKey(nodeMap, "LinkInfo"); v != nil { 163 node.Link = gconv.String(v) 164 } 165 if _, v := gutil.MapPossibleItemByKey(nodeMap, "Link"); v != nil { 166 node.Link = gconv.String(v) 167 } 168 // Parse link syntax. 169 if node.Link != "" && node.Type == "" { 170 match, _ := gregex.MatchString(`([a-z]+):(.+)`, node.Link) 171 if len(match) == 3 { 172 node.Type = gstr.Trim(match[1]) 173 node.Link = gstr.Trim(match[2]) 174 } 175 } 176 return node 177 }