gins_database.go 5.4 KB

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