github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/utils/schema.go (about) 1 // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. 2 3 package utils 4 5 import ( 6 "context" 7 "fmt" 8 "strings" 9 10 "github.com/pingcap/errors" 11 backuppb "github.com/pingcap/kvproto/pkg/backup" 12 "github.com/pingcap/parser/model" 13 "github.com/pingcap/parser/mysql" 14 15 "github.com/pingcap/br/pkg/metautil" 16 ) 17 18 // temporaryDBNamePrefix is the prefix name of system db, e.g. mysql system db will be rename to __TiDB_BR_Temporary_mysql 19 const temporaryDBNamePrefix = "__TiDB_BR_Temporary_" 20 21 // NeedAutoID checks whether the table needs backing up with an autoid. 22 func NeedAutoID(tblInfo *model.TableInfo) bool { 23 hasRowID := !tblInfo.PKIsHandle && !tblInfo.IsCommonHandle 24 hasAutoIncID := tblInfo.GetAutoIncrementColInfo() != nil 25 return hasRowID || hasAutoIncID 26 } 27 28 // Database wraps the schema and tables of a database. 29 type Database struct { 30 Info *model.DBInfo 31 Tables []*metautil.Table 32 } 33 34 // GetTable returns a table of the database by name. 35 func (db *Database) GetTable(name string) *metautil.Table { 36 for _, table := range db.Tables { 37 if table.Info.Name.String() == name { 38 return table 39 } 40 } 41 return nil 42 } 43 44 // LoadBackupTables loads schemas from BackupMeta. 45 func LoadBackupTables(ctx context.Context, reader *metautil.MetaReader) (map[string]*Database, error) { 46 ch := make(chan *metautil.Table) 47 errCh := make(chan error) 48 go func() { 49 if err := reader.ReadSchemasFiles(ctx, ch); err != nil { 50 errCh <- errors.Trace(err) 51 } 52 close(ch) 53 }() 54 55 databases := make(map[string]*Database) 56 for { 57 select { 58 case <-ctx.Done(): 59 return nil, ctx.Err() 60 case err := <-errCh: 61 return nil, errors.Trace(err) 62 case table, ok := <-ch: 63 if !ok { 64 close(errCh) 65 return databases, nil 66 } 67 dbName := table.DB.Name.String() 68 db, ok := databases[dbName] 69 if !ok { 70 db = &Database{ 71 Info: table.DB, 72 Tables: make([]*metautil.Table, 0), 73 } 74 databases[dbName] = db 75 } 76 db.Tables = append(db.Tables, table) 77 } 78 } 79 } 80 81 // ArchiveSize returns the total size of the backup archive. 82 func ArchiveSize(meta *backuppb.BackupMeta) uint64 { 83 total := uint64(meta.Size()) 84 for _, file := range meta.Files { 85 total += file.Size_ 86 } 87 return total 88 } 89 90 // EncloseName formats name in sql. 91 func EncloseName(name string) string { 92 return "`" + strings.ReplaceAll(name, "`", "``") + "`" 93 } 94 95 // EncloseDBAndTable formats the database and table name in sql. 96 func EncloseDBAndTable(database, table string) string { 97 return fmt.Sprintf("%s.%s", EncloseName(database), EncloseName(table)) 98 } 99 100 // IsSysDB tests whether the database is system DB. 101 // Currently, the only system DB is mysql. 102 func IsSysDB(dbLowerName string) bool { 103 return dbLowerName == mysql.SystemDB 104 } 105 106 // TemporaryDBName makes a 'private' database name. 107 func TemporaryDBName(db string) model.CIStr { 108 return model.NewCIStr(temporaryDBNamePrefix + db) 109 } 110 111 // GetSysDBName get the original name of system DB 112 func GetSysDBName(tempDB model.CIStr) (string, bool) { 113 if ok := strings.HasPrefix(tempDB.O, temporaryDBNamePrefix); !ok { 114 return tempDB.O, false 115 } 116 return tempDB.O[len(temporaryDBNamePrefix):], true 117 }