mirror of
https://github.com/TECHNOFAB11/dbmate.git
synced 2025-12-11 23:50:04 +01:00
Add Up command to create database and migrate
This commit is contained in:
parent
1c4cf2c122
commit
164ec81370
5 changed files with 125 additions and 31 deletions
26
commands.go
26
commands.go
|
|
@ -14,6 +14,32 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// UpCommand creates the database (if necessary) and runs migrations
|
||||
func UpCommand(ctx *cli.Context) error {
|
||||
u, err := GetDatabaseURL(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
drv, err := driver.Get(u.Scheme)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create database if it does not already exist
|
||||
// skip this step if we cannot determine status
|
||||
// (e.g. user does not have list database permission)
|
||||
exists, err := drv.DatabaseExists(u)
|
||||
if err == nil && !exists {
|
||||
if err := drv.CreateDatabase(u); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// migrate
|
||||
return MigrateCommand(ctx)
|
||||
}
|
||||
|
||||
// CreateCommand creates the current database
|
||||
func CreateCommand(ctx *cli.Context) error {
|
||||
u, err := GetDatabaseURL(ctx)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
// Driver provides top level database functions
|
||||
type Driver interface {
|
||||
Open(*url.URL) (*sql.DB, error)
|
||||
DatabaseExists(*url.URL) (bool, error)
|
||||
CreateDatabase(*url.URL) error
|
||||
DropDatabase(*url.URL) error
|
||||
CreateMigrationsTable(*sql.DB) error
|
||||
|
|
|
|||
|
|
@ -18,39 +18,66 @@ func (postgres Driver) Open(u *url.URL) (*sql.DB, error) {
|
|||
}
|
||||
|
||||
// postgresExec runs a sql statement on the "postgres" database
|
||||
func (postgres Driver) postgresExec(u *url.URL, statement string) error {
|
||||
func (postgres Driver) openPostgresDB(u *url.URL) (*sql.DB, error) {
|
||||
// connect to postgres database
|
||||
postgresURL := *u
|
||||
postgresURL.Path = "postgres"
|
||||
|
||||
db, err := postgres.Open(&postgresURL)
|
||||
return postgres.Open(&postgresURL)
|
||||
}
|
||||
|
||||
// CreateDatabase creates the specified database
|
||||
func (postgres Driver) CreateDatabase(u *url.URL) error {
|
||||
name := shared.DatabaseName(u)
|
||||
fmt.Printf("Creating: %s\n", name)
|
||||
|
||||
db, err := postgres.openPostgresDB(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// run statement
|
||||
_, err = db.Exec(statement)
|
||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s",
|
||||
pq.QuoteIdentifier(name)))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateDatabase creates the specified database
|
||||
func (postgres Driver) CreateDatabase(u *url.URL) error {
|
||||
database := shared.DatabaseName(u)
|
||||
fmt.Printf("Creating: %s\n", database)
|
||||
|
||||
return postgres.postgresExec(u, fmt.Sprintf("CREATE DATABASE %s",
|
||||
pq.QuoteIdentifier(database)))
|
||||
}
|
||||
|
||||
// DropDatabase drops the specified database (if it exists)
|
||||
func (postgres Driver) DropDatabase(u *url.URL) error {
|
||||
database := shared.DatabaseName(u)
|
||||
fmt.Printf("Dropping: %s\n", database)
|
||||
name := shared.DatabaseName(u)
|
||||
fmt.Printf("Dropping: %s\n", name)
|
||||
|
||||
return postgres.postgresExec(u, fmt.Sprintf("DROP DATABASE IF EXISTS %s",
|
||||
pq.QuoteIdentifier(database)))
|
||||
db, err := postgres.openPostgresDB(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s",
|
||||
pq.QuoteIdentifier(name)))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DatabaseExists determines whether the database exists
|
||||
func (postgres Driver) DatabaseExists(u *url.URL) (bool, error) {
|
||||
name := shared.DatabaseName(u)
|
||||
|
||||
db, err := postgres.openPostgresDB(u)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
exists := false
|
||||
err = db.QueryRow("SELECT true FROM pg_database WHERE datname = $1", name).
|
||||
Scan(&exists)
|
||||
if err == sql.ErrNoRows {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return exists, err
|
||||
}
|
||||
|
||||
// HasMigrationsTable returns true if the schema_migrations table exists
|
||||
|
|
|
|||
|
|
@ -61,3 +61,36 @@ func TestCreateDropDatabase(t *testing.T) {
|
|||
require.Equal(t, "pq: database \"dbmate\" does not exist", err.Error())
|
||||
}()
|
||||
}
|
||||
|
||||
func TestDatabaseExists(t *testing.T) {
|
||||
d := postgres.Driver{}
|
||||
u := testURL(t)
|
||||
|
||||
// drop any existing database
|
||||
err := d.DropDatabase(u)
|
||||
require.Nil(t, err)
|
||||
|
||||
// DatabaseExists should return false
|
||||
exists, err := d.DatabaseExists(u)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, false, exists)
|
||||
|
||||
// create database
|
||||
err = d.CreateDatabase(u)
|
||||
require.Nil(t, err)
|
||||
|
||||
// DatabaseExists should return true
|
||||
exists, err = d.DatabaseExists(u)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, true, exists)
|
||||
}
|
||||
|
||||
func TestDatabaseExists_error(t *testing.T) {
|
||||
d := postgres.Driver{}
|
||||
u := testURL(t)
|
||||
u.User = url.User("invalid")
|
||||
|
||||
exists, err := d.DatabaseExists(u)
|
||||
require.Equal(t, "pq: role \"invalid\" does not exist", err.Error())
|
||||
require.Equal(t, false, exists)
|
||||
}
|
||||
|
|
|
|||
35
main.go
35
main.go
|
|
@ -35,20 +35,6 @@ func NewApp() *cli.App {
|
|||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "migrate",
|
||||
Usage: "Migrate to the latest version",
|
||||
Action: func(ctx *cli.Context) {
|
||||
runCommand(MigrateCommand, ctx)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "rollback",
|
||||
Usage: "Rollback the most recent migration",
|
||||
Action: func(ctx *cli.Context) {
|
||||
runCommand(RollbackCommand, ctx)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "new",
|
||||
Usage: "Generate a new migration file",
|
||||
|
|
@ -56,6 +42,13 @@ func NewApp() *cli.App {
|
|||
runCommand(NewCommand, ctx)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "up",
|
||||
Usage: "Create database (if necessary) and migrate to the latest version",
|
||||
Action: func(ctx *cli.Context) {
|
||||
runCommand(UpCommand, ctx)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "create",
|
||||
Usage: "Create database",
|
||||
|
|
@ -70,6 +63,20 @@ func NewApp() *cli.App {
|
|||
runCommand(DropCommand, ctx)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "migrate",
|
||||
Usage: "Migrate to the latest version",
|
||||
Action: func(ctx *cli.Context) {
|
||||
runCommand(MigrateCommand, ctx)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "rollback",
|
||||
Usage: "Rollback the most recent migration",
|
||||
Action: func(ctx *cli.Context) {
|
||||
runCommand(RollbackCommand, ctx)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return app
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue