use floz_orm as floz;
floz_orm::schema! {
model User("users") {
id: integer("id").auto_increment().primary(),
name: varchar("name", 100),
age: short("age").nullable(),
bio: text("bio"),
}
}
#[test]
fn user_struct_exists() {
let u = User::default();
assert_eq!(u.id, 0);
assert_eq!(u.name, "");
assert!(u.age.is_none());
assert_eq!(u.bio, "");
assert_eq!(u._dirty_flags, 0);
}
#[test]
fn user_table_exists() {
assert_eq!(UserTable::TABLE_NAME, "users");
assert_eq!(UserTable::COLUMNS, ["id", "name", "age", "bio"]);
}
#[test]
fn user_column_constants() {
assert_eq!(UserTable::id.name(), "id");
assert_eq!(UserTable::id.table(), "users");
assert_eq!(UserTable::name.name(), "name");
assert_eq!(UserTable::age.name(), "age");
assert_eq!(UserTable::bio.name(), "bio");
}
#[test]
fn user_column_dsl_operators() {
let _ = UserTable::age.gt(25i16);
let _ = UserTable::name.eq("Alice");
let _ = UserTable::name.contains("foo");
let _ = UserTable::age.is_null();
let _ = UserTable::id.in_list(vec![1, 2, 3]);
}
#[test]
fn user_dirty_tracking() {
let mut u = User::default();
assert!(!u.is_dirty());
u.set_name("Alice".to_string());
assert!(u.is_dirty());
assert!(u.is_field_dirty(1));
u.set_age(Some(30));
assert!(u.is_field_dirty(2));
assert!(!u.is_field_dirty(0)); assert!(!u.is_field_dirty(3));
u.clear_dirty();
assert!(!u.is_dirty());
}
#[test]
fn user_default_does_not_set_dirty() {
let u = User::default();
assert_eq!(u._dirty_flags, 0);
}
#[test]
fn user_serde_roundtrip() {
let mut u = User::default();
u.id = 1;
u.name = "Alice".to_string();
u.age = Some(30);
u.bio = "Hello!".to_string();
u._dirty_flags = 0xFF;
let json = serde_json::to_string(&u).unwrap();
assert!(!json.contains("dirty"));
let u2: User = serde_json::from_str(&json).unwrap();
assert_eq!(u2.name, "Alice");
assert_eq!(u2._dirty_flags, 0); }
floz_orm::schema! {
model AuditLog("audit.logs") {
event: text("event"),
timestamp: datetime("created_at").tz(),
}
}
#[test]
fn schema_qualified_table() {
assert_eq!(AuditLogTable::TABLE_NAME, "audit.logs");
}
#[test]
fn datetime_with_tz() {
let log = AuditLog::default();
let _: chrono::DateTime<chrono::Utc> = log.timestamp;
}
floz_orm::schema! {
model Product("products") {
product_id: integer("id").primary(),
product_name: varchar("display_name", 255),
}
}
#[test]
fn renamed_columns() {
assert_eq!(ProductTable::product_id.name(), "id");
assert_eq!(ProductTable::product_name.name(), "display_name");
let p = Product::default();
let _ = p.product_id;
let _ = p.product_name;
}
floz_orm::schema! {
model Author("authors") {
id: integer("id").primary(),
name: varchar("name", 100),
}
model Book("books") {
id: integer("id").primary(),
title: text("title"),
author_id: integer("author_id"),
}
}
#[test]
fn multiple_models() {
assert_eq!(AuthorTable::TABLE_NAME, "authors");
assert_eq!(BookTable::TABLE_NAME, "books");
let _ = Author::default();
let _ = Book::default();
}
floz_orm::schema! {
model TypeTest("type_test") {
a_int: integer("a_int"),
b_short: short("b_short"),
c_bigint: bigint("c_bigint"),
d_real: real("d_real"),
e_double: double("e_double"),
f_text: text("f_text"),
g_bool: bool("g_bool"),
h_uuid: uuid("h_uuid"),
i_varchar: varchar("i_varchar", 50),
j_binary: binary("j_binary"),
k_date: date("k_date"),
l_time: time("l_time"),
m_naive: datetime("m_naive"),
n_tz: datetime("n_tz").tz(),
}
}
#[test]
fn all_types_default() {
let t = TypeTest::default();
assert_eq!(t.a_int, 0i32);
assert_eq!(t.b_short, 0i16);
assert_eq!(t.c_bigint, 0i64);
assert_eq!(t.d_real, 0.0f32);
assert_eq!(t.e_double, 0.0f64);
assert_eq!(t.f_text, "");
assert!(!t.g_bool);
assert_eq!(t.h_uuid, uuid::Uuid::nil());
assert_eq!(t.i_varchar, "");
assert!(t.j_binary.is_empty());
}
floz_orm::schema! {
model NullableTest("nullable_test") {
id: integer("id"),
name: text("name").nullable(),
age: short("age").nullable(),
score: double("score").nullable(),
tag: uuid("tag").nullable(),
}
}
#[test]
fn nullable_defaults() {
let t = NullableTest::default();
assert_eq!(t.id, 0);
assert!(t.name.is_none());
assert!(t.age.is_none());
assert!(t.score.is_none());
assert!(t.tag.is_none());
}
floz_orm::schema! {
model WithArrays("with_arrays") {
id: integer("id"),
tags: text_array("tags"),
scores: int_array("scores"),
ids: uuid_array("ids"),
}
}
#[test]
fn array_columns() {
let w = WithArrays::default();
assert!(w.tags.is_empty());
assert!(w.scores.is_empty());
assert!(w.ids.is_empty());
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, sqlx::Type, utoipa::ToSchema)]
#[sqlx(type_name = "varchar", rename_all = "lowercase")]
pub enum Status {
Active,
Inactive,
}
impl Default for Status {
fn default() -> Self {
Status::Active
}
}
impl std::fmt::Display for Status {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Status::Active => write!(f, "active"),
Status::Inactive => write!(f, "inactive"),
}
}
}
floz_orm::schema! {
model WithExotics("exotics") {
id: integer("id").auto_increment().primary(),
data: json("data"),
meta: jsonb("meta").nullable(),
status: enumeration("status", Status),
}
}
#[test]
fn exotic_columns() {
let e = WithExotics::default();
assert_eq!(e.data, serde_json::Value::Null);
assert!(e.meta.is_none());
assert!(matches!(e.status, Status::Active));
}