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:
Bouke van der Bijl 2021-02-18 23:10:57 +01:00 committed by GitHub
parent 454f93a000
commit 2bac2c7590
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 26 deletions

View file

@ -4,6 +4,7 @@ import (
"database/sql"
"errors"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
@ -41,6 +42,7 @@ type DB struct {
WaitBefore bool
WaitInterval time.Duration
WaitTimeout time.Duration
Log io.Writer
}
// migrationFileRegexp pattern for valid migration files
@ -63,6 +65,7 @@ func New(databaseURL *url.URL) *DB {
WaitBefore: false,
WaitInterval: DefaultWaitInterval,
WaitTimeout: DefaultWaitTimeout,
Log: os.Stdout,
}
}
@ -80,6 +83,7 @@ func (db *DB) GetDriver() (Driver, error) {
config := DriverConfig{
DatabaseURL: db.DatabaseURL,
MigrationsTableName: db.MigrationsTableName,
Log: db.Log,
}
return driverFunc(config), nil
@ -104,22 +108,22 @@ func (db *DB) wait(drv Driver) error {
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 {
fmt.Print(".")
fmt.Fprint(db.Log, ".")
time.Sleep(db.WaitInterval)
// attempt connection to database server
err = drv.Ping()
if err == nil {
// connection successful
fmt.Print("\n")
fmt.Fprint(db.Log, "\n")
return nil
}
}
// 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)
}
@ -214,7 +218,7 @@ func (db *DB) dumpSchema(drv Driver) error {
return err
}
fmt.Printf("Writing: %s\n", db.SchemaFile)
fmt.Fprintf(db.Log, "Writing: %s\n", db.SchemaFile)
// ensure schema directory exists
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
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) {
return fmt.Errorf("file already exists")
@ -345,7 +349,7 @@ func (db *DB) migrate(drv Driver) error {
continue
}
fmt.Printf("Applying: %s\n", filename)
fmt.Fprintf(db.Log, "Applying: %s\n", filename)
up, _, err := parseMigration(filepath.Join(db.MigrationsDir, filename))
if err != nil {
@ -358,7 +362,7 @@ func (db *DB) migrate(drv Driver) error {
if err != nil {
return err
} else if db.Verbose {
printVerbose(result)
db.printVerbose(result)
}
// record migration
@ -386,14 +390,14 @@ func (db *DB) migrate(drv Driver) error {
return nil
}
func printVerbose(result sql.Result) {
func (db *DB) printVerbose(result sql.Result) {
lastInsertID, err := result.LastInsertId()
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()
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
}
fmt.Printf("Rolling back: %s\n", filename)
fmt.Fprintf(db.Log, "Rolling back: %s\n", filename)
_, down, err := parseMigration(filepath.Join(db.MigrationsDir, filename))
if err != nil {
@ -498,7 +502,7 @@ func (db *DB) Rollback() error {
if err != nil {
return err
} else if db.Verbose {
printVerbose(result)
db.printVerbose(result)
}
// remove migration record
@ -548,15 +552,15 @@ func (db *DB) Status(quiet bool) (int, error) {
line = fmt.Sprintf("[ ] %s", res.Filename)
}
if !quiet {
fmt.Println(line)
fmt.Fprintln(db.Log, line)
}
}
totalPending := len(results) - totalApplied
if !quiet {
fmt.Println()
fmt.Printf("Applied: %d\n", totalApplied)
fmt.Printf("Pending: %d\n", totalPending)
fmt.Fprintln(db.Log)
fmt.Fprintf(db.Log, "Applied: %d\n", totalApplied)
fmt.Fprintf(db.Log, "Pending: %d\n", totalPending)
}
return totalPending, nil

View file

@ -2,6 +2,7 @@ package dbmate
import (
"database/sql"
"io"
"net/url"
"github.com/amacneil/dbmate/pkg/dbutil"
@ -25,6 +26,7 @@ type Driver interface {
type DriverConfig struct {
DatabaseURL *url.URL
MigrationsTableName string
Log io.Writer
}
// DriverFunc represents a driver constructor

View file

@ -4,6 +4,7 @@ import (
"bytes"
"database/sql"
"fmt"
"io"
"net/url"
"regexp"
"sort"
@ -23,6 +24,7 @@ func init() {
type Driver struct {
migrationsTableName string
databaseURL *url.URL
log io.Writer
}
// NewDriver initializes the driver
@ -30,6 +32,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
return &Driver{
migrationsTableName: config.MigrationsTableName,
databaseURL: config.DatabaseURL,
log: config.Log,
}
}
@ -108,7 +111,7 @@ func (drv *Driver) quoteIdentifier(str string) string {
// CreateDatabase creates the specified database
func (drv *Driver) CreateDatabase() error {
name := drv.databaseName()
fmt.Printf("Creating: %s\n", name)
fmt.Fprintf(drv.log, "Creating: %s\n", name)
db, err := drv.openClickHouseDB()
if err != nil {
@ -124,7 +127,7 @@ func (drv *Driver) CreateDatabase() error {
// DropDatabase drops the specified database (if it exists)
func (drv *Driver) DropDatabase() error {
name := drv.databaseName()
fmt.Printf("Dropping: %s\n", name)
fmt.Fprintf(drv.log, "Dropping: %s\n", name)
db, err := drv.openClickHouseDB()
if err != nil {

View file

@ -4,6 +4,7 @@ import (
"bytes"
"database/sql"
"fmt"
"io"
"net/url"
"strings"
@ -21,6 +22,7 @@ func init() {
type Driver struct {
migrationsTableName string
databaseURL *url.URL
log io.Writer
}
// NewDriver initializes the driver
@ -28,6 +30,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
return &Driver{
migrationsTableName: config.MigrationsTableName,
databaseURL: config.DatabaseURL,
log: config.Log,
}
}
@ -92,7 +95,7 @@ func (drv *Driver) quoteIdentifier(str string) string {
// CreateDatabase creates the specified database
func (drv *Driver) CreateDatabase() error {
name := dbutil.DatabaseName(drv.databaseURL)
fmt.Printf("Creating: %s\n", name)
fmt.Fprintf(drv.log, "Creating: %s\n", name)
db, err := drv.openRootDB()
if err != nil {
@ -109,7 +112,7 @@ func (drv *Driver) CreateDatabase() error {
// DropDatabase drops the specified database (if it exists)
func (drv *Driver) DropDatabase() error {
name := dbutil.DatabaseName(drv.databaseURL)
fmt.Printf("Dropping: %s\n", name)
fmt.Fprintf(drv.log, "Dropping: %s\n", name)
db, err := drv.openRootDB()
if err != nil {

View file

@ -4,6 +4,7 @@ import (
"bytes"
"database/sql"
"fmt"
"io"
"net/url"
"strings"
@ -22,6 +23,7 @@ func init() {
type Driver struct {
migrationsTableName string
databaseURL *url.URL
log io.Writer
}
// NewDriver initializes the driver
@ -29,6 +31,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
return &Driver{
migrationsTableName: config.MigrationsTableName,
databaseURL: config.DatabaseURL,
log: config.Log,
}
}
@ -112,7 +115,7 @@ func (drv *Driver) openPostgresDB() (*sql.DB, error) {
// CreateDatabase creates the specified database
func (drv *Driver) CreateDatabase() error {
name := dbutil.DatabaseName(drv.databaseURL)
fmt.Printf("Creating: %s\n", name)
fmt.Fprintf(drv.log, "Creating: %s\n", name)
db, err := drv.openPostgresDB()
if err != nil {
@ -129,7 +132,7 @@ func (drv *Driver) CreateDatabase() error {
// DropDatabase drops the specified database (if it exists)
func (drv *Driver) DropDatabase() error {
name := dbutil.DatabaseName(drv.databaseURL)
fmt.Printf("Dropping: %s\n", name)
fmt.Fprintf(drv.log, "Dropping: %s\n", name)
db, err := drv.openPostgresDB()
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 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))
if err != nil {
return err

View file

@ -6,6 +6,7 @@ import (
"bytes"
"database/sql"
"fmt"
"io"
"net/url"
"os"
"regexp"
@ -27,6 +28,7 @@ func init() {
type Driver struct {
migrationsTableName string
databaseURL *url.URL
log io.Writer
}
// NewDriver initializes the driver
@ -34,6 +36,7 @@ func NewDriver(config dbmate.DriverConfig) dbmate.Driver {
return &Driver{
migrationsTableName: config.MigrationsTableName,
databaseURL: config.DatabaseURL,
log: config.Log,
}
}
@ -56,7 +59,7 @@ func (drv *Driver) Open() (*sql.DB, error) {
// CreateDatabase creates the specified database
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()
if err != nil {
@ -70,7 +73,7 @@ func (drv *Driver) CreateDatabase() error {
// DropDatabase drops the specified database (if it exists)
func (drv *Driver) DropDatabase() error {
path := ConnectionString(drv.databaseURL)
fmt.Printf("Dropping: %s\n", path)
fmt.Fprintf(drv.log, "Dropping: %s\n", path)
exists, err := drv.DatabaseExists()
if err != nil {