fix(contrib/drivers/pgsql): add unix socket connection support (#4028)

This commit is contained in:
John Guo
2024-12-11 09:58:26 +08:00
committed by GitHub
parent 69969b1723
commit b7c74c9a35
15 changed files with 226 additions and 230 deletions

View File

@ -638,8 +638,8 @@ const (
ctxKeyCatchSQL gctx.StrKey = `CtxKeyCatchSQL`
ctxKeyInternalProducedSQL gctx.StrKey = `CtxKeyInternalProducedSQL`
// type:[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]
linkPattern = `(\w+):([\w\-\$]*):(.*?)@(\w+?)\((.+?)\)/{0,1}([^\?]*)\?{0,1}(.*)`
linkPattern = `(\w+):([\w\-\$]*):(.*?)@(\w+?)\((.+?)\)/{0,1}([^\?]*)\?{0,1}(.*)`
linkPatternDescription = `type:username:password@protocol(host:port)/dbname?param1=value1&...&paramN=valueN`
)
type ctxTimeoutType int
@ -843,7 +843,10 @@ func NewByGroup(group ...string) (db DB, err error) {
// So all db type configurations in the same group should be the same.
func newDBByConfigNode(node *ConfigNode, group string) (db DB, err error) {
if node.Link != "" {
node = parseConfigNodeLink(node)
node, err = parseConfigNodeLink(node)
if err != nil {
return
}
}
c := &Core{
group: group,

View File

@ -10,6 +10,8 @@ import (
"sync"
"time"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/text/gregex"
@ -73,42 +75,64 @@ func init() {
// SetConfig sets the global configuration for package.
// It will overwrite the old configuration of package.
func SetConfig(config Config) {
func SetConfig(config Config) error {
defer instances.Clear()
configs.Lock()
defer configs.Unlock()
for k, nodes := range config {
for i, node := range nodes {
nodes[i] = parseConfigNode(node)
parsedNode, err := parseConfigNode(node)
if err != nil {
return err
}
nodes[i] = parsedNode
}
config[k] = nodes
}
configs.config = config
return nil
}
// SetConfigGroup sets the configuration for given group.
func SetConfigGroup(group string, nodes ConfigGroup) {
func SetConfigGroup(group string, nodes ConfigGroup) error {
defer instances.Clear()
configs.Lock()
defer configs.Unlock()
for i, node := range nodes {
nodes[i] = parseConfigNode(node)
parsedNode, err := parseConfigNode(node)
if err != nil {
return err
}
nodes[i] = parsedNode
}
configs.config[group] = nodes
return nil
}
// AddConfigNode adds one node configuration to configuration of given group.
func AddConfigNode(group string, node ConfigNode) {
func AddConfigNode(group string, node ConfigNode) error {
defer instances.Clear()
configs.Lock()
defer configs.Unlock()
configs.config[group] = append(configs.config[group], parseConfigNode(node))
parsedNode, err := parseConfigNode(node)
if err != nil {
return err
}
configs.config[group] = append(configs.config[group], parsedNode)
return nil
}
// parseConfigNode parses `Link` configuration syntax.
func parseConfigNode(node ConfigNode) ConfigNode {
func parseConfigNode(node ConfigNode) (ConfigNode, error) {
if node.Link != "" {
node = *parseConfigNodeLink(&node)
parsedLinkNode, err := parseConfigNodeLink(&node)
if err != nil {
return node, err
}
node = *parsedLinkNode
}
if node.Link != "" && node.Type == "" {
match, _ := gregex.MatchString(`([a-z]+):(.+)`, node.Link)
@ -117,17 +141,17 @@ func parseConfigNode(node ConfigNode) ConfigNode {
node.Link = gstr.Trim(match[2])
}
}
return node
return node, nil
}
// AddDefaultConfigNode adds one node configuration to configuration of default group.
func AddDefaultConfigNode(node ConfigNode) {
AddConfigNode(DefaultGroupName, node)
func AddDefaultConfigNode(node ConfigNode) error {
return AddConfigNode(DefaultGroupName, node)
}
// AddDefaultConfigGroup adds multiple node configurations to configuration of default group.
func AddDefaultConfigGroup(nodes ConfigGroup) {
SetConfigGroup(DefaultGroupName, nodes)
func AddDefaultConfigGroup(nodes ConfigGroup) error {
return SetConfigGroup(DefaultGroupName, nodes)
}
// GetConfig retrieves and returns the configuration of given group.
@ -266,34 +290,39 @@ func (c *Core) GetSchema() string {
return schema
}
func parseConfigNodeLink(node *ConfigNode) *ConfigNode {
func parseConfigNodeLink(node *ConfigNode) (*ConfigNode, error) {
var match []string
if node.Link != "" {
match, _ = gregex.MatchString(linkPattern, node.Link)
if len(match) > 5 {
node.Type = match[1]
node.User = match[2]
node.Pass = match[3]
node.Protocol = match[4]
array := gstr.Split(match[5], ":")
if node.Protocol == "file" {
node.Name = match[5]
} else {
if len(array) == 2 {
// link with port.
node.Host = array[0]
node.Port = array[1]
} else {
// link without port.
node.Host = array[0]
}
node.Name = match[6]
}
if len(match) > 6 && match[7] != "" {
node.Extra = match[7]
}
node.Link = ""
if len(match) <= 5 {
return nil, gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid link configuration: %s, shuold be pattern like: %s`,
node.Link, linkPatternDescription,
)
}
node.Type = match[1]
node.User = match[2]
node.Pass = match[3]
node.Protocol = match[4]
array := gstr.Split(match[5], ":")
if node.Protocol == "file" {
node.Name = match[5]
} else {
if len(array) == 2 {
// link with port.
node.Host = array[0]
node.Port = array[1]
} else {
// link without port.
node.Host = array[0]
}
node.Name = match[6]
}
if len(match) > 6 && match[7] != "" {
node.Extra = match[7]
}
node.Link = ""
}
if node.Extra != "" {
if m, _ := gstr.Parse(node.Extra); len(m) > 0 {
@ -307,5 +336,5 @@ func parseConfigNodeLink(node *ConfigNode) *ConfigNode {
if node.Protocol == "" {
node.Protocol = defaultProtocol
}
return node
return node, nil
}

View File

@ -53,7 +53,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)/khaos_oss?loc=Local&parseTime=true&charset=latin`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -68,7 +69,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)/khaos_oss?`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -83,7 +85,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)/khaos_oss`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -99,7 +102,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)/?loc=Local&parseTime=true&charset=latin`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -114,7 +118,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)?loc=Local&parseTime=true&charset=latin`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -129,7 +134,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)/`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -144,7 +150,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@tcp(9.135.69.119:3306)`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -160,7 +167,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `mysql:root:CxzhD*624:27jh@udp(9.135.69.119:3306)`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -175,7 +183,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `sqlite:root:CxzhD*624:27jh@file(/var/data/db.sqlite3)?local=Local&parseTime=true`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `sqlite`)
t.Assert(newNode.User, `root`)
t.Assert(newNode.Pass, `CxzhD*624:27jh`)
@ -190,7 +199,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `sqlite::CxzhD*624:2@7jh@file(/var/data/db.sqlite3)`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `sqlite`)
t.Assert(newNode.User, ``)
t.Assert(newNode.Pass, `CxzhD*624:2@7jh`)
@ -205,7 +215,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `sqlite::@file(/var/data/db.sqlite3)`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `sqlite`)
t.Assert(newNode.User, ``)
t.Assert(newNode.Pass, ``)
@ -221,7 +232,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: `pgsql:BASIC$xxxx:123456@tcp(xxxx.hologres.aliyuncs.com:80)/xxx`,
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `pgsql`)
t.Assert(newNode.User, `BASIC$xxxx`)
t.Assert(newNode.Pass, `123456`)
@ -237,7 +249,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: "mysql:user:pwd@tcp(rdsid.mysql.rds.aliyuncs.com)/dbname?charset=utf8&loc=Local",
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `user`)
t.Assert(newNode.Pass, `pwd`)
@ -253,7 +266,8 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) {
node := &ConfigNode{
Link: "mysql:username:password@unix(/tmp/mysql.sock)/dbname",
}
newNode := parseConfigNodeLink(node)
newNode, err := parseConfigNodeLink(node)
t.AssertNil(err)
t.Assert(newNode.Type, `mysql`)
t.Assert(newNode.User, `username`)
t.Assert(newNode.Pass, `password`)