Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 54d0179

Browse files
committed
Updated for transaction and fully documented
1 parent 44da132 commit 54d0179

File tree

4 files changed

+178
-25
lines changed

4 files changed

+178
-25
lines changed

README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Goshia
2+
3+
Goshia 是採用 [go-gorm/gorm](https://github.com/go-gorm/gorm/)[teacat/rushia](https://github.com/teacat/rushia/) 的私有套件,這能夠以 Gorm(資料庫連線)作為 Rushia(SQL 語法建置函式庫)的執行基底。
4+
5+
## 使用方式
6+
7+
打開終端機並且透過 `go get` 安裝此套件即可,這個套件的版本通常會與 Rushia 相同。
8+
9+
```bash
10+
$ go get github.com/teacat/goshia/v3
11+
```
12+
13+
### 初始化
14+
15+
使用 Goshia 之前,需要先初始化一個 Gorm 資料庫連線並最後將其帶入至 `goshia.New(db)`
16+
17+
```go
18+
// 初始化 Gorm 至資料庫的連線。
19+
db, err := gorm.Open(mysql.Open(dsn))
20+
if err != nil {
21+
log.Fatalf(err)
22+
}
23+
// 將 Gorm 帶入給 Goshia 並初始化一個輔助函式。
24+
goshia := goshia.New(db)
25+
```
26+
27+
### 查詢(Query)
28+
29+
這是最常使用的函式,查詢(如:Select 語法)可以讓 Goshia 將資料直接映射到指定的指針。
30+
31+
```go
32+
var user User
33+
err := goshia.Query(rushia.NewQuery("Users").Where("user_id = ?", ColumnUserID, 10).Select(), &user)
34+
// 等效於:SELECT * FROM Users WHERE `user_id` = ?
35+
```
36+
37+
### 查詢與計數(QueryCount)
38+
39+
這與 `Query` 的用法相同,但會私底下額外執行一個相同但沒有筆數限制的 SQL 去取得計數筆數。
40+
41+
這個使用時機通常是:希望進行分頁並且需要知道總筆數。由於執行 `LIMIT 1, 10` 諸如此類篩選限制 SQL 會導致沒辦法取得真正的總筆數,
42+
43+
因此需要透過 `QueryCount` 自動額外取得不受限制時的總筆數資料。
44+
45+
```go
46+
var users []User
47+
count, err := goshia.Query(rushia.NewQuery("Users").Limit(10, 20).Select(), &users)
48+
// 等效於:SELECT * FROM Users LIMIT 10, 20
49+
// 等效於:SELECT COUNT(*) FROM Users
50+
```
51+
52+
### 執行(Exec)
53+
54+
執行 `DELETE``UPDATE`…等語法時,可以使用 `Exec` 執行並且取得影響的筆數為何。
55+
56+
```go
57+
var user User
58+
affectedRows, err := goshia.Query(rushia.NewQuery("Users").Where("user_id = ?", 30).Update(user))
59+
// 等效於:UPDATE Users SET ... WHERE `user_id` = ?
60+
```
61+
62+
### 執行與編號(ExecID)
63+
64+
如果欄位帶有自動遞增且希望在 `INSERT` 插入時取得這個新的遞增值,就可以使用 `ExecID` 來取得這個新的編號。
65+
66+
```go
67+
var user User
68+
id, affectedRows, err := goshia.Query(rushia.NewQuery("Users").Insert(user))
69+
// 等效於:INSERT INTO Users SET ...
70+
```
71+
72+
### 交易與回溯(Transaction)
73+
74+
若希望初始化一個事務交易(Transaction),正如其名可以直接呼叫 `Transaction` 並在裡面執行 SQL 語法。
75+
76+
如果該處理函式回傳任何 `error` 則會導致 Goshia 自動回溯所有行為。
77+
78+
如果一個 Goshia 不是由 `Transaction` 被建立的而卻呼叫其事務交易函式會直接觸發 `panic`
79+
80+
除此之外,Goshia 也提供使用 Gorm 的 `Rollback``RollbackTo``SavePoint`…等函式。
81+
82+
```go
83+
goshia.Transaction(func (tx *goshia.Goshia) error {
84+
_, err := tx.Exec(rushia.NewQuery("Users").Where("user_id = ?", 30).Update(user))
85+
// 等效於:UPDATE Users SET ... WHERE `user_id` = ?
86+
if err != nil {
87+
return err
88+
}
89+
// 蹦蹦!記得要 Commit!
90+
tx.Commit()
91+
return nil
92+
})
93+
```
94+
95+
### 輔助資料型態
96+
97+
透過 `goshia.Int``goshia.Bool` 等函式,可以將一個值轉換成指針作為填補 SQL 的 Nullable 欄位。這個用法正如 [AWS SDK](https://docs.aws.amazon.com/sdk-for-go/api/aws/) 一樣。

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
module github.com/teacat/goshia
1+
module github.com/teacat/goshia/v3
22

33
go 1.16
44

55
require (
6-
github.com/teacat/rushia/v2 v2.0.4
6+
github.com/teacat/rushia/v3 v3.0.0
77
gorm.io/gorm v1.21.16
88
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
99
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
1010
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
1111
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
12-
github.com/teacat/rushia/v2 v2.0.4 h1:LIUBaGYfDJ81eQh+NV0YIPhY8KmI74KoZGWfcJNSJ9c=
13-
github.com/teacat/rushia/v2 v2.0.4/go.mod h1:DwC5hz+pMv1NihJnlYcIC6NQLaBos6xA6nG7dI5Ldf0=
12+
github.com/teacat/rushia/v3 v3.0.0 h1:PGsJteCB3yn8BLWb599LqNawGx+/vnOcEqFHxtrf+qA=
13+
github.com/teacat/rushia/v3 v3.0.0/go.mod h1:hq1jtclK8gQjOw8JCd934rWZjrJgG6JXaoWZRdDjguM=
1414
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1515
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
1616
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

goshia.go

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
package goshia
22

33
import (
4-
"reflect"
4+
"errors"
55
"time"
66

7-
"github.com/teacat/rushia/v2"
7+
"github.com/teacat/rushia/v3"
88
"gorm.io/gorm"
99
)
1010

11+
var (
12+
ErrNotTransaction = errors.New("goshia: processing non-transaction")
13+
)
14+
1115
// Goshia
1216
type Goshia struct {
13-
Gorm *gorm.DB
17+
Gorm *gorm.DB
18+
isTransaction bool
19+
}
20+
21+
//
22+
type Transaction struct {
1423
}
1524

16-
// NewGoshia
17-
func NewGoshia(g *gorm.DB) *Goshia {
25+
// New
26+
func New(g *gorm.DB) *Goshia {
1827
return &Goshia{
1928
Gorm: g,
2029
}
@@ -28,7 +37,7 @@ func (g *Goshia) Query(q *rushia.Query, dest interface{}) error {
2837

2938
// QueryCount
3039
func (g *Goshia) QueryCount(q *rushia.Query, dest interface{}) (count int, err error) {
31-
countQuery, countParams := rushia.Build(q.Copy().ClearLimit())
40+
countQuery, countParams := rushia.Build(q.Copy().ClearLimit().Select("COUNT(*)"))
3241
if err := g.Gorm.Raw(countQuery, countParams...).Scan(&count).Error; err != nil {
3342
return 0, err
3443
}
@@ -37,13 +46,16 @@ func (g *Goshia) QueryCount(q *rushia.Query, dest interface{}) (count int, err e
3746
}
3847

3948
// Exec
40-
func (g *Goshia) Exec(q *rushia.Query) error {
49+
func (g *Goshia) Exec(q *rushia.Query) (affectedRows int, err error) {
4150
query, params := rushia.Build(q)
42-
return g.Gorm.Exec(query, params...).Error
51+
result := g.Gorm.Exec(query, params...)
52+
affectedRows = int(result.RowsAffected)
53+
err = result.Error
54+
return
4355
}
4456

4557
// ExecID
46-
func (g *Goshia) ExecID(q *rushia.Query) (id int, err error) {
58+
func (g *Goshia) ExecID(q *rushia.Query) (id int, affectedRows int, err error) {
4759
query, params := rushia.Build(q)
4860

4961
err = g.Gorm.Transaction(func(tx *gorm.DB) error {
@@ -58,37 +70,81 @@ func (g *Goshia) ExecID(q *rushia.Query) (id int, err error) {
5870
return
5971
}
6072

61-
// Interfaces
62-
func Interfaces(v interface{}) []interface{} {
63-
valuesVal := reflect.ValueOf(v)
64-
interfaceVals := make([]interface{}, 0)
65-
for i := range interfaceVals {
66-
interfaceVals[i] = valuesVal.Index(i).Interface()
73+
// Transaction
74+
func (g *Goshia) Transaction(handler func(tx *Goshia) error) error {
75+
return g.Gorm.Transaction(func(tx *gorm.DB) error {
76+
return handler(&Goshia{
77+
Gorm: tx,
78+
isTransaction: true,
79+
})
80+
})
81+
}
82+
83+
// Rollback
84+
func (g *Goshia) Rollback() *Goshia {
85+
if !g.isTransaction {
86+
panic(ErrNotTransaction)
87+
}
88+
return &Goshia{
89+
Gorm: g.Gorm.Rollback(),
90+
isTransaction: true,
91+
}
92+
}
93+
94+
// RollbackTo
95+
func (g *Goshia) RollbackTo(name string) *Goshia {
96+
if !g.isTransaction {
97+
panic(ErrNotTransaction)
98+
}
99+
return &Goshia{
100+
Gorm: g.Gorm.RollbackTo(name),
101+
isTransaction: true,
102+
}
103+
}
104+
105+
// Commit
106+
func (g *Goshia) Commit() *Goshia {
107+
if !g.isTransaction {
108+
panic(ErrNotTransaction)
109+
}
110+
return &Goshia{
111+
Gorm: g.Gorm.Commit(),
112+
isTransaction: true,
113+
}
114+
}
115+
116+
// SavePoint
117+
func (g *Goshia) SavePoint(name string) *Goshia {
118+
if !g.isTransaction {
119+
panic(ErrNotTransaction)
120+
}
121+
return &Goshia{
122+
Gorm: g.Gorm.SavePoint(name),
123+
isTransaction: true,
67124
}
68-
return interfaceVals
69125
}
70126

71-
// String
127+
// String 會回傳一個指針字串,這用來填補 SQL 中的 Nullable 欄位。
72128
func String(v string) *string {
73129
return &v
74130
}
75131

76-
// Bool
132+
// Bool 會回傳一個指針布林值,這用來填補 SQL 中的 Nullable 欄位。
77133
func Bool(v bool) *bool {
78134
return &v
79135
}
80136

81-
// Int
137+
// Int 會回傳一個指針正整數,這用來填補 SQL 中的 Nullable 欄位。
82138
func Int(v int) *int {
83139
return &v
84140
}
85141

86-
// Float64
142+
// Float64 會回傳一個指針浮點數,這用來填補 SQL 中的 Nullable 欄位。
87143
func Float64(v float64) *float64 {
88144
return &v
89145
}
90146

91-
// Time
147+
// Time 會回傳一個指針時間,這用來填補 SQL 中的 Nullable 欄位。
92148
func Time(v time.Time) *time.Time {
93149
return &v
94150
}

0 commit comments

Comments
 (0)