Skip to content

Instantly share code, notes, and snippets.

@dbudworth
Created April 10, 2016 15:38
Show Gist options
  • Save dbudworth/babe3eae9676724d5aa2807212893bb0 to your computer and use it in GitHub Desktop.
Save dbudworth/babe3eae9676724d5aa2807212893bb0 to your computer and use it in GitHub Desktop.
simple migrator for go
package main
import (
"bufio"
"database/sql"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"sort"
)
var createTrackerSQL = `create table if not exists schema_migrator(name varchar(255) primary key)`
var addTrackerSQL = `insert into schema_migrator values($1)`
// Migrate performs db migration by loaing files from db/*.sql
// and applying any previously unran ones in alphabetical order
func Migrate(db *sql.DB) error {
db.Exec(createTrackerSQL)
return loadFiles(db)
}
func loadFiles(db *sql.DB) error {
rows, err := db.Query("select * from schema_migrator order by name")
if err != nil {
return err
}
defer rows.Close()
has := map[string]bool{}
for rows.Next() {
var s string
err = rows.Scan(&s)
if err != nil {
return err
}
has[s] = true
}
files, err := filepath.Glob("db/*.sql")
if err != nil {
return err
}
sort.Strings(files)
for _, file := range files {
b := filepath.Base(file)
if has[b] {
// log.Println("Skipping:", b)
} else {
err = loadFile(file, db)
if err != nil {
return fmt.Errorf("Error applying: %s, reason: %v", b, err)
}
}
}
return nil
}
func loadFile(file string, db *sql.DB) error {
f, err := os.Open(file)
if err != nil {
return fmt.Errorf("Error reading: %s, reason: %v", file, err)
}
defer f.Close()
r := bufio.NewReader(f)
buff, err := ioutil.ReadAll(r)
if err != nil {
return err
}
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
_, err = tx.Exec(string(buff))
if err != nil {
return fmt.Errorf("SQL:\n%s\nFile: %s\nERROR: %v", string(buff), file, err)
}
_, err = tx.Exec(addTrackerSQL, filepath.Base(file))
if err != nil {
return fmt.Errorf("Error recording schema migration tracker: %v", err)
}
log.Println("Applied migration:", file)
tx.Commit()
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment