97 lines
2.3 KiB
V
97 lines
2.3 KiB
V
module mssql
|
|
|
|
@[params]
|
|
pub struct Config {
|
|
pub:
|
|
conn_str string
|
|
dsn string
|
|
driver string
|
|
server string
|
|
port int
|
|
uid string
|
|
user string
|
|
pwd string
|
|
password string
|
|
// if dbname empty, conn str will not contain Database info,
|
|
// and it is up to the server to choose which db to connect to.
|
|
dbname string
|
|
options map[string]string
|
|
}
|
|
|
|
// connect creates a new connection using the provided configuration.
|
|
pub fn connect(config Config) !Connection {
|
|
return open(config.get_conn_str())
|
|
}
|
|
|
|
// open creates a new connection using a raw ODBC connection string.
|
|
pub fn open(conn_str string) !Connection {
|
|
mut conn := Connection{}
|
|
conn.connect(conn_str)!
|
|
return conn
|
|
}
|
|
|
|
fn preferred_value(primary string, fallback string) string {
|
|
if primary != '' {
|
|
return primary
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
fn needs_odbc_braces(value string) bool {
|
|
return value.contains_any(' \t\r\n;{}')
|
|
}
|
|
|
|
fn format_odbc_value(value string) string {
|
|
if value == '' {
|
|
return ''
|
|
}
|
|
if needs_odbc_braces(value) {
|
|
return '{' + value.replace('}', '}}') + '}'
|
|
}
|
|
return value
|
|
}
|
|
|
|
fn append_conn_part(mut parts []string, key string, value string) {
|
|
if value == '' {
|
|
return
|
|
}
|
|
parts << '${key}=${format_odbc_value(value)}'
|
|
}
|
|
|
|
// get_conn_str builds an ODBC connection string from the configured fields.
|
|
pub fn (cfg Config) get_conn_str() string {
|
|
if cfg.conn_str != '' {
|
|
return cfg.conn_str
|
|
}
|
|
mut parts := []string{}
|
|
append_conn_part(mut parts, 'DSN', cfg.dsn)
|
|
append_conn_part(mut parts, 'Driver', cfg.driver)
|
|
append_conn_part(mut parts, 'Server', cfg.server)
|
|
if cfg.port > 0 {
|
|
parts << 'Port=${cfg.port}'
|
|
}
|
|
append_conn_part(mut parts, 'UID', preferred_value(cfg.uid, cfg.user))
|
|
append_conn_part(mut parts, 'PWD', preferred_value(cfg.pwd, cfg.password))
|
|
if cfg.dbname != '' {
|
|
append_conn_part(mut parts, 'Database', cfg.dbname)
|
|
}
|
|
if cfg.options.len > 0 {
|
|
mut option_keys := cfg.options.keys()
|
|
// Manual insertion sort avoids relying on the generic .sort() helper,
|
|
// which has tripped bounds-check builds in CI.
|
|
for i in 1 .. option_keys.len {
|
|
key := option_keys[i]
|
|
mut j := i
|
|
for j > 0 && option_keys[j - 1] > key {
|
|
option_keys[j] = option_keys[j - 1]
|
|
j--
|
|
}
|
|
option_keys[j] = key
|
|
}
|
|
for key in option_keys {
|
|
append_conn_part(mut parts, key, cfg.options[key])
|
|
}
|
|
}
|
|
return parts.join(';')
|
|
}
|