grorm/orm/model.rs
1use crate::types::Value;
2
3/// Metadata about a single column in a model's table schema.
4///
5/// Generated automatically by `#[derive(DeriveModel)]` and used by
6/// [`QueryBuilder::create_table`] to generate DDL statements.
7///
8/// # Example
9///
10/// ```rust
11/// use grorm::{DeriveModel, ColumnInfo, Model};
12///
13/// #[derive(Debug, DeriveModel)]
14/// #[table = "users"]
15/// struct User {
16/// id: i64,
17/// #[index]
18/// name: String,
19/// #[unique]
20/// email: String,
21/// age: i32,
22/// }
23///
24/// let schema = User::table_schema();
25/// assert_eq!(schema.len(), 4);
26/// assert!(schema[0].is_primary_key);
27/// assert!(schema[1].is_index);
28/// assert!(schema[2].is_unique);
29/// ```
30#[derive(Debug, Clone)]
31pub struct ColumnInfo {
32 /// Column name in the database
33 pub name: &'static str,
34 /// Rust type name (e.g. `"i64"`, `"String"`)
35 pub rust_type: &'static str,
36 /// Whether this column is part of the primary key
37 pub is_primary_key: bool,
38 /// Whether this column is auto-increment (integer primary key)
39 pub is_auto_increment: bool,
40 /// Whether a regular index should be created on this column (`#[index]`)
41 pub is_index: bool,
42 /// Whether a unique constraint should be created on this column (`#[unique]`)
43 pub is_unique: bool,
44 /// Name of the composite unique index group (`#[unique_index = "name"]`).
45 /// Columns with the same name form a composite unique index.
46 pub unique_index_name: Option<&'static str>,
47}
48
49/// Trait implemented by `#[derive(DeriveModel)]` for ORM model types.
50///
51/// Provides table metadata, column information, and row serialization/deserialization.
52///
53/// # Derivable
54///
55/// This trait is typically derived using `#[derive(DeriveModel)]`:
56///
57/// ```rust
58/// use grorm::DeriveModel;
59///
60/// #[derive(Debug, DeriveModel)]
61/// #[table = "users"]
62/// struct User {
63/// id: i64,
64/// name: String,
65/// email: String,
66/// age: i32,
67/// }
68/// ```
69///
70/// # Attributes
71///
72/// | Attribute | Scope | Description |
73/// |-----------|-------|-------------|
74/// | `#[table = "name"]` | struct | Override table name (default: lowercase struct name + "s") |
75/// | `#[primary_key = "col"]` | struct | Override primary key column (default: `id`) |
76/// | `#[index]` | field | Create a regular index on this column |
77/// | `#[unique]` | field | Create a unique constraint on this column |
78/// | `#[unique_index = "name"]` | field | Group columns into a composite unique index |
79pub trait Model: Sized {
80 /// Returns the database table name
81 fn table_name() -> &'static str;
82 /// Returns the primary key column name
83 fn primary_key() -> &'static str;
84 /// Returns all column names in order
85 fn columns() -> &'static [&'static str];
86 /// Returns full column metadata for DDL generation
87 fn table_schema() -> &'static [ColumnInfo];
88 /// Deserialize a database row into this model
89 fn from_row(row: &[Value]) -> Result<Self, String>;
90 /// Serialize this model into database values
91 fn to_values(&self) -> Vec<Value>;
92}