Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions internal/database/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"gorm.io/gorm/clause"
)

var errUnsupportedAnalysisDialect = errors.New("unsupported database dialect for analysis merge")
var errUnsupportedDialect = errors.New("unsupported database dialect for analysis merge")

// MergeAnalysis atomically replaces the namespaces in patch while preserving
// every namespace that is already stored but absent from patch. It writes
Expand All @@ -26,7 +26,12 @@ func MergeAnalysis(
patch = common.AnalysisData{}
}

expression, err := analysisMergeExpression(gormdb.Name(), patch)
dialect, err := DialectOf(gormdb)
if err != nil {
return nil, err
}

expression, err := analysisMergeExpression(dialect, patch)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -57,7 +62,7 @@ func MergeAnalysis(
return merged, nil
}

func analysisMergeExpression(dialect string, patch common.AnalysisData) (clause.Expr, error) {
func analysisMergeExpression(dialect Dialect, patch common.AnalysisData) (clause.Expr, error) {
patchJSON, err := json.Marshal(patch)
if err != nil {
return clause.Expr{}, fmt.Errorf("marshal analysis patch: %w", err)
Expand Down Expand Up @@ -94,6 +99,6 @@ func analysisMergeExpression(dialect string, patch common.AnalysisData) (clause.
string(patchJSON),
), nil
default:
return clause.Expr{}, fmt.Errorf("%w: %s", errUnsupportedAnalysisDialect, dialect)
return clause.Expr{}, fmt.Errorf("%w: %q", errUnsupportedDialect, dialect)
}
}
2 changes: 1 addition & 1 deletion internal/database/analysis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func openAnalysisTestDatabase(t *testing.T) *gorm.DB {
if dsn != "" {
var err error

dialect, err = Dialect(dsn)
dialect, err = DialectFromDSN(dsn)
require.NoError(t, err)
}

Expand Down
33 changes: 26 additions & 7 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,23 @@ import (
"gorm.io/gorm/schema"
)

type Dialect string

const (
SQLite = "sqlite"
Postgres = "postgres"
SQLite Dialect = "sqlite"
Postgres Dialect = "postgres"
)

var ErrUnknownDialect = errors.New(
`unrecognized database DSN: expected a "file:" SQLite DSN, a "postgres://" URL or a key=value connection string`,
)

// Dialect reports which database a DSN points at. Everything that opens
// a connection goes through here, so the application and the test
var errUnknownGormDialect = errors.New("unrecognized gorm driver name")

// DialectFromDSN reports which database a DSN points at. Everything that
// opens a connection goes through here, so the application and the test
// harness can't disagree and end up talking to two different databases.
func Dialect(connection string) (string, error) {
func DialectFromDSN(connection string) (Dialect, error) {
switch {
case strings.HasPrefix(connection, "file:"):
return SQLite, nil
Expand All @@ -39,8 +43,23 @@ func Dialect(connection string) (string, error) {
return "", fmt.Errorf("%w: %q", ErrUnknownDialect, connection)
}

// DialectOf reports the Dialect an already open *gorm.DB is talking to, read
// from the driver name gorm reports for it. It is the one place that maps a
// gorm driver name back to a Dialect, so a request handler and NewDatabase
// read the same fact instead of each guessing from the connection.
func DialectOf(gormdb *gorm.DB) (Dialect, error) {
switch name := gormdb.Name(); name {
case string(SQLite):
return SQLite, nil
case string(Postgres):
return Postgres, nil
default:
return "", fmt.Errorf("%w: %q", errUnknownGormDialect, name)
}
}

func NewDatabase(connection string) (*gorm.DB, error) {
dialect, err := Dialect(connection)
dialect, err := DialectFromDSN(connection)
if err != nil {
return nil, err
}
Expand All @@ -52,7 +71,7 @@ func NewDatabase(connection string) (*gorm.DB, error) {
log.Println("using SQLite database")

database, err = gorm.Open(sqlite.Open(connection), &gorm.Config{})
default:
case Postgres:
log.Println("using Postgres database")

database, err = gorm.Open(postgres.Open(connection), &gorm.Config{
Expand Down
2 changes: 1 addition & 1 deletion internal/database/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func testConnection(t *testing.T) string {
return sqliteTestConnection(t)
}

dialect, err := Dialect(connection)
dialect, err := DialectFromDSN(connection)
require.NoError(t, err)

if dialect == SQLite {
Expand Down
4 changes: 2 additions & 2 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ func init() {

dsn := os.Getenv("DATABASE_DSN")

dialect, err := database.Dialect(dsn)
dialect, err := database.DialectFromDSN(dsn)
if err != nil {
log.Fatal(err)
}

// database/sql registers the SQLite driver under a name of its own.
dbDriver = dialect
dbDriver = string(dialect)
if dialect == database.SQLite {
dbDriver = "sqlite3"
}
Expand Down
Loading