chore: improve DSN handling for SQLite (#26011)

This commit is contained in:
Blaž Dular 2025-12-14 11:35:54 +01:00 • committed by GitHub
parent 117963dcb5
commit 893d610891
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 94 additions and 6 deletions

View file

@ -22,21 +22,44 @@ func New(driver, dsn string) (*gorm.DB, error) {
switch driver {
case "sqlite":
file, err := homedir.Expand(dsn)
// Example DSNs:
//"path/to/database.db"
// "~/database.db",
// "database.db?cache=shared&journal_mode=WAL"
// ":memory:"
// Split database path and connection parameters
dbPath, connectionParams, _ := strings.Cut(dsn, "?")
file, err := homedir.Expand(dbPath)
if err != nil {
return nil, err
}
if err := os.MkdirAll(filepath.Dir(file), 0700); err != nil {
return nil, err
}
// Store the expanded file path for later use
FilePath = file
if err := os.MkdirAll(filepath.Dir(file), 0700); err != nil {
return nil, err
// Add busy_timeout pragma if not already present
if !strings.Contains(connectionParams, "_pragma=busy_timeout") {
// Append '&' if there are existing connection parameters
if len(connectionParams) > 0 {
connectionParams += "&"
}
// Add busy_timeout pragma to connection parameters
connectionParams += "_pragma=busy_timeout(5000)"
}
util.NewLogger("main").INFO.Println("using sqlite database:", file)
connectionStr := file + "?" + connectionParams
// avoid busy errors
dialect = sqlite.Open(file + "?_pragma=busy_timeout(5000)")
util.NewLogger("main").INFO.Println("using sqlite database:", connectionStr)
dialect = sqlite.Open(connectionStr)
// case "postgres":
// dialect = postgres.Open(dsn)
// case "mysql":

65
server/db/db_test.go Normal file
View file

@ -0,0 +1,65 @@
package db
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestUnitNewDriver(t *testing.T) {
tmpDir := t.TempDir()
tests := []struct {
name string
driver string
dsn string
expectedFilePath string
wantErr bool
}{
{
name: "SQLite In-Memory",
driver: "sqlite",
dsn: ":memory:",
expectedFilePath: ":memory:",
wantErr: false,
},
{
name: "SQLite File",
driver: "sqlite",
dsn: tmpDir + "/evcc.db",
expectedFilePath: tmpDir + "/evcc.db",
wantErr: false,
},
{
name: "SQLite with connection parameters",
driver: "sqlite",
dsn: tmpDir + "evcc.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)",
wantErr: false,
expectedFilePath: tmpDir + "evcc.db",
},
{
name: "Unsupported Driver",
driver: "postgresql",
dsn: "/var/lib/evcc/evcc.db",
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// Reset file path
FilePath = ""
driver, err := New(test.driver, test.dsn)
if test.wantErr {
assert.Error(t, err)
assert.Nil(t, driver)
} else {
assert.NoError(t, err)
assert.NotNil(t, driver)
}
assert.Equal(t, test.expectedFilePath, FilePath)
})
}
}