github.com/pluswing/datasync@v1.1.1-0.20240218052257-9077f6fc4ae3/dump/dump_mysql/mysql.go (about)

     1  package dump_mysql
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/pingcap/tidb/parser"
    13  	"github.com/pingcap/tidb/parser/format"
    14  	_ "github.com/pingcap/tidb/parser/test_driver"
    15  
    16  	"github.com/aliakseiz/go-mysqldump"
    17  
    18  	"github.com/briandowns/spinner"
    19  	"github.com/go-sql-driver/mysql"
    20  	"github.com/pluswing/datasync/data"
    21  	"github.com/spf13/cobra"
    22  )
    23  
    24  func MysqlDumpFile(dumpDir string, cfg data.TargetMysqlType) string {
    25  	dumpFilename := fmt.Sprintf("%s-%s.sql", "mysql", cfg.Database)
    26  	dumpFile := filepath.Join(dumpDir, dumpFilename)
    27  	return dumpFile
    28  }
    29  
    30  func Dump(dumpFile string, cfg data.TargetMysqlType) {
    31  	s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
    32  	s.Suffix = fmt.Sprintf(" mysql dump ... (database: %s)", cfg.Database)
    33  	s.Start()
    34  
    35  	config := mysql.NewConfig()
    36  	config.User = cfg.User
    37  	config.Passwd = cfg.Password
    38  	config.DBName = cfg.Database
    39  	config.Net = "tcp"
    40  	config.Addr = fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
    41  
    42  	filename := strings.Replace(filepath.Base(dumpFile), ".sql", "", 1)
    43  	dumpDir := filepath.Dir(dumpFile)
    44  
    45  	db, err := sql.Open("mysql", config.FormatDSN())
    46  	cobra.CheckErr(err)
    47  
    48  	dumper, err := mysqldump.Register(db, dumpDir, filename, config.DBName)
    49  	cobra.CheckErr(err)
    50  
    51  	err = dumper.Dump()
    52  	cobra.CheckErr(err)
    53  
    54  	dumper.Close()
    55  
    56  	s.Stop()
    57  	fmt.Printf("✔︎ mysql dump completed. (database: %s)\n", cfg.Database)
    58  }
    59  
    60  func Import(dumpFile string, cfg data.TargetMysqlType) {
    61  	s := spinner.New(spinner.CharSets[14], 100*time.Millisecond)
    62  	s.Suffix = fmt.Sprintf(" mysql import ... (database: %s)", cfg.Database)
    63  	s.Start()
    64  
    65  	config := mysql.NewConfig()
    66  	config.User = cfg.User
    67  	config.Passwd = cfg.Password
    68  	config.DBName = cfg.Database
    69  	config.Net = "tcp"
    70  	config.Addr = fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
    71  
    72  	db, err := sql.Open("mysql", config.FormatDSN())
    73  	cobra.CheckErr(err)
    74  
    75  	content, err := os.ReadFile(dumpFile)
    76  	cobra.CheckErr(err)
    77  
    78  	p := parser.New()
    79  
    80  	stmts, _, err := p.Parse(string(content), "", "")
    81  	if err != nil {
    82  		fmt.Printf("failed to parse seed sql: %v\n", err)
    83  		return
    84  	}
    85  
    86  	var buf bytes.Buffer
    87  	for _, stmt := range stmts {
    88  		buf.Reset()
    89  
    90  		// 各ast.StmtNodeをSQL文字列に復元する
    91  		stmt.Restore(format.NewRestoreCtx(format.DefaultRestoreFlags, &buf))
    92  
    93  		sql := buf.String()
    94  		if _, err := db.Exec(sql); err != nil {
    95  			fmt.Printf("failed to execute sql: err=%v sql=%s\n", err, sql[:100])
    96  		}
    97  	}
    98  	s.Stop()
    99  	fmt.Printf("✔︎ mysql import completed. (database: %s)\n", cfg.Database)
   100  }