gins_database.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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/v2/database/gdb"
  11. "github.com/gogf/gf/v2/errors/gcode"
  12. "github.com/gogf/gf/v2/errors/gerror"
  13. "github.com/gogf/gf/v2/internal/consts"
  14. "github.com/gogf/gf/v2/internal/instance"
  15. "github.com/gogf/gf/v2/internal/intlog"
  16. "github.com/gogf/gf/v2/os/gcfg"
  17. "github.com/gogf/gf/v2/os/glog"
  18. "github.com/gogf/gf/v2/util/gconv"
  19. "github.com/gogf/gf/v2/util/gutil"
  20. )
  21. // Database returns an instance of database ORM object with specified configuration group name.
  22. // Note that it panics if any error occurs duration instance creating.
  23. func Database(name ...string) gdb.DB {
  24. var (
  25. ctx = context.Background()
  26. group = gdb.DefaultGroupName
  27. )
  28. if len(name) > 0 && name[0] != "" {
  29. group = name[0]
  30. }
  31. instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameDatabase, group)
  32. db := instance.GetOrSetFuncLock(instanceKey, func() interface{} {
  33. // It ignores returned error to avoid file no found error while it's not necessary.
  34. var (
  35. configMap map[string]interface{}
  36. configNodeKey = consts.ConfigNodeNameDatabase
  37. )
  38. // It firstly searches the configuration of the instance name.
  39. if configData, _ := Config().Data(ctx); len(configData) > 0 {
  40. if v, _ := gutil.MapPossibleItemByKey(configData, consts.ConfigNodeNameDatabase); v != "" {
  41. configNodeKey = v
  42. }
  43. }
  44. if v, _ := Config().Get(ctx, configNodeKey); !v.IsEmpty() {
  45. configMap = v.Map()
  46. }
  47. // No configuration found, it formats and panics error.
  48. if len(configMap) == 0 && !gdb.IsConfigured() {
  49. // File configuration object checks.
  50. var err error
  51. if fileConfig, ok := Config().GetAdapter().(*gcfg.AdapterFile); ok {
  52. if _, err = fileConfig.GetFilePath(); err != nil {
  53. panic(gerror.WrapCode(gcode.CodeMissingConfiguration, err,
  54. `configuration not found, did you miss the configuration file or misspell the configuration file name`,
  55. ))
  56. }
  57. }
  58. // Panic if nothing found in Config object or in gdb configuration.
  59. if len(configMap) == 0 && !gdb.IsConfigured() {
  60. panic(gerror.NewCodef(
  61. gcode.CodeMissingConfiguration,
  62. `database initialization failed: configuration missing for database node "%s"`,
  63. consts.ConfigNodeNameDatabase,
  64. ))
  65. }
  66. }
  67. if len(configMap) == 0 {
  68. configMap = make(map[string]interface{})
  69. }
  70. // Parse `m` as map-slice and adds it to global configurations for package gdb.
  71. for g, groupConfig := range configMap {
  72. cg := gdb.ConfigGroup{}
  73. switch value := groupConfig.(type) {
  74. case []interface{}:
  75. for _, v := range value {
  76. if node := parseDBConfigNode(v); node != nil {
  77. cg = append(cg, *node)
  78. }
  79. }
  80. case map[string]interface{}:
  81. if node := parseDBConfigNode(value); node != nil {
  82. cg = append(cg, *node)
  83. }
  84. }
  85. if len(cg) > 0 {
  86. if gdb.GetConfig(group) == nil {
  87. intlog.Printf(ctx, "add configuration for group: %s, %#v", g, cg)
  88. gdb.SetConfigGroup(g, cg)
  89. } else {
  90. intlog.Printf(ctx, "ignore configuration as it already exists for group: %s, %#v", g, cg)
  91. intlog.Printf(ctx, "%s, %#v", g, cg)
  92. }
  93. }
  94. }
  95. // Parse `m` as a single node configuration,
  96. // which is the default group configuration.
  97. if node := parseDBConfigNode(configMap); node != nil {
  98. cg := gdb.ConfigGroup{}
  99. if node.Link != "" || node.Host != "" {
  100. cg = append(cg, *node)
  101. }
  102. if len(cg) > 0 {
  103. if gdb.GetConfig(group) == nil {
  104. intlog.Printf(ctx, "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg)
  105. gdb.SetConfigGroup(gdb.DefaultGroupName, cg)
  106. } else {
  107. intlog.Printf(
  108. ctx,
  109. "ignore configuration as it already exists for group: %s, %#v",
  110. gdb.DefaultGroupName, cg,
  111. )
  112. intlog.Printf(ctx, "%s, %#v", gdb.DefaultGroupName, cg)
  113. }
  114. }
  115. }
  116. // Create a new ORM object with given configurations.
  117. if db, err := gdb.NewByGroup(name...); err == nil {
  118. // Initialize logger for ORM.
  119. var (
  120. loggerConfigMap map[string]interface{}
  121. loggerNodeName = fmt.Sprintf("%s.%s", configNodeKey, consts.ConfigNodeNameLogger)
  122. )
  123. if v, _ := Config().Get(ctx, loggerNodeName); !v.IsEmpty() {
  124. loggerConfigMap = v.Map()
  125. }
  126. if len(loggerConfigMap) == 0 {
  127. if v, _ := Config().Get(ctx, configNodeKey); !v.IsEmpty() {
  128. loggerConfigMap = v.Map()
  129. }
  130. }
  131. if len(loggerConfigMap) > 0 {
  132. if logger, ok := db.GetLogger().(*glog.Logger); ok {
  133. if err = logger.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. func parseDBConfigNode(value interface{}) *gdb.ConfigNode {
  151. nodeMap, ok := value.(map[string]interface{})
  152. if !ok {
  153. return nil
  154. }
  155. var (
  156. node = &gdb.ConfigNode{}
  157. err = gconv.Struct(nodeMap, node)
  158. )
  159. if err != nil {
  160. panic(err)
  161. }
  162. // Find possible `Link` configuration content.
  163. if _, v := gutil.MapPossibleItemByKey(nodeMap, "Link"); v != nil {
  164. node.Link = gconv.String(v)
  165. }
  166. return node
  167. }