gins_database.go 4.9 KB

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