use std::fs;
use anyhow::{Result, anyhow, bail};
use crate::cli::QueryCommand;
pub(crate) fn load_query(cmd: &QueryCommand) -> Result<String> {
if let Some(sql) = &cmd.sql {
return Ok(sql.clone());
}
if let Some(query_path) = &cmd.query_file {
return fs::read_to_string(query_path)
.map_err(Into::into)
.map(|content| content.trim().to_owned());
}
bail!("provide either --sql or --query-file")
}
pub(crate) fn parse_query_params(entries: &[String]) -> Result<Vec<query_forge::QueryParam>> {
entries
.iter()
.map(|entry| {
let (name, value) = entry
.split_once('=')
.ok_or_else(|| anyhow!("invalid --param '{entry}', expected NAME=VALUE"))?;
if name.trim().is_empty() {
bail!("invalid --param '{entry}', parameter name cannot be empty");
}
Ok(query_forge::QueryParam {
name: name.trim().to_owned(),
value: parse_param_value(value.trim()),
})
})
.collect()
}
fn parse_param_value(raw_value: &str) -> query_forge::QueryValue {
if raw_value.eq_ignore_ascii_case("null") {
return query_forge::QueryValue::Null;
}
if raw_value.eq_ignore_ascii_case("true") {
return query_forge::QueryValue::Integer(1);
}
if raw_value.eq_ignore_ascii_case("false") {
return query_forge::QueryValue::Integer(0);
}
if let Ok(integer) = raw_value.parse::<i64>() {
return query_forge::QueryValue::Integer(integer);
}
if let Ok(real) = raw_value.parse::<f64>() {
return query_forge::QueryValue::Real(real);
}
query_forge::QueryValue::Text(raw_value.to_owned())
}
#[cfg(test)]
mod tests {
use super::parse_query_params;
#[test]
fn parses_query_params() {
let entries = vec![
"wbs=IEV092500011.2.2.4".to_owned(),
"min=10".to_owned(),
"enabled=true".to_owned(),
];
let params = parse_query_params(&entries).expect("valid params");
assert_eq!(params.len(), 3);
assert_eq!(params[0].name, "wbs");
assert_eq!(params[1].name, "min");
assert_eq!(params[2].name, "enabled");
}
}