OSDN Git Service

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