gf/g/database/gdb/gdb_transaction.go

186 lines
6.3 KiB
Go
Raw Normal View History

// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
2018-03-09 17:55:42 +08:00
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
2018-03-09 17:55:42 +08:00
package gdb
import (
2019-06-19 09:06:52 +08:00
"database/sql"
"fmt"
"github.com/gogf/gf/g/text/gregex"
"reflect"
2018-03-09 17:55:42 +08:00
)
// 数据库事务对象
2018-12-14 18:35:51 +08:00
type TX struct {
2019-06-19 09:06:52 +08:00
db DB
tx *sql.Tx
master *sql.DB
2018-03-12 11:46:12 +08:00
}
// 事务操作,提交
2018-12-14 18:35:51 +08:00
func (tx *TX) Commit() error {
2019-06-19 09:06:52 +08:00
return tx.tx.Commit()
2018-03-12 11:46:12 +08:00
}
2018-03-09 17:55:42 +08:00
2018-03-12 11:46:12 +08:00
// 事务操作,回滚
2018-12-14 18:35:51 +08:00
func (tx *TX) Rollback() error {
2019-06-19 09:06:52 +08:00
return tx.tx.Rollback()
2018-03-09 17:55:42 +08:00
}
2018-03-12 15:38:27 +08:00
// (事务)数据库sql查询操作主要执行查询
2018-12-14 18:35:51 +08:00
func (tx *TX) Query(query string, args ...interface{}) (rows *sql.Rows, err error) {
2019-06-19 09:06:52 +08:00
return tx.db.doQuery(tx.tx, query, args...)
2018-03-09 17:55:42 +08:00
}
2018-03-12 15:38:27 +08:00
// (事务)执行一条sql并返回执行情况主要用于非查询操作
2018-12-14 18:35:51 +08:00
func (tx *TX) Exec(query string, args ...interface{}) (sql.Result, error) {
2019-06-19 09:06:52 +08:00
return tx.db.doExec(tx.tx, query, args...)
}
// sql预处理执行完成后调用返回值sql.Stmt.Exec完成sql操作
func (tx *TX) Prepare(query string) (*sql.Stmt, error) {
2019-06-19 09:06:52 +08:00
return tx.db.doPrepare(tx.tx, query)
2018-03-09 17:55:42 +08:00
}
// 数据库查询,获取查询结果集,以列表结构返回
2018-12-14 18:35:51 +08:00
func (tx *TX) GetAll(query string, args ...interface{}) (Result, error) {
2019-06-19 09:06:52 +08:00
rows, err := tx.Query(query, args...)
if err != nil || rows == nil {
return nil, err
}
defer rows.Close()
return tx.db.rowsToResult(rows)
2018-03-09 17:55:42 +08:00
}
// 数据库查询,获取查询结果记录,以关联数组结构返回
2018-12-14 18:35:51 +08:00
func (tx *TX) GetOne(query string, args ...interface{}) (Record, error) {
2019-06-19 09:06:52 +08:00
list, err := tx.GetAll(query, args...)
if err != nil {
return nil, err
}
if len(list) > 0 {
return list[0], nil
}
return nil, nil
}
// 数据库查询获取查询结果记录自动映射数据到给定的struct对象中
2018-12-14 18:35:51 +08:00
func (tx *TX) GetStruct(obj interface{}, query string, args ...interface{}) error {
2019-06-19 09:06:52 +08:00
one, err := tx.GetOne(query, args...)
if err != nil {
return err
}
return one.ToStruct(obj)
2018-03-09 17:55:42 +08:00
}
// 数据库查询查询多条记录并自动转换为指定的slice对象, 如: []struct/[]*struct。
func (tx *TX) GetStructs(objPointerSlice interface{}, query string, args ...interface{}) error {
2019-06-19 09:06:52 +08:00
all, err := tx.GetAll(query, args...)
if err != nil {
return err
}
return all.ToStructs(objPointerSlice)
}
// 将结果转换为指定的struct/*struct/[]struct/[]*struct,
// 参数应该为指针类型,否则返回失败。
// 该方法自动识别参数类型调用Struct/Structs方法。
func (tx *TX) GetScan(objPointer interface{}, query string, args ...interface{}) error {
2019-06-19 09:06:52 +08:00
t := reflect.TypeOf(objPointer)
k := t.Kind()
if k != reflect.Ptr {
return fmt.Errorf("params should be type of pointer, but got: %v", k)
}
k = t.Elem().Kind()
switch k {
case reflect.Array:
case reflect.Slice:
return tx.db.GetStructs(objPointer, query, args...)
case reflect.Struct:
return tx.db.GetStruct(objPointer, query, args...)
default:
return fmt.Errorf("element type should be type of struct/slice, unsupported: %v", k)
}
return nil
}
// 数据库查询,获取查询字段值
2018-12-14 18:35:51 +08:00
func (tx *TX) GetValue(query string, args ...interface{}) (Value, error) {
2019-06-19 09:06:52 +08:00
one, err := tx.GetOne(query, args...)
if err != nil {
return nil, err
}
for _, v := range one {
return v, nil
}
return nil, nil
2018-03-09 17:55:42 +08:00
}
// 数据库查询,获取查询数量
2018-12-14 18:35:51 +08:00
func (tx *TX) GetCount(query string, args ...interface{}) (int, error) {
2019-06-19 09:06:52 +08:00
if !gregex.IsMatchString(`(?i)SELECT\s+COUNT\(.+\)\s+FROM`, query) {
query, _ = gregex.ReplaceString(`(?i)(SELECT)\s+(.+)\s+(FROM)`, `$1 COUNT($2) $3`, query)
}
value, err := tx.GetValue(query, args...)
if err != nil {
return 0, err
}
return value.Int(), nil
2018-03-09 17:55:42 +08:00
}
// CURD操作:单条数据写入, 仅仅执行写入操作,如果存在冲突的主键或者唯一索引,那么报错返回
2019-06-19 09:06:52 +08:00
func (tx *TX) Insert(table string, data interface{}, batch ...int) (sql.Result, error) {
return tx.db.doInsert(tx.tx, table, data, OPTION_INSERT, batch...)
2018-03-09 17:55:42 +08:00
}
// CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
2019-06-19 09:06:52 +08:00
func (tx *TX) Replace(table string, data interface{}, batch ...int) (sql.Result, error) {
return tx.db.doInsert(tx.tx, table, data, OPTION_REPLACE, batch...)
2018-03-09 17:55:42 +08:00
}
// CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
2019-06-19 09:06:52 +08:00
func (tx *TX) Save(table string, data interface{}, batch ...int) (sql.Result, error) {
return tx.db.doInsert(tx.tx, table, data, OPTION_SAVE, batch...)
2018-03-09 17:55:42 +08:00
}
// CURD操作:批量数据指定批次量写入
2019-06-19 09:06:52 +08:00
func (tx *TX) BatchInsert(table string, list interface{}, batch ...int) (sql.Result, error) {
return tx.db.doBatchInsert(tx.tx, table, list, OPTION_INSERT, batch...)
2018-03-09 17:55:42 +08:00
}
// CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
2019-06-19 09:06:52 +08:00
func (tx *TX) BatchReplace(table string, list interface{}, batch ...int) (sql.Result, error) {
return tx.db.doBatchInsert(tx.tx, table, list, OPTION_REPLACE, batch...)
2018-03-09 17:55:42 +08:00
}
// CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
2019-06-19 09:06:52 +08:00
func (tx *TX) BatchSave(table string, list interface{}, batch ...int) (sql.Result, error) {
return tx.db.doBatchInsert(tx.tx, table, list, OPTION_SAVE, batch...)
2018-03-09 17:55:42 +08:00
}
2019-03-17 22:26:41 +08:00
// CURD操作:数据更新统一采用sql预处理,
// data参数支持字符串或者关联数组类型内部会自行做判断处理.
2018-12-14 18:35:51 +08:00
func (tx *TX) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) {
2019-06-19 09:06:52 +08:00
newWhere, newArgs := formatCondition(condition, args)
return tx.doUpdate(table, data, newWhere, newArgs...)
2019-03-17 22:26:41 +08:00
}
// 与Update方法的区别是不处理条件参数
func (tx *TX) doUpdate(table string, data interface{}, condition string, args ...interface{}) (sql.Result, error) {
2019-06-19 09:06:52 +08:00
return tx.db.doUpdate(tx.tx, table, data, condition, args...)
2018-03-09 17:55:42 +08:00
}
// CURD操作:删除数据
2018-12-14 18:35:51 +08:00
func (tx *TX) Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) {
2019-06-19 09:06:52 +08:00
newWhere, newArgs := formatCondition(condition, args)
return tx.doDelete(table, newWhere, newArgs...)
2019-03-17 22:26:41 +08:00
}
// 与Delete方法的区别是不处理条件参数
func (tx *TX) doDelete(table string, condition string, args ...interface{}) (sql.Result, error) {
2019-06-19 09:06:52 +08:00
return tx.db.doDelete(tx.tx, table, condition, args...)
2018-03-09 17:55:42 +08:00
}