func (driver *Driver) Migrate(f file.File, pipe chan interface{}) { var err error defer func() { if err != nil { // Invert version direction if we couldn't apply the changes for some reason. if err := driver.version(f.Direction, true); err != nil { pipe <- err } pipe <- err } close(pipe) }() pipe <- f if err = driver.version(f.Direction, false); err != nil { return } if err = f.ReadContent(); err != nil { return } for _, query := range strings.Split(string(f.Content), ";") { query = strings.TrimSpace(query) if len(query) == 0 { continue } if err = driver.session.Query(query).Exec(); err != nil { return } } }
func (driver *Driver) Migrate(f file.File, pipe chan interface{}) { defer close(pipe) pipe <- f // http://go-database-sql.org/modifying.html, Working with Transactions // You should not mingle the use of transaction-related functions such as Begin() and Commit() with SQL statements such as BEGIN and COMMIT in your SQL code. tx, err := driver.db.Begin() if err != nil { pipe <- err return } if f.Direction == direction.Up { if _, err := tx.Exec("INSERT INTO "+tableName+" (version) VALUES (?)", f.Version); err != nil { pipe <- err if err := tx.Rollback(); err != nil { pipe <- err } return } } else if f.Direction == direction.Down { if _, err := tx.Exec("DELETE FROM "+tableName+" WHERE version = ?", f.Version); err != nil { pipe <- err if err := tx.Rollback(); err != nil { pipe <- err } return } } if err := f.ReadContent(); err != nil { pipe <- err return } f.Content = bytes.TrimSpace(f.Content) if driver.multiStatements && len(f.Content) > 0 { if _, err := tx.Exec(string(f.Content)); err != nil { pipe <- err if err := tx.Rollback(); err != nil { pipe <- err } return } } else { if err := driver.multiStatementsFallback(f.Content, tx); err != nil { pipe <- err if err := tx.Rollback(); err != nil { pipe <- err } return } } if err := tx.Commit(); err != nil { pipe <- err return } }
func (driver *Driver) Migrate(f file.File, pipe chan interface{}) { defer close(pipe) pipe <- f tx, err := driver.db.Begin() if err != nil { pipe <- err return } if f.Direction == direction.Up { if _, err := tx.Exec("INSERT INTO "+tableName+" (version) VALUES ($1)", f.Version); err != nil { pipe <- err if err := tx.Rollback(); err != nil { pipe <- err } return } } else if f.Direction == direction.Down { if _, err := tx.Exec("DELETE FROM "+tableName+" WHERE version=$1", f.Version); err != nil { pipe <- err if err := tx.Rollback(); err != nil { pipe <- err } return } } if err := f.ReadContent(); err != nil { pipe <- err return } if _, err := tx.Exec(string(f.Content)); err != nil { pqErr := err.(*pq.Error) offset, err := strconv.Atoi(pqErr.Position) if err == nil && offset >= 0 { lineNo, columnNo := file.LineColumnFromOffset(f.Content, offset-1) errorPart := file.LinesBeforeAndAfter(f.Content, lineNo, 5, 5, true) pipe <- errors.New(fmt.Sprintf("%s %v: %s in line %v, column %v:\n\n%s", pqErr.Severity, pqErr.Code, pqErr.Message, lineNo, columnNo, string(errorPart))) } else { pipe <- errors.New(fmt.Sprintf("%s %v: %s", pqErr.Severity, pqErr.Code, pqErr.Message)) } if err := tx.Rollback(); err != nil { pipe <- err } return } if err := tx.Commit(); err != nil { pipe <- err return } }