Skip to content

Commit 66a9d99

Browse files
authored
Merge pull request #1 from mashiike/feature/new-with-sql-db
Feature/new with sql db
2 parents 187d8e8 + c4518aa commit 66a9d99

File tree

8 files changed

+127
-45
lines changed

8 files changed

+127
-45
lines changed

.github/workflows/release.yaml

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,25 @@ on:
44
branches:
55
- "!**/*"
66
tags:
7-
- "v*"
7+
- "v*.*.*"
88

99
jobs:
1010
release:
1111
name: Release
1212
runs-on: ubuntu-latest
1313
steps:
14-
- name: Set up Go
15-
uses: actions/setup-go@v2
16-
with:
17-
go-version: 1.16
14+
- name: Set up Go
15+
uses: actions/setup-go@v1
16+
with:
17+
go-version: 1.17
1818

19-
- name: Check out code into the Go module directory
20-
uses: actions/checkout@v2
19+
- name: Check out code into the Go module directory
20+
uses: actions/checkout@v2
2121

22-
- name: setup tools
23-
run: |
24-
mkdir ~/bin
25-
curl -sL https://github.com/Songmu/goxz/releases/download/v0.4.1/goxz_v0.4.1_linux_amd64.tar.gz | tar zxvf - && install goxz_v0.4.1_linux_amd64/goxz ~/bin/
26-
curl -sL https://github.com/tcnksm/ghr/releases/download/v0.13.0/ghr_v0.13.0_linux_amd64.tar.gz | tar zxvf - && install ghr_v0.13.0_linux_amd64/ghr ~/bin/
27-
- name: dist
28-
run: PATH=~/bin:$PATH make dist
29-
30-
- name: release
31-
run: PATH=~/bin:$PATH make release
32-
env:
33-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22+
- name: Run GoReleaser
23+
uses: goreleaser/goreleaser-action@v1
24+
with:
25+
version: latest
26+
args: release --rm-dist
27+
env:
28+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jobs:
55
strategy:
66
matrix:
77
go:
8-
- 1.16
8+
- 1.17
99
name: Build
1010
runs-on: ubuntu-latest
1111
steps:

.goreleaser.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This is an example goreleaser.yaml file with some sane defaults.
2+
# Make sure to check the documentation at http://goreleaser.com
3+
before:
4+
hooks:
5+
- go mod download
6+
builds:
7+
- env:
8+
- CGO_ENABLED=0
9+
main: ./cmd/mysqlbatch
10+
binary: mysqlbatch
11+
ldflags:
12+
- -s -w
13+
- -X main.Version=v{{.Version}}
14+
- -X main.BuildDate=v{{.Date}}
15+
goos:
16+
- darwin
17+
- linux
18+
- windows
19+
goarch:
20+
- amd64
21+
- arm64
22+
release:
23+
prerelease: true
24+
archives:
25+
checksum:
26+
name_template: "checksums.txt"
27+
snapshot:
28+
name_template: "{{ .Env.NIGHTLY_VERSION }}"
29+
changelog:
30+
sort: asc
31+
filters:
32+
exclude:
33+
- "^docs:"
34+
- "^test:"

Makefile

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
GIT_VER := $(shell git describe --tags)
2-
DATE := $(shell date +%Y-%m-%dT%H:%M:%S%z)
3-
GO_VER := $(shell go version)
4-
51
export GO111MODULE := on
62

7-
.PHONY: test binary install clean dist
3+
.PHONY: test clean
84
cmd/mysqlbatch/mysqlbatch: *.go cmd/mysqlbatch/*.go
9-
cd cmd/mysqlbatch && go build -ldflags "-s -w -X 'main.Version=${GIT_VER}' -X 'main.BuildDate=${DATE}' -X 'main.GoVersion=${GO_VER}'" -gcflags="-trimpath=${PWD}"
5+
cd cmd/mysqlbatch && go build .
106

117
test:
128
go test -race .
@@ -15,12 +11,3 @@ test:
1511
clean:
1612
rm -f cmd/mysqlbatch/mysqlbatch
1713
rm -fr dist/
18-
19-
dist:
20-
CGO_ENABLED=0 \
21-
goxz -pv=$(GIT_VER) \
22-
-build-ldflags="-s -w -X 'main.Version=${GIT_VER}' -X 'main.BuildDate=${DATE}' -X 'main.GoVersion=${GO_VER}'" \
23-
-os=darwin,linux -arch=amd64 -d=dist ./cmd/mysqlbatch
24-
25-
release:
26-
ghr -u mashiike -r mysqlbatch -n "$(GIT_VER)" $(GIT_VER) dist/

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,23 @@ $ mysqlbatch -u root -p ${password} -h localhost < batch.sql
3535
```
3636

3737

38+
## Usage as a library
39+
40+
41+
```go
42+
executer, err := mysqlbatch.Open("root:password@tcp(localhost:3306)/testdb?parseTime=true")
43+
if err != nil {
44+
//...
45+
}
46+
defer executer.Close()
47+
if err := executer.Execute(strings.NewReader("UPDATE users SET name = 'hoge';")); err != nil {
48+
//...
49+
}
50+
```
51+
52+
more infomation see [go doc](https://godoc.org/github.com/mashiike/mysqlbatch).
53+
54+
## License
55+
56+
see [LICENSE](https://github.com/mashiike/mysqlbatch/blob/master/LICENSE) file.
57+

cmd/mysqlbatch/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log"
88
"os"
99
"os/signal"
10+
"runtime"
1011
"syscall"
1112

1213
"github.com/mashiike/mysqlbatch"
@@ -15,7 +16,6 @@ import (
1516
var (
1617
Version = "current"
1718
BuildDate = "(no data)"
18-
GoVersion = "(no data)"
1919
)
2020

2121
func main() {
@@ -34,7 +34,7 @@ func main() {
3434

3535
if *versionFlag {
3636
fmt.Printf("version : %s\n", Version)
37-
fmt.Printf("go version: %s\n", GoVersion)
37+
fmt.Printf("go version: %s\n", runtime.Version())
3838
fmt.Printf("build date: %s\n", BuildDate)
3939
return
4040
}

executer.go

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"github.com/pkg/errors"
1616
)
1717

18+
// Config is a connection setting to MySQL.
19+
// Exists to generate a Golang connection DSN to MySQL
1820
type Config struct {
1921
DSN string
2022
User string
@@ -24,6 +26,7 @@ type Config struct {
2426
Database string
2527
}
2628

29+
// NewDefaultConfig returns the config for connecting to the local MySQL server
2730
func NewDefaultConfig() *Config {
2831
return &Config{
2932
User: "root",
@@ -32,6 +35,7 @@ func NewDefaultConfig() *Config {
3235
}
3336
}
3437

38+
//GetDSN returns a DSN dedicated to connecting to MySQL.
3539
func (c *Config) GetDSN() string {
3640
if c.DSN == "" {
3741
return fmt.Sprintf(
@@ -46,32 +50,43 @@ func (c *Config) GetDSN() string {
4650
return strings.TrimPrefix(c.DSN, "mysql://")
4751
}
4852

53+
//Executer queries the DB. There is no parallelism
4954
type Executer struct {
5055
mu sync.Mutex
51-
dsn string
5256
db *sql.DB
5357
lastExecuteTime time.Time
5458
selectHook func(query string, columns []string, rows [][]string)
5559
executeHook func(query string, rowsAffected int64, lastInsertId int64)
60+
isSelectFunc func(query string) bool
61+
timeCheckQuery string
5662
}
5763

64+
//New return Executer with config
5865
func New(config *Config) (*Executer, error) {
5966
return Open(config.GetDSN())
6067
}
6168

69+
//Open with dsn
6270
func Open(dsn string) (*Executer, error) {
6371
db, err := sql.Open("mysql", dsn)
6472
if err != nil {
6573
return nil, errors.Wrap(err, "mysql connect failed")
6674
}
75+
return NewWithDB(db), nil
76+
}
77+
78+
// NewWithDB returns Executer with *sql.DB
79+
// Note: Since it is made assuming MySQL, it may be inconvenient for other DBs.
80+
func NewWithDB(db *sql.DB) *Executer {
6781
db.SetMaxIdleConns(1)
6882
db.SetMaxOpenConns(1)
6983
return &Executer{
70-
dsn: dsn,
71-
db: db,
72-
}, nil
84+
db: db,
85+
timeCheckQuery: "SELECT NOW()",
86+
}
7387
}
7488

89+
// Close DB
7590
func (e *Executer) Close() error {
7691
e.mu.Lock()
7792
defer e.mu.Unlock()
@@ -81,10 +96,12 @@ func (e *Executer) Close() error {
8196
return e.db.Close()
8297
}
8398

99+
//Execute SQL
84100
func (e *Executer) Execute(queryReader io.Reader) error {
85101
return e.ExecuteContext(context.Background(), queryReader)
86102
}
87103

104+
//ExecuteContext SQL execute with context.Context
88105
func (e *Executer) ExecuteContext(ctx context.Context, queryReader io.Reader) error {
89106
e.mu.Lock()
90107
defer e.mu.Unlock()
@@ -95,7 +112,7 @@ func (e *Executer) ExecuteContext(ctx context.Context, queryReader io.Reader) er
95112
}
96113

97114
func (e *Executer) updateLastExecuteTime(ctx context.Context) error {
98-
row := e.db.QueryRowContext(ctx, "SELECT NOW()")
115+
row := e.db.QueryRowContext(ctx, e.timeCheckQuery)
99116
if err := row.Err(); err != nil {
100117
return errors.Wrap(err, "get db time")
101118
}
@@ -116,7 +133,15 @@ func (e *Executer) executeContext(ctx context.Context, queryReader io.Reader) er
116133
}
117134
if e.selectHook != nil {
118135
upperedQuery := strings.ToUpper(query)
119-
if strings.HasPrefix(upperedQuery, "SELECT") || strings.HasPrefix(upperedQuery, "SHOW") {
136+
var isSelect bool
137+
if e.isSelectFunc == nil {
138+
if strings.HasPrefix(upperedQuery, "SELECT") || strings.HasPrefix(upperedQuery, "SHOW") || strings.HasPrefix(upperedQuery, `\`) {
139+
isSelect = true
140+
}
141+
} else {
142+
isSelect = e.isSelectFunc(upperedQuery)
143+
}
144+
if isSelect {
120145
if err := e.queryContext(ctx, query); err != nil {
121146
return errors.Wrap(err, "query rows failed")
122147
}
@@ -175,18 +200,32 @@ func (e *Executer) queryContext(ctx context.Context, query string) error {
175200
return nil
176201
}
177202

203+
//LastExecuteTime returns last execute time on DB
178204
func (e *Executer) LastExecuteTime() time.Time {
179205
return e.lastExecuteTime
180206
}
181207

208+
//SetExecuteHook set non select query hook
182209
func (e *Executer) SetExecuteHook(hook func(query string, rowsAffected, lastInsertId int64)) {
183210
e.executeHook = hook
184211
}
185212

213+
//SetSelectHook set select query hook
186214
func (e *Executer) SetSelectHook(hook func(query string, columns []string, rows [][]string)) {
187215
e.selectHook = hook
188216
}
189217

218+
//SetIsSelectFunc :Set the function to decide whether to execute in QueryContext
219+
func (e *Executer) SetIsSelectFunc(f func(query string) bool) {
220+
e.isSelectFunc = f
221+
}
222+
223+
//SetTimeCheckQuery set time check query for non mysql db
224+
func (e *Executer) SetTimeCheckQuery(query string) {
225+
e.timeCheckQuery = query
226+
}
227+
228+
//SetTimeCheckQuery set select query hook, but result is table string
190229
func (e *Executer) SetTableSelectHook(hook func(query, table string)) {
191230
e.selectHook = func(query string, columns []string, rows [][]string) {
192231
var buf strings.Builder
@@ -198,10 +237,12 @@ func (e *Executer) SetTableSelectHook(hook func(query, table string)) {
198237
}
199238
}
200239

240+
// QueryScanner separate string by ; and delete newline
201241
type QueryScanner struct {
202242
*bufio.Scanner
203243
}
204244

245+
//NewQueryScanner returns QueryScanner
205246
func NewQueryScanner(queryReader io.Reader) *QueryScanner {
206247
scanner := bufio.NewScanner(queryReader)
207248
onSplit := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
@@ -224,6 +265,7 @@ func NewQueryScanner(queryReader io.Reader) *QueryScanner {
224265
}
225266
}
226267

268+
//Query return
227269
func (s *QueryScanner) Query() string {
228270
return strings.Trim(strings.NewReplacer(
229271
"\r\n", " ",

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
module github.com/mashiike/mysqlbatch
22

3-
go 1.16
3+
go 1.17
44

55
require (
66
github.com/go-sql-driver/mysql v1.6.0
7-
github.com/mattn/go-runewidth v0.0.13 // indirect
87
github.com/olekukonko/tablewriter v0.0.5
98
github.com/pkg/errors v0.9.1
109
github.com/sergi/go-diff v1.1.0
1110
)
11+
12+
require (
13+
github.com/mattn/go-runewidth v0.0.13 // indirect
14+
github.com/rivo/uniseg v0.2.0 // indirect
15+
)

0 commit comments

Comments
 (0)