2013-10-25 14:04:48 +04:00
package gorm
2013-11-16 07:36:30 +04:00
import (
"database/sql"
2014-07-30 16:48:36 +04:00
"errors"
"fmt"
"reflect"
2015-01-20 07:15:24 +03:00
"strings"
2016-03-08 16:45:20 +03:00
"time"
2013-11-16 14:01:44 +04:00
)
2013-11-10 18:29:53 +04:00
2016-03-07 09:54:20 +03:00
// DB contains information for current db connection
2013-10-25 14:04:48 +04:00
type DB struct {
2015-02-28 06:48:18 +03:00
Value interface { }
Error error
RowsAffected int64
2016-01-16 16:55:00 +03:00
callbacks * Callback
2015-02-28 06:48:18 +03:00
db sqlCommon
parent * DB
search * search
logMode int
logger logger
dialect Dialect
singularTable bool
source string
values map [ string ] interface { }
joinTableHandlers map [ string ] JoinTableHandler
2013-10-25 14:04:48 +04:00
}
2016-03-07 16:09:05 +03:00
// Open initialize a new db connection, need to import driver first, e.g:
2016-03-07 09:54:20 +03:00
//
// import _ "github.com/go-sql-driver/mysql"
// func main() {
// db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
// }
2016-03-07 16:09:05 +03:00
// GORM has wrapped some drivers, for easier to remember driver's import path, so you could import the mysql driver with
2016-03-07 09:54:20 +03:00
// import _ "github.com/jinzhu/gorm/dialects/mysql"
2016-03-07 16:09:05 +03:00
// // import _ "github.com/jinzhu/gorm/dialects/postgres"
// // import _ "github.com/jinzhu/gorm/dialects/sqlite"
// // import _ "github.com/jinzhu/gorm/dialects/mssql"
2016-01-10 16:26:55 +03:00
func Open ( dialect string , args ... interface { } ) ( * DB , error ) {
2014-08-05 06:32:15 +04:00
var db DB
2014-01-23 12:43:39 +04:00
var err error
2014-08-05 06:32:15 +04:00
2014-11-22 22:24:26 +03:00
if len ( args ) == 0 {
2014-08-05 06:32:15 +04:00
err = errors . New ( "invalid database source" )
2015-02-17 17:55:14 +03:00
} else {
var source string
2016-03-07 09:54:20 +03:00
var dbSQL sqlCommon
2015-02-17 17:55:14 +03:00
switch value := args [ 0 ] . ( type ) {
case string :
var driver = dialect
if len ( args ) == 1 {
source = value
} else if len ( args ) >= 2 {
driver = value
source = args [ 1 ] . ( string )
}
2016-03-07 09:54:20 +03:00
dbSQL , err = sql . Open ( driver , source )
2015-02-17 17:55:14 +03:00
case sqlCommon :
source = reflect . Indirect ( reflect . ValueOf ( value ) ) . FieldByName ( "dsn" ) . String ( )
2016-03-07 09:54:20 +03:00
dbSQL = value
2015-02-17 17:55:14 +03:00
}
2014-08-05 06:32:15 +04:00
2015-02-17 17:55:14 +03:00
db = DB {
2016-03-07 09:54:20 +03:00
dialect : newDialect ( dialect , dbSQL . ( * sql . DB ) ) ,
2016-01-16 14:20:52 +03:00
logger : defaultLogger ,
2016-03-05 14:22:29 +03:00
callbacks : DefaultCallback ,
2016-01-16 14:20:52 +03:00
source : source ,
values : map [ string ] interface { } { } ,
2016-03-07 09:54:20 +03:00
db : dbSQL ,
2014-11-22 22:24:26 +03:00
}
2015-02-17 17:55:14 +03:00
db . parent = & db
2015-08-02 02:37:33 +03:00
if err == nil {
err = db . DB ( ) . Ping ( ) // Send a ping to make sure the database connection is alive.
}
2014-08-05 06:32:15 +04:00
}
2014-11-22 22:24:26 +03:00
2016-01-10 16:26:55 +03:00
return & db , err
2013-10-25 14:04:48 +04:00
}
2016-03-07 09:54:20 +03:00
// Close close current db connection
2014-04-24 06:54:27 +04:00
func ( s * DB ) Close ( ) error {
return s . parent . db . ( * sql . DB ) . Close ( )
}
2016-03-07 09:54:20 +03:00
// DB get `*sql.DB` from current connection
2013-12-04 10:29:44 +04:00
func ( s * DB ) DB ( ) * sql . DB {
return s . db . ( * sql . DB )
}
2016-03-07 16:09:05 +03:00
// New clone a new db connection without search conditions
2015-03-04 08:55:39 +03:00
func ( s * DB ) New ( ) * DB {
clone := s . clone ( )
clone . search = nil
clone . Value = nil
return clone
}
2016-03-07 09:54:20 +03:00
// NewScope create a scope for current operation
2016-01-15 16:03:35 +03:00
func ( s * DB ) NewScope ( value interface { } ) * Scope {
dbClone := s . clone ( )
2015-02-26 07:35:33 +03:00
dbClone . Value = value
2015-03-12 08:52:29 +03:00
return & Scope { db : dbClone , Search : dbClone . search . clone ( ) , Value : value }
2015-02-26 07:35:33 +03:00
}
2016-03-07 16:09:05 +03:00
// CommonDB return the underlying `*sql.DB` or `*sql.Tx` instance, mainly intended to allow coexistence with legacy non-GORM code.
2014-03-17 14:08:44 +04:00
func ( s * DB ) CommonDB ( ) sqlCommon {
return s . db
2014-03-16 20:24:32 +04:00
}
2016-03-07 16:09:05 +03:00
// Callback return `Callbacks` container, you could add/change/delete callbacks with it
2016-03-07 09:54:20 +03:00
// db.Callback().Create().Register("update_created_at", updateCreated)
2016-03-07 16:09:05 +03:00
// Refer https://jinzhu.github.io/gorm/development.html#callbacks
2016-01-16 16:55:00 +03:00
func ( s * DB ) Callback ( ) * Callback {
2016-01-16 14:20:52 +03:00
s . parent . callbacks = s . parent . callbacks . clone ( )
return s . parent . callbacks
2014-01-29 06:25:58 +04:00
}
2016-03-07 09:54:20 +03:00
// SetLogger replace default logger
func ( s * DB ) SetLogger ( log logger ) {
s . logger = log
2013-11-11 05:05:14 +04:00
}
2016-03-07 09:54:20 +03:00
// LogMode set log mode, `true` for detailed logs, `false` for no log, default, will only print error logs
2015-02-17 17:55:14 +03:00
func ( s * DB ) LogMode ( enable bool ) * DB {
if enable {
2013-12-17 15:16:03 +04:00
s . logMode = 2
} else {
s . logMode = 1
}
2013-11-16 11:01:31 +04:00
return s
2013-11-16 07:36:30 +04:00
}
2016-03-07 09:54:20 +03:00
// SingularTable use singular table by default
2015-02-17 17:55:14 +03:00
func ( s * DB ) SingularTable ( enable bool ) {
2015-10-01 02:09:00 +03:00
modelStructsMap = newModelStructsMap ( )
2015-02-17 17:55:14 +03:00
s . parent . singularTable = enable
2013-11-16 07:36:30 +04:00
}
2016-03-07 16:09:05 +03:00
// Where return a new relation, filter records with given conditions, accepts `map`, `struct` or `string` as conditions, refer http://jinzhu.github.io/gorm/curd.html#query
2013-11-16 07:36:30 +04:00
func ( s * DB ) Where ( query interface { } , args ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Where ( query , args ... ) . db
2013-11-16 07:36:30 +04:00
}
2016-03-07 16:09:05 +03:00
// Or filter records that match before conditions or this one, similar to `Where`
2013-11-16 07:36:30 +04:00
func ( s * DB ) Or ( query interface { } , args ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Or ( query , args ... ) . db
2013-11-16 07:36:30 +04:00
}
2016-03-07 16:09:05 +03:00
// Not filter records that don't match current conditions, similar to `Where`
2013-11-16 07:36:30 +04:00
func ( s * DB ) Not ( query interface { } , args ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Not ( query , args ... ) . db
2013-11-16 07:36:30 +04:00
}
2016-03-07 09:54:20 +03:00
// Limit specify the number of records to be retrieved
2016-01-18 15:32:52 +03:00
func ( s * DB ) Limit ( limit int ) * DB {
return s . clone ( ) . search . Limit ( limit ) . db
2013-11-16 07:36:30 +04:00
}
2016-03-07 09:54:20 +03:00
// Offset specify the number of records to skip before starting to return the records
2016-01-18 15:32:52 +03:00
func ( s * DB ) Offset ( offset int ) * DB {
return s . clone ( ) . search . Offset ( offset ) . db
2013-11-16 07:36:30 +04:00
}
2016-03-07 16:09:05 +03:00
// Order specify order when retrieve records from database, set reorder to `true` to overwrite defined conditions
2013-11-16 07:36:30 +04:00
func ( s * DB ) Order ( value string , reorder ... bool ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Order ( value , reorder ... ) . db
2013-11-11 07:11:49 +04:00
}
2016-03-07 16:09:05 +03:00
// Select specify fields that you want to retrieve from database when querying, by default, will select all fields;
2016-03-07 09:54:20 +03:00
// When creating/updating, specify fields that you want to save to database
2014-11-17 15:12:32 +03:00
func ( s * DB ) Select ( query interface { } , args ... interface { } ) * DB {
2015-03-12 10:50:38 +03:00
return s . clone ( ) . search . Select ( query , args ... ) . db
2013-11-06 17:43:41 +04:00
}
2016-03-07 16:09:05 +03:00
// Omit specify fields that you want to ignore when saving to database for creating, updating
2015-03-12 13:01:27 +03:00
func ( s * DB ) Omit ( columns ... string ) * DB {
return s . clone ( ) . search . Omit ( columns ... ) . db
}
2016-03-07 09:54:20 +03:00
// Group specify the group method on the find
2013-11-17 09:22:09 +04:00
func ( s * DB ) Group ( query string ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Group ( query ) . db
2013-11-17 09:22:09 +04:00
}
2016-03-07 09:54:20 +03:00
// Having specify HAVING conditions for GROUP BY
2013-11-17 09:22:09 +04:00
func ( s * DB ) Having ( query string , values ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Having ( query , values ... ) . db
2013-11-17 09:22:09 +04:00
}
2016-03-07 09:54:20 +03:00
// Joins specify Joins conditions
// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user)
2016-02-16 17:48:26 +03:00
func ( s * DB ) Joins ( query string , args ... interface { } ) * DB {
return s . clone ( ) . search . Joins ( query , args ... ) . db
2013-11-17 09:22:09 +04:00
}
2016-03-07 13:43:15 +03:00
// Scopes pass current database connection to arguments `func(*DB) *DB`, which could be used to add conditions dynamically
2016-03-07 16:09:05 +03:00
// func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
// return db.Where("amount > ?", 1000)
// }
//
// func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
// return func (db *gorm.DB) *gorm.DB {
// return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status)
// }
// }
//
// db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
// Refer https://jinzhu.github.io/gorm/curd.html#scopes
2013-11-18 10:35:44 +04:00
func ( s * DB ) Scopes ( funcs ... func ( * DB ) * DB ) * DB {
for _ , f := range funcs {
2015-02-17 17:55:14 +03:00
s = f ( s )
2013-11-18 10:35:44 +04:00
}
2015-02-17 17:55:14 +03:00
return s
2013-11-18 10:35:44 +04:00
}
2016-03-07 16:09:05 +03:00
// Unscoped return all record including deleted record, refer Soft Delete https://jinzhu.github.io/gorm/curd.html#soft-delete
2013-11-16 07:36:30 +04:00
func ( s * DB ) Unscoped ( ) * DB {
2015-03-12 10:01:59 +03:00
return s . clone ( ) . search . unscoped ( ) . db
2013-10-25 14:04:48 +04:00
}
2016-03-08 16:45:20 +03:00
// Attrs initialize struct with argument if record not found with `FirstOrInit` https://jinzhu.github.io/gorm/curd.html#firstorinit or `FirstOrCreate` https://jinzhu.github.io/gorm/curd.html#firstorcreate
2014-01-28 05:48:44 +04:00
func ( s * DB ) Attrs ( attrs ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Attrs ( attrs ... ) . db
2014-01-28 05:48:44 +04:00
}
2016-03-07 13:43:15 +03:00
// Assign assign result with argument regardless it is found or not with `FirstOrInit` https://jinzhu.github.io/gorm/curd.html#firstorinit or `FirstOrCreate` https://jinzhu.github.io/gorm/curd.html#firstorcreate
2014-01-28 05:48:44 +04:00
func ( s * DB ) Assign ( attrs ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Assign ( attrs ... ) . db
2014-01-28 05:48:44 +04:00
}
2016-03-07 13:43:15 +03:00
// First find first record that match given conditions, order by primary key
2013-11-16 07:36:30 +04:00
func ( s * DB ) First ( out interface { } , where ... interface { } ) * DB {
2014-10-28 12:18:11 +03:00
newScope := s . clone ( ) . NewScope ( out )
2015-03-12 08:52:29 +03:00
newScope . Search . Limit ( 1 )
2015-03-23 06:07:39 +03:00
return newScope . Set ( "gorm:order_by_primary_key" , "ASC" ) .
2016-01-16 14:20:52 +03:00
inlineCondition ( where ... ) . callCallbacks ( s . parent . callbacks . queries ) . db
2013-10-25 14:04:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Last find last record that match given conditions, order by primary key
2013-11-16 07:36:30 +04:00
func ( s * DB ) Last ( out interface { } , where ... interface { } ) * DB {
2014-10-28 12:18:11 +03:00
newScope := s . clone ( ) . NewScope ( out )
2015-03-12 08:52:29 +03:00
newScope . Search . Limit ( 1 )
2015-03-23 06:07:39 +03:00
return newScope . Set ( "gorm:order_by_primary_key" , "DESC" ) .
2016-01-16 14:20:52 +03:00
inlineCondition ( where ... ) . callCallbacks ( s . parent . callbacks . queries ) . db
2013-10-31 13:31:00 +04:00
}
2014-01-28 05:30:30 +04:00
2016-03-07 13:43:15 +03:00
// Find find records that match given conditions
2013-11-16 07:36:30 +04:00
func ( s * DB ) Find ( out interface { } , where ... interface { } ) * DB {
2016-01-16 14:20:52 +03:00
return s . clone ( ) . NewScope ( out ) . inlineCondition ( where ... ) . callCallbacks ( s . parent . callbacks . queries ) . db
2013-10-25 14:04:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Scan scan value to a struct
2015-04-17 13:27:20 +03:00
func ( s * DB ) Scan ( dest interface { } ) * DB {
2016-01-16 14:20:52 +03:00
return s . clone ( ) . NewScope ( s . Value ) . Set ( "gorm:query_destination" , dest ) . callCallbacks ( s . parent . callbacks . queries ) . db
2015-04-17 13:27:20 +03:00
}
2016-03-07 16:09:05 +03:00
// Row return `*sql.Row` with given conditions
2013-11-17 08:02:22 +04:00
func ( s * DB ) Row ( ) * sql . Row {
2014-01-28 05:48:44 +04:00
return s . NewScope ( s . Value ) . row ( )
2013-11-17 08:02:22 +04:00
}
2016-03-07 16:09:05 +03:00
// Rows return `*sql.Rows` with given conditions
2013-11-17 08:02:22 +04:00
func ( s * DB ) Rows ( ) ( * sql . Rows , error ) {
2014-01-28 05:48:44 +04:00
return s . NewScope ( s . Value ) . rows ( )
2013-11-17 08:02:22 +04:00
}
2016-03-07 13:43:15 +03:00
// ScanRows scan `*sql.Rows` to give struct
func ( s * DB ) ScanRows ( rows * sql . Rows , result interface { } ) error {
2016-02-14 18:29:06 +03:00
var (
clone = s . clone ( )
2016-03-07 13:43:15 +03:00
scope = clone . NewScope ( result )
2016-02-14 18:29:06 +03:00
columns , err = rows . Columns ( )
)
if clone . AddError ( err ) == nil {
2016-03-10 12:13:48 +03:00
scope . scan ( rows , columns , scope . Fields ( ) )
2016-02-14 18:29:06 +03:00
}
return clone . Error
}
2016-03-07 13:43:15 +03:00
// Pluck used to query single column from a model as a map
2016-03-07 16:09:05 +03:00
// var ages []int64
// db.Find(&users).Pluck("age", &ages)
2015-04-17 13:27:20 +03:00
func ( s * DB ) Pluck ( column string , value interface { } ) * DB {
return s . NewScope ( s . Value ) . pluck ( column , value ) . db
}
2016-03-07 13:43:15 +03:00
// Count get how many records for a model
2015-04-17 13:27:20 +03:00
func ( s * DB ) Count ( value interface { } ) * DB {
return s . NewScope ( s . Value ) . count ( value ) . db
}
2016-03-07 13:43:15 +03:00
// Related get related associations
2015-04-17 13:27:20 +03:00
func ( s * DB ) Related ( value interface { } , foreignKeys ... string ) * DB {
return s . clone ( ) . NewScope ( s . Value ) . related ( value , foreignKeys ... ) . db
2013-10-30 11:21:58 +04:00
}
2016-03-08 16:45:20 +03:00
// FirstOrInit find first matched record or initialize a new one with given conditions (only works with struct, map conditions)
2016-03-07 16:09:05 +03:00
// https://jinzhu.github.io/gorm/curd.html#firstorinit
2013-11-16 07:36:30 +04:00
func ( s * DB ) FirstOrInit ( out interface { } , where ... interface { } ) * DB {
2013-11-16 14:01:44 +04:00
c := s . clone ( )
2015-02-17 17:55:14 +03:00
if result := c . First ( out , where ... ) ; result . Error != nil {
if ! result . RecordNotFound ( ) {
return result
2014-06-23 16:10:50 +04:00
}
2014-01-28 08:28:44 +04:00
c . NewScope ( out ) . inlineCondition ( where ... ) . initialize ( )
2014-01-28 06:23:31 +04:00
} else {
2016-03-09 11:18:01 +03:00
c . NewScope ( out ) . updatedAttrsWithValues ( c . search . assignAttrs )
2013-11-16 07:36:30 +04:00
}
2013-11-16 14:01:44 +04:00
return c
2013-10-31 04:15:19 +04:00
}
2016-03-07 13:43:15 +03:00
// FirstOrCreate find first matched record or create a new one with given conditions (only works with struct, map conditions)
2016-03-07 16:09:05 +03:00
// https://jinzhu.github.io/gorm/curd.html#firstorcreate
2013-11-16 07:36:30 +04:00
func ( s * DB ) FirstOrCreate ( out interface { } , where ... interface { } ) * DB {
2013-11-16 14:01:44 +04:00
c := s . clone ( )
2015-02-17 17:55:14 +03:00
if result := c . First ( out , where ... ) ; result . Error != nil {
if ! result . RecordNotFound ( ) {
return result
2014-06-23 16:10:50 +04:00
}
2016-01-16 14:20:52 +03:00
c . AddError ( c . NewScope ( out ) . inlineCondition ( where ... ) . initialize ( ) . callCallbacks ( c . parent . callbacks . creates ) . db . Error )
2015-03-12 08:52:29 +03:00
} else if len ( c . search . assignAttrs ) > 0 {
2016-01-16 14:20:52 +03:00
c . AddError ( c . NewScope ( out ) . InstanceSet ( "gorm:update_interface" , c . search . assignAttrs ) . callCallbacks ( c . parent . callbacks . updates ) . db . Error )
2013-11-16 07:36:30 +04:00
}
2013-11-16 14:01:44 +04:00
return c
2013-10-29 14:02:28 +04:00
}
2016-03-07 13:43:15 +03:00
// Update update attributes with callbacks, refer: https://jinzhu.github.io/gorm/curd.html#update
2013-11-16 08:19:35 +04:00
func ( s * DB ) Update ( attrs ... interface { } ) * DB {
return s . Updates ( toSearchableMap ( attrs ... ) , true )
}
2016-03-07 13:43:15 +03:00
// Updates update attributes with callbacks, refer: https://jinzhu.github.io/gorm/curd.html#update
2014-01-27 07:06:13 +04:00
func ( s * DB ) Updates ( values interface { } , ignoreProtectedAttrs ... bool ) * DB {
2014-08-20 13:05:02 +04:00
return s . clone ( ) . NewScope ( s . Value ) .
2014-01-27 18:36:08 +04:00
Set ( "gorm:ignore_protected_attrs" , len ( ignoreProtectedAttrs ) > 0 ) .
2014-08-20 13:05:02 +04:00
InstanceSet ( "gorm:update_interface" , values ) .
2016-01-16 14:20:52 +03:00
callCallbacks ( s . parent . callbacks . updates ) . db
2013-11-16 08:19:35 +04:00
}
2016-03-07 13:43:15 +03:00
// UpdateColumn update attributes without callbacks, refer: https://jinzhu.github.io/gorm/curd.html#update
2013-11-17 17:39:50 +04:00
func ( s * DB ) UpdateColumn ( attrs ... interface { } ) * DB {
2014-01-28 04:27:12 +04:00
return s . UpdateColumns ( toSearchableMap ( attrs ... ) )
2013-11-17 17:39:50 +04:00
}
2016-03-07 13:43:15 +03:00
// UpdateColumns update attributes without callbacks, refer: https://jinzhu.github.io/gorm/curd.html#update
2014-01-28 04:27:12 +04:00
func ( s * DB ) UpdateColumns ( values interface { } ) * DB {
2014-08-20 13:05:02 +04:00
return s . clone ( ) . NewScope ( s . Value ) .
2014-01-28 04:27:12 +04:00
Set ( "gorm:update_column" , true ) .
2015-03-29 00:15:12 +03:00
Set ( "gorm:save_associations" , false ) .
2014-08-20 13:05:02 +04:00
InstanceSet ( "gorm:update_interface" , values ) .
2016-01-16 14:20:52 +03:00
callCallbacks ( s . parent . callbacks . updates ) . db
2013-11-17 17:39:50 +04:00
}
2016-03-07 16:09:05 +03:00
// Save update value in database, if the value doesn't have primary key, will insert it
2013-11-16 07:36:30 +04:00
func ( s * DB ) Save ( value interface { } ) * DB {
2014-01-27 04:26:59 +04:00
scope := s . clone ( ) . NewScope ( value )
2014-01-26 15:34:06 +04:00
if scope . PrimaryKeyZero ( ) {
2016-01-16 14:20:52 +03:00
return scope . callCallbacks ( s . parent . callbacks . creates ) . db
2014-01-26 15:34:06 +04:00
}
2016-01-16 14:20:52 +03:00
return scope . callCallbacks ( s . parent . callbacks . updates ) . db
2013-10-29 14:02:28 +04:00
}
2016-03-07 13:43:15 +03:00
// Create insert the value into database
2014-06-12 00:51:27 +04:00
func ( s * DB ) Create ( value interface { } ) * DB {
scope := s . clone ( ) . NewScope ( value )
2016-01-16 14:20:52 +03:00
return scope . callCallbacks ( s . parent . callbacks . creates ) . db
2014-06-12 00:51:27 +04:00
}
2016-03-07 16:09:05 +03:00
// Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition
2014-07-24 14:30:12 +04:00
func ( s * DB ) Delete ( value interface { } , where ... interface { } ) * DB {
2016-01-16 14:20:52 +03:00
return s . clone ( ) . NewScope ( value ) . inlineCondition ( where ... ) . callCallbacks ( s . parent . callbacks . deletes ) . db
2013-10-25 14:04:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Raw use raw sql as conditions, won't run it unless invoked by other methods
// db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
2014-01-03 14:14:51 +04:00
func ( s * DB ) Raw ( sql string , values ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Raw ( true ) . Where ( sql , values ... ) . db
2014-01-03 14:14:51 +04:00
}
2016-03-07 13:43:15 +03:00
// Exec execute raw sql
2013-11-17 12:47:39 +04:00
func ( s * DB ) Exec ( sql string , values ... interface { } ) * DB {
2014-01-28 06:29:12 +04:00
scope := s . clone ( ) . NewScope ( nil )
2016-01-15 16:03:35 +03:00
generatedSQL := scope . buildWhereCondition ( map [ string ] interface { } { "query" : sql , "args" : values } )
generatedSQL = strings . TrimSuffix ( strings . TrimPrefix ( generatedSQL , "(" ) , ")" )
scope . Raw ( generatedSQL )
2014-01-28 06:29:12 +04:00
return scope . Exec ( ) . db
2013-10-25 14:04:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Model specify the model you would like to run db operations
// // update all users's name to `hello`
// db.Model(&User{}).Update("name", "hello")
// // if user's primary key is non-blank, will use it as condition, then will only update the user's name to `hello`
// db.Model(&user).Update("name", "hello")
2013-11-16 07:36:30 +04:00
func ( s * DB ) Model ( value interface { } ) * DB {
c := s . clone ( )
2014-01-04 11:08:00 +04:00
c . Value = value
2013-11-16 07:36:30 +04:00
return c
2013-10-25 14:04:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Table specify the table you would like to run db operations
2013-11-16 07:36:30 +04:00
func ( s * DB ) Table ( name string ) * DB {
2015-02-26 11:08:15 +03:00
clone := s . clone ( )
2015-03-12 08:52:29 +03:00
clone . search . Table ( name )
2015-02-26 11:08:15 +03:00
clone . Value = nil
return clone
2013-10-25 14:04:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Debug start debug mode
2013-11-16 07:36:30 +04:00
func ( s * DB ) Debug ( ) * DB {
2013-11-16 11:01:31 +04:00
return s . clone ( ) . LogMode ( true )
2013-11-16 07:36:30 +04:00
}
2016-03-07 13:43:15 +03:00
// Begin begin a transaction
2013-11-16 07:36:30 +04:00
func ( s * DB ) Begin ( ) * DB {
c := s . clone ( )
if db , ok := c . db . ( sqlDb ) ; ok {
tx , err := db . Begin ( )
c . db = interface { } ( tx ) . ( sqlCommon )
2015-08-13 11:42:13 +03:00
c . AddError ( err )
2013-11-16 07:36:30 +04:00
} else {
2016-03-07 09:54:20 +03:00
c . AddError ( ErrCantStartTransaction )
2013-11-16 07:36:30 +04:00
}
return c
2013-10-29 05:01:48 +04:00
}
2016-03-07 13:43:15 +03:00
// Commit commit a transaction
2013-11-16 07:36:30 +04:00
func ( s * DB ) Commit ( ) * DB {
if db , ok := s . db . ( sqlTx ) ; ok {
2015-08-13 11:42:13 +03:00
s . AddError ( db . Commit ( ) )
2013-11-16 07:36:30 +04:00
} else {
2016-03-07 09:54:20 +03:00
s . AddError ( ErrInvalidTransaction )
2013-11-16 07:36:30 +04:00
}
return s
}
2016-03-07 13:43:15 +03:00
// Rollback rollback a transaction
2013-11-16 07:36:30 +04:00
func ( s * DB ) Rollback ( ) * DB {
if db , ok := s . db . ( sqlTx ) ; ok {
2015-08-13 11:42:13 +03:00
s . AddError ( db . Rollback ( ) )
2013-11-16 07:36:30 +04:00
} else {
2016-03-07 09:54:20 +03:00
s . AddError ( ErrInvalidTransaction )
2013-11-16 07:36:30 +04:00
}
return s
2013-10-25 14:04:48 +04:00
}
2013-10-26 11:47:30 +04:00
2016-03-07 16:09:05 +03:00
// NewRecord check if value's primary key is blank
2013-11-23 17:38:31 +04:00
func ( s * DB ) NewRecord ( value interface { } ) bool {
2015-08-12 19:32:18 +03:00
return s . clone ( ) . NewScope ( value ) . PrimaryKeyZero ( )
2013-11-23 17:38:31 +04:00
}
2016-03-07 16:09:05 +03:00
// RecordNotFound check if returning ErrRecordNotFound error
2013-11-24 07:29:37 +04:00
func ( s * DB ) RecordNotFound ( ) bool {
2016-03-07 16:09:05 +03:00
for _ , err := range s . GetErrors ( ) {
if err == ErrRecordNotFound {
return true
}
}
return false
2013-11-24 07:29:37 +04:00
}
2016-01-15 16:03:35 +03:00
// CreateTable create table for models
func ( s * DB ) CreateTable ( models ... interface { } ) * DB {
2016-03-17 13:12:21 +03:00
db := s . Unscoped ( )
2016-01-15 16:03:35 +03:00
for _ , model := range models {
db = db . NewScope ( model ) . createTable ( ) . db
2015-08-26 06:54:07 +03:00
}
return db
2013-10-27 04:06:01 +04:00
}
2016-01-15 16:03:35 +03:00
// DropTable drop table for models
2015-08-26 06:54:07 +03:00
func ( s * DB ) DropTable ( values ... interface { } ) * DB {
db := s . clone ( )
for _ , value := range values {
2016-01-03 12:20:24 +03:00
if tableName , ok := value . ( string ) ; ok {
db = db . Table ( tableName )
}
2015-08-26 06:54:07 +03:00
db = db . NewScope ( value ) . dropTable ( ) . db
}
return db
2013-10-28 16:27:25 +04:00
}
2016-03-07 16:33:48 +03:00
// DropTableIfExists drop table if it is exist
func ( s * DB ) DropTableIfExists ( values ... interface { } ) * DB {
db := s . clone ( )
for _ , value := range values {
if s . HasTable ( value ) {
db . AddError ( s . DropTable ( value ) . Error )
}
}
return db
}
2016-03-07 13:43:15 +03:00
// HasTable check has table or not
2014-08-29 09:28:54 +04:00
func ( s * DB ) HasTable ( value interface { } ) bool {
2016-02-14 09:17:14 +03:00
var (
scope = s . clone ( ) . NewScope ( value )
tableName string
)
if name , ok := value . ( string ) ; ok {
tableName = name
} else {
tableName = scope . TableName ( )
}
2016-02-15 09:09:24 +03:00
has := scope . Dialect ( ) . HasTable ( tableName )
2015-08-13 11:42:13 +03:00
s . AddError ( scope . db . Error )
2015-08-09 00:08:25 +03:00
return has
2014-08-29 09:28:54 +04:00
}
2016-03-07 13:43:15 +03:00
// AutoMigrate run auto migration for given models, will only add missing fields, won't delete/change current data
2014-08-20 07:56:39 +04:00
func ( s * DB ) AutoMigrate ( values ... interface { } ) * DB {
2016-03-17 13:12:21 +03:00
db := s . Unscoped ( )
2014-08-20 07:56:39 +04:00
for _ , value := range values {
2016-01-17 12:12:19 +03:00
db = db . NewScope ( value ) . autoMigrate ( ) . db
2014-08-20 07:56:39 +04:00
}
return db
2013-10-26 11:47:30 +04:00
}
2013-11-01 11:01:39 +04:00
2016-03-07 13:43:15 +03:00
// ModifyColumn modify column to type
2013-11-17 16:38:43 +04:00
func ( s * DB ) ModifyColumn ( column string , typ string ) * DB {
2015-06-24 01:27:21 +03:00
scope := s . clone ( ) . NewScope ( s . Value )
scope . modifyColumn ( column , typ )
return scope . db
2013-11-01 11:01:39 +04:00
}
2013-11-07 05:09:54 +04:00
2016-03-07 13:43:15 +03:00
// DropColumn drop a column
2013-11-16 07:36:30 +04:00
func ( s * DB ) DropColumn ( column string ) * DB {
2015-06-24 01:27:21 +03:00
scope := s . clone ( ) . NewScope ( s . Value )
scope . dropColumn ( column )
return scope . db
2013-11-07 05:09:54 +04:00
}
2013-11-11 09:16:08 +04:00
2016-03-07 13:43:15 +03:00
// AddIndex add index for columns with given name
func ( s * DB ) AddIndex ( indexName string , columns ... string ) * DB {
2016-01-12 08:44:16 +03:00
scope := s . Unscoped ( ) . NewScope ( s . Value )
2016-03-07 13:43:15 +03:00
scope . addIndex ( false , indexName , columns ... )
2015-06-24 01:27:21 +03:00
return scope . db
2014-06-01 02:35:56 +04:00
}
2016-03-07 13:43:15 +03:00
// AddUniqueIndex add unique index for columns with given name
func ( s * DB ) AddUniqueIndex ( indexName string , columns ... string ) * DB {
2016-03-17 13:12:21 +03:00
scope := s . Unscoped ( ) . NewScope ( s . Value )
2016-03-07 13:43:15 +03:00
scope . addIndex ( true , indexName , columns ... )
2015-06-24 01:27:21 +03:00
return scope . db
2015-03-02 18:02:40 +03:00
}
2016-03-07 13:43:15 +03:00
// RemoveIndex remove index with name
2015-03-02 18:02:40 +03:00
func ( s * DB ) RemoveIndex ( indexName string ) * DB {
2015-06-24 01:27:21 +03:00
scope := s . clone ( ) . NewScope ( s . Value )
scope . removeIndex ( indexName )
return scope . db
2015-03-02 18:02:40 +03:00
}
2016-03-07 16:09:05 +03:00
// AddForeignKey Add foreign key to the given scope, e.g:
// db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT")
2015-02-07 14:04:10 +03:00
func ( s * DB ) AddForeignKey ( field string , dest string , onDelete string , onUpdate string ) * DB {
2015-06-24 01:27:21 +03:00
scope := s . clone ( ) . NewScope ( s . Value )
scope . addForeignKey ( field , dest , onDelete , onUpdate )
2015-06-24 09:09:59 +03:00
return scope . db
2015-02-07 14:04:10 +03:00
}
2016-03-07 13:43:15 +03:00
// Association start `Association Mode` to handler relations things easir in that mode, refer: https://jinzhu.github.io/gorm/associations.html#association-mode
2014-07-30 10:30:21 +04:00
func ( s * DB ) Association ( column string ) * Association {
2015-02-17 17:55:14 +03:00
var err error
2014-07-30 10:30:21 +04:00
scope := s . clone ( ) . NewScope ( s . Value )
2014-07-30 16:48:36 +04:00
2015-03-11 06:28:30 +03:00
if primaryField := scope . PrimaryField ( ) ; primaryField . IsBlank {
2015-02-17 17:55:14 +03:00
err = errors . New ( "primary key can't be nil" )
2014-07-30 16:48:36 +04:00
} else {
2015-02-17 17:55:14 +03:00
if field , ok := scope . FieldByName ( column ) ; ok {
2015-07-30 09:26:48 +03:00
if field . Relationship == nil || len ( field . Relationship . ForeignFieldNames ) == 0 {
2015-02-17 17:55:14 +03:00
err = fmt . Errorf ( "invalid association %v for %v" , column , scope . IndirectValue ( ) . Type ( ) )
} else {
2016-01-16 07:18:04 +03:00
return & Association { scope : scope , column : column , field : field }
2015-02-17 17:55:14 +03:00
}
} else {
err = fmt . Errorf ( "%v doesn't have column %v" , scope . IndirectValue ( ) . Type ( ) , column )
}
2014-07-30 16:48:36 +04:00
}
2015-02-17 17:55:14 +03:00
return & Association { Error : err }
2013-11-11 09:16:08 +04:00
}
2014-08-20 12:25:01 +04:00
2016-03-07 16:09:05 +03:00
// Preload preload associations with given conditions
// db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
2015-02-01 18:19:29 +03:00
func ( s * DB ) Preload ( column string , conditions ... interface { } ) * DB {
2015-03-12 08:52:29 +03:00
return s . clone ( ) . search . Preload ( column , conditions ... ) . db
2015-02-01 18:19:29 +03:00
}
2016-03-07 13:43:15 +03:00
// Set set setting by name, which could be used in callbacks, will clone a new db, and update its setting
2014-08-20 12:25:01 +04:00
func ( s * DB ) Set ( name string , value interface { } ) * DB {
2014-08-25 13:10:46 +04:00
return s . clone ( ) . InstantSet ( name , value )
2014-08-20 13:05:02 +04:00
}
2016-03-07 13:43:15 +03:00
// InstantSet instant set setting, will affect current db
2014-08-25 13:10:46 +04:00
func ( s * DB ) InstantSet ( name string , value interface { } ) * DB {
2014-08-20 12:25:01 +04:00
s . values [ name ] = value
return s
}
2016-03-07 13:43:15 +03:00
// Get get setting by name
2014-08-20 12:25:01 +04:00
func ( s * DB ) Get ( name string ) ( value interface { } , ok bool ) {
value , ok = s . values [ name ]
return
}
2015-03-19 13:23:54 +03:00
2016-03-07 13:43:15 +03:00
// SetJoinTableHandler set a model's join table handler for a relation
2015-03-19 13:23:54 +03:00
func ( s * DB ) SetJoinTableHandler ( source interface { } , column string , handler JoinTableHandlerInterface ) {
2015-06-23 09:19:59 +03:00
scope := s . NewScope ( source )
for _ , field := range scope . GetModelStruct ( ) . StructFields {
2015-03-19 13:23:54 +03:00
if field . Name == column || field . DBName == column {
2016-01-03 05:00:18 +03:00
if many2many := field . TagSettings [ "MANY2MANY" ] ; many2many != "" {
2015-03-20 06:11:30 +03:00
source := ( & Scope { Value : source } ) . GetModelStruct ( ) . ModelType
destination := ( & Scope { Value : reflect . New ( field . Struct . Type ) . Interface ( ) } ) . GetModelStruct ( ) . ModelType
handler . Setup ( field . Relationship , many2many , source , destination )
field . Relationship . JoinTableHandler = handler
2016-02-15 09:09:24 +03:00
if table := handler . Table ( s ) ; scope . Dialect ( ) . HasTable ( table ) {
2015-06-23 09:19:59 +03:00
s . Table ( table ) . AutoMigrate ( handler )
}
2015-03-20 06:11:30 +03:00
}
2015-03-19 13:23:54 +03:00
}
}
}
2015-08-13 11:42:13 +03:00
2016-03-07 13:43:15 +03:00
// AddError add error to the db
2015-08-13 11:42:13 +03:00
func ( s * DB ) AddError ( err error ) error {
if err != nil {
2016-03-07 09:54:20 +03:00
if err != ErrRecordNotFound {
2015-08-13 11:42:13 +03:00
if s . logMode == 0 {
go s . print ( fileWithLineNum ( ) , err )
} else {
s . log ( err )
}
2015-08-18 06:06:10 +03:00
errors := Errors { errors : s . GetErrors ( ) }
errors . Add ( err )
if len ( errors . GetErrors ( ) ) > 1 {
err = errors
2015-08-14 09:53:26 +03:00
}
2015-08-13 11:42:13 +03:00
}
s . Error = err
}
return err
}
2016-03-07 16:09:05 +03:00
// GetErrors get happened errors from the db
2015-08-14 09:53:26 +03:00
func ( s * DB ) GetErrors ( ) ( errors [ ] error ) {
if errs , ok := s . Error . ( errorsInterface ) ; ok {
return errs . GetErrors ( )
} else if s . Error != nil {
2015-08-13 11:42:13 +03:00
return [ ] error { s . Error }
}
2015-08-14 09:53:26 +03:00
return
2015-08-13 11:42:13 +03:00
}
2016-03-08 16:45:20 +03:00
////////////////////////////////////////////////////////////////////////////////
// Private Methods For *gorm.DB
////////////////////////////////////////////////////////////////////////////////
func ( s * DB ) clone ( ) * DB {
db := DB { db : s . db , parent : s . parent , logger : s . logger , logMode : s . logMode , values : map [ string ] interface { } { } , Value : s . Value , Error : s . Error }
for key , value := range s . values {
db . values [ key ] = value
}
if s . search == nil {
db . search = & search { limit : - 1 , offset : - 1 }
} else {
db . search = s . search . clone ( )
}
db . search . db = & db
return & db
}
func ( s * DB ) print ( v ... interface { } ) {
s . logger . ( logger ) . Print ( v ... )
}
func ( s * DB ) log ( v ... interface { } ) {
if s != nil && s . logMode == 2 {
s . print ( append ( [ ] interface { } { "log" , fileWithLineNum ( ) } , v ... ) ... )
}
}
func ( s * DB ) slog ( sql string , t time . Time , vars ... interface { } ) {
if s . logMode == 2 {
s . print ( "sql" , fileWithLineNum ( ) , NowFunc ( ) . Sub ( t ) , sql , vars )
}
}