main.go 26 KB

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