Skip to content

Commit

Permalink
Allow developers to change the migrations table
Browse files Browse the repository at this point in the history
Let's allow engineers to change the table depending on their preferences
or naming convention.
  • Loading branch information
iamralch committed Jul 27, 2021
1 parent 6dfb9ed commit 016f649
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 19 deletions.
13 changes: 5 additions & 8 deletions sqlmigr/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package sqlmigr
import (
"bytes"
"fmt"
"regexp"
"strings"
"time"

"github.com/go-openapi/inflect"
"github.com/phogolabs/log"
)

var migrationRgxp = regexp.MustCompile(`CREATE TABLE IF NOT EXISTS\s*([a-z]+)\s*`)

// Executor provides a group of operations that works with migrations.
type Executor struct {
// Logger logs each execution step
Expand All @@ -25,14 +28,8 @@ type Executor struct {
// Setup setups the current project for database migrations by creating
// migration directory and related database.
func (m *Executor) Setup() error {
migration := &Migration{
ID: min.Format(format),
Description: "setup",
Drivers: []string{every},
CreatedAt: time.Now(),
}

up := &bytes.Buffer{}

fmt.Fprintln(up, "CREATE TABLE IF NOT EXISTS migrations (")
fmt.Fprintln(up, " id VARCHAR(15) NOT NULL PRIMARY KEY,")
fmt.Fprintln(up, " description TEXT NOT NULL,")
Expand All @@ -48,7 +45,7 @@ func (m *Executor) Setup() error {
DownCommand: down,
}

return m.Generator.Write(migration, content)
return m.Generator.Write(setup, content)
}

// Create creates a migration script successfully if the project has already
Expand Down
6 changes: 4 additions & 2 deletions sqlmigr/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ func (g *Generator) write(filename string, data []byte, perm os.FileMode) error
err = io.ErrShortWrite
}
}
if err1 := f.Close(); err == nil {
err = err1

if xerr := f.Close(); err == nil {
err = xerr
}

return err
}
16 changes: 13 additions & 3 deletions sqlmigr/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ var (
every = "sql"
)

var (
// setup migration
setup = &Migration{
ID: min.Format(format),
Description: "setup",
Drivers: []string{every},
CreatedAt: time.Now(),
}
)

// FileSystem provides with primitives to work with the underlying file system
type FileSystem = fs.FS

Expand Down Expand Up @@ -163,13 +173,13 @@ func IsNotExist(err error) bool {

switch {
// SQLite
case msg == "no such table: migrations":
case strings.HasPrefix(msg, "no such table"):
return true
// PostgreSQL
case msg == `pq: relation "migrations" does not exist`:
case strings.HasSuffix(msg, "does not exist"):
return true
// MySQL
case strings.HasSuffix(msg, "migrations' doesn't exist"):
case strings.HasSuffix(msg, "doesn't exist"):
return true
default:
return false
Expand Down
30 changes: 25 additions & 5 deletions sqlmigr/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package sqlmigr
import (
"bytes"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
Expand Down Expand Up @@ -39,7 +40,7 @@ func (m *Provider) Migrations() ([]*Migration, error) {
func (m *Provider) files() ([]*Migration, error) {
local := []*Migration{}

err := fs.WalkDir(m.FileSystem, ".", func(path string, info os.DirEntry, err error) error {
err := fs.WalkDir(m.FileSystem, ".", func(path string, info os.DirEntry, xerr error) error {
if ferr := m.filter(info); ferr != nil {
if ferr.Error() == "skip" {
ferr = nil
Expand Down Expand Up @@ -109,7 +110,7 @@ func (m *Provider) supported(drivers []string) bool {
func (m *Provider) query() ([]*Migration, error) {
query := &bytes.Buffer{}
query.WriteString("SELECT id, description, created_at ")
query.WriteString("FROM migrations ")
query.WriteString("FROM " + m.table() + " ")
query.WriteString("ORDER BY id ASC")

remote := []*Migration{}
Expand All @@ -126,7 +127,7 @@ func (m *Provider) Insert(item *Migration) error {
item.CreatedAt = time.Now()

builder := &bytes.Buffer{}
builder.WriteString("INSERT INTO migrations(id, description, created_at) ")
builder.WriteString("INSERT INTO " + m.table() + "(id, description, created_at) ")
builder.WriteString("VALUES (?, ?, ?)")

query := m.DB.Rebind(builder.String())
Expand All @@ -140,7 +141,7 @@ func (m *Provider) Insert(item *Migration) error {
// Delete deletes applied sqlmigr item from sqlmigrs table.
func (m *Provider) Delete(item *Migration) error {
builder := &bytes.Buffer{}
builder.WriteString("DELETE FROM migrations ")
builder.WriteString("DELETE FROM " + m.table() + " ")
builder.WriteString("WHERE id = ?")

query := m.DB.Rebind(builder.String())
Expand All @@ -155,7 +156,7 @@ func (m *Provider) Delete(item *Migration) error {
func (m *Provider) Exists(item *Migration) bool {
count := 0

if err := m.DB.Get(&count, "SELECT count(id) FROM migrations WHERE id = ?", item.ID); err != nil {
if err := m.DB.Get(&count, "SELECT count(id) FROM "+m.table()+" WHERE id = ?", item.ID); err != nil {
return false
}

Expand Down Expand Up @@ -183,3 +184,22 @@ func (m *Provider) merge(remote, local []*Migration) ([]*Migration, error) {

return result, nil
}

func (m *Provider) table() string {
for _, path := range setup.Filenames() {
file, err := m.FileSystem.Open(path)
if err != nil {
continue
}
// close the file
defer file.Close()

if data, err := io.ReadAll(file); err == nil {
if match := migrationRgxp.FindSubmatch(data); len(match) == 2 {
return string(match[1])
}
}
}

return "migrations"
}
5 changes: 4 additions & 1 deletion sqlmigr/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"github.com/jmoiron/sqlx"
"github.com/phogolabs/log"
"github.com/phogolabs/prana/sqlexec"
)

Expand Down Expand Up @@ -41,7 +42,9 @@ func (r *Runner) exec(step string, m *Migration) error {

for _, query := range statements {
if _, err := tx.Exec(query); err != nil {
tx.Rollback()
if xerr := tx.Rollback(); xerr != nil {
log.WithError(xerr).Error("rollback failure")
}

return &RunnerError{
Err: err,
Expand Down

0 comments on commit 016f649

Please sign in to comment.