Repository: amacneil/dbmate
Pull request #263 (2022-01-19 01:51:01)

Add scoop install instructions for windows
Pending merge of: https://github.com/ScoopInstaller/Extras/pull/7785

Enrico204: LGTM
amacneil: How does scoop stay up to date with new versions? For homebrew on macos we automated this (see [here](https://github.com/amacneil/dbmate/blob/main/.github/workflows/release.yml)).
rminderhoud: In the scoop definition, it gets the version based on the github release:

https://github.com/ScoopInstaller/Main/pull/3204/files#diff-624786e9a86009e319ee1f36d228f664841a87c2ccc36bf4e55de48451d37df4R17

The scoop auto update facility checks this url: `https://github.com/amacneil/dbmate/releases/download/v$version/dbmate-windows-amd64#/dbmate.exe`

Matching `$version` in the url to determine if a new version is related. So creating new releases on github while keeping the current naming convention will keep scoop up to date as well.


Patch:
diff --git a/README.md b/README.md
index 826f2ce..a66967e 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,14 @@ $ sudo curl -fsSL -o /usr/local/bin/dbmate https://github.com/amacneil/dbmate/re
 $ sudo chmod +x /usr/local/bin/dbmate
 ```
 
+**Windows**
+
+Download using [scoop](https://scoop.sh)
+
+```pwsh
+scoop install dbmate
+```
+
 **Docker**
 
 Docker images are published to both Docker Hub ([`amacneil/dbmate`](https://hub.docker.com/r/amacneil/dbmate)) and Github Container Registry ([`ghcr.io/amacneil/dbmate`](https://ghcr.io/amacneil/dbmate)).
diff --git a/pkg/dbmate/db.go b/pkg/dbmate/db.go
index f64dd88..cb70ed7 100644
--- a/pkg/dbmate/db.go
+++ b/pkg/dbmate/db.go
@@ -576,17 +576,26 @@ func (db *DB) CheckMigrationsStatus(drv Driver) ([]StatusResult, error) {
 		return nil, fmt.Errorf("no migration files found")
 	}
 
-	sqlDB, err := db.openDatabaseForMigration(drv)
+	sqlDB, err := drv.Open()
 	if err != nil {
 		return nil, err
 	}
 	defer dbutil.MustClose(sqlDB)
 
-	applied, err := drv.SelectMigrations(sqlDB, -1)
+	applied := map[string]bool{}
+
+	migrationsTableExists, err := drv.MigrationsTableExists(sqlDB)
 	if err != nil {
 		return nil, err
 	}
 
+	if migrationsTableExists {
+		applied, err = drv.SelectMigrations(sqlDB, -1)
+		if err != nil {
+			return nil, err
+		}
+	}
+
 	var results []StatusResult
 
 	for _, filename := range files {
diff --git a/pkg/dbmate/driver.go b/pkg/dbmate/driver.go
index e79d60d..730a29b 100644
--- a/pkg/dbmate/driver.go
+++ b/pkg/dbmate/driver.go
@@ -15,6 +15,7 @@ type Driver interface {
 	CreateDatabase() error
 	DropDatabase() error
 	DumpSchema(*sql.DB) ([]byte, error)
+	MigrationsTableExists(*sql.DB) (bool, error)
 	CreateMigrationsTable(*sql.DB) error
 	SelectMigrations(*sql.DB, int) (map[string]bool, error)
 	InsertMigration(dbutil.Transaction, string) error
diff --git a/pkg/driver/clickhouse/clickhouse.go b/pkg/driver/clickhouse/clickhouse.go
index 83571a8..4bd8aab 100644
--- a/pkg/driver/clickhouse/clickhouse.go
+++ b/pkg/driver/clickhouse/clickhouse.go
@@ -230,6 +230,18 @@ func (drv *Driver) DatabaseExists() (bool, error) {
 	return exists, err
 }
 
+// MigrationsTableExists checks if the schema_migrations table exists
+func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) {
+	exists := false
+	err := db.QueryRow("EXISTS TABLE $1", drv.quotedMigrationsTableName()).
+		Scan(&exists)
+	if err == sql.ErrNoRows {
+		return false, nil
+	}
+
+	return exists, err
+}
+
 // CreateMigrationsTable creates the schema migrations table
 func (drv *Driver) CreateMigrationsTable(db *sql.DB) error {
 	_, err := db.Exec(fmt.Sprintf(`
diff --git a/pkg/driver/mysql/mysql.go b/pkg/driver/mysql/mysql.go
index fd25747..ab042c8 100644
--- a/pkg/driver/mysql/mysql.go
+++ b/pkg/driver/mysql/mysql.go
@@ -215,6 +215,19 @@ func (drv *Driver) DatabaseExists() (bool, error) {
 	return exists, err
 }
 
+// MigrationsTableExists checks if the schema_migrations table exists
+func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) {
+	match := ""
+	err := db.QueryRow(fmt.Sprintf("SHOW TABLES LIKE \"%s\"",
+		drv.migrationsTableName)).
+		Scan(&match)
+	if err == sql.ErrNoRows {
+		return false, nil
+	}
+
+	return match != "", err
+}
+
 // CreateMigrationsTable creates the schema_migrations table
 func (drv *Driver) CreateMigrationsTable(db *sql.DB) error {
 	_, err := db.Exec(fmt.Sprintf("create table if not exists %s "+
diff --git a/pkg/driver/postgres/postgres.go b/pkg/driver/postgres/postgres.go
index 60b1333..93dcf06 100644
--- a/pkg/driver/postgres/postgres.go
+++ b/pkg/driver/postgres/postgres.go
@@ -219,6 +219,26 @@ func (drv *Driver) DatabaseExists() (bool, error) {
 	return exists, err
 }
 
+// MigrationsTableExists checks if the schema_migrations table exists
+func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) {
+	schema, migrationsTable, err := drv.quotedMigrationsTableNameParts(db)
+	if err != nil {
+		return false, err
+	}
+
+	exists := false
+	err = db.QueryRow("SELECT 1 FROM information_schema.tables "+
+		"WHERE  table_schema = $1 "+
+		"AND    table_name   = $2",
+		schema, migrationsTable).
+		Scan(&exists)
+	if err == sql.ErrNoRows {
+		return false, nil
+	}
+
+	return exists, err
+}
+
 // CreateMigrationsTable creates the schema_migrations table
 func (drv *Driver) CreateMigrationsTable(db *sql.DB) error {
 	schema, migrationsTable, err := drv.quotedMigrationsTableNameParts(db)
diff --git a/pkg/driver/sqlite/sqlite.go b/pkg/driver/sqlite/sqlite.go
index be2c5f1..c3f6878 100644
--- a/pkg/driver/sqlite/sqlite.go
+++ b/pkg/driver/sqlite/sqlite.go
@@ -141,6 +141,20 @@ func (drv *Driver) DatabaseExists() (bool, error) {
 	return true, nil
 }
 
+// MigrationsTableExists checks if the schema_migrations table exists
+func (drv *Driver) MigrationsTableExists(db *sql.DB) (bool, error) {
+	exists := false
+	err := db.QueryRow("SELECT 1 FROM sqlite_master "+
+		"WHERE type='table' AND name=$1",
+		drv.migrationsTableName).
+		Scan(&exists)
+	if err == sql.ErrNoRows {
+		return false, nil
+	}
+
+	return exists, err
+}
+
 // CreateMigrationsTable creates the schema migrations table
 func (drv *Driver) CreateMigrationsTable(db *sql.DB) error {
 	_, err := db.Exec(


Test patch:
diff --git a/pkg/dbmate/db_test.go b/pkg/dbmate/db_test.go
index d2e42e5..dcfb0d6 100644
--- a/pkg/dbmate/db_test.go
+++ b/pkg/dbmate/db_test.go
@@ -393,6 +393,9 @@ func TestStatus(t *testing.T) {
 			require.Len(t, results, 2)
 			require.False(t, results[0].Applied)
 			require.False(t, results[1].Applied)
+			migrationsTableExists, err := drv.MigrationsTableExists(sqlDB)
+			require.NoError(t, err)
+			require.False(t, migrationsTableExists)
 
 			// run migrations
 			err = db.Migrate()