main.go 23 KB

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