use sz_orm_core::dynamic_sql::{DynamicSqlParser, ParamValue, SqlParams};
#[test]
fn test_sql_params_new_is_empty_contract() {
let params = SqlParams::new();
assert!(params.names().is_empty());
}
#[test]
fn test_sql_params_set_str_contract() {
let mut p = SqlParams::new();
p.set("name", "Alice");
match p.get("name") {
Some(ParamValue::String(s)) => assert_eq!(s, "Alice"),
other => panic!("期望 ParamValue::String,实际: {:?}", other),
}
}
#[test]
fn test_sql_params_set_int_contract() {
let mut p = SqlParams::new();
p.set_int("age", 18);
match p.get("age") {
Some(ParamValue::Int(18)) => {}
other => panic!("期望 ParamValue::Int(18),实际: {:?}", other),
}
}
#[test]
fn test_sql_params_set_float_contract() {
let mut p = SqlParams::new();
p.set_float("score", 3.15);
match p.get("score") {
Some(ParamValue::Float(f)) => assert!((f - 3.15).abs() < 1e-6),
other => panic!("期望 ParamValue::Float,实际: {:?}", other),
}
}
#[test]
fn test_sql_params_set_bool_contract() {
let mut p = SqlParams::new();
p.set_bool("active", true);
match p.get("active") {
Some(ParamValue::Bool(true)) => {}
other => panic!("期望 ParamValue::Bool(true),实际: {:?}", other),
}
}
#[test]
fn test_sql_params_set_null_contract() {
let mut p = SqlParams::new();
p.set_null("deleted_at");
match p.get("deleted_at") {
Some(ParamValue::Null) => {}
other => panic!("期望 ParamValue::Null,实际: {:?}", other),
}
}
#[test]
fn test_sql_params_set_array_contract() {
let mut p = SqlParams::new();
p.set_array(
"ids",
vec![ParamValue::Int(1), ParamValue::Int(2), ParamValue::Int(3)],
);
match p.get("ids") {
Some(ParamValue::Array(items)) => assert_eq!(items.len(), 3),
other => panic!("期望 ParamValue::Array,实际: {:?}", other),
}
}
#[test]
fn test_sql_params_get_missing_returns_none_contract() {
let p = SqlParams::new();
assert!(p.get("missing").is_none());
}
#[test]
fn test_sql_params_contains_existing_key_contract() {
let mut p = SqlParams::new();
p.set("name", "Alice");
assert!(p.contains("name"));
}
#[test]
fn test_sql_params_contains_missing_key_contract() {
let p = SqlParams::new();
assert!(!p.contains("missing"));
}
#[test]
fn test_sql_params_contains_returns_true_for_null_value_contract() {
let mut p = SqlParams::new();
p.set_null("deleted_at");
assert!(
p.contains("deleted_at"),
"contains 对 Null 值应返回 true(不检查 Null)"
);
}
#[test]
fn test_sql_params_is_null_for_missing_key_contract() {
let p = SqlParams::new();
assert!(p.is_null("missing"), "is_null 对不存在的 key 应返回 true");
}
#[test]
fn test_sql_params_is_null_for_null_value_contract() {
let mut p = SqlParams::new();
p.set_null("deleted_at");
assert!(p.is_null("deleted_at"));
}
#[test]
fn test_sql_params_is_null_for_non_null_value_contract() {
let mut p = SqlParams::new();
p.set("name", "Alice");
assert!(!p.is_null("name"));
}
#[test]
fn test_sql_params_is_not_null_is_opposite_of_is_null_contract() {
let mut p = SqlParams::new();
p.set("name", "Alice");
p.set_null("deleted_at");
assert!(!p.is_not_null("missing")); assert!(p.is_not_null("name"));
assert!(!p.is_not_null("deleted_at"));
}
#[test]
fn test_sql_params_names_contract() {
let mut p = SqlParams::new();
p.set("a", "1");
p.set_int("b", 2);
p.set_bool("c", true);
let names = p.names();
assert_eq!(names.len(), 3);
assert!(names.contains(&"a".to_string()));
assert!(names.contains(&"b".to_string()));
assert!(names.contains(&"c".to_string()));
}
#[test]
fn test_dynamic_sql_parser_from_xml_contract() {
let xml = r#"
<select id="find_users">
SELECT * FROM users
</select>
"#;
let parser = DynamicSqlParser::from_xml(xml).unwrap();
let params = SqlParams::new();
let sql = parser.build("find_users", ¶ms).unwrap();
assert!(sql.contains("SELECT"));
assert!(sql.contains("users"));
}
#[test]
fn test_dynamic_sql_parser_missing_id_returns_err_contract() {
let xml = r#"
<select>
SELECT * FROM users
</select>
"#;
let result = DynamicSqlParser::from_xml(xml);
assert!(result.is_err());
}
#[test]
fn test_dynamic_sql_parser_build_missing_statement_returns_err_contract() {
let xml = r#"
<select id="find_users">
SELECT * FROM users
</select>
"#;
let parser = DynamicSqlParser::from_xml(xml).unwrap();
let params = SqlParams::new();
let result = parser.build("missing_id", ¶ms);
assert!(result.is_err());
}
#[test]
fn test_dynamic_sql_if_tag_includes_block_when_param_present_contract() {
let xml = r#"
<select id="find">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
</where>
</select>
"#;
let parser = DynamicSqlParser::from_xml(xml).unwrap();
let mut params = SqlParams::new();
params.set("name", "Alice");
let sql = parser.build("find", ¶ms).unwrap();
assert!(sql.contains("name"), "if 块应被包含: {}", sql);
}
#[test]
fn test_dynamic_sql_if_tag_skips_block_when_param_missing_contract() {
let xml = r#"
<select id="find">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
</where>
</select>
"#;
let parser = DynamicSqlParser::from_xml(xml).unwrap();
let params = SqlParams::new();
let sql = parser.build("find", ¶ms).unwrap();
assert!(
!sql.contains("AND name"),
"if 块应被跳过(参数缺失): {}",
sql
);
}
#[test]
fn test_dynamic_sql_where_tag_strips_leading_and_contract() {
let xml = r#"
<select id="find">
SELECT * FROM users
<where>
<if test="name != null">AND name = #{name}</if>
</where>
</select>
"#;
let parser = DynamicSqlParser::from_xml(xml).unwrap();
let mut params = SqlParams::new();
params.set("name", "Alice");
let sql = parser.build("find", ¶ms).unwrap();
assert!(
!sql.contains("WHERE AND"),
"<where> 应自动移除首个 AND: {}",
sql
);
}