@@ -98,8 +98,8 @@ func main() {
98
98
Flags : cliapp .Flags ,
99
99
},
100
100
{
101
- Name : "delete" ,
102
- Usage : "Delete specific backup" ,
101
+ Name : "delete" ,
102
+ Usage : "Delete specific backup" ,
103
103
UsageText : "clickhouse-backup delete <local|s3> <backup_name>" ,
104
104
Action : func (c * cli.Context ) error {
105
105
config := getConfig (c )
@@ -223,36 +223,73 @@ func main() {
223
223
}
224
224
}
225
225
226
+ func addTable (tables []Table , table Table ) []Table {
227
+ for _ , t := range tables {
228
+ if (t .Database == table .Database ) && (t .Name == table .Name ) {
229
+ return tables
230
+ }
231
+ }
232
+ return append (tables , table )
233
+ }
234
+
235
+ func addBackupTable (tables []BackupTable , table BackupTable ) []BackupTable {
236
+ for _ , t := range tables {
237
+ if (t .Database == table .Database ) && (t .Name == table .Name ) {
238
+ return tables
239
+ }
240
+ }
241
+ return append (tables , table )
242
+ }
243
+
244
+ func addRestoreTable (tables []RestoreTable , table RestoreTable ) []RestoreTable {
245
+ for _ , t := range tables {
246
+ if (t .Database == table .Database ) && (t .Table == table .Table ) {
247
+ return tables
248
+ }
249
+ }
250
+ return append (tables , table )
251
+ }
252
+
226
253
func parseTablePatternForFreeze (tables []Table , tablePattern string ) ([]Table , error ) {
227
254
if tablePattern == "" {
228
255
return tables , nil
229
256
}
257
+ tablePatterns := strings .Split (tablePattern , "," )
230
258
var result []Table
231
259
for _ , t := range tables {
232
- if matched , _ := filepath .Match (tablePattern , fmt .Sprintf ("%s.%s" , t .Database , t .Name )); matched {
233
- result = append (result , t )
260
+ for _ , pattern := range tablePatterns {
261
+ if matched , _ := filepath .Match (pattern , fmt .Sprintf ("%s.%s" , t .Database , t .Name )); matched {
262
+ result = addTable (result , t )
263
+ }
234
264
}
235
265
}
236
266
return result , nil
237
267
}
238
268
239
269
func parseTablePatternForRestoreData (tables map [string ]BackupTable , tablePattern string ) ([]BackupTable , error ) {
240
- if tablePattern == "" {
241
- tablePattern = "*"
270
+ tablePatterns := []string {"*" }
271
+ if tablePattern != "" {
272
+ tablePatterns = strings .Split (tablePattern , "," )
242
273
}
243
274
result := []BackupTable {}
244
275
for _ , t := range tables {
245
- tableName := fmt .Sprintf ("%s.%s" , t .Database , t .Name )
246
- if matched , _ := filepath .Match (tablePattern , tableName ); matched {
247
- result = append (result , t )
276
+ for _ , pattern := range tablePatterns {
277
+ tableName := fmt .Sprintf ("%s.%s" , t .Database , t .Name )
278
+ if matched , _ := filepath .Match (pattern , tableName ); matched {
279
+ result = addBackupTable (result , t )
280
+ }
248
281
}
249
282
}
250
283
return result , nil
251
284
}
252
285
253
- func parseTablePatternForRestoreSchema (metadataPath , tablePattern string ) ([]RestoreTable , error ) {
286
+ func parseTablePatternForRestoreSchema (metadataPath string , tablePattern string ) ([]RestoreTable , error ) {
254
287
regularTables := []RestoreTable {}
255
288
distributedTables := []RestoreTable {}
289
+ tablePatterns := []string {"*" }
290
+ if tablePattern != "" {
291
+ tablePatterns = strings .Split (tablePattern , "," )
292
+ }
256
293
filepath .Walk (metadataPath , func (filePath string , info os.FileInfo , err error ) error {
257
294
if ! strings .HasSuffix (filePath , ".sql" ) || ! info .Mode ().IsRegular () {
258
295
return nil
@@ -268,23 +305,25 @@ func parseTablePatternForRestoreSchema(metadataPath, tablePattern string) ([]Res
268
305
return nil
269
306
}
270
307
tableName := fmt .Sprintf ("%s.%s" , database , table )
271
- if matched , _ := filepath .Match (tablePattern , tableName ); ! matched {
272
- return nil
273
- }
274
- data , err := ioutil .ReadFile (filePath )
275
- if err != nil {
276
- return err
277
- }
278
- restoreTable := RestoreTable {
279
- Database : database ,
280
- Table : table ,
281
- Query : strings .Replace (string (data ), "ATTACH" , "CREATE" , 1 ),
282
- }
283
- if strings .Contains (restoreTable .Query , "ENGINE = Distributed" ) {
284
- distributedTables = append (distributedTables , restoreTable )
285
- return nil
308
+ for _ , p := range tablePatterns {
309
+ if matched , _ := filepath .Match (p , tableName ); matched {
310
+ data , err := ioutil .ReadFile (filePath )
311
+ if err != nil {
312
+ return err
313
+ }
314
+ restoreTable := RestoreTable {
315
+ Database : database ,
316
+ Table : table ,
317
+ Query : strings .Replace (string (data ), "ATTACH" , "CREATE" , 1 ),
318
+ }
319
+ if strings .Contains (restoreTable .Query , "ENGINE = Distributed" ) {
320
+ distributedTables = addRestoreTable (distributedTables , restoreTable )
321
+ return nil
322
+ }
323
+ regularTables = addRestoreTable (regularTables , restoreTable )
324
+ return nil
325
+ }
286
326
}
287
- regularTables = append (regularTables , restoreTable )
288
327
return nil
289
328
})
290
329
return append (regularTables , distributedTables ... ), nil
@@ -327,9 +366,6 @@ func restoreSchema(config Config, backupName string, tablePattern string, dryRun
327
366
if dataPath == "" {
328
367
return ErrUnknownClickhouseDataPath
329
368
}
330
- if tablePattern == "" {
331
- tablePattern = "*"
332
- }
333
369
metadataPath := path .Join (dataPath , "backup" , backupName , "metadata" )
334
370
info , err := os .Stat (metadataPath )
335
371
if err != nil {
@@ -569,17 +605,38 @@ func restoreData(config Config, backupName string, tablePattern string, dryRun b
569
605
}
570
606
defer ch .Close ()
571
607
572
- allTables , err := ch .GetBackupTables (backupName )
608
+ allBackupTables , err := ch .GetBackupTables (backupName )
573
609
if err != nil {
574
610
return err
575
611
}
576
- restoreTables , err := parseTablePatternForRestoreData (allTables , tablePattern )
612
+ restoreTables , err := parseTablePatternForRestoreData (allBackupTables , tablePattern )
613
+ if err != nil {
614
+ return err
615
+ }
616
+ chTables , err := ch .GetTables ()
577
617
if err != nil {
578
618
return err
579
619
}
580
620
if len (restoreTables ) == 0 {
581
621
return fmt .Errorf ("Backup doesn't have tables to restore" )
582
622
}
623
+ allTablesCreated := true
624
+ for _ , restoreTable := range restoreTables {
625
+ found := false
626
+ for _ , chTable := range chTables {
627
+ if (restoreTable .Database == chTable .Database ) && (restoreTable .Name == chTable .Name ) {
628
+ found = true
629
+ break
630
+ }
631
+ }
632
+ if ! found {
633
+ log .Printf ("Table '%s.%s' is not created" , restoreTable .Database , restoreTable .Name )
634
+ allTablesCreated = false
635
+ }
636
+ }
637
+ if ! allTablesCreated {
638
+ return fmt .Errorf ("Run 'restore-schema' first" )
639
+ }
583
640
for _ , table := range restoreTables {
584
641
if err := ch .CopyData (table ); err != nil {
585
642
return fmt .Errorf ("can't restore '%s.%s' with %v" , table .Database , table .Name , err )
@@ -784,7 +841,6 @@ func removeBackupS3(config Config, backupName string) error {
784
841
return fmt .Errorf ("backup '%s' not found on s3" , backupName )
785
842
}
786
843
787
-
788
844
func getConfig (ctx * cli.Context ) * Config {
789
845
configPath := ctx .String ("config" )
790
846
if configPath == defaultConfigPath {
0 commit comments