尝试从Go中使用golang-migrate/migrate作为一个包

golang-migrate/migrate 是什么?

使用Go编写的数据库迁移工具
与pressly/goose并列,这是一个受欢迎的Go制作的迁移工具
可以从CLI和Go项目(作为导入的包使用)两者中使用。

    • レポジトリ

 

    • golang-migrate/migrate

 

    mattes/migrateをforkしたもので、もともとのmattes/migrateは非推奨になってメンテナンスすでに行われていない

因为CLI在安装环境上会有可能出现安装或不安装的问题,并且也很容易忘记命令或出错,所以为了将其编码,我尝试将其用作Go语言包的备忘录。

环境

    • AWS Cloud9 (シンガポールリージョンのEC2上で動作)

 

    • Amazon Linux2

 

    • zsh

 

    mysql

Go的版本

使用Go的版本为1.11.5。
从1.11开始,可以使用go mod而不是dep包管理器来管理模块。
dep还不支持语义化版本控制。
由于golang-migrate/migrate未来将优先从v4的语义化版本开始进行维护和更新,因此建议使用go mod。

    • go modについてはこの記事が詳しかった

 

    Go 1.11 の modules・vgo を試す – 実際に使っていく上で考えないといけないこと #golang

创建SQL文件(向上、向下)

将_.up.sql和_.down.sql两个SQL文件作为一个集合进行处理
例如

1_create_table.up.sql
1_create_table.down.sql

在这种情况下,migrate只关注于的部分,而部分则只需关注可读性,因此最好为其命名为可以理解SQL内容的名称。

向上

填写要进行更改的 SQL 文件,例如编写 create table 语句、update 语句和 insert 语句。

下去 (xià qù)

从进行了更改的状态返回到更改之前的状态,编写查询以执行此操作。例如,对于创建表(create table)可以使用删除表(drop table)等操作。

将进行了更改的状态还原为之前的状态,编写查询以实现此操作。例如,可以使用删除表(drop table)等语句来对创建表(create table)进行操作。

请用汉语衍述以下内容,仅需要一个选项:

版本

可以按照1 → 2 → 3 …的方式递增,也可以使用日期时间的时间戳,如201902101130 → 201902101230。关键是只要能确定SQL文件的顺序,就需要将其设置为升序。

我們決定將創建檔案的日期和時間作為來使用。

    • いちいち自分でファイル名を書くのは面倒なのでシェルスクリプトを書きました

 

    引数にとった文字列でを先頭につけた空ファイルを作成する

创建一个导入包的批处理文件

    • Goのパッケージとしてのドキュメントはこちら

https://godoc.org/github.com/golang-migrate/migrate

package main

import (
    "flag"
    "fmt"
    "github.com/golang-migrate/migrate/v4"
    _ "github.com/golang-migrate/migrate/v4/database/mysql"
    _ "github.com/golang-migrate/migrate/v4/source/file"
    "os"
)

//sql and database info
const (
    Source   = "file://./sql/"
    Database = "mysql://user:password@tcp(0.0.0.0:3306)/database"
)

//declare command line options
var (
    Command = flag.String("exec", "", "set up or down as a argument")
    Force   = flag.Bool("f", false, "force exec fixed sql")
)

//available command list
var AvailableExecCommands = map[string]string{
    "up":      "Execute up sqls",
    "down":    "Execute down sqls",
    "version": "Just check current migrate version",
}

func main() {

    flag.Parse()
    if len(*Command) < 1 {
        fmt.Println("\nerror: no argument\n")
        showUsageMessge()
        os.Exit(1)
        return
    }

    m, err := migrate.New(Source, Database)
    if err != nil {
        fmt.Println("err", err)
    }
    version, dirty, err := m.Version()
    showVersionInfo(version, dirty, err)

    fmt.Println("command: exec", *Command)
    applyQuery(m, version, dirty)
}

//exec up or down sqls
//with force option if needed
func applyQuery(m *migrate.Migrate, version uint, dirty bool) {
    if dirty && *Force {
        fmt.Println("force=true: force execute current version sql")
        m.Force(int(version))
    }

    var err error
    switch *Command {
    case "up":
        err = m.Up()
    case "down":
        err = m.Down()
    case "version":
        //do nothing
        return
    default:
        fmt.Println("\nerror: invalid command '" + *Command + "'\n")
        showUsageMessge()
        os.Exit(1)
    }

    if err != nil {
        fmt.Println("err", err)
        os.Exit(1)
    } else {
        fmt.Println("success:", *Command+"\n")
        fmt.Println("updated version info")
        version, dirty, err := m.Version()
        showVersionInfo(version, dirty, err)
    }
}

func showUsageMessge() {
    fmt.Println("-------------------------------------")
    fmt.Println("Usage")
    fmt.Println("  go run migrate.go -exec <command>\n")
    fmt.Println("Available Exec Commands: ")
    for available_command, detail := range AvailableExecCommands {
        fmt.Println("  " + available_command + " : " + detail)
    }
    fmt.Println("-------------------------------------")
}

func showVersionInfo(version uint, dirty bool, err error) {
    fmt.Println("-------------------")
    fmt.Println("version  : ", version)
    fmt.Println("dirty    : ", dirty)
    fmt.Println("error    : ", err)
    fmt.Println("-------------------")
}

总之,只要使用’up’和’down’,如果需要的话可以使用’force’,就可以将代码设定为如上所示的形式。

往上

% go run migrate.go -exec up

向下

% go run migrate.go -exec down

– 强制选项

% go run migrate.go -exec up -f

项目结构

% tree
.
├── create_sql.sh
├── go.mod
├── go.sum
├── migrate.go
└── sql/

因为不知道什么是最佳实践,所以希望今后在开发过程中寻找答案。

广告
将在 10 秒后关闭
bannerAds