@@ -2,6 +2,7 @@ package gomaxcompute
2
2
3
3
import (
4
4
"fmt"
5
+ "net/url"
5
6
"regexp"
6
7
"strings"
7
8
)
@@ -13,10 +14,11 @@ var (
13
14
)
14
15
15
16
type Config struct {
16
- AccessID string
17
- AccessKey string
18
- Project string
19
- Endpoint string
17
+ AccessID string
18
+ AccessKey string
19
+ Project string
20
+ Endpoint string
21
+ QueryHints map [string ]string
20
22
}
21
23
22
24
func ParseDSN (dsn string ) (* Config , error ) {
@@ -26,32 +28,41 @@ func ParseDSN(dsn string) (*Config, error) {
26
28
}
27
29
id , key , endpointURL := sub [1 ], sub [2 ], sub [3 ]
28
30
29
- query := make (map [string ]string )
30
- for _ , s := range strings .Split (sub [4 ], "&" ) {
31
- pair := reQuery .FindStringSubmatch (s )
32
- if len (pair ) != 3 {
33
- return nil , fmt .Errorf ("dsn %s doesn't match access_id:access_key@url?curr_project=project&scheme=http|https" , dsn )
34
- }
35
- if pair [1 ] != "scheme" && pair [1 ] != currentProject {
36
- return nil , fmt .Errorf ("dsn %s 's query is neither scheme or %s" , dsn , currentProject )
37
- }
38
- query [pair [1 ]] = pair [2 ]
31
+ var schemeArgs []string
32
+ var currProjArgs []string
33
+ var ok bool
34
+ queryHints := make (map [string ]string )
35
+
36
+ querys , err := url .ParseQuery (sub [4 ])
37
+ if err != nil {
38
+ return nil , err
39
+ }
40
+
41
+ if schemeArgs , ok = querys ["scheme" ]; ! ok || len (schemeArgs ) != 1 {
42
+ return nil , fmt .Errorf ("dsn %s should have one scheme argument" , dsn )
39
43
}
40
- if _ , ok := query [currentProject ]; ! ok {
41
- return nil , fmt .Errorf ("dsn %s doesn't have curr_project " , dsn )
44
+ if currProjArgs , ok = querys [currentProject ]; ! ok || len ( currProjArgs ) != 1 {
45
+ return nil , fmt .Errorf ("dsn %s should have one current_project argument " , dsn )
42
46
}
43
- if _ , ok := query ["scheme" ]; ! ok {
44
- return nil , fmt .Errorf ("dsn %s doesn't have scheme" , dsn )
47
+
48
+ for k , v := range querys {
49
+ // The query args such as hints_odps.sql.mapper.split_size=16
50
+ // would be converted to the maxcompute query hints: {"odps.sql.mapper.split_size": "16"}
51
+ if strings .HasPrefix (k , "hints_" ) {
52
+ queryHints [k [6 :]] = v [0 ]
53
+ }
45
54
}
46
- if query ["scheme" ] != "http" && query ["scheme" ] != "https" {
55
+
56
+ if schemeArgs [0 ] != "http" && schemeArgs [0 ] != "https" {
47
57
return nil , fmt .Errorf ("dsn %s 's scheme is neither http nor https" , dsn )
48
58
}
49
59
50
60
config := & Config {
51
- AccessID : id ,
52
- AccessKey : key ,
53
- Project : query [currentProject ],
54
- Endpoint : query ["scheme" ] + "://" + endpointURL }
61
+ AccessID : id ,
62
+ AccessKey : key ,
63
+ Project : currProjArgs [0 ],
64
+ Endpoint : schemeArgs [0 ] + "://" + endpointURL ,
65
+ QueryHints : queryHints }
55
66
56
67
return config , nil
57
68
}
@@ -62,6 +73,12 @@ func (cfg *Config) FormatDSN() string {
62
73
return ""
63
74
}
64
75
scheme , endpointURL := pair [0 ], pair [1 ]
65
- return fmt .Sprintf ("%s:%s@%s?curr_project=%s&scheme=%s" ,
76
+ dsnFormt := fmt .Sprintf ("%s:%s@%s?curr_project=%s&scheme=%s" ,
66
77
cfg .AccessID , cfg .AccessKey , endpointURL , cfg .Project , scheme )
78
+ if len (cfg .QueryHints ) != 0 {
79
+ for k , v := range cfg .QueryHints {
80
+ dsnFormt = fmt .Sprintf ("%s&hints_%s=%v" , dsnFormt , k , v )
81
+ }
82
+ }
83
+ return dsnFormt
67
84
}
0 commit comments