mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
fix(contrib/drivers/pgsql): add unix socket connection support (#4028)
This commit is contained in:
@ -638,8 +638,8 @@ const (
|
||||
ctxKeyCatchSQL gctx.StrKey = `CtxKeyCatchSQL`
|
||||
ctxKeyInternalProducedSQL gctx.StrKey = `CtxKeyInternalProducedSQL`
|
||||
|
||||
// type:[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=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&...¶mN=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,
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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`)
|
||||
|
||||
Reference in New Issue
Block a user