main.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. package gorm
  2. import (
  3. "database/sql"
  4. "errors"
  5. "fmt"
  6. "reflect"
  7. "strings"
  8. "time"
  9. )
  10. // DB contains information for current db connection
  11. type DB struct {
  12. Value interface{}
  13. Error error
  14. RowsAffected int64
  15. callbacks *Callback
  16. db sqlCommon
  17. parent *DB
  18. search *search
  19. logMode int
  20. logger logger
  21. dialect Dialect
  22. singularTable bool
  23. source string
  24. values map[string]interface{}
  25. joinTableHandlers map[string]JoinTableHandler
  26. blockGlobalUpdate bool
  27. }
  28. // Open initialize a new db connection, need to import driver first, e.g:
  29. //
  30. // import _ "github.com/go-sql-driver/mysql"
  31. // func main() {
  32. // db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
  33. // }
  34. // GORM has wrapped some drivers, for easier to remember driver's import path, so you could import the mysql driver with
  35. // import _ "github.com/jinzhu/gorm/dialects/mysql"
  36. // // import _ "github.com/jinzhu/gorm/dialects/postgres"
  37. // // import _ "github.com/jinzhu/gorm/dialects/sqlite"
  38. // // import _ "github.com/jinzhu/gorm/dialects/mssql"
  39. func Open(dialect string, args ...interface{}) (*DB, error) {
  40. var db DB
  41. var err error
  42. if len(args) == 0 {
  43. err = errors.New("invalid database source")
  44. return nil, err
  45. }
  46. var source string
  47. var dbSQL sqlCommon
  48. switch value := args[0].(type) {
  49. case string:
  50. var driver = dialect
  51. if len(args) == 1 {
  52. source = value
  53. } else if len(args) >= 2 {
  54. driver = value
  55. source = args[1].(string)
  56. }
  57. dbSQL, err = sql.Open(driver, source)
  58. case sqlCommon:
  59. source = reflect.Indirect(reflect.ValueOf(value)).FieldByName("dsn").String()
  60. dbSQL = value
  61. }
  62. db = DB{
  63. dialect: newDialect(dialect, dbSQL.(*sql.DB)),
  64. logger: defaultLogger,
  65. callbacks: DefaultCallback,
  66. source: source,
  67. values: map[string]interface{}{},
  68. db: dbSQL,
  69. }
  70. db.parent = &db
  71. if err == nil {
  72. err = db.DB().Ping() // Send a ping to make sure the database connection is alive.
  73. if err != nil {
  74. db.DB().Close()
  75. }
  76. }
  77. return &db, err
  78. }
  79. // Close close current db connection
  80. func (s *DB) Close() error {
  81. return s.parent.db.(*sql.DB).Close()
  82. }
  83. // DB get `*sql.DB` from current connection
  84. func (s *DB) DB() *sql.DB {
  85. return s.db.(*sql.DB)
  86. }
  87. // Dialect get dialect
  88. func (s *DB) Dialect() Dialect {
  89. return s.parent.dialect
  90. }
  91. // New clone a new db connection without search conditions
  92. func (s *DB) New() *DB {
  93. clone := s.clone()
  94. clone.search = nil
  95. clone.Value = nil
  96. return clone
  97. }
  98. // NewScope create a scope for current operation
  99. func (s *DB) NewScope(value interface{}) *Scope {
  100. dbClone := s.clone()
  101. dbClone.Value = value
  102. return &Scope{db: dbClone, Search: dbClone.search.clone(), Value: value}
  103. }
  104. // CommonDB return the underlying `*sql.DB` or `*sql.Tx` instance, mainly intended to allow coexistence with legacy non-GORM code.
  105. func (s *DB) CommonDB() sqlCommon {
  106. return s.db
  107. }
  108. // Callback return `Callbacks` container, you could add/change/delete callbacks with it
  109. // db.Callback().Create().Register("update_created_at", updateCreated)
  110. // Refer https://jinzhu.github.io/gorm/development.html#callbacks
  111. func (s *DB) Callback() *Callback {
  112. s.parent.callbacks = s.parent.callbacks.clone()
  113. return s.parent.callbacks
  114. }
  115. // SetLogger replace default logger
  116. func (s *DB) SetLogger(log logger) {
  117. s.logger = log
  118. }
  119. // LogMode set log mode, `true` for detailed logs, `false` for no log, default, will only print error logs
  120. func (s *DB) LogMode(enable bool) *DB {
  121. if enable {
  122. s.logMode = 2
  123. } else {
  124. s.logMode = 1
  125. }
  126. return s
  127. }
  128. // BlockGlobalUpdate if true, generates an error on update/delete without where clause.
  129. // This is to prevent eventual error with empty objects updates/deletions
  130. func (s *DB) BlockGlobalUpdate(enable bool) *DB {
  131. s.blockGlobalUpdate = enable
  132. return s
  133. }
  134. // HasBlockGlobalUpdate return state of block
  135. func (s *DB) HasBlockGlobalUpdate() bool {
  136. return s.blockGlobalUpdate
  137. }
  138. // SingularTable use singular table by default
  139. func (s *DB) SingularTable(enable bool) {
  140. modelStructsMap = newModelStructsMap()
  141. s.parent.singularTable = enable
  142. }
  143. // Where return a new relation, filter records with given conditions, accepts `map`, `struct` or `string` as conditions, refer http://jinzhu.github.io/gorm/crud.html#query
  144. func (s *DB) Where(query interface{}, args ...interface{}) *DB {
  145. return s.clone().search.Where(query, args...).db
  146. }
  147. // Or filter records that match before conditions or this one, similar to `Where`
  148. func (s *DB) Or(query interface{}, args ...interface{}) *DB {
  149. return s.clone().search.Or(query, args...).db
  150. }
  151. // Not filter records that don't match current conditions, similar to `Where`
  152. func (s *DB) Not(query interface{}, args ...interface{}) *DB {
  153. return s.clone().search.Not(query, args...).db
  154. }
  155. // Limit specify the number of records to be retrieved
  156. func (s *DB) Limit(limit interface{}) *DB {
  157. return s.clone().search.Limit(limit).db
  158. }
  159. // Offset specify the number of records to skip before starting to return the records
  160. func (s *DB) Offset(offset interface{}) *DB {
  161. return s.clone().search.Offset(offset).db
  162. }
  163. // Order specify order when retrieve records from database, set reorder to `true` to overwrite defined conditions
  164. // db.Order("name DESC")
  165. // db.Order("name DESC", true) // reorder
  166. // db.Order(gorm.Expr("name = ? DESC", "first")) // sql expression
  167. func (s *DB) Order(value interface{}, reorder ...bool) *DB {
  168. return s.clone().search.Order(value, reorder...).db
  169. }
  170. // Select specify fields that you want to retrieve from database when querying, by default, will select all fields;
  171. // When creating/updating, specify fields that you want to save to database
  172. func (s *DB) Select(query interface{}, args ...interface{}) *DB {
  173. return s.clone().search.Select(query, args...).db
  174. }
  175. // Omit specify fields that you want to ignore when saving to database for creating, updating
  176. func (s *DB) Omit(columns ...string) *DB {
  177. return s.clone().search.Omit(columns...).db
  178. }
  179. // Group specify the group method on the find
  180. func (s *DB) Group(query string) *DB {
  181. return s.clone().search.Group(query).db
  182. }
  183. // Having specify HAVING conditions for GROUP BY
  184. func (s *DB) Having(query string, values ...interface{}) *DB {
  185. return s.clone().search.Having(query, values...).db
  186. }
  187. // Joins specify Joins conditions
  188. // db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user)
  189. func (s *DB) Joins(query string, args ...interface{}) *DB {
  190. return s.clone().search.Joins(query, args...).db
  191. }
  192. // Scopes pass current database connection to arguments `func(*DB) *DB`, which could be used to add conditions dynamically
  193. // func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
  194. // return db.Where("amount > ?", 1000)
  195. // }
  196. //
  197. // func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
  198. // return func (db *gorm.DB) *gorm.DB {
  199. // return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status)
  200. // }
  201. // }
  202. //
  203. // db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
  204. // Refer https://jinzhu.github.io/gorm/crud.html#scopes
  205. func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB {
  206. for _, f := range funcs {
  207. s = f(s)
  208. }
  209. return s
  210. }
  211. // Unscoped return all record including deleted record, refer Soft Delete https://jinzhu.github.io/gorm/crud.html#soft-delete
  212. func (s *DB) Unscoped() *DB {
  213. return s.clone().search.unscoped().db
  214. }
  215. // Attrs initialize struct with argument if record not found with `FirstOrInit` https://jinzhu.github.io/gorm/crud.html#firstorinit or `FirstOrCreate` https://jinzhu.github.io/gorm/crud.html#firstorcreate
  216. func (s *DB) Attrs(attrs ...interface{}) *DB {
  217. return s.clone().search.Attrs(attrs...).db
  218. }
  219. // Assign assign result with argument regardless it is found or not with `FirstOrInit` https://jinzhu.github.io/gorm/crud.html#firstorinit or `FirstOrCreate` https://jinzhu.github.io/gorm/crud.html#firstorcreate
  220. func (s *DB) Assign(attrs ...interface{}) *DB {
  221. return s.clone().search.Assign(attrs...).db
  222. }
  223. // First find first record that match given conditions, order by primary key
  224. func (s *DB) First(out interface{}, where ...interface{}) *DB {
  225. newScope := s.clone().NewScope(out)
  226. newScope.Search.Limit(1)
  227. return newScope.Set("gorm:order_by_primary_key", "ASC").
  228. inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db
  229. }
  230. // Last find last record that match given conditions, order by primary key
  231. func (s *DB) Last(out interface{}, where ...interface{}) *DB {
  232. newScope := s.clone().NewScope(out)
  233. newScope.Search.Limit(1)
  234. return newScope.Set("gorm:order_by_primary_key", "DESC").
  235. inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db
  236. }
  237. // Find find records that match given conditions
  238. func (s *DB) Find(out interface{}, where ...interface{}) *DB {
  239. return s.clone().NewScope(out).inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db
  240. }
  241. // Scan scan value to a struct
  242. func (s *DB) Scan(dest interface{}) *DB {
  243. return s.clone().NewScope(s.Value).Set("gorm:query_destination", dest).callCallbacks(s.parent.callbacks.queries).db
  244. }
  245. // Row return `*sql.Row` with given conditions
  246. func (s *DB) Row() *sql.Row {
  247. return s.NewScope(s.Value).row()
  248. }
  249. // Rows return `*sql.Rows` with given conditions
  250. func (s *DB) Rows() (*sql.Rows, error) {
  251. return s.NewScope(s.Value).rows()
  252. }
  253. // ScanRows scan `*sql.Rows` to give struct
  254. func (s *DB) ScanRows(rows *sql.Rows, result interface{}) error {
  255. var (
  256. clone = s.clone()
  257. scope = clone.NewScope(result)
  258. columns, err = rows.Columns()
  259. )
  260. if clone.AddError(err) == nil {
  261. scope.scan(rows, columns, scope.Fields())
  262. }
  263. return clone.Error
  264. }
  265. // Pluck used to query single column from a model as a map
  266. // var ages []int64
  267. // db.Find(&users).Pluck("age", &ages)
  268. func (s *DB) Pluck(column string, value interface{}) *DB {
  269. return s.NewScope(s.Value).pluck(column, value).db
  270. }
  271. // Count get how many records for a model
  272. func (s *DB) Count(value interface{}) *DB {
  273. return s.NewScope(s.Value).count(value).db
  274. }
  275. // Related get related associations
  276. func (s *DB) Related(value interface{}, foreignKeys ...string) *DB {
  277. return s.clone().NewScope(s.Value).related(value, foreignKeys...).db
  278. }
  279. // FirstOrInit find first matched record or initialize a new one with given conditions (only works with struct, map conditions)
  280. // https://jinzhu.github.io/gorm/crud.html#firstorinit
  281. func (s *DB) FirstOrInit(out interface{}, where ...interface{}) *DB {
  282. c := s.clone()
  283. if result := c.First(out, where...); result.Error != nil {
  284. if !result.RecordNotFound() {
  285. return result
  286. }
  287. c.NewScope(out).inlineCondition(where...).initialize()
  288. } else {
  289. c.NewScope(out).updatedAttrsWithValues(c.search.assignAttrs)
  290. }
  291. return c
  292. }
  293. // FirstOrCreate find first matched record or create a new one with given conditions (only works with struct, map conditions)
  294. // https://jinzhu.github.io/gorm/crud.html#firstorcreate
  295. func (s *DB) FirstOrCreate(out interface{}, where ...interface{}) *DB {
  296. c := s.clone()
  297. if result := s.First(out, where...); result.Error != nil {
  298. if !result.RecordNotFound() {
  299. return result
  300. }
  301. return c.NewScope(out).inlineCondition(where...).initialize().callCallbacks(c.parent.callbacks.creates).db
  302. } else if len(c.search.assignAttrs) > 0 {
  303. return c.NewScope(out).InstanceSet("gorm:update_interface", c.search.assignAttrs).callCallbacks(c.parent.callbacks.updates).db
  304. }
  305. return c
  306. }
  307. // Update update attributes with callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update
  308. func (s *DB) Update(attrs ...interface{}) *DB {
  309. return s.Updates(toSearchableMap(attrs...), true)
  310. }
  311. // Updates update attributes with callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update
  312. func (s *DB) Updates(values interface{}, ignoreProtectedAttrs ...bool) *DB {
  313. return s.clone().NewScope(s.Value).
  314. Set("gorm:ignore_protected_attrs", len(ignoreProtectedAttrs) > 0).
  315. InstanceSet("gorm:update_interface", values).
  316. callCallbacks(s.parent.callbacks.updates).db
  317. }
  318. // UpdateColumn update attributes without callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update
  319. func (s *DB) UpdateColumn(attrs ...interface{}) *DB {
  320. return s.UpdateColumns(toSearchableMap(attrs...))
  321. }
  322. // UpdateColumns update attributes without callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update
  323. func (s *DB) UpdateColumns(values interface{}) *DB {
  324. return s.clone().NewScope(s.Value).
  325. Set("gorm:update_column", true).
  326. Set("gorm:save_associations", false).
  327. InstanceSet("gorm:update_interface", values).
  328. callCallbacks(s.parent.callbacks.updates).db
  329. }
  330. // Save update value in database, if the value doesn't have primary key, will insert it
  331. func (s *DB) Save(value interface{}) *DB {
  332. scope := s.clone().NewScope(value)
  333. if !scope.PrimaryKeyZero() {
  334. newDB := scope.callCallbacks(s.parent.callbacks.updates).db
  335. if newDB.Error == nil && newDB.RowsAffected == 0 {
  336. return s.New().FirstOrCreate(value)
  337. }
  338. return newDB
  339. }
  340. return scope.callCallbacks(s.parent.callbacks.creates).db
  341. }
  342. // Create insert the value into database
  343. func (s *DB) Create(value interface{}) *DB {
  344. scope := s.clone().NewScope(value)
  345. return scope.callCallbacks(s.parent.callbacks.creates).db
  346. }
  347. // Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition
  348. func (s *DB) Delete(value interface{}, where ...interface{}) *DB {
  349. return s.clone().NewScope(value).inlineCondition(where...).callCallbacks(s.parent.callbacks.deletes).db
  350. }
  351. // Raw use raw sql as conditions, won't run it unless invoked by other methods
  352. // db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
  353. func (s *DB) Raw(sql string, values ...interface{}) *DB {
  354. return s.clone().search.Raw(true).Where(sql, values...).db
  355. }
  356. // Exec execute raw sql
  357. func (s *DB) Exec(sql string, values ...interface{}) *DB {
  358. scope := s.clone().NewScope(nil)
  359. generatedSQL := scope.buildWhereCondition(map[string]interface{}{"query": sql, "args": values})
  360. generatedSQL = strings.TrimSuffix(strings.TrimPrefix(generatedSQL, "("), ")")
  361. scope.Raw(generatedSQL)
  362. return scope.Exec().db
  363. }
  364. // Model specify the model you would like to run db operations
  365. // // update all users's name to `hello`
  366. // db.Model(&User{}).Update("name", "hello")
  367. // // if user's primary key is non-blank, will use it as condition, then will only update the user's name to `hello`
  368. // db.Model(&user).Update("name", "hello")
  369. func (s *DB) Model(value interface{}) *DB {
  370. c := s.clone()
  371. c.Value = value
  372. return c
  373. }
  374. // Table specify the table you would like to run db operations
  375. func (s *DB) Table(name string) *DB {
  376. clone := s.clone()
  377. clone.search.Table(name)
  378. clone.Value = nil
  379. return clone
  380. }
  381. // Debug start debug mode
  382. func (s *DB) Debug() *DB {
  383. return s.clone().LogMode(true)
  384. }
  385. // Begin begin a transaction
  386. func (s *DB) Begin() *DB {
  387. c := s.clone()
  388. if db, ok := c.db.(sqlDb); ok {
  389. tx, err := db.Begin()
  390. c.db = interface{}(tx).(sqlCommon)
  391. c.AddError(err)
  392. } else {
  393. c.AddError(ErrCantStartTransaction)
  394. }
  395. return c
  396. }
  397. // Commit commit a transaction
  398. func (s *DB) Commit() *DB {
  399. if db, ok := s.db.(sqlTx); ok {
  400. s.AddError(db.Commit())
  401. } else {
  402. s.AddError(ErrInvalidTransaction)
  403. }
  404. return s
  405. }
  406. // Rollback rollback a transaction
  407. func (s *DB) Rollback() *DB {
  408. if db, ok := s.db.(sqlTx); ok {
  409. s.AddError(db.Rollback())
  410. } else {
  411. s.AddError(ErrInvalidTransaction)
  412. }
  413. return s
  414. }
  415. // NewRecord check if value's primary key is blank
  416. func (s *DB) NewRecord(value interface{}) bool {
  417. return s.clone().NewScope(value).PrimaryKeyZero()
  418. }
  419. // RecordNotFound check if returning ErrRecordNotFound error
  420. func (s *DB) RecordNotFound() bool {
  421. for _, err := range s.GetErrors() {
  422. if err == ErrRecordNotFound {
  423. return true
  424. }
  425. }
  426. return false
  427. }
  428. // CreateTable create table for models
  429. func (s *DB) CreateTable(models ...interface{}) *DB {
  430. db := s.Unscoped()
  431. for _, model := range models {
  432. db = db.NewScope(model).createTable().db
  433. }
  434. return db
  435. }
  436. // DropTable drop table for models
  437. func (s *DB) DropTable(values ...interface{}) *DB {
  438. db := s.clone()
  439. for _, value := range values {
  440. if tableName, ok := value.(string); ok {
  441. db = db.Table(tableName)
  442. }
  443. db = db.NewScope(value).dropTable().db
  444. }
  445. return db
  446. }
  447. // DropTableIfExists drop table if it is exist
  448. func (s *DB) DropTableIfExists(values ...interface{}) *DB {
  449. db := s.clone()
  450. for _, value := range values {
  451. if s.HasTable(value) {
  452. db.AddError(s.DropTable(value).Error)
  453. }
  454. }
  455. return db
  456. }
  457. // HasTable check has table or not
  458. func (s *DB) HasTable(value interface{}) bool {
  459. var (
  460. scope = s.clone().NewScope(value)
  461. tableName string
  462. )
  463. if name, ok := value.(string); ok {
  464. tableName = name
  465. } else {
  466. tableName = scope.TableName()
  467. }
  468. has := scope.Dialect().HasTable(tableName)
  469. s.AddError(scope.db.Error)
  470. return has
  471. }
  472. // AutoMigrate run auto migration for given models, will only add missing fields, won't delete/change current data
  473. func (s *DB) AutoMigrate(values ...interface{}) *DB {
  474. db := s.Unscoped()
  475. for _, value := range values {
  476. db = db.NewScope(value).autoMigrate().db
  477. }
  478. return db
  479. }
  480. // ModifyColumn modify column to type
  481. func (s *DB) ModifyColumn(column string, typ string) *DB {
  482. scope := s.clone().NewScope(s.Value)
  483. scope.modifyColumn(column, typ)
  484. return scope.db
  485. }
  486. // DropColumn drop a column
  487. func (s *DB) DropColumn(column string) *DB {
  488. scope := s.clone().NewScope(s.Value)
  489. scope.dropColumn(column)
  490. return scope.db
  491. }
  492. // AddIndex add index for columns with given name
  493. func (s *DB) AddIndex(indexName string, columns ...string) *DB {
  494. scope := s.Unscoped().NewScope(s.Value)
  495. scope.addIndex(false, indexName, columns...)
  496. return scope.db
  497. }
  498. // AddUniqueIndex add unique index for columns with given name
  499. func (s *DB) AddUniqueIndex(indexName string, columns ...string) *DB {
  500. scope := s.Unscoped().NewScope(s.Value)
  501. scope.addIndex(true, indexName, columns...)
  502. return scope.db
  503. }
  504. // RemoveIndex remove index with name
  505. func (s *DB) RemoveIndex(indexName string) *DB {
  506. scope := s.clone().NewScope(s.Value)
  507. scope.removeIndex(indexName)
  508. return scope.db
  509. }
  510. // AddForeignKey Add foreign key to the given scope, e.g:
  511. // db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT")
  512. func (s *DB) AddForeignKey(field string, dest string, onDelete string, onUpdate string) *DB {
  513. scope := s.clone().NewScope(s.Value)
  514. scope.addForeignKey(field, dest, onDelete, onUpdate)
  515. return scope.db
  516. }
  517. // Association start `Association Mode` to handler relations things easir in that mode, refer: https://jinzhu.github.io/gorm/associations.html#association-mode
  518. func (s *DB) Association(column string) *Association {
  519. var err error
  520. var scope = s.Set("gorm:association:source", s.Value).NewScope(s.Value)
  521. if primaryField := scope.PrimaryField(); primaryField.IsBlank {
  522. err = errors.New("primary key can't be nil")
  523. } else {
  524. if field, ok := scope.FieldByName(column); ok {
  525. if field.Relationship == nil || len(field.Relationship.ForeignFieldNames) == 0 {
  526. err = fmt.Errorf("invalid association %v for %v", column, scope.IndirectValue().Type())
  527. } else {
  528. return &Association{scope: scope, column: column, field: field}
  529. }
  530. } else {
  531. err = fmt.Errorf("%v doesn't have column %v", scope.IndirectValue().Type(), column)
  532. }
  533. }
  534. return &Association{Error: err}
  535. }
  536. // Preload preload associations with given conditions
  537. // db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
  538. func (s *DB) Preload(column string, conditions ...interface{}) *DB {
  539. return s.clone().search.Preload(column, conditions...).db
  540. }
  541. // Set set setting by name, which could be used in callbacks, will clone a new db, and update its setting
  542. func (s *DB) Set(name string, value interface{}) *DB {
  543. return s.clone().InstantSet(name, value)
  544. }
  545. // InstantSet instant set setting, will affect current db
  546. func (s *DB) InstantSet(name string, value interface{}) *DB {
  547. s.values[name] = value
  548. return s
  549. }
  550. // Get get setting by name
  551. func (s *DB) Get(name string) (value interface{}, ok bool) {
  552. value, ok = s.values[name]
  553. return
  554. }
  555. // SetJoinTableHandler set a model's join table handler for a relation
  556. func (s *DB) SetJoinTableHandler(source interface{}, column string, handler JoinTableHandlerInterface) {
  557. scope := s.NewScope(source)
  558. for _, field := range scope.GetModelStruct().StructFields {
  559. if field.Name == column || field.DBName == column {
  560. if many2many := field.TagSettings["MANY2MANY"]; many2many != "" {
  561. source := (&Scope{Value: source}).GetModelStruct().ModelType
  562. destination := (&Scope{Value: reflect.New(field.Struct.Type).Interface()}).GetModelStruct().ModelType
  563. handler.Setup(field.Relationship, many2many, source, destination)
  564. field.Relationship.JoinTableHandler = handler
  565. if table := handler.Table(s); scope.Dialect().HasTable(table) {
  566. s.Table(table).AutoMigrate(handler)
  567. }
  568. }
  569. }
  570. }
  571. }
  572. // AddError add error to the db
  573. func (s *DB) AddError(err error) error {
  574. if err != nil {
  575. if err != ErrRecordNotFound {
  576. if s.logMode == 0 {
  577. go s.print(fileWithLineNum(), err)
  578. } else {
  579. s.log(err)
  580. }
  581. errors := Errors(s.GetErrors())
  582. errors = errors.Add(err)
  583. if len(errors) > 1 {
  584. err = errors
  585. }
  586. }
  587. s.Error = err
  588. }
  589. return err
  590. }
  591. // GetErrors get happened errors from the db
  592. func (s *DB) GetErrors() []error {
  593. if errs, ok := s.Error.(Errors); ok {
  594. return errs
  595. } else if s.Error != nil {
  596. return []error{s.Error}
  597. }
  598. return []error{}
  599. }
  600. ////////////////////////////////////////////////////////////////////////////////
  601. // Private Methods For *gorm.DB
  602. ////////////////////////////////////////////////////////////////////////////////
  603. func (s *DB) clone() *DB {
  604. db := DB{
  605. db: s.db,
  606. parent: s.parent,
  607. logger: s.logger,
  608. logMode: s.logMode,
  609. values: map[string]interface{}{},
  610. Value: s.Value,
  611. Error: s.Error,
  612. blockGlobalUpdate: s.blockGlobalUpdate,
  613. }
  614. for key, value := range s.values {
  615. db.values[key] = value
  616. }
  617. if s.search == nil {
  618. db.search = &search{limit: -1, offset: -1}
  619. } else {
  620. db.search = s.search.clone()
  621. }
  622. db.search.db = &db
  623. return &db
  624. }
  625. func (s *DB) print(v ...interface{}) {
  626. s.logger.(logger).Print(v...)
  627. }
  628. func (s *DB) log(v ...interface{}) {
  629. if s != nil && s.logMode == 2 {
  630. s.print(append([]interface{}{"log", fileWithLineNum()}, v...)...)
  631. }
  632. }
  633. func (s *DB) slog(sql string, t time.Time, vars ...interface{}) {
  634. if s.logMode == 2 {
  635. s.print("sql", fileWithLineNum(), NowFunc().Sub(t), sql, vars)
  636. }
  637. }