package sqlite import ( "fmt" "net/url" "path/filepath" "runtime" "strings" ) const connectionScheme = `file` // ConnectionURL implements a SQLite connection struct. type ConnectionURL struct { Database string Options map[string]string } func (c ConnectionURL) String() (s string) { vv := url.Values{} if c.Database == "" { return "" } // Did the user provided a full database path? if !strings.HasPrefix(c.Database, "/") { c.Database, _ = filepath.Abs(c.Database) if runtime.GOOS == "windows" { // Closes https://github.com/upper/db/issues/60 c.Database = "/" + strings.Replace(c.Database, `\`, `/`, -1) } } // Do we have any options? if c.Options == nil { c.Options = map[string]string{} } if _, ok := c.Options["_busy_timeout"]; !ok { c.Options["_busy_timeout"] = "10000" } // Converting options into URL values. for k, v := range c.Options { vv.Set(k, v) } // Building URL. u := url.URL{ Scheme: connectionScheme, Path: c.Database, RawQuery: vv.Encode(), } return u.String() } // ParseURL parses s into a ConnectionURL struct. func ParseURL(s string) (conn ConnectionURL, err error) { var u *url.URL if !strings.HasPrefix(s, connectionScheme+"://") { return conn, fmt.Errorf(`Expecting file:// connection scheme.`) } if u, err = url.Parse(s); err != nil { return conn, err } conn.Database = u.Host + u.Path conn.Options = map[string]string{} var vv url.Values if vv, err = url.ParseQuery(u.RawQuery); err != nil { return conn, err } for k := range vv { conn.Options[k] = vv.Get(k) } if _, ok := conn.Options["cache"]; !ok { conn.Options["cache"] = "shared" } return conn, err }