main.go 25 KB

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