Escape state_dir in the db_url derived from it (closes #290)

The derived db_url put state_dir into a file: URL as it was, so SQLite
decoded a %HH in the name and ended the path at a ? or #, and the
journal mode parameter was lost. It is now built with net/url, which
percent-encodes the directory name; SQLite decodes it back and opens
state.sqlite3 in that directory. OmitHost keeps the usual form
file:/var/lib/pixa/state.sqlite3 and a relative state_dir a path.

Model: opus-5-5
This commit is contained in:
2026-10-16 02:27:58 +00:00
parent a997ede32b
commit d104d5d936
3 changed files with 32 additions and 7 deletions
+19 -2
View File
@@ -338,8 +338,7 @@ func newFromSmartConfig(sc *smartconfig.Config) (*Config, error) {
settingName(keyDBURL), errValueEmpty)
}
// The driver sets the journal mode only through a _pragma parameter.
c.DBURL = fmt.Sprintf("file:%s/state.sqlite3?_pragma=journal_mode(WAL)", c.StateDir)
c.DBURL = defaultDBURL(c.StateDir)
}
if loader.err != nil {
@@ -354,6 +353,24 @@ func newFromSmartConfig(sc *smartconfig.Config) (*Config, error) {
return c, nil
}
// defaultDBURL returns the db_url used when db_url is omitted: the file
// state.sqlite3 in stateDir, in WAL mode, which the driver sets only
// through a _pragma parameter. String() percent-encodes any %, ? or # in
// the directory name, which SQLite decodes back, so the URL names exactly
// this file. OmitHost writes file:/var/lib/pixa/... instead of
// file:///var/lib/pixa/..., and keeps a relative stateDir from being read
// as a host name.
func defaultDBURL(stateDir string) string {
dbURL := url.URL{
Scheme: "file",
OmitHost: true,
Path: stateDir + "/state.sqlite3",
RawQuery: "_pragma=journal_mode(WAL)",
}
return dbURL.String()
}
// validateKnownKeys rejects configuration files containing keys the
// application does not understand, so typos fail at startup instead of
// being silently ignored, and rejects keys that are explicitly set to