gorm/finisher_api.go

243 lines
6.5 KiB
Go
Raw Normal View History

2020-01-29 14:22:44 +03:00
package gorm
import (
"database/sql"
2020-03-08 08:24:08 +03:00
"reflect"
2020-02-22 15:57:29 +03:00
"strings"
2020-02-04 03:56:15 +03:00
"github.com/jinzhu/gorm/clause"
2020-01-29 14:22:44 +03:00
)
2020-02-03 05:40:03 +03:00
// Create insert the value into database
func (db *DB) Create(value interface{}) (tx *DB) {
tx = db.getInstance()
tx.Statement.Dest = value
tx.callbacks.Create().Execute(tx)
return
}
// Save update value in database, if the value doesn't have primary key, will insert it
func (db *DB) Save(value interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
2020-03-08 08:24:08 +03:00
tx.Statement.Dest = value
if err := tx.Statement.Parse(value); err != nil && tx.Statement.Schema != nil {
where := clause.Where{Exprs: make([]clause.Expression, len(tx.Statement.Schema.PrimaryFields))}
reflectValue := reflect.ValueOf(value)
for idx, pf := range tx.Statement.Schema.PrimaryFields {
if pv, isZero := pf.ValueOf(reflectValue); isZero {
tx.callbacks.Create().Execute(tx)
where.Exprs[idx] = clause.Eq{Column: pf.DBName, Value: pv}
return
}
}
tx.Statement.AddClause(where)
}
if len(tx.Statement.Selects) == 0 {
tx.Statement.Selects = []string{"*"}
}
tx.callbacks.Update().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
// First find first record that match given conditions, order by primary key
2020-03-07 08:43:20 +03:00
func (db *DB) First(out interface{}, conds ...interface{}) (tx *DB) {
2020-02-07 18:45:35 +03:00
tx = db.getInstance().Limit(1).Order(clause.OrderByColumn{
2020-02-04 03:56:15 +03:00
Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
})
2020-03-07 08:43:20 +03:00
if len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(conds[0], conds[1:]...)})
}
2020-03-03 09:18:12 +03:00
tx.Statement.RaiseErrorOnNotFound = true
2020-02-02 09:40:44 +03:00
tx.Statement.Dest = out
tx.callbacks.Query().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
// Take return a record that match given conditions, the order will depend on the database implementation
2020-03-07 08:43:20 +03:00
func (db *DB) Take(out interface{}, conds ...interface{}) (tx *DB) {
2020-03-03 09:18:12 +03:00
tx = db.getInstance().Limit(1)
2020-03-07 08:43:20 +03:00
if len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(conds[0], conds[1:]...)})
}
2020-03-03 09:18:12 +03:00
tx.Statement.RaiseErrorOnNotFound = true
2020-02-23 18:28:35 +03:00
tx.Statement.Dest = out
tx.callbacks.Query().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
// Last find last record that match given conditions, order by primary key
2020-03-07 08:43:20 +03:00
func (db *DB) Last(out interface{}, conds ...interface{}) (tx *DB) {
2020-02-23 18:28:35 +03:00
tx = db.getInstance().Limit(1).Order(clause.OrderByColumn{
Column: clause.Column{Table: clause.CurrentTable, Name: clause.PrimaryKey},
2020-03-04 06:32:36 +03:00
Desc: true,
2020-02-23 18:28:35 +03:00
})
2020-03-07 08:43:20 +03:00
if len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(conds[0], conds[1:]...)})
}
2020-03-03 09:18:12 +03:00
tx.Statement.RaiseErrorOnNotFound = true
2020-02-23 18:28:35 +03:00
tx.Statement.Dest = out
tx.callbacks.Query().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
// Find find records that match given conditions
2020-03-07 08:43:20 +03:00
func (db *DB) Find(out interface{}, conds ...interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
2020-03-07 08:43:20 +03:00
if len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(conds[0], conds[1:]...)})
}
2020-03-03 09:18:12 +03:00
tx.Statement.Dest = out
tx.callbacks.Query().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
2020-02-03 05:40:03 +03:00
func (db *DB) FirstOrInit(out interface{}, where ...interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
return
}
2020-02-03 05:40:03 +03:00
func (db *DB) FirstOrCreate(out interface{}, where ...interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
return
}
// Update update attributes with callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update
func (db *DB) Update(column string, value interface{}) (tx *DB) {
tx = db.getInstance()
2020-03-07 08:43:20 +03:00
tx.Statement.Dest = map[string]interface{}{column: value}
tx.callbacks.Update().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
// Updates update attributes with callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update
func (db *DB) Updates(values interface{}) (tx *DB) {
tx = db.getInstance()
2020-03-07 08:43:20 +03:00
tx.Statement.Dest = values
tx.callbacks.Update().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
2020-02-03 05:40:03 +03:00
func (db *DB) UpdateColumn(column string, value interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
2020-03-07 08:43:20 +03:00
tx.Statement.Dest = map[string]interface{}{column: value}
tx.callbacks.Update().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
func (db *DB) UpdateColumns(values interface{}) (tx *DB) {
tx = db.getInstance()
2020-03-07 08:43:20 +03:00
tx.Statement.Dest = values
tx.callbacks.Update().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
2020-02-03 05:40:03 +03:00
// Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition
2020-03-08 09:51:52 +03:00
func (db *DB) Delete(value interface{}, conds ...interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
2020-03-08 09:51:52 +03:00
if len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: tx.Statement.BuildCondtion(conds[0], conds[1:]...)})
}
tx.Statement.Dest = value
tx.callbacks.Delete().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}
2020-02-03 05:40:03 +03:00
func (db *DB) Count(value interface{}) (tx *DB) {
2020-01-29 14:22:44 +03:00
tx = db.getInstance()
return
}
2020-02-03 05:40:03 +03:00
func (db *DB) Row() *sql.Row {
2020-02-22 14:41:01 +03:00
tx := db.getInstance()
tx.callbacks.Row().Execute(tx)
return tx.Statement.Dest.(*sql.Row)
2020-02-03 05:40:03 +03:00
}
func (db *DB) Rows() (*sql.Rows, error) {
2020-02-22 14:41:01 +03:00
tx := db.Set("rows", true)
tx.callbacks.Row().Execute(tx)
return tx.Statement.Dest.(*sql.Rows), tx.Error
2020-02-03 05:40:03 +03:00
}
// Scan scan value to a struct
func (db *DB) Scan(dest interface{}) (tx *DB) {
2020-01-30 10:14:48 +03:00
tx = db.getInstance()
return
}
2020-02-03 05:40:03 +03:00
func (db *DB) ScanRows(rows *sql.Rows, result interface{}) error {
2020-01-30 10:14:48 +03:00
return nil
}
2020-02-23 18:28:35 +03:00
// Transaction start a transaction as a block, return error will rollback, otherwise to commit.
2020-01-29 14:22:44 +03:00
func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) {
panicked := true
tx := db.Begin(opts...)
defer func() {
// Make sure to rollback when panic, Block error or Commit error
if panicked || err != nil {
tx.Rollback()
}
}()
2020-02-22 18:08:20 +03:00
err = fc(tx.Session(&Session{}))
2020-01-29 14:22:44 +03:00
if err == nil {
err = tx.Commit().Error
}
panicked = false
return
}
2020-02-23 18:28:35 +03:00
// Begin begins a transaction
2020-01-29 14:22:44 +03:00
func (db *DB) Begin(opts ...*sql.TxOptions) (tx *DB) {
tx = db.getInstance()
2020-03-09 08:10:48 +03:00
if beginner, ok := tx.Statement.ConnPool.(TxBeginner); ok {
2020-02-23 18:28:35 +03:00
var opt *sql.TxOptions
var err error
if len(opts) > 0 {
opt = opts[0]
}
2020-03-09 08:10:48 +03:00
if tx.Statement.ConnPool, err = beginner.BeginTx(db.Statement.Context, opt); err != nil {
2020-02-23 18:28:35 +03:00
tx.AddError(err)
}
} else {
tx.AddError(ErrInvalidTransaction)
}
2020-01-29 14:22:44 +03:00
return
}
2020-02-23 18:28:35 +03:00
// Commit commit a transaction
func (db *DB) Commit() *DB {
2020-03-09 08:10:48 +03:00
if comminter, ok := db.Statement.ConnPool.(TxCommiter); ok && comminter != nil {
2020-02-23 18:28:35 +03:00
db.AddError(comminter.Commit())
} else {
db.AddError(ErrInvalidTransaction)
}
return db
2020-01-29 14:22:44 +03:00
}
2020-02-23 18:28:35 +03:00
// Rollback rollback a transaction
func (db *DB) Rollback() *DB {
2020-03-09 08:10:48 +03:00
if comminter, ok := db.Statement.ConnPool.(TxCommiter); ok && comminter != nil {
2020-02-23 18:28:35 +03:00
db.AddError(comminter.Rollback())
} else {
db.AddError(ErrInvalidTransaction)
}
return db
2020-01-29 14:22:44 +03:00
}
2020-02-23 18:28:35 +03:00
// Exec execute raw sql
2020-01-29 14:22:44 +03:00
func (db *DB) Exec(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-02-22 14:41:01 +03:00
tx.callbacks.Raw().Execute(tx)
2020-01-29 14:22:44 +03:00
return
}