Skip to content

Commit f00cfb1

Browse files
committed
Starting to transaction wrap
1 parent 89292d2 commit f00cfb1

File tree

3 files changed

+67
-28
lines changed

3 files changed

+67
-28
lines changed

dump.go

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@ import (
1414
/*
1515
Data struct to configure dump behavior
1616
17-
Out: Stream to wite to
18-
Connection: Database connection to dump
19-
IgnoreTables: Mark sensitive tables to ignore
17+
Out: Stream to wite to
18+
Connection: Database connection to dump
19+
IgnoreTables: Mark sensitive tables to ignore
20+
LockTables: Lock all tables for the duration of the dump
21+
SingleTransaction: Do the entire dump in one transaction
2022
*/
2123
type Data struct {
22-
Out io.Writer
23-
Connection *sql.DB
24-
IgnoreTables []string
25-
MaxAllowedPacket int
26-
LockTables bool
27-
24+
Out io.Writer
25+
Connection *sql.DB
26+
IgnoreTables []string
27+
MaxAllowedPacket int
28+
LockTables bool
29+
SingleTransaction bool
30+
31+
tx *sql.Tx
2832
headerTmpl *template.Template
2933
tableTmpl *template.Template
3034
footerTmpl *template.Template
@@ -49,7 +53,7 @@ type metaData struct {
4953

5054
const (
5155
// Version of this plugin for easy reference
52-
Version = "0.5.0"
56+
Version = "0.6.0"
5357

5458
defaultMaxAllowedPacket = 4194304
5559
)
@@ -123,15 +127,20 @@ func (data *Data) Dump() error {
123127
data.MaxAllowedPacket = defaultMaxAllowedPacket
124128
}
125129

126-
if err := meta.updateServerVersion(data.Connection); err != nil {
130+
if err := data.getTemplates(); err != nil {
127131
return err
128132
}
129133

130-
if err := data.getTemplates(); err != nil {
134+
if err := data.headerTmpl.Execute(data.Out, meta); err != nil {
131135
return err
132136
}
133137

134-
if err := data.headerTmpl.Execute(data.Out, meta); err != nil {
138+
if err := data.begin(); err != nil {
139+
return err
140+
}
141+
defer data.rollback()
142+
143+
if err := meta.updateServerVersion(data); err != nil {
135144
return err
136145
}
137146

@@ -173,6 +182,18 @@ func (data *Data) Dump() error {
173182

174183
// MARK: - Private methods
175184

185+
func (data *Data) begin() (err error) {
186+
data.tx, err = data.Connection.BeginTx(nil, &sql.TxOptions{
187+
Isolation: sql.LevelRepeatableRead,
188+
ReadOnly: true,
189+
})
190+
return
191+
}
192+
193+
func (data *Data) rollback() error {
194+
return data.tx.Rollback()
195+
}
196+
176197
// MARK: writter methods
177198

178199
func (data *Data) dumpTable(name string) error {
@@ -214,7 +235,7 @@ func (data *Data) getTemplates() (err error) {
214235
func (data *Data) getTables() ([]string, error) {
215236
tables := make([]string, 0)
216237

217-
rows, err := data.Connection.Query("SHOW TABLES")
238+
rows, err := data.tx.Query("SHOW TABLES")
218239
if err != nil {
219240
return tables, err
220241
}
@@ -241,10 +262,10 @@ func (data *Data) isIgnoredTable(name string) bool {
241262
return false
242263
}
243264

244-
func (data *metaData) updateServerVersion(db *sql.DB) (err error) {
265+
func (meta *metaData) updateServerVersion(data *Data) (err error) {
245266
var serverVersion sql.NullString
246-
err = db.QueryRow("SELECT version()").Scan(&serverVersion)
247-
data.ServerVersion = serverVersion.String
267+
err = data.tx.QueryRow("SELECT version()").Scan(&serverVersion)
268+
meta.ServerVersion = serverVersion.String
248269
return
249270
}
250271

@@ -263,7 +284,7 @@ func (table *table) NameEsc() string {
263284

264285
func (table *table) CreateSQL() (string, error) {
265286
var tableReturn, tableSQL sql.NullString
266-
if err := table.data.Connection.QueryRow("SHOW CREATE TABLE "+table.NameEsc()).Scan(&tableReturn, &tableSQL); err != nil {
287+
if err := table.data.tx.QueryRow("SHOW CREATE TABLE "+table.NameEsc()).Scan(&tableReturn, &tableSQL); err != nil {
267288
return "", err
268289
}
269290

@@ -280,7 +301,7 @@ func (table *table) Init() (err error) {
280301
return errors.New("can't init twice")
281302
}
282303

283-
table.rows, err = table.data.Connection.Query("SELECT * FROM " + table.NameEsc())
304+
table.rows, err = table.data.tx.Query("SELECT * FROM " + table.NameEsc())
284305
if err != nil {
285306
return err
286307
}

dump_test.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,31 @@ import (
1010
"github.com/stretchr/testify/assert"
1111
)
1212

13-
func TestGetTablesOk(t *testing.T) {
13+
func GetMockData() (data *Data, mock sqlmock.Sqlmock, err error) {
1414
db, mock, err := sqlmock.New()
15+
if err != nil {
16+
return
17+
}
18+
mock.ExpectBegin()
19+
20+
data = &Data{
21+
Connection: db,
22+
}
23+
err = data.begin()
24+
return
25+
}
26+
27+
func TestGetTablesOk(t *testing.T) {
28+
data, mock, err := GetMockData()
1529
assert.NoError(t, err, "an error was not expected when opening a stub database connection")
16-
defer db.Close()
30+
defer data.Close()
1731

1832
rows := sqlmock.NewRows([]string{"Tables_in_Testdb"}).
1933
AddRow("Test_Table_1").
2034
AddRow("Test_Table_2")
2135

2236
mock.ExpectQuery("^SHOW TABLES$").WillReturnRows(rows)
2337

24-
data := Data{
25-
Connection: db,
26-
}
27-
2838
result, err := data.getTables()
2939
assert.NoError(t, err)
3040

@@ -94,11 +104,15 @@ func TestGetServerVersionOk(t *testing.T) {
94104
rows := sqlmock.NewRows([]string{"Version()"}).
95105
AddRow("test_version")
96106

107+
mock.ExpectBegin()
97108
mock.ExpectQuery("^SELECT version()").WillReturnRows(rows)
98109

99110
meta := metaData{}
100111

101-
assert.NoError(t, meta.updateServerVersion(db), "error was not expected while updating stats")
112+
tx, _ := db.Begin()
113+
assert.NoError(t, meta.updateServerVersion(&Data{
114+
tx: tx,
115+
}), "error was not expected while updating stats")
102116

103117
// we make sure that all expectations were met
104118
assert.NoError(t, mock.ExpectationsWereMet(), "there were unfulfilled expections")

mysqldump_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,13 @@ func RunDump(t testing.TB, data *Data) {
7676
AddRow(1, nil, "Test Name 1").
7777
AddRow(2, "[email protected]", "Test Name 2")
7878

79+
mock.ExpectBegin()
7980
mock.ExpectQuery(`^SELECT version\(\)$`).WillReturnRows(serverVersionRows)
80-
mock.ExpectQuery("^SHOW TABLES$").WillReturnRows(showTablesRows)
81+
mock.ExpectQuery(`^SHOW TABLES$`).WillReturnRows(showTablesRows)
8182
mock.ExpectExec("^LOCK TABLES `Test_Table` READ /\\*!32311 LOCAL \\*/$").WillReturnResult(sqlmock.NewResult(1, 1))
8283
mock.ExpectQuery("^SHOW CREATE TABLE `Test_Table`$").WillReturnRows(createTableRows)
8384
mock.ExpectQuery("^SELECT (.+) FROM `Test_Table`$").WillReturnRows(createTableValueRows)
85+
mock.ExpectRollback()
8486

8587
assert.NoError(t, data.Dump(), "an error was not expected when dumping a stub database connection")
8688
}
@@ -124,10 +126,12 @@ func TestNoLockOk(t *testing.T) {
124126
AddRow(1, nil, "Test Name 1").
125127
AddRow(2, "[email protected]", "Test Name 2")
126128

129+
mock.ExpectBegin()
127130
mock.ExpectQuery(`^SELECT version\(\)$`).WillReturnRows(serverVersionRows)
128-
mock.ExpectQuery("^SHOW TABLES$").WillReturnRows(showTablesRows)
131+
mock.ExpectQuery(`^SHOW TABLES$`).WillReturnRows(showTablesRows)
129132
mock.ExpectQuery("^SHOW CREATE TABLE `Test_Table`$").WillReturnRows(createTableRows)
130133
mock.ExpectQuery("^SELECT (.+) FROM `Test_Table`$").WillReturnRows(createTableValueRows)
134+
mock.ExpectRollback()
131135

132136
assert.NoError(t, data.Dump(), "an error was not expected when dumping a stub database connection")
133137

0 commit comments

Comments
 (0)