github.com/gogf/gf/v2@v2.7.4/database/gdb/gdb_core_config.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 gdb 8 9 import ( 10 "sync" 11 "time" 12 13 "github.com/gogf/gf/v2/os/gcache" 14 "github.com/gogf/gf/v2/os/glog" 15 "github.com/gogf/gf/v2/text/gregex" 16 "github.com/gogf/gf/v2/text/gstr" 17 "github.com/gogf/gf/v2/util/gconv" 18 ) 19 20 // Config is the configuration management object. 21 type Config map[string]ConfigGroup 22 23 // ConfigGroup is a slice of configuration node for specified named group. 24 type ConfigGroup []ConfigNode 25 26 // ConfigNode is configuration for one node. 27 type ConfigNode struct { 28 Host string `json:"host"` // Host of server, ip or domain like: 127.0.0.1, localhost 29 Port string `json:"port"` // Port, it's commonly 3306. 30 User string `json:"user"` // Authentication username. 31 Pass string `json:"pass"` // Authentication password. 32 Name string `json:"name"` // Default used database name. 33 Type string `json:"type"` // Database type: mysql, mariadb, sqlite, mssql, pgsql, oracle, clickhouse, dm. 34 Link string `json:"link"` // (Optional) Custom link information for all configuration in one single string. 35 Extra string `json:"extra"` // (Optional) Extra configuration according the registered third-party database driver. 36 Role string `json:"role"` // (Optional, "master" in default) Node role, used for master-slave mode: master, slave. 37 Debug bool `json:"debug"` // (Optional) Debug mode enables debug information logging and output. 38 Prefix string `json:"prefix"` // (Optional) Table prefix. 39 DryRun bool `json:"dryRun"` // (Optional) Dry run, which does SELECT but no INSERT/UPDATE/DELETE statements. 40 Weight int `json:"weight"` // (Optional) Weight for load balance calculating, it's useless if there's just one node. 41 Charset string `json:"charset"` // (Optional, "utf8" in default) Custom charset when operating on database. 42 Protocol string `json:"protocol"` // (Optional, "tcp" in default) See net.Dial for more information which networks are available. 43 Timezone string `json:"timezone"` // (Optional) Sets the time zone for displaying and interpreting time stamps. 44 Namespace string `json:"namespace"` // (Optional) Namespace for some databases. Eg, in pgsql, the `Name` acts as the `catalog`, the `NameSpace` acts as the `schema`. 45 MaxIdleConnCount int `json:"maxIdle"` // (Optional) Max idle connection configuration for underlying connection pool. 46 MaxOpenConnCount int `json:"maxOpen"` // (Optional) Max open connection configuration for underlying connection pool. 47 MaxConnLifeTime time.Duration `json:"maxLifeTime"` // (Optional) Max amount of time a connection may be idle before being closed. 48 QueryTimeout time.Duration `json:"queryTimeout"` // (Optional) Max query time for per dql. 49 ExecTimeout time.Duration `json:"execTimeout"` // (Optional) Max exec time for dml. 50 TranTimeout time.Duration `json:"tranTimeout"` // (Optional) Max exec time for a transaction. 51 PrepareTimeout time.Duration `json:"prepareTimeout"` // (Optional) Max exec time for prepare operation. 52 CreatedAt string `json:"createdAt"` // (Optional) The field name of table for automatic-filled created datetime. 53 UpdatedAt string `json:"updatedAt"` // (Optional) The field name of table for automatic-filled updated datetime. 54 DeletedAt string `json:"deletedAt"` // (Optional) The field name of table for automatic-filled updated datetime. 55 TimeMaintainDisabled bool `json:"timeMaintainDisabled"` // (Optional) Disable the automatic time maintaining feature. 56 } 57 58 const ( 59 DefaultGroupName = "default" // Default group name. 60 ) 61 62 // configs specifies internal used configuration object. 63 var configs struct { 64 sync.RWMutex 65 config Config // All configurations. 66 group string // Default configuration group. 67 } 68 69 func init() { 70 configs.config = make(Config) 71 configs.group = DefaultGroupName 72 } 73 74 // SetConfig sets the global configuration for package. 75 // It will overwrite the old configuration of package. 76 func SetConfig(config Config) { 77 defer instances.Clear() 78 configs.Lock() 79 defer configs.Unlock() 80 for k, nodes := range config { 81 for i, node := range nodes { 82 nodes[i] = parseConfigNode(node) 83 } 84 config[k] = nodes 85 } 86 configs.config = config 87 } 88 89 // SetConfigGroup sets the configuration for given group. 90 func SetConfigGroup(group string, nodes ConfigGroup) { 91 defer instances.Clear() 92 configs.Lock() 93 defer configs.Unlock() 94 for i, node := range nodes { 95 nodes[i] = parseConfigNode(node) 96 } 97 configs.config[group] = nodes 98 } 99 100 // AddConfigNode adds one node configuration to configuration of given group. 101 func AddConfigNode(group string, node ConfigNode) { 102 defer instances.Clear() 103 configs.Lock() 104 defer configs.Unlock() 105 configs.config[group] = append(configs.config[group], parseConfigNode(node)) 106 } 107 108 // parseConfigNode parses `Link` configuration syntax. 109 func parseConfigNode(node ConfigNode) ConfigNode { 110 if node.Link != "" { 111 node = *parseConfigNodeLink(&node) 112 } 113 if node.Link != "" && node.Type == "" { 114 match, _ := gregex.MatchString(`([a-z]+):(.+)`, node.Link) 115 if len(match) == 3 { 116 node.Type = gstr.Trim(match[1]) 117 node.Link = gstr.Trim(match[2]) 118 } 119 } 120 return node 121 } 122 123 // AddDefaultConfigNode adds one node configuration to configuration of default group. 124 func AddDefaultConfigNode(node ConfigNode) { 125 AddConfigNode(DefaultGroupName, node) 126 } 127 128 // AddDefaultConfigGroup adds multiple node configurations to configuration of default group. 129 func AddDefaultConfigGroup(nodes ConfigGroup) { 130 SetConfigGroup(DefaultGroupName, nodes) 131 } 132 133 // GetConfig retrieves and returns the configuration of given group. 134 func GetConfig(group string) ConfigGroup { 135 configs.RLock() 136 defer configs.RUnlock() 137 return configs.config[group] 138 } 139 140 // SetDefaultGroup sets the group name for default configuration. 141 func SetDefaultGroup(name string) { 142 defer instances.Clear() 143 configs.Lock() 144 defer configs.Unlock() 145 configs.group = name 146 } 147 148 // GetDefaultGroup returns the { name of default configuration. 149 func GetDefaultGroup() string { 150 defer instances.Clear() 151 configs.RLock() 152 defer configs.RUnlock() 153 return configs.group 154 } 155 156 // IsConfigured checks and returns whether the database configured. 157 // It returns true if any configuration exists. 158 func IsConfigured() bool { 159 configs.RLock() 160 defer configs.RUnlock() 161 return len(configs.config) > 0 162 } 163 164 // SetLogger sets the logger for orm. 165 func (c *Core) SetLogger(logger glog.ILogger) { 166 c.logger = logger 167 } 168 169 // GetLogger returns the (logger) of the orm. 170 func (c *Core) GetLogger() glog.ILogger { 171 return c.logger 172 } 173 174 // SetMaxIdleConnCount sets the maximum number of connections in the idle 175 // connection pool. 176 // 177 // If MaxOpenConns is greater than 0 but less than the new MaxIdleConns, 178 // then the new MaxIdleConns will be reduced to match the MaxOpenConns limit. 179 // 180 // If n <= 0, no idle connections are retained. 181 // 182 // The default max idle connections is currently 2. This may change in 183 // a future release. 184 func (c *Core) SetMaxIdleConnCount(n int) { 185 c.dynamicConfig.MaxIdleConnCount = n 186 } 187 188 // SetMaxOpenConnCount sets the maximum number of open connections to the database. 189 // 190 // If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than 191 // MaxIdleConns, then MaxIdleConns will be reduced to match the new 192 // MaxOpenConns limit. 193 // 194 // If n <= 0, then there is no limit on the number of open connections. 195 // The default is 0 (unlimited). 196 func (c *Core) SetMaxOpenConnCount(n int) { 197 c.dynamicConfig.MaxOpenConnCount = n 198 } 199 200 // SetMaxConnLifeTime sets the maximum amount of time a connection may be reused. 201 // 202 // Expired connections may be closed lazily before reuse. 203 // 204 // If d <= 0, connections are not closed due to a connection's age. 205 func (c *Core) SetMaxConnLifeTime(d time.Duration) { 206 c.dynamicConfig.MaxConnLifeTime = d 207 } 208 209 // GetConfig returns the current used node configuration. 210 func (c *Core) GetConfig() *ConfigNode { 211 var configNode = c.getConfigNodeFromCtx(c.db.GetCtx()) 212 if configNode != nil { 213 // Note: 214 // It so here checks and returns the config from current DB, 215 // if different schemas between current DB and config.Name from context, 216 // for example, in nested transaction scenario, the context is passed all through the logic procedure, 217 // but the config.Name from context may be still the original one from the first transaction object. 218 if c.config.Name == configNode.Name { 219 return configNode 220 } 221 } 222 return c.config 223 } 224 225 // SetDebug enables/disables the debug mode. 226 func (c *Core) SetDebug(debug bool) { 227 c.debug.Set(debug) 228 } 229 230 // GetDebug returns the debug value. 231 func (c *Core) GetDebug() bool { 232 return c.debug.Val() 233 } 234 235 // GetCache returns the internal cache object. 236 func (c *Core) GetCache() *gcache.Cache { 237 return c.cache 238 } 239 240 // GetGroup returns the group string configured. 241 func (c *Core) GetGroup() string { 242 return c.group 243 } 244 245 // SetDryRun enables/disables the DryRun feature. 246 func (c *Core) SetDryRun(enabled bool) { 247 c.config.DryRun = enabled 248 } 249 250 // GetDryRun returns the DryRun value. 251 func (c *Core) GetDryRun() bool { 252 return c.config.DryRun || allDryRun 253 } 254 255 // GetPrefix returns the table prefix string configured. 256 func (c *Core) GetPrefix() string { 257 return c.config.Prefix 258 } 259 260 // GetSchema returns the schema configured. 261 func (c *Core) GetSchema() string { 262 schema := c.schema 263 if schema == "" { 264 schema = c.db.GetConfig().Name 265 } 266 return schema 267 } 268 269 func parseConfigNodeLink(node *ConfigNode) *ConfigNode { 270 var match []string 271 if node.Link != "" { 272 match, _ = gregex.MatchString(linkPattern, node.Link) 273 if len(match) > 5 { 274 node.Type = match[1] 275 node.User = match[2] 276 node.Pass = match[3] 277 node.Protocol = match[4] 278 array := gstr.Split(match[5], ":") 279 if node.Protocol == "file" { 280 node.Name = match[5] 281 } else { 282 if len(array) == 2 { 283 // link with port. 284 node.Host = array[0] 285 node.Port = array[1] 286 } else { 287 // link without port. 288 node.Host = array[0] 289 } 290 node.Name = match[6] 291 } 292 if len(match) > 6 && match[7] != "" { 293 node.Extra = match[7] 294 } 295 node.Link = "" 296 } 297 } 298 if node.Extra != "" { 299 if m, _ := gstr.Parse(node.Extra); len(m) > 0 { 300 _ = gconv.Struct(m, &node) 301 } 302 } 303 // Default value checks. 304 if node.Charset == "" { 305 node.Charset = defaultCharset 306 } 307 if node.Protocol == "" { 308 node.Protocol = defaultProtocol 309 } 310 return node 311 }