mirror of
https://github.com/TECHNOFAB11/dbmate.git
synced 2026-02-02 09:25:07 +01:00
Write log lines to DB.Log output (#195)
This makes it possible to redirect the logs somewhere else, useful if you embed dbmate into your application.
This commit is contained in:
parent
454f93a000
commit
2bac2c7590
6 changed files with 44 additions and 26 deletions
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -41,6 +42,7 @@ type DB struct {
|
||||||
WaitBefore bool
|
WaitBefore bool
|
||||||
WaitInterval time.Duration
|
WaitInterval time.Duration
|
||||||
WaitTimeout time.Duration
|
WaitTimeout time.Duration
|
||||||
|
Log io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// migrationFileRegexp pattern for valid migration files
|
// migrationFileRegexp pattern for valid migration files
|
||||||
|
|
@ -63,6 +65,7 @@ func New(databaseURL *url.URL) *DB {
|
||||||
WaitBefore: false,
|
WaitBefore: false,
|
||||||
WaitInterval: DefaultWaitInterval,
|
WaitInterval: DefaultWaitInterval,
|
||||||
WaitTimeout: DefaultWaitTimeout,
|
WaitTimeout: DefaultWaitTimeout,
|
||||||
|
Log: os.Stdout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +83,7 @@ func (db *DB) GetDriver() (Driver, error) {
|
||||||
config := DriverConfig{
|
config := DriverConfig{
|
||||||
DatabaseURL: db.DatabaseURL,
|
DatabaseURL: db.DatabaseURL,
|
||||||
MigrationsTableName: db.MigrationsTableName,
|
MigrationsTableName: db.MigrationsTableName,
|
||||||
|
Log: db.Log,
|
||||||
}
|
}
|
||||||
|
|
||||||
return driverFunc(config), nil
|
return driverFunc(config), nil
|
||||||
|
|
@ -104,22 +108,22 @@ func (db *DB) wait(drv Driver) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print("Waiting for database")
|
fmt.Fprint(db.Log, "Waiting for database")
|
||||||
for i := 0 * time.Second; i < db.WaitTimeout; i += db.WaitInterval {
|
for i := 0 * time.Second; i < db.WaitTimeout; i += db.WaitInterval {
|
||||||
fmt.Print(".")
|
fmt.Fprint(db.Log, ".")
|
||||||
time.Sleep(db.WaitInterval)
|
time.Sleep(db.WaitInterval)
|
||||||
|
|
||||||
// attempt connection to database server
|
// attempt connection to database server
|
||||||
err = drv.Ping()
|
err = drv.Ping()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// connection successful
|
// connection successful
|
||||||
fmt.Print("\n")
|
fmt.Fprint(db.Log, "\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we find outselves here, we could not connect within the timeout
|
// if we find outselves here, we could not connect within the timeout
|
||||||
fmt.Print("\n")
|
fmt.Fprint(db.Log, "\n")
|
||||||
return fmt.Errorf("unable to connect to database: %s", err)
|
return fmt.Errorf("unable to connect to database: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +218,7 @@ func (db *DB) dumpSchema(drv Driver) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Writing: %s\n", db.SchemaFile)
|
fmt.Fprintf(db.Log, "Writing: %s\n", db.SchemaFile)
|
||||||
|
|
||||||
// ensure schema directory exists
|
// ensure schema directory exists
|
||||||
if err = ensureDir(filepath.Dir(db.SchemaFile)); err != nil {
|
if err = ensureDir(filepath.Dir(db.SchemaFile)); err != nil {
|
||||||
|
|
@ -252,7 +256,7 @@ func (db *DB) NewMigration(name string) error {
|
||||||
|
|
||||||
// check file does not already exist
|
// check file does not already exist
|
||||||
path := filepath.Join(db.MigrationsDir, name)
|
path := filepath.Join(db.MigrationsDir, name)
|
||||||
fmt.Printf("Creating migration: %s\n", path)
|
fmt.Fprintf(db.Log, "Creating migration: %s\n", path)
|
||||||
|
|
||||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||||
return fmt.Errorf("file already exists")
|
return fmt.Errorf("file already exists")
|
||||||
|
|
@ -345,7 +349,7 @@ func (db *DB) migrate(drv Driver) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Applying: %s\n", filename)
|
fmt.Fprintf(db.Log, "Applying: %s\n", filename)
|
||||||
|
|
||||||
up, _, err := parseMigration(filepath.Join(db.MigrationsDir, filename))
|
up, _, err := parseMigration(filepath.Join(db.MigrationsDir, filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -358,7 +362,7 @@ func (db *DB) migrate(drv Driver) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if db.Verbose {
|
} else if db.Verbose {
|
||||||
printVerbose(result)
|
db.printVerbose(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// record migration
|
// record migration
|
||||||
|
|
@ -386,14 +390,14 @@ func (db *DB) migrate(drv Driver) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVerbose(result sql.Result) {
|
func (db *DB) printVerbose(result sql.Result) {
|
||||||
lastInsertID, err := result.LastInsertId()
|
lastInsertID, err := result.LastInsertId()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("Last insert ID: %d\n", lastInsertID)
|
fmt.Fprintf(db.Log, "Last insert ID: %d\n", lastInsertID)
|
||||||
}
|
}
|
||||||
rowsAffected, err := result.RowsAffected()
|
rowsAffected, err := result.RowsAffected()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("Rows affected: %d\n", rowsAffected)
|
fmt.Fprintf(db.Log, "Rows affected: %d\n", rowsAffected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,7 +489,7 @@ func (db *DB) Rollback() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Rolling back: %s\n", filename)
|
fmt.Fprintf(db.Log, "Rolling back: %s\n", filename)
|
||||||
|
|
||||||
_, down, err := parseMigration(filepath.Join(db.MigrationsDir, filename))
|
_, down, err := parseMigration(filepath.Join(db.MigrationsDir, filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -498,7 +502,7 @@ func (db *DB) Rollback() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if db.Verbose {
|
} else if db.Verbose {
|
||||||
printVerbose(result)
|
db.printVerbose(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove migration record
|
// remove migration record
|
||||||
|
|
@ -548,15 +552,15 @@ func (db *DB) Status(quiet bool) (int, error) {
|
||||||
line = fmt.Sprintf("[ ] %s", res.Filename)
|
line = fmt.Sprintf("[ ] %s", res.Filename)
|
||||||
}
|
}
|
||||||
if !quiet {
|
if !quiet {
|
||||||
fmt.Println(line)
|
fmt.Fprintln(db.Log, line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
totalPending := len(results) - totalApplied
|
totalPending := len(results) - totalApplied
|
||||||
if !quiet {
|
if !quiet {
|
||||||
fmt.Println()
|
fmt.Fprintln(db.Log)
|
||||||
fmt.Printf("Applied: %d\n", totalApplied)
|
fmt.Fprintf(db.Log, "Applied: %d\n", totalApplied)
|
||||||
fmt.Printf("Pending: %d\n", totalPending)
|
fmt.Fprintf(db.Log, "Pending: %d\n", totalPending)
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalPending, nil
|
return totalPending, nil
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package dbmate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/amacneil/dbmate/pkg/dbutil"
|
"github.com/amacneil/dbmate/pkg/dbutil"
|
||||||
|
|
@ -25,6 +26,7 @@ type Driver interface {
|
||||||
type DriverConfig struct {
|
type DriverConfig struct {
|
||||||
DatabaseURL *url.URL
|
DatabaseURL *url.URL
|
||||||
MigrationsTableName string
|
MigrationsTableName string
|
||||||
|
Log io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// DriverFunc represents a driver constructor
|
// DriverFunc represents a driver constructor
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
@ -23,6 +24,7 @@ func init() {
|
||||||
type Driver struct {
|
type Driver struct {
|
||||||
migrationsTableName string
|
migrationsTableName string
|
||||||
databaseURL *url.URL
|
databaseURL *url.URL
|
||||||
|
log io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDriver initializes the driver
|
// NewDriver initializes the driver
|
||||||
|
|
@ -30,6 +32,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
|
||||||
return &Driver{
|
return &Driver{
|
||||||
migrationsTableName: config.MigrationsTableName,
|
migrationsTableName: config.MigrationsTableName,
|
||||||
databaseURL: config.DatabaseURL,
|
databaseURL: config.DatabaseURL,
|
||||||
|
log: config.Log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,7 +111,7 @@ func (drv *Driver) quoteIdentifier(str string) string {
|
||||||
// CreateDatabase creates the specified database
|
// CreateDatabase creates the specified database
|
||||||
func (drv *Driver) CreateDatabase() error {
|
func (drv *Driver) CreateDatabase() error {
|
||||||
name := drv.databaseName()
|
name := drv.databaseName()
|
||||||
fmt.Printf("Creating: %s\n", name)
|
fmt.Fprintf(drv.log, "Creating: %s\n", name)
|
||||||
|
|
||||||
db, err := drv.openClickHouseDB()
|
db, err := drv.openClickHouseDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -124,7 +127,7 @@ func (drv *Driver) CreateDatabase() error {
|
||||||
// DropDatabase drops the specified database (if it exists)
|
// DropDatabase drops the specified database (if it exists)
|
||||||
func (drv *Driver) DropDatabase() error {
|
func (drv *Driver) DropDatabase() error {
|
||||||
name := drv.databaseName()
|
name := drv.databaseName()
|
||||||
fmt.Printf("Dropping: %s\n", name)
|
fmt.Fprintf(drv.log, "Dropping: %s\n", name)
|
||||||
|
|
||||||
db, err := drv.openClickHouseDB()
|
db, err := drv.openClickHouseDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -21,6 +22,7 @@ func init() {
|
||||||
type Driver struct {
|
type Driver struct {
|
||||||
migrationsTableName string
|
migrationsTableName string
|
||||||
databaseURL *url.URL
|
databaseURL *url.URL
|
||||||
|
log io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDriver initializes the driver
|
// NewDriver initializes the driver
|
||||||
|
|
@ -28,6 +30,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
|
||||||
return &Driver{
|
return &Driver{
|
||||||
migrationsTableName: config.MigrationsTableName,
|
migrationsTableName: config.MigrationsTableName,
|
||||||
databaseURL: config.DatabaseURL,
|
databaseURL: config.DatabaseURL,
|
||||||
|
log: config.Log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +95,7 @@ func (drv *Driver) quoteIdentifier(str string) string {
|
||||||
// CreateDatabase creates the specified database
|
// CreateDatabase creates the specified database
|
||||||
func (drv *Driver) CreateDatabase() error {
|
func (drv *Driver) CreateDatabase() error {
|
||||||
name := dbutil.DatabaseName(drv.databaseURL)
|
name := dbutil.DatabaseName(drv.databaseURL)
|
||||||
fmt.Printf("Creating: %s\n", name)
|
fmt.Fprintf(drv.log, "Creating: %s\n", name)
|
||||||
|
|
||||||
db, err := drv.openRootDB()
|
db, err := drv.openRootDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -109,7 +112,7 @@ func (drv *Driver) CreateDatabase() error {
|
||||||
// DropDatabase drops the specified database (if it exists)
|
// DropDatabase drops the specified database (if it exists)
|
||||||
func (drv *Driver) DropDatabase() error {
|
func (drv *Driver) DropDatabase() error {
|
||||||
name := dbutil.DatabaseName(drv.databaseURL)
|
name := dbutil.DatabaseName(drv.databaseURL)
|
||||||
fmt.Printf("Dropping: %s\n", name)
|
fmt.Fprintf(drv.log, "Dropping: %s\n", name)
|
||||||
|
|
||||||
db, err := drv.openRootDB()
|
db, err := drv.openRootDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -22,6 +23,7 @@ func init() {
|
||||||
type Driver struct {
|
type Driver struct {
|
||||||
migrationsTableName string
|
migrationsTableName string
|
||||||
databaseURL *url.URL
|
databaseURL *url.URL
|
||||||
|
log io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDriver initializes the driver
|
// NewDriver initializes the driver
|
||||||
|
|
@ -29,6 +31,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
|
||||||
return &Driver{
|
return &Driver{
|
||||||
migrationsTableName: config.MigrationsTableName,
|
migrationsTableName: config.MigrationsTableName,
|
||||||
databaseURL: config.DatabaseURL,
|
databaseURL: config.DatabaseURL,
|
||||||
|
log: config.Log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +115,7 @@ func (drv *Driver) openPostgresDB() (*sql.DB, error) {
|
||||||
// CreateDatabase creates the specified database
|
// CreateDatabase creates the specified database
|
||||||
func (drv *Driver) CreateDatabase() error {
|
func (drv *Driver) CreateDatabase() error {
|
||||||
name := dbutil.DatabaseName(drv.databaseURL)
|
name := dbutil.DatabaseName(drv.databaseURL)
|
||||||
fmt.Printf("Creating: %s\n", name)
|
fmt.Fprintf(drv.log, "Creating: %s\n", name)
|
||||||
|
|
||||||
db, err := drv.openPostgresDB()
|
db, err := drv.openPostgresDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -129,7 +132,7 @@ func (drv *Driver) CreateDatabase() error {
|
||||||
// DropDatabase drops the specified database (if it exists)
|
// DropDatabase drops the specified database (if it exists)
|
||||||
func (drv *Driver) DropDatabase() error {
|
func (drv *Driver) DropDatabase() error {
|
||||||
name := dbutil.DatabaseName(drv.databaseURL)
|
name := dbutil.DatabaseName(drv.databaseURL)
|
||||||
fmt.Printf("Dropping: %s\n", name)
|
fmt.Fprintf(drv.log, "Dropping: %s\n", name)
|
||||||
|
|
||||||
db, err := drv.openPostgresDB()
|
db, err := drv.openPostgresDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -233,7 +236,7 @@ func (drv *Driver) CreateMigrationsTable(db *sql.DB) error {
|
||||||
|
|
||||||
// in theory we could attempt to create the schema every time, but we avoid that
|
// in theory we could attempt to create the schema every time, but we avoid that
|
||||||
// in case the user doesn't have permissions to create schemas
|
// in case the user doesn't have permissions to create schemas
|
||||||
fmt.Printf("Creating schema: %s\n", schema)
|
fmt.Fprintf(drv.log, "Creating schema: %s\n", schema)
|
||||||
_, err = db.Exec(fmt.Sprintf("create schema if not exists %s", schema))
|
_, err = db.Exec(fmt.Sprintf("create schema if not exists %s", schema))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
@ -27,6 +28,7 @@ func init() {
|
||||||
type Driver struct {
|
type Driver struct {
|
||||||
migrationsTableName string
|
migrationsTableName string
|
||||||
databaseURL *url.URL
|
databaseURL *url.URL
|
||||||
|
log io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDriver initializes the driver
|
// NewDriver initializes the driver
|
||||||
|
|
@ -34,6 +36,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
|
||||||
return &Driver{
|
return &Driver{
|
||||||
migrationsTableName: config.MigrationsTableName,
|
migrationsTableName: config.MigrationsTableName,
|
||||||
databaseURL: config.DatabaseURL,
|
databaseURL: config.DatabaseURL,
|
||||||
|
log: config.Log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +59,7 @@ func (drv *Driver) Open() (*sql.DB, error) {
|
||||||
|
|
||||||
// CreateDatabase creates the specified database
|
// CreateDatabase creates the specified database
|
||||||
func (drv *Driver) CreateDatabase() error {
|
func (drv *Driver) CreateDatabase() error {
|
||||||
fmt.Printf("Creating: %s\n", ConnectionString(drv.databaseURL))
|
fmt.Fprintf(drv.log, "Creating: %s\n", ConnectionString(drv.databaseURL))
|
||||||
|
|
||||||
db, err := drv.Open()
|
db, err := drv.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -70,7 +73,7 @@ func (drv *Driver) CreateDatabase() error {
|
||||||
// DropDatabase drops the specified database (if it exists)
|
// DropDatabase drops the specified database (if it exists)
|
||||||
func (drv *Driver) DropDatabase() error {
|
func (drv *Driver) DropDatabase() error {
|
||||||
path := ConnectionString(drv.databaseURL)
|
path := ConnectionString(drv.databaseURL)
|
||||||
fmt.Printf("Dropping: %s\n", path)
|
fmt.Fprintf(drv.log, "Dropping: %s\n", path)
|
||||||
|
|
||||||
exists, err := drv.DatabaseExists()
|
exists, err := drv.DatabaseExists()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue