Use variadic parameters for DropColumns.

Also add some comments.
This commit is contained in:
Nurahmadie 2014-03-16 10:52:28 +07:00
parent 571f7d02b0
commit 44ffb70813
11 changed files with 64 additions and 36 deletions

View file

@ -57,6 +57,7 @@ func Init(name, datasource string) error {
return nil return nil
} }
// Close database connection.
func Close() { func Close() {
db.Close() db.Close()
} }

View file

@ -21,6 +21,6 @@ func (r *Rev3) Up(mg *MigrationDriver) error {
} }
func (r *Rev3) Down(mg *MigrationDriver) error { func (r *Rev3) Down(mg *MigrationDriver) error {
_, err := mg.DropColumns("settings", []string{"github_domain", "github_apiurl"}) _, err := mg.DropColumns("settings", "github_domain", "github_apiurl")
return err return err
} }

View file

@ -16,6 +16,6 @@ func (r *rev20140310104446) Up(mg *MigrationDriver) error {
} }
func (r *rev20140310104446) Down(mg *MigrationDriver) error { func (r *rev20140310104446) Down(mg *MigrationDriver) error {
_, err := mg.DropColumns("settings", []string{"open_invitations"}) _, err := mg.DropColumns("settings", "open_invitations")
return err return err
} }

View file

@ -1,5 +1,9 @@
package migrate package migrate
// All is called to collect all migration scripts
// and adds them to Revision list. New Revision
// should be added here ordered by its revision
// number.
func (m *Migration) All() *Migration { func (m *Migration) All() *Migration {
// List all migrations here // List all migrations here

View file

@ -8,29 +8,56 @@ import (
// Implementation details is specific for each database, // Implementation details is specific for each database,
// see migrate/sqlite.go for implementation reference. // see migrate/sqlite.go for implementation reference.
type Operation interface { type Operation interface {
// CreateTable may be used to create a table named `tableName`
// with its columns specification listed in `args` as an array of string
CreateTable(tableName string, args []string) (sql.Result, error) CreateTable(tableName string, args []string) (sql.Result, error)
// RenameTable simply rename table from `tableName` to `newName`
RenameTable(tableName, newName string) (sql.Result, error) RenameTable(tableName, newName string) (sql.Result, error)
// DropTable drops table named `tableName`
DropTable(tableName string) (sql.Result, error) DropTable(tableName string) (sql.Result, error)
// AddColumn adds single new column to `tableName`, columnSpec is
// a standard column definition (column name included) which may looks like this:
//
// mg.AddColumn("example", "email VARCHAR(255) UNIQUE")
//
// it's equivalent to:
//
// mg.AddColumn("example", mg.T.String("email", UNIQUE))
//
AddColumn(tableName, columnSpec string) (sql.Result, error) AddColumn(tableName, columnSpec string) (sql.Result, error)
// ChangeColumn may be used to change the type of a column
// `newType` should always specify the column's new type even
// if the type is not meant to be change. Eg.
//
// mg.ChangeColumn("example", "name", "VARCHAR(255) UNIQUE")
//
ChangeColumn(tableName, columnName, newType string) (sql.Result, error) ChangeColumn(tableName, columnName, newType string) (sql.Result, error)
DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) // DropColumns drops a list of columns
DropColumns(tableName string, columnsToDrop ...string) (sql.Result, error)
// RenameColumns will rename columns listed in `columnChanges`
RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error) RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error)
// AddIndex adds index on `tableName` indexed by `columns`
AddIndex(tableName string, columns []string, flags ...string) (sql.Result, error) AddIndex(tableName string, columns []string, flags ...string) (sql.Result, error)
// DropIndex drops index indexed by `columns` from `tableName`
DropIndex(tableName string, columns []string) (sql.Result, error) DropIndex(tableName string, columns []string) (sql.Result, error)
} }
// MigrationDriver drives migration script by injecting transaction object (*sql.Tx),
// `Operation` implementation and column type helper.
type MigrationDriver struct { type MigrationDriver struct {
Operation Operation
T *columnType T *columnType
Tx *sql.Tx Tx *sql.Tx
} }
// DriverBuilder is a constructor for MigrationDriver
type DriverBuilder func(tx *sql.Tx) *MigrationDriver type DriverBuilder func(tx *sql.Tx) *MigrationDriver

View file

@ -12,16 +12,20 @@ const (
AUTOINCREMENT AUTOINCREMENT
NULL NULL
NOTNULL NOTNULL
TSTRING
TTEXT
) )
// columnType will be injected to migration script
// along with MigrationDriver. `AttrMap` is used to
// defines distinct column's attribute between database
// implementation. e.g. 'AUTOINCREMENT' in sqlite and
// 'AUTO_INCREMENT' in mysql.
type columnType struct { type columnType struct {
Driver string Driver string
AttrMap map[int]string AttrMap map[int]string
} }
// defaultMap defines default values for column's attribute
// lookup.
var defaultMap = map[int]string{ var defaultMap = map[int]string{
UNIQUE: "UNIQUE", UNIQUE: "UNIQUE",
PRIMARYKEY: "PRIMARY KEY", PRIMARYKEY: "PRIMARY KEY",
@ -30,34 +34,45 @@ var defaultMap = map[int]string{
NOTNULL: "NOT NULL", NOTNULL: "NOT NULL",
} }
// Integer returns column definition for INTEGER typed column.
// Additional attributes may be specified as string or predefined key
// listed in defaultMap.
func (c *columnType) Integer(colName string, spec ...interface{}) string { func (c *columnType) Integer(colName string, spec ...interface{}) string {
return fmt.Sprintf("%s INTEGER %s", colName, c.parseAttr(spec)) return fmt.Sprintf("%s INTEGER %s", colName, c.parseAttr(spec))
} }
// String returns column definition for VARCHAR(255) typed column.
func (c *columnType) String(colName string, spec ...interface{}) string { func (c *columnType) String(colName string, spec ...interface{}) string {
return fmt.Sprintf("%s VARCHAR(255) %s", colName, c.parseAttr(spec)) return fmt.Sprintf("%s VARCHAR(255) %s", colName, c.parseAttr(spec))
} }
// Text returns column definition for TEXT typed column.
func (c *columnType) Text(colName string, spec ...interface{}) string { func (c *columnType) Text(colName string, spec ...interface{}) string {
return fmt.Sprintf("%s TEXT %s", colName, c.parseAttr(spec)) return fmt.Sprintf("%s TEXT %s", colName, c.parseAttr(spec))
} }
// Blob returns column definition for BLOB typed column
func (c *columnType) Blob(colName string, spec ...interface{}) string { func (c *columnType) Blob(colName string, spec ...interface{}) string {
return fmt.Sprintf("%s BLOB %s", colName, c.parseAttr(spec)) return fmt.Sprintf("%s BLOB %s", colName, c.parseAttr(spec))
} }
// Timestamp returns column definition for TIMESTAMP typed column
func (c *columnType) Timestamp(colName string, spec ...interface{}) string { func (c *columnType) Timestamp(colName string, spec ...interface{}) string {
return fmt.Sprintf("%s TIMESTAMP %s", colName, c.parseAttr(spec)) return fmt.Sprintf("%s TIMESTAMP %s", colName, c.parseAttr(spec))
} }
// Bool returns column definition for BOOLEAN typed column
func (c *columnType) Bool(colName string, spec ...interface{}) string { func (c *columnType) Bool(colName string, spec ...interface{}) string {
return fmt.Sprintf("%s BOOLEAN %s", colName, c.parseAttr(spec)) return fmt.Sprintf("%s BOOLEAN %s", colName, c.parseAttr(spec))
} }
// Varchar returns column definition for VARCHAR typed column.
// column's max length is specified as `length`.
func (c *columnType) Varchar(colName string, length int, spec ...interface{}) string { func (c *columnType) Varchar(colName string, length int, spec ...interface{}) string {
return fmt.Sprintf("%s VARCHAR(%d) %s", colName, length, c.parseAttr(spec)) return fmt.Sprintf("%s VARCHAR(%d) %s", colName, length, c.parseAttr(spec))
} }
// attr returns string representation of column attribute specified as key for defaultMap.
func (c *columnType) attr(flag int) string { func (c *columnType) attr(flag int) string {
if v, ok := c.AttrMap[flag]; ok { if v, ok := c.AttrMap[flag]; ok {
return v return v
@ -65,6 +80,8 @@ func (c *columnType) attr(flag int) string {
return defaultMap[flag] return defaultMap[flag]
} }
// parseAttr reflects spec value for its type and returns the string
// representation returned by `attr`
func (c *columnType) parseAttr(spec []interface{}) string { func (c *columnType) parseAttr(spec []interface{}) string {
var attrs []string var attrs []string
for _, v := range spec { for _, v := range spec {

View file

@ -1,24 +1,3 @@
// Usage
// migrate.To(2)
// .Add(Version_1)
// .Add(Version_2)
// .Add(Version_3)
// .Exec(db)
//
// migrate.ToLatest()
// .Add(Version_1)
// .Add(Version_2)
// .Add(Version_3)
// .SetDialect(migrate.MySQL)
// .Exec(db)
//
// migrate.ToLatest()
// .Add(Version_1)
// .Add(Version_2)
// .Add(Version_3)
// .Backup(path)
// .Exec()
package migrate package migrate
import ( import (
@ -72,7 +51,7 @@ func (m *Migration) Add(rev ...Revision) *Migration {
return m return m
} }
// Execute the full list of migrations. // Migrate executes the full list of migrations.
func (m *Migration) Migrate() error { func (m *Migration) Migrate() error {
var target int64 var target int64
if len(m.revs) > 0 { if len(m.revs) > 0 {
@ -84,7 +63,7 @@ func (m *Migration) Migrate() error {
return m.MigrateTo(target) return m.MigrateTo(target)
} }
// Execute all database migration until // MigrateTo executes all database migration until
// you are at the specified revision number. // you are at the specified revision number.
// If the revision number is less than the // If the revision number is less than the
// current revision, then we will downgrade. // current revision, then we will downgrade.

View file

@ -40,7 +40,7 @@ func (m *mysqlDriver) ChangeColumn(tableName, columnName, newSpecs string) (sql.
return m.Tx.Exec(fmt.Sprintf("ALTER TABLE %s MODIFY %s %s", tableName, columnName, newSpecs)) return m.Tx.Exec(fmt.Sprintf("ALTER TABLE %s MODIFY %s %s", tableName, columnName, newSpecs))
} }
func (m *mysqlDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { func (m *mysqlDriver) DropColumns(tableName string, columnsToDrop ...string) (sql.Result, error) {
for k, v := range columnsToDrop { for k, v := range columnsToDrop {
columnsToDrop[k] = fmt.Sprintf("DROP %s", v) columnsToDrop[k] = fmt.Sprintf("DROP %s", v)
} }

View file

@ -36,7 +36,7 @@ func (p *postgresqlDriver) ChangeColumn(tableName, columnName, newSpecs string)
return nil, errors.New("not implemented yet") return nil, errors.New("not implemented yet")
} }
func (p *postgresqlDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { func (p *postgresqlDriver) DropColumns(tableName string, columnsToDrop ...string) (sql.Result, error) {
return nil, errors.New("not implemented yet") return nil, errors.New("not implemented yet")
} }

View file

@ -91,7 +91,7 @@ func (s *sqliteDriver) ChangeColumn(tableName, columnName, newType string) (sql.
} }
func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop ...string) (sql.Result, error) {
var err error var err error
var result sql.Result var result sql.Result

View file

@ -89,7 +89,7 @@ func (r *revision3) Up(mg *MigrationDriver) error {
} }
func (r *revision3) Down(mg *MigrationDriver) error { func (r *revision3) Down(mg *MigrationDriver) error {
_, err := mg.DropColumns("samples", []string{"num", "url"}) _, err := mg.DropColumns("samples", "num", "url")
return err return err
} }
@ -128,7 +128,7 @@ func (r *revision4) Revision() int64 {
type revision5 struct{} type revision5 struct{}
func (r *revision5) Up(mg *MigrationDriver) error { func (r *revision5) Up(mg *MigrationDriver) error {
_, err := mg.AddIndex("samples", []string{"url", "name"}, "") _, err := mg.AddIndex("samples", []string{"url", "name"})
return err return err
} }
@ -170,7 +170,7 @@ func (r *revision6) Revision() int64 {
type revision7 struct{} type revision7 struct{}
func (r *revision7) Up(mg *MigrationDriver) error { func (r *revision7) Up(mg *MigrationDriver) error {
_, err := mg.DropColumns("samples", []string{"host", "num"}) _, err := mg.DropColumns("samples", "host", "num")
return err return err
} }
@ -200,7 +200,7 @@ func (r *revision8) Up(mg *MigrationDriver) error {
} }
func (r *revision8) Down(mg *MigrationDriver) error { func (r *revision8) Down(mg *MigrationDriver) error {
_, err := mg.DropColumns("samples", []string{"repo", "repo_id"}) _, err := mg.DropColumns("samples", "repo", "repo_id")
return err return err
} }