Skip to content

Commit

Permalink
Merge branch 'release/v0.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
afrase committed Jan 26, 2018
2 parents 5ebc950 + a1ae335 commit ad08050
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 44 deletions.
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ Split a mysqldump into separate files for each table.
```
Usage of mysqldumpsplit:
-combine
Combine all tables into a single file, deletes individual table files
Combine all tables into a single file, deletes individual table files
-combineFile string
The path to output a single SQL file
Only used if combine flag is set (default "dumpfile.sql")
The path to output a single SQL file
Only used if combine flag is set (default "dumpfile.sql")
-i string
The file to read from, can be a gzip file
The file to read from, can be a gzip file
-o string
The output path (default "output")
The output path (default "output")
-skipData value
Comma separated list of tables you want to skip outputing the data for.
Use '*' to skip all.
Comma separated list of tables you want to skip outputting the data for.
Use '*' to skip all.
-skipTable value
Comma separated list of tables to skip.
Names can contain '*' for wildcard values
-version
Display the version and exit
Display the version and exit
```

# Install
Expand Down
18 changes: 12 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ type config struct {
CombineFilePath string
Combine bool
Version bool
Skip msds.SkipTables
SkipTable msds.CsvFlagType
SkipData msds.CsvFlagType
}

func parseFlags() *config {
Expand All @@ -27,8 +28,10 @@ func parseFlags() *config {
flag.StringVar(&conf.InputFile, "i", "", "The file to read from, can be a gzip file")
flag.StringVar(&conf.OutputPath, "o", "output", "The output path ")

flag.Var(&conf.Skip, "skipData",
"Comma separated list of tables you want to skip outputing the data for.\n\tUse '*' to skip all.")
flag.Var(&conf.SkipData, "skipData",
"Comma separated list of tables you want to skip outputting the data for.\n\tUse '*' to skip all.")
flag.Var(&conf.SkipTable, "skipTable",
"Comma separated list of tables to skip.\n\tNames can contain '*' for wildcard values")

flag.BoolVar(&conf.Combine, "combine", false,
"Combine all tables into a single file, deletes individual table files")
Expand Down Expand Up @@ -70,16 +73,19 @@ func main() {
go msds.Logger(bus)

bus.Log <- fmt.Sprintf("outputing all tables to %s\n", conf.OutputPath)
if len(conf.Skip) > 0 {
bus.Log <- fmt.Sprintf("skiping data from tables %s\n", strings.Join(conf.Skip, ", "))
if len(conf.SkipData) > 0 {
bus.Log <- fmt.Sprintf("skiping data from tables %s\n", strings.Join(conf.SkipData, ", "))
}
if len(conf.SkipTable) > 0 {
bus.Log <- fmt.Sprintf("skiping tables %s\n", strings.Join(conf.SkipTable, ", "))
}

start := time.Now()
bus.Log <- fmt.Sprintf("begin processing %s\n", conf.InputFile)
// create a pipeline of goroutines
go msds.LineReader(file, bus)
go msds.LineParser(bus, conf.Combine)
go msds.Writer(conf.OutputPath, conf.Skip, bus)
go msds.Writer(conf.OutputPath, conf.SkipData, conf.SkipTable, bus)

// wait for the writer to finish.
<-bus.Finished
Expand Down
36 changes: 31 additions & 5 deletions msds/mysqldumpsplit.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,33 +105,59 @@ func LineParser(bus ChannelBus, combineFiles bool) {
}

// Writer writes the data from the different channels to different files.
func Writer(outputDir string, skipTables []string, bus ChannelBus) {
func Writer(outputDir string, skipData []string, skipTables []string, bus ChannelBus) {
os.Mkdir(outputDir, os.ModePerm)
numTables := 0

for tableName := range bus.TableName {
bus.Log <- fmt.Sprintf("extracting table: %s\n", tableName)
numTables++
var skipTableData bool
skipTable := StringInArray(tableName, &skipTables)

if skipTable {
// also skip the data for the table.
skipTableData = true
bus.Log <- fmt.Sprintf("skipping table: %s\n", tableName)
} else {
bus.Log <- fmt.Sprintf("extracting table: %s\n", tableName)
numTables++
skipTableData = StringInArray(tableName, &skipData)
}

// to keep the code somewhat DRY, we create the sql file even if skipping the table.
// we then delete it at the end of the loop.
tablePath := filepath.Join(outputDir, tableName+".sql")
tableFile, _ := os.Create(tablePath)

for tableData := range bus.TableScheme {
if tableData == sentinelString {
break
}
tableFile.WriteString(tableData)

if !skipTable {
tableFile.WriteString(tableData)
}
}

if skipTableData && !skipTable {
// not skipping table but skipping data
bus.Log <- fmt.Sprintf("skipping data for table: %s\n", tableName)
}

for tableData := range bus.TableData {
if tableData == sentinelString {
break
}

if !StringInArray(tableName, &skipTables) {
if !skipTableData {
tableFile.WriteString(tableData)
}
}

tableFile.Close()

if skipTable {
os.Remove(tablePath)
}
}
bus.Log <- fmt.Sprintf("extracted %d tables\n", numTables)
bus.Finished <- true
Expand Down
9 changes: 5 additions & 4 deletions msds/mysqldumpsplit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ func TestLineParser(t *testing.T) {

func TestWriter(t *testing.T) {
type args struct {
outputDir string
skipTables []string
bus ChannelBus
outputDir string
skipTable []string
skipData []string
bus ChannelBus
}
tests := []struct {
name string
Expand All @@ -97,7 +98,7 @@ func TestWriter(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Writer(tt.args.outputDir, tt.args.skipTables, tt.args.bus)
Writer(tt.args.outputDir, tt.args.skipData, tt.args.skipTable, tt.args.bus)
})
}
}
Expand Down
12 changes: 6 additions & 6 deletions msds/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import (
"strings"
)

// SkipTables converts a comma separated list into an array of strings.
type SkipTables []string
// CsvFlagType converts a comma separated list into an array of strings.
type CsvFlagType []string

func (s *SkipTables) String() string {
func (s *CsvFlagType) String() string {
return fmt.Sprint(*s)
}

// Set sets the value
func (s *SkipTables) Set(value string) error {
func (s *CsvFlagType) Set(value string) error {
if len(*s) > 0 {
return errors.New("skip tables flag already set")
return errors.New("flag already set")
}
for _, v := range strings.Split(value, ",") {
*s = append(*s, strings.TrimSpace(v))
Expand All @@ -29,7 +29,7 @@ func (s *SkipTables) Set(value string) error {
// StringInArray loops over `arrayOfStrings` and returns `true` if `str` is in the array.
func StringInArray(str string, arrayOfStrings *[]string) bool {
for _, a := range *arrayOfStrings {
if WildcardMatch(a, str) {
if WildcardMatch(str, a) {
return true
}
}
Expand Down
30 changes: 15 additions & 15 deletions msds/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,45 @@ import (
"testing"
)

func TestSkipTables_String(t *testing.T) {
func TestCsvFlagType_String(t *testing.T) {
tests := []struct {
name string
s *SkipTables
s *CsvFlagType
want string
}{
{"Single table", &SkipTables{"table1"}, "[table1]"},
{"Multiple tables", &SkipTables{"table1", "table2", "table3"}, "[table1 table2 table3]"},
{"Same table twice", &SkipTables{"table1", "table2", "table2"}, "[table1 table2 table2]"},
{"Single table", &CsvFlagType{"table1"}, "[table1]"},
{"Multiple tables", &CsvFlagType{"table1", "table2", "table3"}, "[table1 table2 table3]"},
{"Same table twice", &CsvFlagType{"table1", "table2", "table2"}, "[table1 table2 table2]"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.s.String(); got != tt.want {
t.Errorf("SkipTables.String() = %v, want %v", got, tt.want)
t.Errorf("CsvFlagType.String() = %v, want %v", got, tt.want)
}
})
}
}

func TestSkipTables_Set(t *testing.T) {
func TestCsvFlagType_Set(t *testing.T) {
type args struct {
value string
}

tests := []struct {
name string
s *SkipTables
s *CsvFlagType
args args
wantErr bool
}{
{"No error single table", &SkipTables{}, args{"table1"}, false},
{"No error multiple tables", &SkipTables{}, args{"table1,table2, table3"}, false},
{"Returns error single table", &SkipTables{"table1"}, args{"table1"}, true},
{"Returns error multiple tables", &SkipTables{"table1"}, args{"table1,table2"}, true},
{"No error single table", &CsvFlagType{}, args{"table1"}, false},
{"No error multiple tables", &CsvFlagType{}, args{"table1,table2, table3"}, false},
{"Returns error single table", &CsvFlagType{"table1"}, args{"table1"}, true},
{"Returns error multiple tables", &CsvFlagType{"table1"}, args{"table1,table2"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.s.Set(tt.args.value); (err != nil) != tt.wantErr {
t.Errorf("SkipTables.Set() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("CsvFlagType.Set() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
Expand All @@ -62,8 +62,8 @@ func TestStringInArray(t *testing.T) {
}{
{"String in array", args{"bar", &[]string{"foo", "bar", "baz"}}, true},
{"String not in array", args{"bar", &[]string{"foo", "baz"}}, false},
{"Wildcard in array", args{"f*", &[]string{"foo", "bar", "baz"}}, true},
{"Single character in array", args{"b?r", &[]string{"foo", "bar", "baz"}}, true},
{"Wildcard in array", args{"foo", &[]string{"f*", "bar", "baz"}}, true},
{"Single character in array", args{"bar", &[]string{"foo", "b?r", "baz"}}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit ad08050

Please sign in to comment.