diff --git a/pkg/database/database.go b/pkg/database/database.go index 2c2ff216a..1966aee41 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -51,7 +51,9 @@ func Init(name, datasource string) error { } migration := migrate.New(db) - migration.All().Migrate() + if err := migration.All().Migrate(); err != nil { + return err + } return nil } diff --git a/pkg/database/migrate/1_setup_tables.go b/pkg/database/migrate/1_setup_tables.go index e893cecc2..92d62ab32 100644 --- a/pkg/database/migrate/1_setup_tables.go +++ b/pkg/database/migrate/1_setup_tables.go @@ -52,7 +52,7 @@ func (r *rev1st) Up(mg *MigrationDriver) error { if _, err := mg.CreateTable("repos", []string{ t.Integer("id", PRIMARYKEY, AUTOINCREMENT), - t.Varchar("slug", 1024, UNIQUE), + t.String("slug", UNIQUE), t.String("host"), t.String("owner"), t.String("name"), @@ -113,7 +113,7 @@ func (r *rev1st) Up(mg *MigrationDriver) error { } _, err := mg.CreateTable("settings", []string{ - t.Integer("id", PRIMARYKEY), + t.Integer("id", PRIMARYKEY, AUTOINCREMENT), t.String("github_key"), t.String("github_secret"), t.String("bitbucket_key"), diff --git a/pkg/database/migrate/2_setup_indices.go b/pkg/database/migrate/2_setup_indices.go index 851516aed..aea6db8cd 100644 --- a/pkg/database/migrate/2_setup_indices.go +++ b/pkg/database/migrate/2_setup_indices.go @@ -13,11 +13,11 @@ func (r *rev2nd) Up(mg *MigrationDriver) error { return err } - if _, err := mg.AddIndex("members", []string{"team_id"}, ""); err != nil { + if _, err := mg.AddIndex("members", []string{"team_id"}); err != nil { return err } - if _, err := mg.AddIndex("members", []string{"user_id"}, ""); err != nil { + if _, err := mg.AddIndex("members", []string{"user_id"}); err != nil { return err } @@ -25,27 +25,27 @@ func (r *rev2nd) Up(mg *MigrationDriver) error { return err } - if _, err := mg.AddIndex("commits", []string{"repo_id"}, ""); err != nil { + if _, err := mg.AddIndex("commits", []string{"repo_id"}); err != nil { return err } - if _, err := mg.AddIndex("commits", []string{"repo_id", "branch"}, ""); err != nil { + if _, err := mg.AddIndex("commits", []string{"repo_id", "branch"}); err != nil { return err } - if _, err := mg.AddIndex("repos", []string{"team_id"}, ""); err != nil { + if _, err := mg.AddIndex("repos", []string{"team_id"}); err != nil { return err } - if _, err := mg.AddIndex("repos", []string{"user_id"}, ""); err != nil { + if _, err := mg.AddIndex("repos", []string{"user_id"}); err != nil { return err } - if _, err := mg.AddIndex("builds", []string{"commit_id"}, ""); err != nil { + if _, err := mg.AddIndex("builds", []string{"commit_id"}); err != nil { return err } - _, err := mg.AddIndex("builds", []string{"commit_id", "slug"}, "") + _, err := mg.AddIndex("builds", []string{"commit_id", "slug"}) return err } diff --git a/pkg/database/migrate/api.go b/pkg/database/migrate/api.go index 562fedae4..c93d5b43f 100644 --- a/pkg/database/migrate/api.go +++ b/pkg/database/migrate/api.go @@ -22,7 +22,7 @@ type Operation interface { RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error) - AddIndex(tableName string, columns []string, flag string) (sql.Result, error) + AddIndex(tableName string, columns []string, flags ...string) (sql.Result, error) DropIndex(tableName string, columns []string) (sql.Result, error) } diff --git a/pkg/database/migrate/migrate.go b/pkg/database/migrate/migrate.go index d6487a22a..ba4e8137e 100644 --- a/pkg/database/migrate/migrate.go +++ b/pkg/database/migrate/migrate.go @@ -28,7 +28,7 @@ import ( const migrationTableStmt = ` CREATE TABLE IF NOT EXISTS migration ( - revision NUMBER PRIMARY KEY + revision BIGINT PRIMARY KEY ) ` diff --git a/pkg/database/migrate/mysql.go b/pkg/database/migrate/mysql.go index 61421fd83..c05926a99 100644 --- a/pkg/database/migrate/mysql.go +++ b/pkg/database/migrate/mysql.go @@ -2,7 +2,8 @@ package migrate import ( "database/sql" - "errors" + "fmt" + "strings" ) type mysqlDriver struct { @@ -13,41 +14,96 @@ func MySQL(tx *sql.Tx) *MigrationDriver { return &MigrationDriver{ Tx: tx, Operation: &mysqlDriver{Tx: tx}, + T: &columnType{ + AttrMap: map[int]string{AUTOINCREMENT: "AUTO_INCREMENT"}, + }, } } func (m *mysqlDriver) CreateTable(tableName string, args []string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + return m.Tx.Exec(fmt.Sprintf("CREATE TABLE %s (%s) ROW_FORMAT=DYNAMIC", tableName, strings.Join(args, ", "))) } func (m *mysqlDriver) RenameTable(tableName, newName string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + return m.Tx.Exec(fmt.Sprintf("ALTER TABLE %s RENAME TO %s", tableName, newName)) } func (m *mysqlDriver) DropTable(tableName string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + return m.Tx.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s", tableName)) } func (m *mysqlDriver) AddColumn(tableName, columnSpec string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + return m.Tx.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN (%s)", tableName, columnSpec)) } func (m *mysqlDriver) ChangeColumn(tableName, columnName, newSpecs string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + 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) { - return nil, errors.New("not implemented yet") + for k, v := range columnsToDrop { + columnsToDrop[k] = fmt.Sprintf("DROP %s", v) + } + return m.Tx.Exec(fmt.Sprintf("ALTER TABLE %s %s", tableName, strings.Join(columnsToDrop, ", "))) } func (m *mysqlDriver) RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + var columns []string + + tableSQL, err := m.getTableDefinition(tableName) + if err != nil { + return nil, err + } + + columns, err = fetchColumns(tableSQL) + if err != nil { + return nil, err + } + + var colspec []string + for k, v := range columnChanges { + for _, col := range columns { + col = strings.Trim(col, " \n") + cols := strings.SplitN(col, " ", 2) + if quote(k) == cols[0] { + colspec = append(colspec, fmt.Sprintf("CHANGE %s %s %s", k, v, cols[1])) + break + } + } + } + + return m.Tx.Exec(fmt.Sprintf("ALTER TABLE %s %s", tableName, strings.Join(colspec, ", "))) } -func (m *mysqlDriver) AddIndex(tableName string, columns []string, flag string) (sql.Result, error) { - return nil, errors.New("not implemented yet") +func (m *mysqlDriver) AddIndex(tableName string, columns []string, flags ...string) (sql.Result, error) { + flag := "" + if len(flags) > 0 { + switch strings.ToUpper(flags[0]) { + case "UNIQUE": + fallthrough + case "FULLTEXT": + fallthrough + case "SPATIAL": + flag = flags[0] + } + } + return m.Tx.Exec(fmt.Sprintf("CREATE %s INDEX %s ON %s (%s)", flag, + indexName(tableName, columns), tableName, strings.Join(columns, ", "))) } func (m *mysqlDriver) DropIndex(tableName string, columns []string) (sql.Result, error) { - return nil, errors.New("not implemented yet") + return m.Tx.Exec(fmt.Sprintf("DROP INDEX %s on %s", indexName(tableName, columns), tableName)) +} + +func (m *mysqlDriver) getTableDefinition(tableName string) (string, error) { + var name, def string + st := fmt.Sprintf("SHOW CREATE TABLE %s", tableName) + if err := m.Tx.QueryRow(st).Scan(&name, &def); err != nil { + return "", err + } + return def, nil +} + +func quote(name string) string { + return fmt.Sprintf("`%s`", name) } diff --git a/pkg/database/migrate/postgresql.go b/pkg/database/migrate/postgresql.go index 93ba3855f..a473412a5 100644 --- a/pkg/database/migrate/postgresql.go +++ b/pkg/database/migrate/postgresql.go @@ -44,7 +44,7 @@ func (p *postgresqlDriver) RenameColumns(tableName string, columnChanges map[str return nil, errors.New("not implemented yet") } -func (p *postgresqlDriver) AddIndex(tableName string, columns []string, flag string) (sql.Result, error) { +func (p *postgresqlDriver) AddIndex(tableName string, columns []string, flags ...string) (sql.Result, error) { return nil, errors.New("not implemented yet") } diff --git a/pkg/database/migrate/sqlite.go b/pkg/database/migrate/sqlite.go index ed2965a59..bed6f7f5a 100644 --- a/pkg/database/migrate/sqlite.go +++ b/pkg/database/migrate/sqlite.go @@ -19,19 +19,19 @@ func SQLite(tx *sql.Tx) *MigrationDriver { } func (s *sqliteDriver) CreateTable(tableName string, args []string) (sql.Result, error) { - return s.Tx.Exec(fmt.Sprintf("CREATE TABLE %s (%s);", tableName, strings.Join(args, ", "))) + return s.Tx.Exec(fmt.Sprintf("CREATE TABLE %s (%s)", tableName, strings.Join(args, ", "))) } func (s *sqliteDriver) RenameTable(tableName, newName string) (sql.Result, error) { - return s.Tx.Exec(fmt.Sprintf("ALTER TABLE %s RENAME TO %s;", tableName, newName)) + return s.Tx.Exec(fmt.Sprintf("ALTER TABLE %s RENAME TO %s", tableName, newName)) } func (s *sqliteDriver) DropTable(tableName string) (sql.Result, error) { - return s.Tx.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s;", tableName)) + return s.Tx.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s", tableName)) } func (s *sqliteDriver) AddColumn(tableName, columnSpec string) (sql.Result, error) { - return s.Tx.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s;", tableName, columnSpec)) + return s.Tx.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s", tableName, columnSpec)) } func (s *sqliteDriver) ChangeColumn(tableName, columnName, newType string) (sql.Result, error) { @@ -173,7 +173,7 @@ func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop []string) (sq } // Move data from old table - if result, err = s.Tx.Exec(fmt.Sprintf("INSERT INTO %s SELECT %s FROM %s;", tableName, + if result, err = s.Tx.Exec(fmt.Sprintf("INSERT INTO %s SELECT %s FROM %s", tableName, strings.Join(selectName(preparedColumns), ", "), proxy)); err != nil { return result, err } @@ -291,9 +291,12 @@ func (s *sqliteDriver) RenameColumns(tableName string, columnChanges map[string] return result, err } -func (s *sqliteDriver) AddIndex(tableName string, columns []string, flag string) (sql.Result, error) { - if strings.ToUpper(flag) != "UNIQUE" { - flag = "" +func (s *sqliteDriver) AddIndex(tableName string, columns []string, flags ...string) (sql.Result, error) { + flag := "" + if len(flags) > 0 { + if strings.ToUpper(flags[0]) == "UNIQUE" { + flag = flags[0] + } } return s.Tx.Exec(fmt.Sprintf("CREATE %s INDEX %s ON %s (%s)", flag, indexName(tableName, columns), tableName, strings.Join(columns, ", "))) @@ -305,7 +308,7 @@ func (s *sqliteDriver) DropIndex(tableName string, columns []string) (sql.Result func (s *sqliteDriver) getTableDefinition(tableName string) (string, error) { var sql string - query := `SELECT sql FROM sqlite_master WHERE type='table' and name=?;` + query := `SELECT sql FROM sqlite_master WHERE type='table' and name=?` err := s.Tx.QueryRow(query, tableName).Scan(&sql) if err != nil { return "", err @@ -316,7 +319,7 @@ func (s *sqliteDriver) getTableDefinition(tableName string) (string, error) { func (s *sqliteDriver) getIndexDefinition(tableName string) ([]string, error) { var sqls []string - query := `SELECT sql FROM sqlite_master WHERE type='index' and tbl_name=?;` + query := `SELECT sql FROM sqlite_master WHERE type='index' and tbl_name=?` rows, err := s.Tx.Query(query, tableName) if err != nil { return sqls, err