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" )
2016-10-07 14:42:29 +03:00
return nil , err
}
var source string
var dbSQL sqlCommon
2015-02-17 17:55:14 +03:00
2016-10-07 14:42:29 +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 )
2015-02-17 17:55:14 +03:00
}
2016-10-07 14:42:29 +03:00
dbSQL , err = sql . Open ( driver , source )
case sqlCommon :
source = reflect . Indirect ( reflect . ValueOf ( value ) ) . FieldByName ( "dsn" ) . String ( )
dbSQL = value
}
2014-08-05 06:32:15 +04:00
2016-10-07 14:42:29 +03:00
db = DB {
dialect : newDialect ( dialect , dbSQL . ( * sql . DB ) ) ,
logger : defaultLogger ,
callbacks : DefaultCallback ,
source : source ,
values : map [ string ] interface { } { } ,
db : dbSQL ,
}
db . parent = & db
2015-08-02 02:37:33 +03:00
2016-10-07 14:42:29 +03:00
if err == nil {
err = db . DB ( ) . Ping ( ) // Send a ping to make sure the database connection is alive.
if err != nil {
db . DB ( ) . Close ( )
2015-08-02 02:37:33 +03:00
}
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-09-13 02:41:42 +03:00
// Dialect get dialect
func ( s * DB ) Dialect ( ) Dialect {
return s . parent . dialect
}
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-06-21 06:13:33 +03:00
func ( s * DB ) Limit ( limit interface { } ) * DB {
2016-01-18 15:32:52 +03:00
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-06-21 06:13:33 +03:00
func ( s * DB ) Offset ( offset interface { } ) * DB {
2016-01-18 15:32:52 +03:00
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
2016-06-28 06:15:42 +03:00
// db.Order("name DESC")
// db.Order("name DESC", true) // reorder
// db.Order(gorm.Expr("name = ? DESC", "first")) // sql expression
func ( s * DB ) Order ( value interface { } , 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 ( )
2016-10-21 06:30:17 +03:00
if result := s . First ( out , where ... ) ; result . Error != nil {
2015-02-17 17:55:14 +03:00
if ! result . RecordNotFound ( ) {
return result
2014-06-23 16:10:50 +04:00
}
2016-10-21 06:30:17 +03:00
return c . NewScope ( out ) . inlineCondition ( where ... ) . initialize ( ) . callCallbacks ( c . parent . callbacks . creates ) . db
2015-03-12 08:52:29 +03:00
} else if len ( c . search . assignAttrs ) > 0 {
2016-10-21 06:30:17 +03:00
return c . NewScope ( out ) . InstanceSet ( "gorm:update_interface" , c . search . assignAttrs ) . callCallbacks ( c . parent . callbacks . updates ) . db
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 )
2016-09-07 16:54:19 +03:00
if ! scope . PrimaryKeyZero ( ) {
newDB := scope . callCallbacks ( s . parent . callbacks . updates ) . db
if newDB . Error == nil && newDB . RowsAffected == 0 {
return s . New ( ) . FirstOrCreate ( value )
}
return newDB
2014-01-26 15:34:06 +04:00
}
2016-09-07 16:54:19 +03:00
return scope . callCallbacks ( s . parent . callbacks . creates ) . 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 )
}
Make gorm.Errors available for use outside gorm
gorm.Errors, which usefully implements `error` for an `[]error` as
returned by `DB.GetError()` was already exported, but because it used a
private field `errors`, it was not able to be created due to the
compile-time error:
implicit assignment of unexported field 'errors' in gorm.Errors literal
The trivial solution would be to export the `errors` field on
`gorm.Errors`, but this led to the issue that the common pattern of
checking `err != nil` failed because a struct{error: nil} != nil.
We can take advantage of type aliasing here to make Errors an []error,
which can in fact be nil and would pass `err != nil` on the happy path.
* Remove `(Errors) GetErrors()`, as it's less useful when Errors is an
[]error which can be iterated over. While this is technically a
breaking change, we never expose an Errors and its difficult to build
one (it can be done with the existing `(Errors) Add(error)`), but
awkwardly. This removal can be reverted without issue and we can make
it an identity method, but it seemed an opportune time to reduce API
surface area on something that likely isn't used.
* Remove errorsInterface, as it's not useful without `(Errors)
GetErrors()`
* Change `(*Errors) Add(error)` => `(Errors) Add(error...) Errors`
because we can't modify even a *Errors when it's a type alias. This is
more idiomatic as it follows the pattern of `slice = append(slice,
element)` Go developers are familiar with.
2016-10-25 19:22:50 +03:00
errors := Errors ( s . GetErrors ( ) )
2016-11-09 05:22:42 +03:00
errors = errors . Add ( err )
Make gorm.Errors available for use outside gorm
gorm.Errors, which usefully implements `error` for an `[]error` as
returned by `DB.GetError()` was already exported, but because it used a
private field `errors`, it was not able to be created due to the
compile-time error:
implicit assignment of unexported field 'errors' in gorm.Errors literal
The trivial solution would be to export the `errors` field on
`gorm.Errors`, but this led to the issue that the common pattern of
checking `err != nil` failed because a struct{error: nil} != nil.
We can take advantage of type aliasing here to make Errors an []error,
which can in fact be nil and would pass `err != nil` on the happy path.
* Remove `(Errors) GetErrors()`, as it's less useful when Errors is an
[]error which can be iterated over. While this is technically a
breaking change, we never expose an Errors and its difficult to build
one (it can be done with the existing `(Errors) Add(error)`), but
awkwardly. This removal can be reverted without issue and we can make
it an identity method, but it seemed an opportune time to reduce API
surface area on something that likely isn't used.
* Remove errorsInterface, as it's not useful without `(Errors)
GetErrors()`
* Change `(*Errors) Add(error)` => `(Errors) Add(error...) Errors`
because we can't modify even a *Errors when it's a type alias. This is
more idiomatic as it follows the pattern of `slice = append(slice,
element)` Go developers are familiar with.
2016-10-25 19:22:50 +03:00
if len ( errors ) > 1 {
2015-08-18 06:06:10 +03:00
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
2016-11-09 05:22:42 +03:00
func ( s * DB ) GetErrors ( ) [ ] error {
Make gorm.Errors available for use outside gorm
gorm.Errors, which usefully implements `error` for an `[]error` as
returned by `DB.GetError()` was already exported, but because it used a
private field `errors`, it was not able to be created due to the
compile-time error:
implicit assignment of unexported field 'errors' in gorm.Errors literal
The trivial solution would be to export the `errors` field on
`gorm.Errors`, but this led to the issue that the common pattern of
checking `err != nil` failed because a struct{error: nil} != nil.
We can take advantage of type aliasing here to make Errors an []error,
which can in fact be nil and would pass `err != nil` on the happy path.
* Remove `(Errors) GetErrors()`, as it's less useful when Errors is an
[]error which can be iterated over. While this is technically a
breaking change, we never expose an Errors and its difficult to build
one (it can be done with the existing `(Errors) Add(error)`), but
awkwardly. This removal can be reverted without issue and we can make
it an identity method, but it seemed an opportune time to reduce API
surface area on something that likely isn't used.
* Remove errorsInterface, as it's not useful without `(Errors)
GetErrors()`
* Change `(*Errors) Add(error)` => `(Errors) Add(error...) Errors`
because we can't modify even a *Errors when it's a type alias. This is
more idiomatic as it follows the pattern of `slice = append(slice,
element)` Go developers are familiar with.
2016-10-25 19:22:50 +03:00
if errs , ok := s . Error . ( Errors ) ; ok {
return errs
2015-08-14 09:53:26 +03:00
} else if s . Error != nil {
2015-08-13 11:42:13 +03:00
return [ ] error { s . Error }
}
2016-11-09 05:22:42 +03:00
return [ ] error { }
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 )
}
}