use toolu_orm_core::column::{Boolean, Integer, Text, Timestamp};
use toolu_orm_core::query_column::{Column, CommonOps, NumericOps};
use toolu_orm_core::value::Value;
#[test]
fn column_new_stores_table_and_name() {
let col: Column<Text> = Column::new("users", "name");
assert_eq!(col.table, "users");
assert_eq!(col.name, "name");
}
#[test]
fn column_qualified_format() {
let col: Column<Integer> = Column::new("orders", "total");
assert_eq!(col.qualified(), r#""orders"."total""#);
}
#[test]
fn text_column_eq_produces_correct_sql() {
let col: Column<Text> = Column::new("users", "email");
let expr = col.eq("alice@example.com");
let (sql, params) = expr.to_sql_fragment(1);
assert_eq!(sql, r#""users"."email" = ?1"#);
assert_eq!(params, vec![Value::from("alice@example.com")]);
}
#[test]
fn column_in_list_produces_correct_sql() {
let col: Column<Integer> = Column::new("orders", "status");
let values = vec![Value::from(1i32), Value::from(2i32), Value::from(3i32)];
let expr = col.in_list(&values);
let (sql, params) = expr.to_sql_fragment(1);
assert_eq!(sql, r#""orders"."status" IN (?1, ?2, ?3)"#);
assert_eq!(
params,
vec![Value::from(1i32), Value::from(2i32), Value::from(3i32)]
);
}
#[test]
fn column_is_null_produces_no_params() {
let col: Column<Text> = Column::new("users", "deleted_at");
let expr = col.is_null();
let (sql, params) = expr.to_sql_fragment(1);
assert_eq!(sql, r#""users"."deleted_at" IS NULL"#);
assert!(params.is_empty());
}
#[test]
fn expr_and_produces_correct_sql_with_param_numbering() {
let col_a: Column<Text> = Column::new("users", "name");
let col_b: Column<Integer> = Column::new("users", "age");
let left = col_a.eq("alice");
let right = col_b.gt(18);
let combined = left.and(right);
let (sql, params) = combined.to_sql_fragment(1);
assert_eq!(sql, r#"("users"."name" = ?1 AND "users"."age" > ?2)"#);
assert_eq!(params, vec![Value::from("alice"), Value::from(18i32)]);
}
#[test]
fn expr_or_produces_correct_sql_with_param_numbering() {
let col_a: Column<Text> = Column::new("users", "role");
let col_b: Column<Text> = Column::new("users", "status");
let left = col_a.eq("admin");
let right = col_b.eq("active");
let combined = left.or(right);
let (sql, params) = combined.to_sql_fragment(1);
assert_eq!(sql, r#"("users"."role" = ?1 OR "users"."status" = ?2)"#);
assert_eq!(params, vec![Value::from("admin"), Value::from("active")]);
}
#[test]
fn column_ne_produces_correct_sql() {
let col: Column<Text> = Column::new("users", "status");
let expr = col.ne("banned");
let (sql, params) = expr.to_sql_fragment(1);
assert_eq!(sql, r#""users"."status" != ?1"#);
assert_eq!(params, vec![Value::from("banned")]);
}
#[test]
fn column_not_in_produces_correct_sql() {
let col: Column<Text> = Column::new("users", "role");
let values = vec![Value::from("admin"), Value::from("moderator")];
let expr = col.not_in(&values);
let (sql, params) = expr.to_sql_fragment(1);
assert_eq!(sql, r#""users"."role" NOT IN (?1, ?2)"#);
assert_eq!(params, vec![Value::from("admin"), Value::from("moderator")]);
}
#[test]
fn column_is_not_null_produces_correct_sql() {
let col: Column<Text> = Column::new("users", "email");
let expr = col.is_not_null();
let (sql, params) = expr.to_sql_fragment(1);
assert_eq!(sql, r#""users"."email" IS NOT NULL"#);
assert!(params.is_empty());
}
fn _assert_integer_has_numeric_ops(col: &Column<Integer>) -> toolu_orm_core::expr::Expr {
col.gt(0)
}
fn _assert_integer_has_common_ops(col: &Column<Integer>) -> toolu_orm_core::expr::Expr {
col.eq(0i32)
}
fn _assert_boolean_has_common_ops(col: &Column<Boolean>) -> toolu_orm_core::expr::Expr {
col.eq(true)
}
fn _assert_timestamp_has_numeric_ops(col: &Column<Timestamp>) -> toolu_orm_core::expr::Expr {
col.gt(1_000_000i64)
}
fn _assert_text_ops_on_text<T: toolu_orm_core::query_column::TextOps>(_: &T) {}
fn _assert_numeric_ops_on_integer<T: NumericOps>(_: &T) {}
fn _assert_common_ops_on_any<T: CommonOps>(_: &T) {}