gorm.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package gorm
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. "github.com/jinzhu/gorm/clause"
  7. "github.com/jinzhu/gorm/logger"
  8. "github.com/jinzhu/gorm/schema"
  9. )
  10. // Config GORM config
  11. type Config struct {
  12. // GORM perform single create, update, delete operations in transactions by default to ensure database data integrity
  13. // You can disable it by setting `SkipDefaultTransaction` to true
  14. SkipDefaultTransaction bool
  15. // NamingStrategy tables, columns naming strategy
  16. NamingStrategy schema.Namer
  17. // Logger
  18. Logger logger.Interface
  19. // NowFunc the function to be used when creating a new timestamp
  20. NowFunc func() time.Time
  21. }
  22. type shared struct {
  23. callbacks *callbacks
  24. cacheStore *sync.Map
  25. quoteChars [2]byte
  26. }
  27. // DB GORM DB definition
  28. type DB struct {
  29. *Config
  30. Dialector
  31. Instance
  32. ClauseBuilders map[string]clause.ClauseBuilder
  33. DB CommonDB
  34. clone bool
  35. *shared
  36. }
  37. // Session session config when create session with Session() method
  38. type Session struct {
  39. Context context.Context
  40. Logger logger.Interface
  41. NowFunc func() time.Time
  42. }
  43. // Open initialize db session based on dialector
  44. func Open(dialector Dialector, config *Config) (db *DB, err error) {
  45. if config == nil {
  46. config = &Config{}
  47. }
  48. if config.NamingStrategy == nil {
  49. config.NamingStrategy = schema.NamingStrategy{}
  50. }
  51. if config.Logger == nil {
  52. config.Logger = logger.Default
  53. }
  54. if config.NowFunc == nil {
  55. config.NowFunc = func() time.Time { return time.Now().Local() }
  56. }
  57. db = &DB{
  58. Config: config,
  59. Dialector: dialector,
  60. ClauseBuilders: map[string]clause.ClauseBuilder{},
  61. clone: true,
  62. shared: &shared{
  63. cacheStore: &sync.Map{},
  64. },
  65. }
  66. db.callbacks = initializeCallbacks(db)
  67. if dialector != nil {
  68. err = dialector.Initialize(db)
  69. db.quoteChars = dialector.QuoteChars()
  70. }
  71. return
  72. }
  73. // Session create new db session
  74. func (db *DB) Session(config *Session) *DB {
  75. var (
  76. tx = db.getInstance()
  77. txConfig = *tx.Config
  78. )
  79. if config.Context != nil {
  80. tx.Context = config.Context
  81. }
  82. if config.Logger != nil {
  83. txConfig.Logger = config.Logger
  84. }
  85. if config.NowFunc != nil {
  86. txConfig.NowFunc = config.NowFunc
  87. }
  88. tx.Config = &txConfig
  89. tx.clone = true
  90. return tx
  91. }
  92. // WithContext change current instance db's context to ctx
  93. func (db *DB) WithContext(ctx context.Context) *DB {
  94. return db.Session(&Session{Context: ctx})
  95. }
  96. // Debug start debug mode
  97. func (db *DB) Debug() (tx *DB) {
  98. return db.Session(&Session{Logger: db.Logger.LogMode(logger.Info)})
  99. }
  100. // Set store value with key into current db instance's context
  101. func (db *DB) Set(key string, value interface{}) *DB {
  102. tx := db.getInstance()
  103. tx.Statement.Settings.Store(key, value)
  104. return tx
  105. }
  106. // Get get value with key from current db instance's context
  107. func (db *DB) Get(key string) (interface{}, bool) {
  108. if db.Statement != nil {
  109. return db.Statement.Settings.Load(key)
  110. }
  111. return nil, false
  112. }
  113. // Callback returns callback manager
  114. func (db *DB) Callback() *callbacks {
  115. return db.callbacks
  116. }
  117. // AutoMigrate run auto migration for given models
  118. func (db *DB) AutoMigrate(dst ...interface{}) error {
  119. return db.Migrator().AutoMigrate(dst...)
  120. }
  121. func (db *DB) getInstance() *DB {
  122. if db.clone {
  123. ctx := db.Instance.Context
  124. if ctx == nil {
  125. ctx = context.Background()
  126. }
  127. return &DB{
  128. Instance: Instance{
  129. Context: ctx,
  130. Statement: &Statement{DB: db, Clauses: map[string]clause.Clause{}},
  131. },
  132. Config: db.Config,
  133. Dialector: db.Dialector,
  134. ClauseBuilders: db.ClauseBuilders,
  135. DB: db.DB,
  136. shared: db.shared,
  137. }
  138. }
  139. return db
  140. }