diff --git a/.golangci.yml b/.golangci.yml index 8624d769..a1a4aea2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -20,12 +20,12 @@ linters-settings: linters: disable-all: true enable: + - copyloopvar - gofmt - gosimple # - govet # Re-enable when all shadow declarations are fixed - ineffassign - predeclared - - exportloopref - staticcheck - unconvert - unused diff --git a/internal/database/database_test.go b/internal/database/database_test.go index e0503473..9be18841 100644 --- a/internal/database/database_test.go +++ b/internal/database/database_test.go @@ -45,7 +45,7 @@ func testDatabase(t *testing.T, dbFactory testDatabaseFactory) { t.Run(testName, func(tInner *testing.T) { ctx := context.TODO() db, err := dbFactory(t, ctx) - assert.NoError(tInner, err, "Error recreating database") + require.NoError(tInner, err, "Error recreating database") testCase(tInner, db) }) } diff --git a/internal/database/migrations.go b/internal/database/migrations.go index dc420849..59ca443c 100644 --- a/internal/database/migrations.go +++ b/internal/database/migrations.go @@ -1,3 +1,4 @@ +// Package database implements database operations and migrations package database import ( @@ -13,13 +14,14 @@ import ( //go:embed migrations/* var migrationFiles embed.FS +// migration represents a database schema migration type migration struct { fromVersion semver.Version toVersion semver.Version migrationFunc func(db *sql.DB) error } -// txFunc is a function that runs in a transaction. +// txFn is a function that runs in a transaction. type txFn func(tx *sql.Tx) error // runInTransaction runs the given function in a transaction. diff --git a/internal/database/pg.go b/internal/database/pg.go index 66df2dd8..a4403ff8 100644 --- a/internal/database/pg.go +++ b/internal/database/pg.go @@ -12,7 +12,7 @@ import ( "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" - _ "github.com/lib/pq" + "github.com/lib/pq" ) var postgresMigrations = []migration{ @@ -25,16 +25,21 @@ var postgresMigrations = []migration{ if err != nil { return fmt.Errorf("failed to start transaction: %w", err) } - defer tx.Rollback() _, err = tx.Exec(`ALTER TABLE bookmark ADD COLUMN has_content BOOLEAN DEFAULT FALSE NOT NULL`) - if err != nil && strings.Contains(err.Error(), `column "has_content" of relation "bookmark" already exists`) { - tx.Rollback() - } else if err != nil { - return fmt.Errorf("failed to add has_content column to bookmark table: %w", err) - } else if err == nil { - if errCommit := tx.Commit(); errCommit != nil { - return fmt.Errorf("failed to commit transaction: %w", errCommit) + if err != nil { + // Check if this is a "column already exists" error (PostgreSQL error code 42701) + // If it's not, return error. + // This is needed for users upgrading from >1.5.4 directly into this version. + pqErr, ok := err.(*pq.Error) + if ok && pqErr.Code == "42701" { + tx.Rollback() + } else { + return fmt.Errorf("failed to add has_content column to bookmark table: %w", err) + } + } else { + if err := tx.Commit(); err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) } } @@ -42,16 +47,21 @@ var postgresMigrations = []migration{ if err != nil { return fmt.Errorf("failed to start transaction: %w", err) } - defer tx.Rollback() _, err = tx.Exec(`ALTER TABLE account ADD COLUMN config JSONB NOT NULL DEFAULT '{}'`) - if err != nil && strings.Contains(err.Error(), `column "config" of relation "account" already exists`) { - tx.Rollback() - } else if err != nil { - return fmt.Errorf("failed to add config column to account table: %w", err) - } else if err == nil { - if errCommit := tx.Commit(); errCommit != nil { - return fmt.Errorf("failed to commit transaction: %w", errCommit) + if err != nil { + // Check if this is a "column already exists" error (PostgreSQL error code 42701) + // If it's not, return error + // This is needed for users upgrading from >1.5.4 directly into this version. + pqErr, ok := err.(*pq.Error) + if ok && pqErr.Code == "42701" { + tx.Rollback() + } else { + return fmt.Errorf("failed to add config column to account table: %w", err) + } + } else { + if err := tx.Commit(); err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) } }