diff --git a/engine/engine.go b/engine/engine.go index ec3e12a..b5b06f3 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -1,17 +1,9 @@ package engine import ( - "context" "database/sql" "fmt" - "github.com/lib/pq" - - _ "github.com/denisenkom/go-mssqldb" - _ "github.com/go-sql-driver/mysql" - "github.com/mattn/go-sqlite3" - _ "github.com/mattn/go-sqlite3" - _ "git.fsdpf.net/go/db/dialect/mysql" _ "git.fsdpf.net/go/db/dialect/postgres" _ "git.fsdpf.net/go/db/dialect/sqlite3" @@ -58,32 +50,8 @@ func (e Engine) MakeConnection(cfg DBConfig) (db *sql.DB) { switch cfg.Driver { case "mysql": case "sqlite3": - defer func() { - if r := recover(); r != nil { - panic(r) - } - if cfg.SQLite.Raw == nil { - return - } - conn, err := db.Conn(context.Background()) - if err != nil { - panic(err) - } - err = conn.Raw(func(driverConn any) error { - sqliteConn := driverConn.(*sqlite3.SQLiteConn) - return cfg.SQLite.Raw(sqliteConn) - }) - if err != nil { - panic(err) - } - }() case "sqlserver": case "postgres": - if url, err := pq.ParseURL(dsn); err == nil { - dsn = url - } else { - panic(err) - } default: panic(fmt.Sprintf("Unsupported driver: %s", cfg.Driver)) } diff --git a/engine/engine_config.go b/engine/engine_config.go index 966af3c..1d6a607 100644 --- a/engine/engine_config.go +++ b/engine/engine_config.go @@ -5,8 +5,6 @@ import ( "fmt" "net/url" "time" - - "github.com/mattn/go-sqlite3" ) type MockDBConfig struct { @@ -56,7 +54,6 @@ type DBConfig struct { Synchronous int Cache string BusyTimeout int - Raw func(*sqlite3.SQLiteConn) error } SQLServer struct { @@ -142,33 +139,77 @@ func (c *DBConfig) toMySQLDSN() string { // toPostgreSQLDSN 生成 PostgreSQL DSN func (c *DBConfig) toPostgreSQLDSN() string { - params := url.Values{} - if c.Host != "" { - params.Add("host", c.Host) - } else if len(c.WriteHosts) > 0 { - params.Add("host", c.WriteHosts[0]) - } else if len(c.ReadHosts) > 0 { - params.Add("host", c.ReadHosts[0]) + // 构建连接字符串参数列表 + var params []string + + // 确定主机地址 + host := c.Host + if host == "" && len(c.WriteHosts) > 0 { + host = c.WriteHosts[0] } - if c.Port == "" { - c.Port = "5432" // 默认 PostgreSQL 端口 + if host == "" && len(c.ReadHosts) > 0 { + host = c.ReadHosts[0] } - params.Add("port", c.Port) - params.Add("dbname", c.Database) - params.Add("user", c.Username) + if host != "" { + params = append(params, fmt.Sprintf("host=%s", host)) + } + + // 设置端口 + port := c.Port + if port == "" { + port = "5432" // 默认 PostgreSQL 端口 + } + params = append(params, fmt.Sprintf("port=%s", port)) + + // 添加用户名 + if c.Username != "" { + params = append(params, fmt.Sprintf("user=%s", c.Username)) + } + + // 添加密码 if c.Password != "" { - params.Add("password", c.Password) + params = append(params, fmt.Sprintf("password=%s", c.Password)) } + + // 添加数据库名 + if c.Database != "" { + params = append(params, fmt.Sprintf("dbname=%s", c.Database)) + } + + // 添加 SSL 模式 if c.PostgreSQL.Sslmode != "" { - params.Add("sslmode", c.PostgreSQL.Sslmode) + params = append(params, fmt.Sprintf("sslmode=%s", c.PostgreSQL.Sslmode)) } + + // 添加连接超时 if c.PostgreSQL.ConnectTimeout > 0 { - params.Add("connect_timeout", fmt.Sprintf("%d", c.PostgreSQL.ConnectTimeout)) + params = append(params, fmt.Sprintf("connect_timeout=%d", c.PostgreSQL.ConnectTimeout)) } + + // 添加应用名称 if c.PostgreSQL.ApplicationName != "" { - params.Add("application_name", c.PostgreSQL.ApplicationName) + params = append(params, fmt.Sprintf("application_name=%s", c.PostgreSQL.ApplicationName)) } - return "postgres://" + c.Username + ":" + url.QueryEscape(c.Password) + "@" + params.Get("host") + ":" + c.Port + "/" + c.Database + "?" + params.Encode() + + // 添加搜索路径 + if c.PostgreSQL.SearchPath != "" { + params = append(params, fmt.Sprintf("search_path=%s", c.PostgreSQL.SearchPath)) + } + + // 用空格连接所有参数 + return joinParams(params, " ") +} + +// joinParams 连接参数列表 +func joinParams(params []string, sep string) string { + if len(params) == 0 { + return "" + } + result := params[0] + for i := 1; i < len(params); i++ { + result += sep + params[i] + } + return result } // toSQLiteDSN 生成 SQLite DSN @@ -388,16 +429,6 @@ func WithSQLiteFile(file string) Option { } } -// SQLite 注册函数 -func WithSQLiteRaw(raw func(*sqlite3.SQLiteConn) error) Option { - return func(c *DBConfig) { - if c.Driver != "sqlite3" { - panic("WithSQLiteRegFn is only valid for sqlite3 driver") - } - c.SQLite.Raw = raw - } -} - func WithSQLiteJournal(journal string) Option { return func(c *DBConfig) { if c.Driver != "sqlite3" { diff --git a/engine/engine_config_test.go b/engine/engine_config_test.go index b9f13ad..bec6b0b 100644 --- a/engine/engine_config_test.go +++ b/engine/engine_config_test.go @@ -5,6 +5,9 @@ import ( "time" "git.fsdpf.net/go/db/engine" + _ "github.com/denisenkom/go-mssqldb" + _ "github.com/go-sql-driver/mysql" + _ "github.com/mattn/go-sqlite3" ) // TestMySQLConfig 测试 MySQL 驱动的配置 @@ -333,7 +336,7 @@ func TestToDSN(t *testing.T) { engine.WithPassword("password"), engine.WithPgSslmode("disable"), ), - wantDSN: "postgres://postgres:password@localhost:5432/testdb?host=localhost&port=5432&dbname=testdb&user=postgres&password=password&sslmode=disable", + wantDSN: "host=localhost port=5432 user=postgres password=password dbname=testdb sslmode=disable", wantErr: false, }, { diff --git a/go.mod b/go.mod index abdef50..d6f4dd0 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,6 @@ require ( github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/crypto v0.11.0 // indirect golang.org/x/text v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 65f6afd..c1b87f4 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=