vitess.io/vitess@v0.16.2/go/vt/binlog/binlogplayer/dbclient.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package binlogplayer 18 19 import ( 20 "context" 21 "fmt" 22 23 "vitess.io/vitess/go/mysql" 24 "vitess.io/vitess/go/sqltypes" 25 "vitess.io/vitess/go/vt/dbconfigs" 26 "vitess.io/vitess/go/vt/log" 27 ) 28 29 // DBClient is a high level interface to the database. 30 type DBClient interface { 31 DBName() string 32 Connect() error 33 Begin() error 34 Commit() error 35 Rollback() error 36 Close() 37 ExecuteFetch(query string, maxrows int) (qr *sqltypes.Result, err error) 38 } 39 40 // dbClientImpl is a real DBClient backed by a mysql connection. 41 type dbClientImpl struct { 42 dbConfig dbconfigs.Connector 43 dbConn *mysql.Conn 44 } 45 46 // NewDBClient creates a DBClient instance 47 func NewDBClient(params dbconfigs.Connector) DBClient { 48 return &dbClientImpl{ 49 dbConfig: params, 50 } 51 } 52 53 func (dc *dbClientImpl) handleError(err error) { 54 if mysql.IsConnErr(err) { 55 dc.Close() 56 } 57 } 58 59 func (dc *dbClientImpl) DBName() string { 60 params, _ := dc.dbConfig.MysqlParams() 61 return params.DbName 62 } 63 64 func (dc *dbClientImpl) Connect() error { 65 var err error 66 ctx := context.Background() 67 dc.dbConn, err = dc.dbConfig.Connect(ctx) 68 if err != nil { 69 return fmt.Errorf("error in connecting to mysql db with connection %v, err %v", dc.dbConn, err) 70 } 71 return nil 72 } 73 74 func (dc *dbClientImpl) Begin() error { 75 _, err := dc.dbConn.ExecuteFetch("begin", 1, false) 76 if err != nil { 77 LogError("BEGIN failed w/ error", err) 78 dc.handleError(err) 79 } 80 return err 81 } 82 83 func (dc *dbClientImpl) Commit() error { 84 _, err := dc.dbConn.ExecuteFetch("commit", 1, false) 85 if err != nil { 86 LogError("COMMIT failed w/ error", err) 87 dc.dbConn.Close() 88 } 89 return err 90 } 91 92 func (dc *dbClientImpl) Rollback() error { 93 _, err := dc.dbConn.ExecuteFetch("rollback", 1, false) 94 if err != nil { 95 LogError("ROLLBACK failed w/ error", err) 96 dc.dbConn.Close() 97 } 98 return err 99 } 100 101 func (dc *dbClientImpl) Close() { 102 dc.dbConn.Close() 103 } 104 105 // LogError logs a message after truncating it to avoid spamming logs 106 func LogError(msg string, err error) { 107 log.Errorf("%s: %s", msg, MessageTruncate(err.Error())) 108 } 109 110 // LimitString truncates string to specified size 111 func LimitString(s string, limit int) string { 112 if len(s) > limit { 113 return s[:limit] 114 } 115 return s 116 } 117 118 func (dc *dbClientImpl) ExecuteFetch(query string, maxrows int) (*sqltypes.Result, error) { 119 mqr, err := dc.dbConn.ExecuteFetch(query, maxrows, true) 120 if err != nil { 121 dc.handleError(err) 122 return nil, err 123 } 124 return mqr, nil 125 }