gormigrate

Minimalistic database migration helper for Gorm ORM

Github星跟踪图

Gormigrate

GoDoc
Go Report Card
Build Status
Build status

Gormigrate is a minimalistic migration helper for Gorm.
Gorm already has useful migrate functions, just misses
proper schema versioning and migration rollback support.

Supported databases

It supports any of the databases Gorm supports:

  • PostgreSQL
  • MySQL
  • SQLite
  • Microsoft SQL Server

Installing

go get -u gopkg.in/gormigrate.v1

Usage

package main

import (
	"log"

	"gopkg.in/gormigrate.v1"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
)

func main() {
	db, err := gorm.Open("sqlite3", "mydb.sqlite3")
	if err != nil {
		log.Fatal(err)
	}

	db.LogMode(true)

	m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
		// create persons table
		{
			ID: "201608301400",
			Migrate: func(tx *gorm.DB) error {
				// it's a good pratice to copy the struct inside the function,
				// so side effects are prevented if the original struct changes during the time
				type Person struct {
					gorm.Model
					Name string
				}
				return tx.AutoMigrate(&Person{}).Error
			},
			Rollback: func(tx *gorm.DB) error {
				return tx.DropTable("people").Error
			},
		},
		// add age column to persons
		{
			ID: "201608301415",
			Migrate: func(tx *gorm.DB) error {
				// when table already exists, it just adds fields as columns
				type Person struct {
					Age int
				}
				return tx.AutoMigrate(&Person{}).Error
			},
			Rollback: func(tx *gorm.DB) error {
				return tx.Table("people").DropColumn("age").Error
			},
		},
		// add pets table
		{
			ID: "201608301430",
			Migrate: func(tx *gorm.DB) error {
				type Pet struct {
					gorm.Model
					Name     string
					PersonID int
				}
				return tx.AutoMigrate(&Pet{}).Error
			},
			Rollback: func(tx *gorm.DB) error {
				return tx.DropTable("pets").Error
			},
		},
	})

	if err = m.Migrate(); err != nil {
		log.Fatalf("Could not migrate: %v", err)
	}
	log.Printf("Migration did run successfully")
}

Having a separated function for initializing the schema

If you have a lot of migrations, it can be a pain to run all them, as example,
when you are deploying a new instance of the app, in a clean database.
To prevent this, you can set a function that will run if no migration was run
before (in a new clean database). Remember to create everything here, all tables,
foreign keys and what more you need in your app.

type Person struct {
	gorm.Model
	Name string
	Age int
}

type Pet struct {
	gorm.Model
	Name     string
	PersonID int
}

m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
    // you migrations here
})

m.InitSchema(func(tx *gorm.DB) error {
	err := tx.AutoMigrate(
		&Person{},
		&Pet{},
		// all other tables of you app
	).Error
	if err != nil {
		return err
	}

	if err := tx.Model(Pet{}).AddForeignKey("person_id", "people (id)", "RESTRICT", "RESTRICT").Error; err != nil {
		return err
	}
	// all other foreign keys...
	return nil
})

Options

This is the options struct, in case you don't want the defaults:

type Options struct {
	// TableName is the migration table.
	TableName string
	// IDColumnName is the name of column where the migration id will be stored.
	IDColumnName string
	// IDColumnSize is the length of the migration id column
	IDColumnSize int
	// UseTransaction makes Gormigrate execute migrations inside a single transaction.
	// Keep in mind that not all databases support DDL commands inside transactions.
	UseTransaction bool
	// ValidateUnknownMigrations will cause migrate to fail if there's unknown migration
	// IDs in the database
	ValidateUnknownMigrations bool
}

Who is Gormigrate for?

Gormigrate was born to be a simple and minimalistic migration tool for small
projects that uses Gorm. You may want to take a look at more advanced
solutions like golang-migrate/migrate
if you plan to scale.

Be aware that Gormigrate has no builtin lock mechanism, so if you're running
it automatically and have a distributed setup (i.e. more than one executable
running running at the same time), you might want to use a
distributed lock/mutex mechanism to
prevent race conditions while running migrations.

Contributing

To run tests, first copy .sample.env as sample.env and edit the connection
string of the database you want to run tests against. Then, run tests like
below:

# running tests for PostgreSQL
go test -tags postgresql

# running test for MySQL
go test -tags mysql

# running tests for SQLite
go test -tags sqlite

# running tests for SQL Server
go test -tags sqlserver

# running test for multiple databases at once
go test -tags 'sqlite postgresql mysql'

Or altenatively, you could use Docker to easily run tests on all databases
at once. To do that, make sure Docker is installed and running in your machine
and then run:

task docker

主要指标

概览
名称与所有者go-gormigrate/gormigrate
主编程语言Go
编程语言Go (语言数: 1)
平台
许可证MIT License
所有者活动
创建于2016-08-31 11:46:23
推送于2025-03-28 16:49:50
最后一次提交2025-03-28 17:44:35
发布数24
最新版本名称v2.1.4 (发布于 )
第一版名称v1.0.0 (发布于 2016-08-31 08:47:31)
用户参与
星数1.1k
关注者数9
派生数104
提交数296
已启用问题?
问题数40
打开的问题数11
拉请求数86
打开的拉请求数6
关闭的拉请求数98
项目设置
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?