Skip to content

Commit 63f07d0

Browse files
committed
db: forge sqlite URLs rejected by url.Parse
Go 1.26.0's net/url regressed and rejects the ":memory:" authority of "sqlite://:memory:" as an invalid port. GitHub's setup-go installs the exact version from the go directive, so CI runs on 1.26.0 and fails to open the in-memory test database even though later 1.26.x releases parse it fine. Keep url.Parse as the normal path and, when it fails on a sqlite or sqlite3 DSN, rebuild the URL by hand the way a lenient parser would. This works on every Go version without pinning the toolchain. Signed-off-by: Robin Jarry <robin@jarry.cc>
1 parent ff090e8 commit 63f07d0

1 file changed

Lines changed: 30 additions & 1 deletion

File tree

‎pkg/db/db.go‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ func Open(cfg *config.Config) (*bun.DB, error) {
4343

4444
u, err := url.Parse(cfg.Database.URL)
4545
if err != nil {
46-
return nil, err
46+
// Go 1.26.0's url.Parse rejects the ":memory:" authority of
47+
// "sqlite://:memory:" as an invalid port. Forge the URL by
48+
// hand for sqlite DSNs so it works regardless of the Go
49+
// version.
50+
u, err = parseSqliteURL(cfg.Database.URL, err)
51+
if err != nil {
52+
return nil, err
53+
}
4754
}
4855

4956
switch u.Scheme {
@@ -122,6 +129,28 @@ func Open(cfg *config.Config) (*bun.DB, error) {
122129
return bun.NewDB(conn, dialect), nil
123130
}
124131

132+
// parseSqliteURL rebuilds a URL for sqlite DSNs that url.Parse rejects,
133+
// mirroring how a lenient url.Parse fills the fields. It only handles the
134+
// sqlite and sqlite3 schemes; other URLs keep the original parse error.
135+
func parseSqliteURL(rawURL string, parseErr error) (*url.URL, error) {
136+
scheme, rest, ok := strings.Cut(rawURL, "://")
137+
if !ok || (scheme != "sqlite" && scheme != "sqlite3") {
138+
return nil, parseErr
139+
}
140+
u := &url.URL{Scheme: scheme}
141+
if path, query, ok := strings.Cut(rest, "?"); ok {
142+
rest = path
143+
u.RawQuery = query
144+
}
145+
// url.Parse puts a relative path in Host and an absolute one in Path.
146+
if strings.HasPrefix(rest, "/") {
147+
u.Path = rest
148+
} else {
149+
u.Host = rest
150+
}
151+
return u, nil
152+
}
153+
125154
// restrictDBFile ensures the sqlite database file exists with
126155
// owner-only (0600) permissions before the driver opens it. Existing
127156
// files created with a laxer umask are tightened as well. The companion

0 commit comments

Comments
 (0)