gormigrate

package module
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2019 License: MIT Imports: 3 Imported by: 90

README

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
}

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

Documentation

Overview

Package gormigrate is a migration helper for Gorm (http://jinzhu.me/gorm/). Gorm already have useful migrate functions (http://jinzhu.me/gorm/database.html#migration), just misses proper schema versioning and rollback cababilities.

Example:

package main

import (
    "log"

    "github.com/go-gormigrate/gormigrate"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/sqlite"
)

type Person struct {
    gorm.Model
    Name string
}

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

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

    db.LogMode(true)

    m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
        {
            ID: "201608301400",
            Migrate: func(tx *gorm.DB) error {
                return tx.AutoMigrate(&Person{}).Error
            },
            Rollback: func(tx *gorm.DB) error {
                return tx.DropTable("people").Error
            },
        },
        {
            ID: "201608301430",
            Migrate: func(tx *gorm.DB) error {
                return tx.AutoMigrate(&Pet{}).Error
            },
            Rollback: func(tx *gorm.DB) error {
                return tx.DropTable("pets").Error
            },
        },
    })

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

Index

Constants

This section is empty.

Variables

View Source
var (
	// DefaultOptions can be used if you don't want to think about options.
	DefaultOptions = &Options{
		TableName:                 "migrations",
		IDColumnName:              "id",
		IDColumnSize:              255,
		UseTransaction:            false,
		ValidateUnknownMigrations: false,
	}

	// ErrRollbackImpossible is returned when trying to rollback a migration
	// that has no rollback function.
	ErrRollbackImpossible = errors.New("gormigrate: It's impossible to rollback this migration")

	// ErrNoMigrationDefined is returned when no migration is defined.
	ErrNoMigrationDefined = errors.New("gormigrate: No migration defined")

	// ErrMissingID is returned when the ID od migration is equal to ""
	ErrMissingID = errors.New("gormigrate: Missing ID in migration")

	// ErrNoRunMigration is returned when any run migration was found while
	// running RollbackLast
	ErrNoRunMigration = errors.New("gormigrate: Could not find last run migration")

	// ErrMigrationIDDoesNotExist is returned when migrating or rolling back to a migration ID that
	// does not exist in the list of migrations
	ErrMigrationIDDoesNotExist = errors.New("gormigrate: Tried to migrate to an ID that doesn't exist")

	// ErrUnknownPastMigration is returned if a migration exists in the DB that doesn't exist in the code
	ErrUnknownPastMigration = errors.New("gormigrate: Found migration in DB that does not exist in code")
)

Functions

This section is empty.

Types

type DuplicatedIDError added in v1.1.4

type DuplicatedIDError struct {
	ID string
}

DuplicatedIDError is returned when more than one migration have the same ID

func (*DuplicatedIDError) Error added in v1.1.4

func (e *DuplicatedIDError) Error() string

type Gormigrate

type Gormigrate struct {
	// contains filtered or unexported fields
}

Gormigrate represents a collection of all migrations of a database schema.

func New

func New(db *gorm.DB, options *Options, migrations []*Migration) *Gormigrate

New returns a new Gormigrate.

func (*Gormigrate) InitSchema added in v1.1.0

func (g *Gormigrate) InitSchema(initSchema InitSchemaFunc)

InitSchema sets a function that is run if no migration is found. The idea is preventing to run all migrations when a new clean database is being migrating. In this function you should create all tables and foreign key necessary to your application.

func (*Gormigrate) Migrate

func (g *Gormigrate) Migrate() error

Migrate executes all migrations that did not run yet.

func (*Gormigrate) MigrateTo added in v1.2.1

func (g *Gormigrate) MigrateTo(migrationID string) error

MigrateTo executes all migrations that did not run yet up to the migration that matches `migrationID`.

func (*Gormigrate) RollbackLast

func (g *Gormigrate) RollbackLast() error

RollbackLast undo the last migration

func (*Gormigrate) RollbackMigration

func (g *Gormigrate) RollbackMigration(m *Migration) error

RollbackMigration undo a migration.

func (*Gormigrate) RollbackTo added in v1.2.1

func (g *Gormigrate) RollbackTo(migrationID string) error

RollbackTo undoes migrations up to the given migration that matches the `migrationID`. Migration with the matching `migrationID` is not rolled back.

type InitSchemaFunc added in v1.1.0

type InitSchemaFunc func(*gorm.DB) error

InitSchemaFunc is the func signature for initializing the schema.

type MigrateFunc

type MigrateFunc func(*gorm.DB) error

MigrateFunc is the func signature for migrating.

type Migration

type Migration struct {
	// ID is the migration identifier. Usually a timestamp like "201601021504".
	ID string
	// Migrate is a function that will br executed while running this migration.
	Migrate MigrateFunc
	// Rollback will be executed on rollback. Can be nil.
	Rollback RollbackFunc
}

Migration represents a database migration (a modification to be made on the database).

type Options

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
}

Options define options for all migrations.

type ReservedIDError added in v1.4.0

type ReservedIDError struct {
	ID string
}

ReservedIDError is returned when a migration is using a reserved ID

func (*ReservedIDError) Error added in v1.4.0

func (e *ReservedIDError) Error() string

type RollbackFunc

type RollbackFunc func(*gorm.DB) error

RollbackFunc is the func signature for rollbacking.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL