func ensureDir(dir string) error {
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("unable to create directory `%s`", dir)
	}
	return nil
}
ensureDir creates a directory if it does not already exist
package dbmate
import (
	"database/sql"
	"errors"
	"fmt"
	"io"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"time"
	"github.com/amacneil/dbmate/pkg/dbutil"
)
const DefaultMigrationsDir = "./db/migrations"
const DefaultMigrationsTableName = "schema_migrations"
const DefaultSchemaFile = "./db/schema.sql"
const DefaultWaitInterval = time.Second
const DefaultWaitTimeout = 60 * time.Second
type DB struct {
	AutoDumpSchema      bool
	DatabaseURL         *url.URL
	MigrationsDir       string
	MigrationsTableName string
	SchemaFile          string
	Verbose             bool
	WaitBefore          bool
	WaitInterval        time.Duration
	WaitTimeout         time.Duration
	Log                 io.Writer
}
var migrationFileRegexp = regexp.MustCompile(`^\d.*\.sql$`)
type StatusResult struct {
	Filename string
	Applied  bool
}
func New(databaseURL *url.URL) *DB {
	return &DB{
		AutoDumpSchema:      true,
		DatabaseURL:         databaseURL,
		MigrationsDir:       DefaultMigrationsDir,
		MigrationsTableName: DefaultMigrationsTableName,
		SchemaFile:          DefaultSchemaFile,
		WaitBefore:          false,
		WaitInterval:        DefaultWaitInterval,
		WaitTimeout:         DefaultWaitTimeout,
		Log:                 os.Stdout,
	}
}
func (db *DB) GetDriver() (Driver, error) {
	if db.DatabaseURL == nil || db.DatabaseURL.Scheme == "" {
		return nil, errors.New("invalid url, have you set your --url flag or DATABASE_URL environment variable?")
	}
	driverFunc := drivers[db.DatabaseURL.Scheme]
	if driverFunc == nil {
		return nil, fmt.Errorf("unsupported driver: %s", db.DatabaseURL.Scheme)
	}
	config := DriverConfig{
		DatabaseURL:         db.DatabaseURL,
		MigrationsTableName: db.MigrationsTableName,
		Log:                 db.Log,
	}
	return driverFunc(config), nil
}
func (db *DB) Wait() error {
	drv, err := db.GetDriver()
	if err != nil {
		return err
	}
	return db.wait(drv)
}
func (db *DB) wait(drv Driver) error {
	err := drv.Ping()
	if err == nil {
		return nil
	}
	fmt.Fprint(db.Log, "Waiting for database")
	for i := 0 * time.Second; i < db.WaitTimeout; i += db.WaitInterval {
		fmt.Fprint(db.Log, ".")
		time.Sleep(db.WaitInterval)
		err = drv.Ping()
		if err == nil {
			fmt.Fprint(db.Log, "\n")
			return nil
		}
	}
	fmt.Fprint(db.Log, "\n")
	return fmt.Errorf("unable to connect to database: %s", err)
}
func (db *DB) CreateAndMigrate() error {
	drv, err := db.GetDriver()
	if err != nil {
		return err
	}
	if db.WaitBefore {
		err := db.wait(drv)
		if err != nil {
			return err
		}
	}
	exists, err := drv.DatabaseExists()
	if err == nil && !exists {
		if err := drv.CreateDatabase(); err != nil {
			return err
		}
	}
	return db.migrate(drv)
}
func (db *DB) Create() error {
	drv, err := db.GetDriver()
	if err != nil {
		return err
	}
	if db.WaitBefore {
		err := db.wait(drv)
		if err != nil {
			return err
		}
	}
	return drv.CreateDatabase()
}
func (db *DB) Drop() error {
	drv, err := db.GetDriver()
	if err != nil {
		return err
	}
	if db.WaitBefore {
		err := db.wait(drv)
		if err != nil {
			return err
		}
	}
	return drv.DropDatabase()
}
func (db *DB) DumpSchema() error {
	drv, err := db.GetDriver()
	if err != nil {
		return err
	}
	return db.dumpSchema(drv)
}
func (db *DB) dumpSchema(drv Driver) error {
	if db.WaitBefore {
		err := db.wait(drv)
		if err != nil {
			return err
		}
	}
	sqlDB, err := db.openDatabaseForMigration(drv)
	if err != nil {
		return err
	}
	defer dbutil.MustClose(sqlDB)
	schema, err := drv.DumpSchema(sqlDB)
	if err != nil {
		return err
	}
	fmt.Fprintf(db.Log, "Writing: %s\n", db.SchemaFile)
	if err = ensureDir(filepath.Dir(db.SchemaFile)); err != nil {
		return err
	}
	return os.WriteFile(db.SchemaFile, schema, 0644)
}