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  }