v / vlib / db / mssql / config.v
96 lines · 88 sloc · 2.3 KB · 4a2f83b4bea4506de5d60ef459d19bcb0cb0a3ee
Raw
1module mssql
2
3@[params]
4pub struct Config {
5pub:
6 conn_str string
7 dsn string
8 driver string
9 server string
10 port int
11 uid string
12 user string
13 pwd string
14 password string
15 // if dbname empty, conn str will not contain Database info,
16 // and it is up to the server to choose which db to connect to.
17 dbname string
18 options map[string]string
19}
20
21// connect creates a new connection using the provided configuration.
22pub fn connect(config Config) !Connection {
23 return open(config.get_conn_str())
24}
25
26// open creates a new connection using a raw ODBC connection string.
27pub fn open(conn_str string) !Connection {
28 mut conn := Connection{}
29 conn.connect(conn_str)!
30 return conn
31}
32
33fn preferred_value(primary string, fallback string) string {
34 if primary != '' {
35 return primary
36 }
37 return fallback
38}
39
40fn needs_odbc_braces(value string) bool {
41 return value.contains_any(' \t\r\n;{}')
42}
43
44fn format_odbc_value(value string) string {
45 if value == '' {
46 return ''
47 }
48 if needs_odbc_braces(value) {
49 return '{' + value.replace('}', '}}') + '}'
50 }
51 return value
52}
53
54fn append_conn_part(mut parts []string, key string, value string) {
55 if value == '' {
56 return
57 }
58 parts << '${key}=${format_odbc_value(value)}'
59}
60
61// get_conn_str builds an ODBC connection string from the configured fields.
62pub fn (cfg Config) get_conn_str() string {
63 if cfg.conn_str != '' {
64 return cfg.conn_str
65 }
66 mut parts := []string{}
67 append_conn_part(mut parts, 'DSN', cfg.dsn)
68 append_conn_part(mut parts, 'Driver', cfg.driver)
69 append_conn_part(mut parts, 'Server', cfg.server)
70 if cfg.port > 0 {
71 parts << 'Port=${cfg.port}'
72 }
73 append_conn_part(mut parts, 'UID', preferred_value(cfg.uid, cfg.user))
74 append_conn_part(mut parts, 'PWD', preferred_value(cfg.pwd, cfg.password))
75 if cfg.dbname != '' {
76 append_conn_part(mut parts, 'Database', cfg.dbname)
77 }
78 if cfg.options.len > 0 {
79 mut option_keys := cfg.options.keys()
80 // Manual insertion sort avoids relying on the generic .sort() helper,
81 // which has tripped bounds-check builds in CI.
82 for i in 1 .. option_keys.len {
83 key := option_keys[i]
84 mut j := i
85 for j > 0 && option_keys[j - 1] > key {
86 option_keys[j] = option_keys[j - 1]
87 j--
88 }
89 option_keys[j] = key
90 }
91 for key in option_keys {
92 append_conn_part(mut parts, key, cfg.options[key])
93 }
94 }
95 return parts.join(';')
96}
97