forked from go-shiori/shiori
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new migrations system (go-shiori#876)
* feat: new migration system * use newFuncMigration * database version -> database schema version * column name * use path instead of filepath for goembed * simplified migrations, added backwards compatible migrations
- Loading branch information
1 parent
81c2db2
commit 44ca738
Showing
33 changed files
with
392 additions
and
301 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package database | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"embed" | ||
"fmt" | ||
"path" | ||
|
||
"github.com/blang/semver" | ||
) | ||
|
||
//go:embed migrations/* | ||
var migrationFiles embed.FS | ||
|
||
type migration struct { | ||
fromVersion semver.Version | ||
toVersion semver.Version | ||
migrationFunc func(db *sql.DB) error | ||
} | ||
|
||
// txFunc is a function that runs in a transaction. | ||
type txFn func(tx *sql.Tx) error | ||
|
||
// runInTransaction runs the given function in a transaction. | ||
func runInTransaction(db *sql.DB, fn txFn) error { | ||
tx, err := db.Begin() | ||
if err != nil { | ||
return fmt.Errorf("failed to start transaction: %w", err) | ||
} | ||
defer tx.Rollback() | ||
|
||
if err := fn(tx); err != nil { | ||
return fmt.Errorf("failed to run transaction: %w", err) | ||
} | ||
|
||
if err := tx.Commit(); err != nil { | ||
return fmt.Errorf("failed to commit transaction: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// newFuncMigration creates a new migration from a function. | ||
func newFuncMigration(fromVersion, toVersion string, migrationFunc func(db *sql.DB) error) migration { | ||
return migration{ | ||
fromVersion: semver.MustParse(fromVersion), | ||
toVersion: semver.MustParse(toVersion), | ||
migrationFunc: migrationFunc, | ||
} | ||
} | ||
|
||
// newFileMigration creates a new migration from a file. | ||
func newFileMigration(fromVersion, toVersion, filename string) migration { | ||
return newFuncMigration(fromVersion, toVersion, func(db *sql.DB) error { | ||
return runInTransaction(db, func(tx *sql.Tx) error { | ||
migrationSQL, err := migrationFiles.ReadFile(path.Join("migrations", filename+".up.sql")) | ||
if err != nil { | ||
return fmt.Errorf("failed to read migration file: %w", err) | ||
} | ||
|
||
if _, err := tx.Exec(string(migrationSQL)); err != nil { | ||
return fmt.Errorf("failed to execute migration %s to %s: %w", fromVersion, toVersion, err) | ||
} | ||
return nil | ||
}) | ||
}) | ||
} | ||
|
||
// runMigrations runs the given migrations. | ||
func runMigrations(ctx context.Context, db DB, migrations []migration) error { | ||
currentVersion := semver.Version{} | ||
|
||
// Get current database version | ||
dbVersion, err := db.GetDatabaseSchemaVersion(ctx) | ||
if err == nil && dbVersion != "" { | ||
currentVersion = semver.MustParse(dbVersion) | ||
} | ||
|
||
for _, migration := range migrations { | ||
if !currentVersion.EQ(migration.fromVersion) { | ||
continue | ||
} | ||
|
||
if err := migration.migrationFunc(db.DBx().DB); err != nil { | ||
return fmt.Errorf("failed to run migration from %s to %s: %w", migration.fromVersion, migration.toVersion, err) | ||
} | ||
|
||
currentVersion = migration.toVersion | ||
|
||
if err := db.SetDatabaseSchemaVersion(ctx, currentVersion.String()); err != nil { | ||
return fmt.Errorf("failed to store database version %s from %s to %s: %w", currentVersion.String(), migration.fromVersion, migration.toVersion, err) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
CREATE TABLE IF NOT EXISTS shiori_system( | ||
database_schema_version VARCHAR(12) NOT NULL DEFAULT '0.0.0' | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
INSERT INTO shiori_system(database_schema_version) VALUES('0.0.0'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
15 changes: 15 additions & 0 deletions
15
internal/database/migrations/mysql/0002_initial_bookmark.up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
CREATE TABLE IF NOT EXISTS bookmark( | ||
id INT(11) NOT NULL AUTO_INCREMENT, | ||
url TEXT NOT NULL, | ||
title TEXT NOT NULL, | ||
excerpt TEXT NOT NULL DEFAULT (''), | ||
author TEXT NOT NULL DEFAULT (''), | ||
public BOOLEAN NOT NULL DEFAULT 0, | ||
content MEDIUMTEXT NOT NULL DEFAULT (''), | ||
html MEDIUMTEXT NOT NULL DEFAULT (''), | ||
modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
has_content BOOLEAN NOT NULL DEFAULT 0, | ||
PRIMARY KEY(id), | ||
UNIQUE KEY bookmark_url_UNIQUE (url(255)), | ||
FULLTEXT (title, excerpt, content)) | ||
CHARACTER SET utf8mb4; |
File renamed without changes.
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
CREATE TABLE IF NOT EXISTS shiori_system( | ||
database_schema_version TEXT NOT NULL DEFAULT '0.0.0' | ||
); | ||
|
||
INSERT INTO shiori_system(database_schema_version) VALUES('0.0.0'); |
24 changes: 13 additions & 11 deletions
24
internal/database/migrations/postgres/0001_initial.up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
CREATE TABLE IF NOT EXISTS shiori_system( | ||
database_schema_version TEXT NOT NULL DEFAULT '0.0.0' | ||
); | ||
|
||
INSERT INTO shiori_system(database_schema_version) VALUES('0.0.0'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 0 additions & 1 deletion
1
internal/database/migrations/sqlite/0002_denormalize_content.down.sql
This file was deleted.
Oops, something went wrong.
3 changes: 0 additions & 3 deletions
3
internal/database/migrations/sqlite/0002_denormalize_content.up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,3 @@ | ||
ALTER TABLE bookmark | ||
ADD has_content BOOLEAN DEFAULT FALSE NOT NULL; | ||
|
||
UPDATE bookmark | ||
SET has_content = bc.has_content FROM (SELECT docid, content <> '' AS has_content FROM bookmark_content) AS bc | ||
WHERE bookmark.id = bc.docid; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.