split sql statements by ;

This commit is contained in:
mattes 2014-10-11 00:49:40 +02:00
parent 2faaebc76a
commit cc23e29eef
1 changed files with 48 additions and 46 deletions

View File

@ -7,15 +7,11 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/go-sql-driver/mysql"
"github.com/mattes/migrate/file"
"github.com/mattes/migrate/migrate/direction"
"regexp"
"strconv"
// Use fork instead of github.com/go-sql-driver/mysql, because it
// has clientMultiStatements enabled.
// see https://github.com/go-sql-driver/mysql/issues/66
"github.com/mattes/mysql"
)
type Driver struct {
@ -93,52 +89,58 @@ func (driver *Driver) Migrate(f file.File, pipe chan interface{}) {
return
}
if _, err := tx.Exec(string(f.Content)); err != nil {
mysqlErr := err.(*mysql.MySQLError)
// TODO this is not good! unfortunately there is no mysql driver that
// supports multiple statements per query.
sqlStmts := bytes.Split(f.Content, ";")
for _, sqlStmt := range sqlStmts {
if _, err := tx.Exec(string(sqlStmt)); err != nil {
mysqlErr := err.(*mysql.MySQLError)
re, err := regexp.Compile(`at line ([0-9]+)$`)
if err != nil {
pipe <- err
if err := tx.Rollback(); err != nil {
pipe <- err
}
}
var lineNo int
lineNoRe := re.FindStringSubmatch(mysqlErr.Message)
if len(lineNoRe) == 2 {
lineNo, err = strconv.Atoi(lineNoRe[1])
}
if err == nil {
// get white-space offset
wsLineOffset := 0
b := bufio.NewReader(bytes.NewBuffer(f.Content))
for {
line, _, err := b.ReadLine()
if err != nil {
break
}
if bytes.TrimSpace(line) == nil {
wsLineOffset += 1
} else {
break
}
}
message := mysqlErr.Error()
message = re.ReplaceAllString(message, fmt.Sprintf("at line %v", lineNo+wsLineOffset))
errorPart := file.LinesBeforeAndAfter(f.Content, lineNo, 5, 5, true)
pipe <- errors.New(fmt.Sprintf("%s\n\n%s", message, string(errorPart)))
} else {
pipe <- errors.New(mysqlErr.Error())
}
re, err := regexp.Compile(`at line ([0-9]+)$`)
if err != nil {
pipe <- err
if err := tx.Rollback(); err != nil {
pipe <- err
}
return
}
var lineNo int
lineNoRe := re.FindStringSubmatch(mysqlErr.Message)
if len(lineNoRe) == 2 {
lineNo, err = strconv.Atoi(lineNoRe[1])
}
if err == nil {
// get white-space offset
wsLineOffset := 0
b := bufio.NewReader(bytes.NewBuffer(f.Content))
for {
line, _, err := b.ReadLine()
if err != nil {
break
}
if bytes.TrimSpace(line) == nil {
wsLineOffset += 1
} else {
break
}
}
message := mysqlErr.Error()
message = re.ReplaceAllString(message, fmt.Sprintf("at line %v", lineNo+wsLineOffset))
errorPart := file.LinesBeforeAndAfter(f.Content, lineNo, 5, 5, true)
pipe <- errors.New(fmt.Sprintf("%s\n\n%s", message, string(errorPart)))
} else {
pipe <- errors.New(mysqlErr.Error())
}
if err := tx.Rollback(); err != nil {
pipe <- err
}
return
}
if err := tx.Commit(); err != nil {