github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf.
     6  
     7  package gdb
     8  
     9  import (
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/wangyougui/gf/v2/os/gcache"
    14  	"github.com/wangyougui/gf/v2/os/glog"
    15  	"github.com/wangyougui/gf/v2/text/gregex"
    16  	"github.com/wangyougui/gf/v2/text/gstr"
    17  	"github.com/wangyougui/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  	internalData := c.GetInternalCtxDataFromCtx(c.db.GetCtx())
   212  	if internalData != nil && internalData.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 == internalData.ConfigNode.Name {
   219  			return internalData.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 len(array) == 2 && node.Protocol != "file" {
   280  				node.Host = array[0]
   281  				node.Port = array[1]
   282  				node.Name = match[6]
   283  			} else {
   284  				node.Name = match[5]
   285  			}
   286  			if len(match) > 6 && match[7] != "" {
   287  				node.Extra = match[7]
   288  			}
   289  			node.Link = ""
   290  		}
   291  	}
   292  	if node.Extra != "" {
   293  		if m, _ := gstr.Parse(node.Extra); len(m) > 0 {
   294  			_ = gconv.Struct(m, &node)
   295  		}
   296  	}
   297  	// Default value checks.
   298  	if node.Charset == "" {
   299  		node.Charset = defaultCharset
   300  	}
   301  	if node.Protocol == "" {
   302  		node.Protocol = defaultProtocol
   303  	}
   304  	return node
   305  }