use std::collections::HashMap;
use std::hash::Hash;
use serde_json::Value;
use crate::{quote, quote_identifier};
pub fn build_update_sql<K>(table: &str, data: HashMap<K, Value>, where_clause: Option<&str>) -> String
where
K: AsRef<str> + Eq + Hash,
{
let mut sets = Vec::new();
for (key, value) in data {
let val_str = match value {
Value::Object(_) => quote(serde_json::to_string(&value).unwrap().as_str()),
Value::Array(_) => quote(serde_json::to_string(&value).unwrap().as_str()),
Value::String(s) => quote(&s),
Value::Number(n) => n.to_string(),
Value::Bool(b) => b.to_string(),
Value::Null => "NULL".to_string(),
};
sets.push(format!("{} = {}", quote_identifier(key.as_ref()), val_str));
}
let mut query = format!("UPDATE {} SET {}", quote_identifier(table.trim()), sets.join(" , "));
if let Some(cond) = where_clause {
if !cond.trim().is_empty() {
query.push_str(&format!(" WHERE {}", cond));
}
}
query
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_update_single() {
let mut data = HashMap::new();
data.insert("name".to_string(), json!("John"));
let sql = build_update_sql("users", data, Some("id = 1"));
assert_eq!(sql, "UPDATE \"users\" SET \"name\" = 'John' WHERE id = 1");
}
#[test]
fn test_update_multiple() {
let mut data = HashMap::new();
data.insert("name".to_string(), json!("John"));
data.insert("age".to_string(), json!(30));
let sql = build_update_sql("users", data, Some("id = 1"));
let valid1 = "UPDATE \"users\" SET \"name\" = 'John' , \"age\" = 30 WHERE id = 1";
let valid2 = "UPDATE \"users\" SET \"age\" = 30 , \"name\" = 'John' WHERE id = 1";
assert!(sql == valid1 || sql == valid2, "Generated SQL: {}", sql);
}
#[test]
fn test_update_no_where() {
let mut data = HashMap::new();
data.insert("active".to_string(), json!(false));
let sql = build_update_sql("users", data, None);
assert_eq!(sql, "UPDATE \"users\" SET \"active\" = false");
}
#[test]
fn test_update_str_keys() {
let mut data = HashMap::new();
data.insert("name", json!("Jane"));
let sql = build_update_sql("users", data, Some("id = 2"));
assert_eq!(sql, "UPDATE \"users\" SET \"name\" = 'Jane' WHERE id = 2");
}
}