github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/syncer/dbconn/upstream_db.go (about) 1 // Copyright 2021 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package dbconn 15 16 import ( 17 "context" 18 "strings" 19 20 "github.com/go-mysql-org/go-mysql/mysql" 21 "github.com/pingcap/failpoint" 22 "github.com/pingcap/tidb/pkg/parser" 23 tmysql "github.com/pingcap/tidb/pkg/parser/mysql" 24 "github.com/pingcap/tidb/pkg/util/filter" 25 "github.com/pingcap/tiflow/dm/pkg/conn" 26 tcontext "github.com/pingcap/tiflow/dm/pkg/context" 27 "github.com/pingcap/tiflow/dm/pkg/log" 28 "github.com/pingcap/tiflow/dm/pkg/terror" 29 "go.uber.org/zap" 30 ) 31 32 // UpStreamConn connect to upstream DB 33 // Normally, we need to get some upstream information through some helper functions 34 // these helper functions are all easy query functions, so we use a pool of connections here 35 // maybe change to one connection some day. 36 type UpStreamConn struct { 37 BaseDB *conn.BaseDB 38 } 39 40 // GetMasterStatus returns binlog location that extracted from SHOW MASTER STATUS. 41 func (c *UpStreamConn) GetMasterStatus(ctx *tcontext.Context, flavor string) (mysql.Position, mysql.GTIDSet, error) { 42 pos, gtidSet, err := conn.GetPosAndGs(ctx, c.BaseDB, flavor) 43 44 failpoint.Inject("GetMasterStatusFailed", func(val failpoint.Value) { 45 err = tmysql.NewErr(uint16(val.(int))) 46 log.L().Warn("GetMasterStatus failed", zap.String("failpoint", "GetMasterStatusFailed"), zap.Error(err)) 47 }) 48 49 return pos, gtidSet, err 50 } 51 52 // GetServerUUID returns upstream server UUID. 53 func (c *UpStreamConn) GetServerUUID(ctx context.Context, flavor string) (string, error) { 54 return conn.GetServerUUID(tcontext.NewContext(ctx, log.L()), c.BaseDB, flavor) 55 } 56 57 // GetServerUnixTS returns the result of current timestamp in upstream. 58 func (c *UpStreamConn) GetServerUnixTS(ctx context.Context) (int64, error) { 59 return conn.GetServerUnixTS(ctx, c.BaseDB) 60 } 61 62 // GetCharsetAndCollationInfo returns charset and collation info. 63 func GetCharsetAndCollationInfo(tctx *tcontext.Context, conn *DBConn) (map[string]string, map[int]string, error) { 64 charsetAndDefaultCollation := make(map[string]string) 65 idAndCollationMap := make(map[int]string) 66 67 // Show an example. 68 /* 69 mysql> SELECT COLLATION_NAME,CHARACTER_SET_NAME,ID,IS_DEFAULT from INFORMATION_SCHEMA.COLLATIONS; 70 +----------------------------+--------------------+-----+------------+ 71 | COLLATION_NAME | CHARACTER_SET_NAME | ID | IS_DEFAULT | 72 +----------------------------+--------------------+-----+------------+ 73 | armscii8_general_ci | armscii8 | 32 | Yes | 74 | armscii8_bin | armscii8 | 64 | | 75 | ascii_general_ci | ascii | 11 | Yes | 76 | ascii_bin | ascii | 65 | | 77 | big5_chinese_ci | big5 | 1 | Yes | 78 | big5_bin | big5 | 84 | | 79 | binary | binary | 63 | Yes | 80 +----------------------------+--------------------+-----+------------+ 81 */ 82 83 rows, err := conn.QuerySQL(tctx, nil, "SELECT COLLATION_NAME,CHARACTER_SET_NAME,ID,IS_DEFAULT from INFORMATION_SCHEMA.COLLATIONS") 84 if err != nil { 85 return nil, nil, terror.DBErrorAdapt(err, conn.Scope(), terror.ErrDBDriverError) 86 } 87 88 defer rows.Close() 89 for rows.Next() { 90 var collation, charset, isDefault string 91 var id int 92 if scanErr := rows.Scan(&collation, &charset, &id, &isDefault); scanErr != nil { 93 return nil, nil, terror.DBErrorAdapt(scanErr, conn.Scope(), terror.ErrDBDriverError) 94 } 95 idAndCollationMap[id] = strings.ToLower(collation) 96 if strings.ToLower(isDefault) == "yes" { 97 charsetAndDefaultCollation[strings.ToLower(charset)] = collation 98 } 99 } 100 101 if err = rows.Close(); err != nil { 102 return nil, nil, terror.DBErrorAdapt(rows.Err(), conn.Scope(), terror.ErrDBDriverError) 103 } 104 return charsetAndDefaultCollation, idAndCollationMap, err 105 } 106 107 // GetParser returns the parser with correct flag for upstream. 108 func (c *UpStreamConn) GetParser(ctx context.Context) (*parser.Parser, error) { 109 return conn.GetParser(tcontext.NewContext(ctx, log.L()), c.BaseDB) 110 } 111 112 // KillConn kills a connection in upstream. 113 func (c *UpStreamConn) KillConn(ctx context.Context, connID uint32) error { 114 return conn.KillConn(tcontext.NewContext(ctx, log.L()), c.BaseDB, connID) 115 } 116 117 // FetchAllDoTables returns tables matches allow-list. 118 func (c *UpStreamConn) FetchAllDoTables(ctx context.Context, bw *filter.Filter) (map[string][]string, error) { 119 return conn.FetchAllDoTables(ctx, c.BaseDB, bw) 120 } 121 122 // CloseUpstreamConn closes the UpStreamConn. 123 func CloseUpstreamConn(tctx *tcontext.Context, conn *UpStreamConn) { 124 if conn != nil { 125 CloseBaseDB(tctx, conn.BaseDB) 126 } 127 }