2020-01-29 14:22:44 +03:00
|
|
|
package gorm
|
|
|
|
|
2020-02-04 03:56:15 +03:00
|
|
|
import (
|
|
|
|
"fmt"
|
2020-02-16 08:45:27 +03:00
|
|
|
"strings"
|
2020-02-04 03:56:15 +03:00
|
|
|
|
|
|
|
"github.com/jinzhu/gorm/clause"
|
|
|
|
)
|
2020-01-30 10:14:48 +03:00
|
|
|
|
2020-01-29 14:22:44 +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")
|
|
|
|
func (db *DB) Model(value interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-01-29 22:03:06 +03:00
|
|
|
tx.Statement.Model = value
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-30 10:14:48 +03:00
|
|
|
// Clauses Add clauses
|
|
|
|
func (db *DB) Clauses(conds ...clause.Expression) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
var whereConds []interface{}
|
|
|
|
|
|
|
|
for _, cond := range conds {
|
|
|
|
if c, ok := cond.(clause.Interface); ok {
|
|
|
|
tx.Statement.AddClause(c)
|
|
|
|
} else {
|
|
|
|
whereConds = append(whereConds, cond)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(whereConds) > 0 {
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(whereConds[0], whereConds[1:]...)})
|
2020-01-30 10:14:48 +03:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-29 14:22:44 +03:00
|
|
|
// Table specify the table you would like to run db operations
|
|
|
|
func (db *DB) Table(name string) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-01-29 22:03:06 +03:00
|
|
|
tx.Statement.Table = name
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select specify fields that you want when querying, creating, updating
|
|
|
|
func (db *DB) Select(query interface{}, args ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-16 08:45:27 +03:00
|
|
|
|
|
|
|
switch v := query.(type) {
|
|
|
|
case []string:
|
|
|
|
tx.Statement.Selects = v
|
|
|
|
|
|
|
|
for _, arg := range args {
|
|
|
|
switch arg := arg.(type) {
|
|
|
|
case string:
|
|
|
|
tx.Statement.Selects = append(tx.Statement.Selects, arg)
|
|
|
|
case []string:
|
|
|
|
tx.Statement.Selects = append(tx.Statement.Selects, arg...)
|
|
|
|
default:
|
|
|
|
tx.AddError(fmt.Errorf("unsupported select args %v %v", query, args))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case string:
|
|
|
|
fields := strings.FieldsFunc(v, isChar)
|
|
|
|
|
|
|
|
// normal field names
|
|
|
|
if len(fields) == 1 || (len(fields) == 3 && strings.ToUpper(fields[1]) == "AS") {
|
|
|
|
tx.Statement.Selects = fields
|
|
|
|
|
|
|
|
for _, arg := range args {
|
|
|
|
switch arg := arg.(type) {
|
|
|
|
case string:
|
|
|
|
tx.Statement.Selects = append(tx.Statement.Selects, arg)
|
|
|
|
case []string:
|
|
|
|
tx.Statement.Selects = append(tx.Statement.Selects, arg...)
|
|
|
|
default:
|
|
|
|
tx.Statement.AddClause(clause.Select{
|
|
|
|
Expression: clause.Expr{SQL: v, Vars: args},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tx.Statement.AddClause(clause.Select{
|
|
|
|
Expression: clause.Expr{SQL: v, Vars: args},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
tx.AddError(fmt.Errorf("unsupported select args %v %v", query, args))
|
|
|
|
}
|
|
|
|
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Omit specify fields that you want to ignore when creating, updating and querying
|
|
|
|
func (db *DB) Omit(columns ...string) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-16 08:45:27 +03:00
|
|
|
|
2020-02-19 07:53:46 +03:00
|
|
|
if len(columns) == 1 && strings.ContainsRune(columns[0], ',') {
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.Omits = strings.FieldsFunc(columns[0], isChar)
|
|
|
|
} else {
|
|
|
|
tx.Statement.Omits = columns
|
|
|
|
}
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Where(query interface{}, args ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(query, args...)})
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not add NOT condition
|
|
|
|
func (db *DB) Not(query interface{}, args ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.Not(tx.Statement.BuildCondtion(query, args...)...)}})
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Or add OR conditions
|
|
|
|
func (db *DB) Or(query interface{}, args ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.Or(tx.Statement.BuildCondtion(query, args...)...)}})
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Joins specify Joins conditions
|
|
|
|
// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user)
|
|
|
|
func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Group specify the group method on the find
|
|
|
|
func (db *DB) Group(column string) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Having specify HAVING conditions for GROUP BY
|
|
|
|
func (db *DB) Having(query interface{}, args ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Order specify order when retrieve records from database
|
|
|
|
// db.Order("name DESC")
|
|
|
|
// db.Order(gorm.Expr("name = ? DESC", "first")) // sql expression
|
|
|
|
func (db *DB) Order(value interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-04 03:56:15 +03:00
|
|
|
|
|
|
|
switch v := value.(type) {
|
2020-02-07 18:45:35 +03:00
|
|
|
case clause.OrderByColumn:
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.AddClause(clause.OrderBy{
|
2020-02-07 18:45:35 +03:00
|
|
|
Columns: []clause.OrderByColumn{v},
|
2020-02-04 03:56:15 +03:00
|
|
|
})
|
|
|
|
default:
|
2020-02-16 08:45:27 +03:00
|
|
|
tx.Statement.AddClause(clause.OrderBy{
|
2020-02-07 18:45:35 +03:00
|
|
|
Columns: []clause.OrderByColumn{{
|
2020-02-04 03:56:15 +03:00
|
|
|
Column: clause.Column{Name: fmt.Sprint(value), Raw: true},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
}
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Limit specify the number of records to be retrieved
|
2020-03-04 18:56:42 +03:00
|
|
|
func (db *DB) Limit(limit int) (tx *DB) {
|
2020-01-29 14:22:44 +03:00
|
|
|
tx = db.getInstance()
|
2020-03-04 18:56:42 +03:00
|
|
|
tx.Statement.AddClause(clause.Limit{Limit: limit})
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Offset specify the number of records to skip before starting to return the records
|
2020-03-04 18:56:42 +03:00
|
|
|
func (db *DB) Offset(offset int) (tx *DB) {
|
2020-01-29 14:22:44 +03:00
|
|
|
tx = db.getInstance()
|
2020-03-04 18:56:42 +03:00
|
|
|
tx.Statement.AddClause(clause.Limit{Offset: offset})
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Scopes pass current database connection to arguments `func(*DB) *DB`, which could be used to add conditions dynamically
|
|
|
|
// 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)
|
2020-01-30 10:14:48 +03:00
|
|
|
func (db *DB) Scopes(funcs ...func(*DB) *DB) *DB {
|
2020-01-29 14:22:44 +03:00
|
|
|
for _, f := range funcs {
|
|
|
|
db = f(db)
|
|
|
|
}
|
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
|
|
|
// Preload preload associations with given conditions
|
|
|
|
// db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
|
|
|
|
func (db *DB) Preload(column string, conditions ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Assign(attrs ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Attrs(attrs ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Unscoped() (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *DB) Raw(sql string, values ...interface{}) (tx *DB) {
|
|
|
|
tx = db.getInstance()
|
2020-02-22 15:57:29 +03:00
|
|
|
tx.Statement.SQL = strings.Builder{}
|
|
|
|
clause.Expr{SQL: sql, Vars: values}.Build(tx.Statement)
|
2020-01-29 14:22:44 +03:00
|
|
|
return
|
|
|
|
}
|