main.go 24 KB

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