Skip to content

Commit

Permalink
Consistently lock in ensureVersionTable and do not call ensureVersion…
Browse files Browse the repository at this point in the history
…Table from Drop across all database implementations
  • Loading branch information
Lukas Joergensen committed Feb 18, 2019
1 parent c0f025d commit dc76765
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 34 deletions.
27 changes: 22 additions & 5 deletions database/cassandra/cassandra.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/gocql/gocql"
"github.com/golang-migrate/migrate/v4/database"
"github.com/hashicorp/go-multierror"
)

func init() {
Expand Down Expand Up @@ -240,13 +241,29 @@ func (c *Cassandra) Drop() error {
return err
}
}
// Re-create the version table
return c.ensureVersionTable()

return nil
}

// Ensure version table exists
func (c *Cassandra) ensureVersionTable() error {
err := c.session.Query(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (version bigint, dirty boolean, PRIMARY KEY(version))", c.config.MigrationsTable)).Exec()
// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Cassandra type.
func (c *Cassandra) ensureVersionTable() (err error) {
if err = c.Lock(); err != nil {
return err
}

defer func() {
if e := c.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

err = c.session.Query(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (version bigint, dirty boolean, PRIMARY KEY(version))", c.config.MigrationsTable)).Exec()
if err != nil {
return err
}
Expand Down
23 changes: 21 additions & 2 deletions database/clickhouse/clickhouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database"
"github.com/hashicorp/go-multierror"
)

var DefaultMigrationsTable = "schema_migrations"
Expand Down Expand Up @@ -159,7 +160,25 @@ func (ch *ClickHouse) SetVersion(version int, dirty bool) error {
return tx.Commit()
}

func (ch *ClickHouse) ensureVersionTable() error {

// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the ClickHouse type.
func (ch *ClickHouse) ensureVersionTable() (err error) {
if err = ch.Lock(); err != nil {
return err
}

defer func() {
if e := ch.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

var (
table string
query = "SHOW TABLES FROM " + ch.config.DatabaseName + " LIKE '" + ch.config.MigrationsTable + "'"
Expand Down Expand Up @@ -207,7 +226,7 @@ func (ch *ClickHouse) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
return ch.ensureVersionTable()
return nil
}

func (ch *ClickHouse) Lock() error { return nil }
Expand Down
23 changes: 19 additions & 4 deletions database/cockroachdb/cockroachdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

import (
"github.com/cockroachdb/cockroach-go/crdb"
"github.com/hashicorp/go-multierror"
"github.com/lib/pq"
)

Expand Down Expand Up @@ -294,15 +295,29 @@ func (c *CockroachDb) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
if err := c.ensureVersionTable(); err != nil {
return err
}
}

return nil
}

func (c *CockroachDb) ensureVersionTable() error {
// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the CockroachDb type.
func (c *CockroachDb) ensureVersionTable() (err error) {
if err = c.Lock(); err != nil {
return err
}

defer func() {
if e := c.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

// check if migration table exists
var count int
query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1`
Expand Down
23 changes: 19 additions & 4 deletions database/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

import (
"github.com/go-sql-driver/mysql"
"github.com/hashicorp/go-multierror"
)

import (
Expand Down Expand Up @@ -342,15 +343,29 @@ func (m *Mysql) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
if err := m.ensureVersionTable(); err != nil {
return err
}
}

return nil
}

func (m *Mysql) ensureVersionTable() error {
// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Mysql type.
func (m *Mysql) ensureVersionTable() (err error) {
if err = m.Lock(); err != nil {
return err
}

defer func() {
if e := m.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

// check if migration table exists
var result string
query := `SHOW TABLES LIKE "` + m.config.MigrationsTable + `"`
Expand Down
6 changes: 3 additions & 3 deletions database/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,14 +325,14 @@ func (p *Postgres) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
if err := p.ensureVersionTable(); err != nil {
return err
}
}

return nil
}

// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Postgres type.
func (p *Postgres) ensureVersionTable() (err error) {
if err = p.Lock(); err != nil {
return err
Expand Down
23 changes: 19 additions & 4 deletions database/ql/ql.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ql
import (
"database/sql"
"fmt"
"github.com/hashicorp/go-multierror"
"io"
"io/ioutil"
"strings"
Expand Down Expand Up @@ -59,7 +60,24 @@ func WithInstance(instance *sql.DB, config *Config) (database.Driver, error) {
}
return mx, nil
}
func (m *Ql) ensureVersionTable() error {
// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Ql type.
func (m *Ql) ensureVersionTable() (err error) {
if err = m.Lock(); err != nil {
return err
}

defer func() {
if e := m.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

tx, err := m.db.Begin()
if err != nil {
return err
Expand Down Expand Up @@ -132,9 +150,6 @@ func (m *Ql) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
if err := m.ensureVersionTable(); err != nil {
return err
}
}

return nil
Expand Down
23 changes: 19 additions & 4 deletions database/redshift/redshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database"
"github.com/hashicorp/go-multierror"
"github.com/lib/pq"
)

Expand Down Expand Up @@ -282,15 +283,29 @@ func (p *Redshift) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
if err := p.ensureVersionTable(); err != nil {
return err
}
}

return nil
}

func (p *Redshift) ensureVersionTable() error {
// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Redshift type.
func (p *Redshift) ensureVersionTable() (err error) {
if err = p.Lock(); err != nil {
return err
}

defer func() {
if e := p.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

// check if migration table exists
var count int
query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1`
Expand Down
22 changes: 18 additions & 4 deletions database/spanner/spanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database"

"github.com/hashicorp/go-multierror"
"google.golang.org/api/iterator"
adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)
Expand Down Expand Up @@ -255,14 +256,27 @@ func (s *Spanner) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(strings.Join(stmts, "; "))}
}

if err := s.ensureVersionTable(); err != nil {
return nil
}

// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Spanner type.
func (s *Spanner) ensureVersionTable() (err error) {
if err = s.Lock(); err != nil {
return err
}

return nil
}
defer func() {
if e := s.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

func (s *Spanner) ensureVersionTable() error {
ctx := context.Background()
tbl := s.config.MigrationsTable
iter := s.db.data.Single().Read(ctx, tbl, spanner.AllKeys(), []string{"Version"})
Expand Down
22 changes: 18 additions & 4 deletions database/sqlite3/sqlite3.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database"
"github.com/hashicorp/go-multierror"
_ "github.com/mattn/go-sqlite3"
)

Expand Down Expand Up @@ -58,7 +59,23 @@ func WithInstance(instance *sql.DB, config *Config) (database.Driver, error) {
return mx, nil
}

func (m *Sqlite) ensureVersionTable() error {
// ensureVersionTable checks if versions table exists and, if not, creates it.
// Note that this function locks the database, which deviates from the usual
// convention of "caller locks" in the Sqlite type.
func (m *Sqlite) ensureVersionTable() (err error) {
if err = m.Lock(); err != nil {
return err
}

defer func() {
if e := m.Unlock(); e != nil {
if err == nil {
err = e
} else {
err = multierror.Append(err, e)
}
}
}()

query := fmt.Sprintf(`
CREATE TABLE IF NOT EXISTS %s (version uint64,dirty bool);
Expand Down Expand Up @@ -125,9 +142,6 @@ func (m *Sqlite) Drop() error {
return &database.Error{OrigErr: err, Query: []byte(query)}
}
}
if err := m.ensureVersionTable(); err != nil {
return err
}
query := "VACUUM"
_, err = m.db.Query(query)
if err != nil {
Expand Down

0 comments on commit dc76765

Please sign in to comment.