diff --git a/pkg/database/migrate/mysql.go b/pkg/database/migrate/mysql.go index 151c063cf..61421fd83 100644 --- a/pkg/database/migrate/mysql.go +++ b/pkg/database/migrate/mysql.go @@ -16,26 +16,38 @@ func MySQL(tx *sql.Tx) *MigrationDriver { } } -func (p *mysqlDriver) CreateTable(tableName string, args []string) (sql.Result, error) { +func (m *mysqlDriver) CreateTable(tableName string, args []string) (sql.Result, error) { return nil, errors.New("not implemented yet") } -func (p *mysqlDriver) RenameTable(tableName, newName string) (sql.Result, error) { +func (m *mysqlDriver) RenameTable(tableName, newName string) (sql.Result, error) { return nil, errors.New("not implemented yet") } -func (p *mysqlDriver) DropTable(tableName string) (sql.Result, error) { +func (m *mysqlDriver) DropTable(tableName string) (sql.Result, error) { return nil, errors.New("not implemented yet") } -func (p *mysqlDriver) AddColumn(tableName, columnSpec string) (sql.Result, error) { +func (m *mysqlDriver) AddColumn(tableName, columnSpec string) (sql.Result, error) { return nil, errors.New("not implemented yet") } -func (p *mysqlDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { +func (m *mysqlDriver) ChangeColumn(tableName, columnName, newSpecs string) (sql.Result, error) { return nil, errors.New("not implemented yet") } -func (p *mysqlDriver) RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error) { +func (m *mysqlDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { + return nil, errors.New("not implemented yet") +} + +func (m *mysqlDriver) RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error) { + return nil, errors.New("not implemented yet") +} + +func (m *mysqlDriver) AddIndex(tableName string, columns []string, flag string) (sql.Result, error) { + return nil, errors.New("not implemented yet") +} + +func (m *mysqlDriver) DropIndex(tableName string, columns []string) (sql.Result, error) { return nil, errors.New("not implemented yet") } diff --git a/pkg/database/migrate/postgresql.go b/pkg/database/migrate/postgresql.go index e3cff1ad9..93ba3855f 100644 --- a/pkg/database/migrate/postgresql.go +++ b/pkg/database/migrate/postgresql.go @@ -32,6 +32,10 @@ func (p *postgresqlDriver) AddColumn(tableName, columnSpec string) (sql.Result, return nil, errors.New("not implemented yet") } +func (p *postgresqlDriver) ChangeColumn(tableName, columnName, newSpecs string) (sql.Result, error) { + return nil, errors.New("not implemented yet") +} + func (p *postgresqlDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { return nil, errors.New("not implemented yet") } @@ -39,3 +43,11 @@ func (p *postgresqlDriver) DropColumns(tableName string, columnsToDrop []string) func (p *postgresqlDriver) RenameColumns(tableName string, columnChanges map[string]string) (sql.Result, error) { return nil, errors.New("not implemented yet") } + +func (p *postgresqlDriver) AddIndex(tableName string, columns []string, flag string) (sql.Result, error) { + return nil, errors.New("not implemented yet") +} + +func (p *postgresqlDriver) DropIndex(tableName string, columns []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 fe6ee2013..c0fdce75b 100644 --- a/pkg/database/migrate/sqlite.go +++ b/pkg/database/migrate/sqlite.go @@ -5,7 +5,6 @@ import ( "fmt" "strings" - "github.com/dchest/uniuri" _ "github.com/mattn/go-sqlite3" ) @@ -36,6 +35,61 @@ func (s *sqliteDriver) AddColumn(tableName, columnSpec string) (sql.Result, erro 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) { + var result sql.Result + var err error + + tableSQL, err := s.getTableDefinition(tableName) + if err != nil { + return nil, err + } + + columns, err := fetchColumns(tableSQL) + if err != nil { + return nil, err + } + + for _, column := range columns { + if columnName == strings.SplitN(column, " ", 2)[0] { + column = fmt.Sprintf("%s %s", columnName, newType) + break + } + } + + indices, err := s.getIndexDefinition(tableName) + if err != nil { + return nil, err + } + + proxy := proxyName(tableName) + if result, err = s.RenameTable(tableName, proxy); err != nil { + return nil, err + } + + if result, err = s.CreateTable(tableName, columns); err != nil { + return nil, err + } + + // Migrate data + if result, err = s.Tx.Exec(fmt.Sprintf("INSERT INTO %s SELECT %s FROM %s", tableName, + strings.Join(columns, ", "), proxy)); err != nil { + return result, err + } + + // Clean up proxy table + if result, err = s.DropTable(proxy); err != nil { + return result, err + } + + for _, idx := range indices { + if result, err = s.Tx.Exec(idx); err != nil { + return result, err + } + } + return result, err + +} + func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop []string) (sql.Result, error) { var err error var result sql.Result @@ -44,7 +98,7 @@ func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop []string) (sq return nil, fmt.Errorf("No columns to drop.") } - tableSQL, err := s.getDDLFromTable(tableName) + tableSQL, err := s.getTableDefinition(tableName) if err != nil { return nil, err } @@ -75,7 +129,7 @@ func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop []string) (sq } // fetch indices for this table - oldSQLIndices, err := s.getDDLFromIndex(tableName) + oldSQLIndices, err := s.getIndexDefinition(tableName) if err != nil { return nil, err } @@ -107,8 +161,8 @@ func (s *sqliteDriver) DropColumns(tableName string, columnsToDrop []string) (sq } // Rename old table, here's our proxy - proxyName := fmt.Sprintf("%s_%s", tableName, uniuri.NewLen(16)) - if result, err := s.RenameTable(tableName, proxyName); err != nil { + proxy := proxyName(tableName) + if result, err := s.RenameTable(tableName, proxy); err != nil { return result, err } @@ -119,12 +173,12 @@ 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, - strings.Join(selectName(preparedColumns), ", "), proxyName)); err != nil { + strings.Join(selectName(preparedColumns), ", "), proxy)); err != nil { return result, err } // Clean up proxy table - if result, err = s.DropTable(proxyName); err != nil { + if result, err = s.DropTable(proxy); err != nil { return result, err } @@ -141,7 +195,7 @@ func (s *sqliteDriver) RenameColumns(tableName string, columnChanges map[string] var err error var result sql.Result - tableSQL, err := s.getDDLFromTable(tableName) + tableSQL, err := s.getTableDefinition(tableName) if err != nil { return nil, err } @@ -173,7 +227,7 @@ func (s *sqliteDriver) RenameColumns(tableName string, columnChanges map[string] } // fetch indices for this table - oldSQLIndices, err := s.getDDLFromIndex(tableName) + oldSQLIndices, err := s.getIndexDefinition(tableName) if err != nil { return nil, err } @@ -207,8 +261,8 @@ func (s *sqliteDriver) RenameColumns(tableName string, columnChanges map[string] } // Rename current table - proxyName := fmt.Sprintf("%s_%s", tableName, uniuri.NewLen(16)) - if result, err := s.RenameTable(tableName, proxyName); err != nil { + proxy := proxyName(tableName) + if result, err := s.RenameTable(tableName, proxy); err != nil { return result, err } @@ -219,12 +273,12 @@ func (s *sqliteDriver) RenameColumns(tableName string, columnChanges map[string] // Migrate data if result, err = s.Tx.Exec(fmt.Sprintf("INSERT INTO %s SELECT %s FROM %s", tableName, - strings.Join(oldColumnsName, ", "), proxyName)); err != nil { + strings.Join(oldColumnsName, ", "), proxy)); err != nil { return result, err } // Clean up proxy table - if result, err = s.DropTable(proxyName); err != nil { + if result, err = s.DropTable(proxy); err != nil { return result, err } @@ -236,7 +290,19 @@ func (s *sqliteDriver) RenameColumns(tableName string, columnChanges map[string] return result, err } -func (s *sqliteDriver) getDDLFromTable(tableName string) (string, error) { +func (s *sqliteDriver) AddIndex(tableName string, columns []string, flag string) (sql.Result, error) { + if strings.ToUpper(flag) != "UNIQUE" { + flag = "" + } + return s.Tx.Exec(fmt.Sprintf("CREATE %s INDEX %s ON %s (%s)", flag, indexName(tableName, columns), + tableName, strings.Join(columns, ", "))) +} + +func (s *sqliteDriver) DropIndex(tableName string, columns []string) (sql.Result, error) { + return s.Tx.Exec(fmt.Sprintf("DROP INDEX %s", indexName(tableName, columns))) +} + +func (s *sqliteDriver) getTableDefinition(tableName string) (string, error) { var sql string query := `SELECT sql FROM sqlite_master WHERE type='table' and name=?;` err := s.Tx.QueryRow(query, tableName).Scan(&sql) @@ -246,7 +312,7 @@ func (s *sqliteDriver) getDDLFromTable(tableName string) (string, error) { return sql, nil } -func (s *sqliteDriver) getDDLFromIndex(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=?;` diff --git a/pkg/database/migrate/util.go b/pkg/database/migrate/util.go index d2001a071..dbb01e8be 100644 --- a/pkg/database/migrate/util.go +++ b/pkg/database/migrate/util.go @@ -3,6 +3,8 @@ package migrate import ( "fmt" "strings" + + "github.com/dchest/uniuri" ) func fetchColumns(sql string) ([]string, error) { @@ -30,3 +32,11 @@ func setForUpdate(left []string, right []string) string { } return strings.Join(results, ", ") } + +func proxyName(tableName string) string { + return fmt.Sprintf("%s_%s", tableName, uniuri.NewLen(16)) +} + +func indexName(tableName string, columns []string) string { + return fmt.Sprintf("idx_%s_on_%s", tableName, strings.Join(columns, "_and_")) +}