Skip to content

Commit f5a2aa3

Browse files
Merge pull request #19 from jamf/JPRO-3315-MySQL-Views-create-database-backup-errors
Jpro 3315 my sql views create database backup errors
2 parents 3254d43 + b4972f9 commit f5a2aa3

File tree

4 files changed

+120
-17
lines changed

4 files changed

+120
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
vendor/*
2+
.idea/*

dump.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ import (
1616
/*
1717
Data struct to configure dump behavior
1818
19-
Out: Stream to wite to
20-
Connection: Database connection to dump
21-
IgnoreTables: Mark sensitive tables to ignore
22-
MaxAllowedPacket: Sets the largest packet size to use in backups
23-
LockTables: Lock all tables for the duration of the dump
19+
Out: Stream to wite to
20+
Connection: Database connection to dump
21+
IgnoreTables: Mark sensitive tables to ignore
22+
MaxAllowedPacket: Sets the largest packet size to use in backups
23+
LockTables: Lock all tables for the duration of the dump
2424
*/
2525
type Data struct {
2626
Out io.Writer
@@ -290,16 +290,40 @@ func (table *table) NameEsc() string {
290290
}
291291

292292
func (table *table) CreateSQL() (string, error) {
293-
var tableReturn, tableSQL sql.NullString
294-
if err := table.data.tx.QueryRow("SHOW CREATE TABLE "+table.NameEsc()).Scan(&tableReturn, &tableSQL); err != nil {
293+
rows, err := table.data.tx.Query("SHOW CREATE TABLE " + table.NameEsc())
294+
if err != nil {
295+
return "", err
296+
}
297+
defer rows.Close()
298+
299+
// get the column names from the query
300+
columnNames, err := rows.Columns()
301+
if err != nil {
295302
return "", err
296303
}
304+
columnCount := len(columnNames)
305+
306+
info := make([]sql.NullString, columnCount)
307+
scans := make([]interface{}, columnCount)
308+
for i := range info {
309+
scans[i] = &info[i]
310+
}
311+
312+
if rows.Next() {
313+
if err := rows.Scan(scans...); err != nil {
314+
return "", err
315+
}
316+
}
317+
318+
if len(info) < 2 {
319+
return "", errors.New("database column information is malformed")
320+
}
297321

298-
if tableReturn.String != table.Name {
299-
return "", errors.New("Returned table is not the same as requested table")
322+
if info[0].String != table.Name {
323+
return "", errors.New("returned table is not the same as requested table")
300324
}
301325

302-
return tableSQL.String, nil
326+
return info[1].String, nil
303327
}
304328

305329
func (table *table) initColumnData() error {

dump_test.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package mysqldump
33
import (
44
"bytes"
55
"database/sql"
6+
"errors"
67
"reflect"
78
"strings"
89
"testing"
910

10-
sqlmock "github.com/DATA-DOG/go-sqlmock"
11+
"github.com/DATA-DOG/go-sqlmock"
1112
"github.com/stretchr/testify/assert"
1213
)
1314

@@ -122,7 +123,7 @@ func TestGetServerVersionOk(t *testing.T) {
122123
assert.Equal(t, "test_version", meta.ServerVersion)
123124
}
124125

125-
func TestCreateTableSQLOk(t *testing.T) {
126+
func TestCreateSQLSQLOk(t *testing.T) {
126127
data, mock, err := getMockData()
127128
assert.NoError(t, err, "an error was not expected when opening a stub database connection")
128129
defer data.Close()
@@ -147,6 +148,83 @@ func TestCreateTableSQLOk(t *testing.T) {
147148
}
148149
}
149150

151+
func TestCreateSQLQueryFail(t *testing.T) {
152+
data, mock, err := getMockData()
153+
assert.NoError(t, err, "an error was not expected when opening a stub database connection")
154+
defer data.Close()
155+
156+
queryError := errors.New("query failure")
157+
mock.ExpectQuery("^SHOW CREATE TABLE `Test_Table`$").WillReturnError(queryError)
158+
159+
table := data.createTable("Test_Table")
160+
161+
result, err := table.CreateSQL()
162+
assert.Error(t, err)
163+
assert.Equal(t, queryError, err)
164+
165+
// we make sure that all expectations were met
166+
assert.NoError(t, mock.ExpectationsWereMet(), "there were unfulfilled expections")
167+
168+
expectedResult := ""
169+
170+
if !reflect.DeepEqual(result, expectedResult) {
171+
t.Fatalf("expected %#v, got %#v", expectedResult, result)
172+
}
173+
}
174+
175+
func TestCreateSQLWrongTable(t *testing.T) {
176+
data, mock, err := getMockData()
177+
assert.NoError(t, err, "an error was not expected when opening a stub database connection")
178+
defer data.Close()
179+
180+
rows := sqlmock.NewRows([]string{"Table", "Create Table"}).
181+
AddRow("Diff_Table", "CREATE TABLE 'Test_Table' (`id` int(11) NOT NULL AUTO_INCREMENT,`s` char(60) DEFAULT NULL, PRIMARY KEY (`id`))ENGINE=InnoDB DEFAULT CHARSET=latin1")
182+
183+
mock.ExpectQuery("^SHOW CREATE TABLE `Test_Table`$").WillReturnRows(rows)
184+
185+
table := data.createTable("Test_Table")
186+
187+
result, err := table.CreateSQL()
188+
assert.Error(t, err)
189+
expectedError := errors.New("returned table is not the same as requested table")
190+
assert.Equal(t, expectedError, err)
191+
192+
// we make sure that all expectations were met
193+
assert.NoError(t, mock.ExpectationsWereMet(), "there were unfulfilled expections")
194+
195+
expectedResult := ""
196+
197+
if !reflect.DeepEqual(result, expectedResult) {
198+
t.Fatalf("expected %#v, got %#v", expectedResult, result)
199+
}
200+
}
201+
202+
func TestCreateTableInvalidColumns(t *testing.T) {
203+
data, mock, err := getMockData()
204+
assert.NoError(t, err, "an error was not expected when opening a stub database connection")
205+
defer data.Close()
206+
207+
rows := sqlmock.NewRows([]string{"Table"}).
208+
AddRow("Test_Table")
209+
210+
mock.ExpectQuery("^SHOW CREATE TABLE `Test_Table`$").WillReturnRows(rows)
211+
212+
table := data.createTable("Test_Table")
213+
214+
result, err := table.CreateSQL()
215+
assert.Error(t, err)
216+
assert.Equal(t, errors.New("database column information is malformed"), err)
217+
218+
// we make sure that all expectations were met
219+
assert.NoError(t, mock.ExpectationsWereMet(), "there were unfulfilled expections")
220+
221+
expectedResult := ""
222+
223+
if !reflect.DeepEqual(result, expectedResult) {
224+
t.Fatalf("expected %#v, got %#v", expectedResult, result)
225+
}
226+
}
227+
150228
func mockTableSelect(mock sqlmock.Sqlmock, name string) {
151229
cols := sqlmock.NewRows([]string{"Field", "Extra"}).
152230
AddRow("id", "").

mysqldump.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ func Dump(db *sql.DB, out io.Writer) error {
5454
// Will also close the database the dumper is connected to as well as the out stream if it has a Close method.
5555
//
5656
// Not required.
57-
func (d *Data) Close() error {
57+
func (data *Data) Close() error {
5858
defer func() {
59-
d.Connection = nil
60-
d.Out = nil
59+
data.Connection = nil
60+
data.Out = nil
6161
}()
62-
if out, ok := d.Out.(io.Closer); ok {
62+
if out, ok := data.Out.(io.Closer); ok {
6363
out.Close()
6464
}
65-
return d.Connection.Close()
65+
return data.Connection.Close()
6666
}
6767

6868
func exists(p string) (bool, os.FileInfo) {

0 commit comments

Comments
 (0)