use super::{Conn, Engine, NewConn};
use crate::ini;
use anyhow::Result;
use std::path::PathBuf;
const KNOWN: [&str; 5] = ["host", "port", "database", "user", "trust_cert"];
pub fn store_path() -> PathBuf {
dirs::config_dir()
.unwrap_or_else(|| dirs::home_dir().unwrap_or_default().join(".config"))
.join("easysql")
.join("mssql.conf")
}
pub fn list() -> Vec<Conn> {
ini::read(&store_path())
.into_iter()
.map(|s| Conn {
engine: Engine::MsSql,
host: s.get("host").unwrap_or_default().to_string(),
port: s.get("port").unwrap_or_default().to_string(),
database: s.get("database").unwrap_or_default().to_string(),
user: s.get("user").unwrap_or_default().to_string(),
extra: s.rest(&KNOWN),
name: s.name,
})
.collect()
}
pub fn trusts_cert(c: &Conn) -> bool {
c.extra
.iter()
.any(|(k, v)| k.eq_ignore_ascii_case("trust_cert") && v == "yes")
}
pub fn flags(c: &Conn) -> Vec<String> {
let host = if c.host.is_empty() {
"localhost"
} else {
&c.host
};
let mut argv = vec!["-S".to_string(), format!("{host},{}", c.port_or_default())];
if !c.database.is_empty() {
argv.push("-d".into());
argv.push(c.database.clone());
}
if !c.user.is_empty() {
argv.push("-U".into());
argv.push(c.user.clone());
}
if trusts_cert(c) {
argv.push("-C".into());
}
argv
}
pub fn save(original: Option<&str>, nc: &NewConn) -> Result<()> {
let mut keys: Vec<(String, String)> = Vec::new();
for (k, v) in [
("host", &nc.host),
("port", &nc.port),
("database", &nc.database),
("user", &nc.user),
] {
let v = v.trim();
if !v.is_empty() {
keys.push((k.to_string(), v.to_string()));
}
}
keys.extend(nc.extra.iter().cloned());
ini::upsert(&store_path(), original, nc.name.trim(), &keys)
}
pub fn delete(name: &str) -> Result<()> {
ini::remove(&store_path(), name)
}
pub fn probe_argv(c: &Conn, s: &crate::settings::Settings) -> (Vec<String>, Vec<(String, String)>) {
let mut argv = c.connect_argv(s);
argv.push("-l".into());
argv.push(s.probe_timeout.to_string());
argv.push("-Q".into());
argv.push("select 1".into());
(argv, vec![("SQLCMDPASSWORD".to_string(), String::new())])
}