-
Notifications
You must be signed in to change notification settings - Fork 2
/
dsn.go
102 lines (86 loc) · 2.71 KB
/
dsn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package fireboltgosdk
import (
"errors"
"fmt"
"regexp"
"strings"
)
type fireboltSettings struct {
clientID string
clientSecret string
database string
engineName string
accountName string
newVersion bool
}
const dsnPattern = `^firebolt://(?:/(?P<database>\w+))?(?:\?(?P<parameters>\w+\=[^=&]+(?:\&\w+=[^=&]+)*))?$`
const dsnPatternV0 = `^firebolt://(?P<username>.*@?.*):(?P<password>.*)@(?P<database>\w+)(?:/(?P<engine>[^?]+))?(?:\?(?P<parameters>\w+\=[^=&]+(?:\&\w+=[^=&]+)*))?$`
const paramsPattern = `(?P<key>\w+)=(?P<value>[^=&]+)`
// ParseDSNString parses a dsn in a format: firebolt://username:password@db_name[/engine_name][?account_name=organization]
// returns a settings object where all parsed values are populated
// returns an error if required fields couldn't be parsed or if after parsing some characters were left unparsed
func ParseDSNString(dsn string) (*fireboltSettings, error) {
dsnExpr := regexp.MustCompile(dsnPattern)
dsnExprV0 := regexp.MustCompile(dsnPatternV0)
infolog.Println("Parsing DSN")
if dsnMatch := dsnExpr.FindStringSubmatch(dsn); len(dsnMatch) > 0 {
return makeSettings(dsnMatch)
} else if dsnMatch := dsnExprV0.FindStringSubmatch(dsn); len(dsnMatch) > 0 {
return makeSettingsV0(dsnMatch)
} else {
return nil, errors.New("invalid connection string format")
}
}
func makeSettings(dsnMatch []string) (*fireboltSettings, error) {
var result fireboltSettings
result.newVersion = true
// Set database if it's provided
if len(dsnMatch[1]) > 0 {
result.database = dsnMatch[1]
}
for _, m := range parseParams(dsnMatch[2]) {
switch m[1] {
case "account_name":
result.accountName = m[2]
case "engine":
result.engineName = m[2]
case "client_id":
result.clientID = m[2]
case "client_secret":
result.clientSecret = m[2]
default:
return nil, fmt.Errorf("unknown parameter name %s", m[1])
}
}
return &result, nil
}
func makeSettingsV0(dsnMatch []string) (*fireboltSettings, error) {
var result fireboltSettings
result.clientID = dsnMatch[1]
result.clientSecret = dsnMatch[2]
result.newVersion = isServiceID(result.clientID)
result.database = dsnMatch[3]
if len(dsnMatch[4]) > 0 {
// engine name was provided
result.engineName = dsnMatch[4]
}
for _, m := range parseParams(dsnMatch[5]) {
switch m[1] {
case "account_name":
result.accountName = m[2]
default:
return nil, fmt.Errorf("unknown parameter name %s", m[1])
}
}
return &result, nil
}
func parseParams(paramsStr string) [][]string {
if len(paramsStr) == 0 {
return make([][]string, 0)
}
paramsExpr := regexp.MustCompile(paramsPattern)
return paramsExpr.FindAllStringSubmatch(paramsStr, -1)
}
func isServiceID(username string) bool {
return !strings.Contains(username, "@")
}