bottle_orm_macro/lib.rs
1//! # Bottle ORM Procedural Macros
2//!
3//! This crate provides procedural macros for the Bottle ORM framework.
4//! It contains the `#[derive(Model)]` macro that automatically implements
5//! the `Model` trait for structs representing database tables.
6//!
7//! ## Overview
8//!
9//! The procedural macros in this crate analyze struct definitions and their
10//! attributes to generate the necessary boilerplate code for ORM functionality.
11//! This includes:
12//!
13//! - Table name resolution
14//! - Column metadata generation
15//! - Type mapping from Rust to SQL
16//! - Serialization methods
17//!
18//! ## Architecture
19//!
20//! The crate is organized into three modules:
21//!
22//! - **`lib.rs`** (this file): Entry point and macro definitions
23//! - **`derive_model.rs`**: Implementation of the Model derive macro
24//! - **`types.rs`**: Type mapping utilities (Rust → SQL)
25//!
26//! ## Usage
27//!
28//! This crate is not meant to be used directly. Instead, it's re-exported
29//! by the main `bottle-orm` crate:
30//!
31//! ```rust,ignore
32//! use bottle_orm::Model;
33//! use uuid::Uuid;
34//!
35//! #[derive(Model)]
36//! struct User {
37//! #[orm(primary_key)]
38//! id: Uuid,
39//! username: String,
40//! }
41//! ```
42//!
43//! ## Supported Attributes
44//!
45//! The `#[orm(...)]` attribute supports the following options:
46//!
47//! ### Primary Key
48//! ```rust,ignore
49//! #[orm(primary_key)]
50//! id: Uuid,
51//! ```
52//! Marks the field as the table's primary key. Generates `PRIMARY KEY` constraint.
53//!
54//! ### Unique Constraint
55//! ```rust,ignore
56//! #[orm(unique)]
57//! username: String,
58//! ```
59//! Adds a `UNIQUE` constraint to prevent duplicate values.
60//!
61//! ### Database Index
62//! ```rust,ignore
63//! #[orm(index)]
64//! email: String,
65//! ```
66//! Creates a database index on the column for faster queries.
67//!
68//! ### Column Size
69//! ```rust,ignore
70//! #[orm(size = 100)]
71//! username: String,
72//! ```
73//! Sets `VARCHAR(N)` size for String fields. Default is `TEXT`.
74//!
75//! ### Auto-Timestamp (Creation)
76//! ```rust,ignore
77//! #[orm(create_time)]
78//! created_at: DateTime<Utc>,
79//! ```
80//! Adds `DEFAULT CURRENT_TIMESTAMP` to auto-populate on INSERT.
81//!
82//! ### Auto-Timestamp (Update)
83//! ```rust,ignore
84//! #[orm(update_time)]
85//! updated_at: DateTime<Utc>,
86//! ```
87//! Auto-updates timestamp on UPDATE (future feature).
88//!
89//! ### Foreign Key
90//! ```rust,ignore
91//! #[orm(foreign_key = "User::id")]
92//! user_id: Uuid,
93//! ```
94//! Creates a foreign key relationship. Format: `"TargetTable::target_column"`.
95//!
96//! ### Combining Attributes
97//! ```rust,ignore
98//! #[orm(size = 50, unique, index)]
99//! username: String,
100//! ```
101//! Multiple attributes can be combined on a single field.
102//!
103//! ## Type Support
104//!
105//! The macro supports automatic type mapping for:
106//!
107//! ### Primitive Types
108//! - `i32` → `INTEGER`
109//! - `i64` → `BIGINT`
110//! - `f64` → `DOUBLE PRECISION`
111//! - `bool` → `BOOLEAN`
112//! - `String` → `TEXT` or `VARCHAR(N)`
113//!
114//! ### UUID Types (All Versions 1-7)
115//! - `Uuid` → `UUID`
116//!
117//! ### Date/Time Types
118//! - `DateTime<Utc>` → `TIMESTAMPTZ`
119//! - `NaiveDateTime` → `TIMESTAMP`
120//! - `NaiveDate` → `DATE`
121//! - `NaiveTime` → `TIME`
122//!
123//! ### Nullable Types
124//! - `Option<T>` → SQL type of `T` with `NULL` allowed
125//!
126//! ## Complete Example
127//!
128//! ```rust,ignore
129//! use bottle_orm::Model;
130//! use uuid::Uuid;
131//! use chrono::{DateTime, Utc};
132//! use serde::{Deserialize, Serialize};
133//! use sqlx::FromRow;
134//!
135//! #[derive(Model, Debug, Clone, Serialize, Deserialize, FromRow)]
136//! struct User {
137//! #[orm(primary_key)]
138//! id: Uuid,
139//!
140//! #[orm(size = 50, unique, index)]
141//! username: String,
142//!
143//! #[orm(size = 100, unique)]
144//! email: String,
145//!
146//! age: Option<i32>,
147//!
148//! active: bool,
149//!
150//! #[orm(create_time)]
151//! created_at: DateTime<Utc>,
152//!
153//! #[orm(update_time)]
154//! updated_at: Option<DateTime<Utc>>,
155//! }
156//!
157//! #[derive(Model, Debug, Clone, Serialize, Deserialize, FromRow)]
158//! struct Post {
159//! #[orm(primary_key)]
160//! id: Uuid,
161//!
162//! #[orm(foreign_key = "User::id", index)]
163//! user_id: Uuid,
164//!
165//! #[orm(size = 200)]
166//! title: String,
167//!
168//! content: String,
169//!
170//! published: bool,
171//!
172//! #[orm(create_time)]
173//! created_at: DateTime<Utc>,
174//! }
175//! ```
176
177// ============================================================================
178// Compiler Directives
179// ============================================================================
180
181// Ensure this crate is only used as a proc-macro crate
182#![warn(missing_docs)]
183
184// ============================================================================
185// External Crate Imports
186// ============================================================================
187
188use proc_macro::TokenStream;
189use syn::{parse_macro_input, DeriveInput};
190
191// ============================================================================
192// Module Declarations
193// ============================================================================
194
195/// Type mapping module - converts Rust types to SQL types.
196///
197/// This module contains the logic for mapping Rust types (including primitives,
198/// UUID, chrono types, and Option<T>) to their corresponding SQL type strings.
199mod types;
200
201/// Model derive implementation module.
202///
203/// This module contains the core logic for expanding the `#[derive(Model)]`
204/// macro, including attribute parsing and code generation.
205mod derive_model;
206
207/// FromAnyRow derive implementation module.
208///
209/// This module contains the logic for expanding the `#[derive(FromAnyRow)]`
210/// macro, facilitating the mapping of `AnyRow` results to Rust structs.
211mod derive_anyrow;
212
213// ============================================================================
214// Procedural Macro Definitions
215// ============================================================================
216
217/// Derives the `Model` trait for a struct.
218///
219/// This procedural macro inspects the struct fields and generates the necessary
220/// code to map the struct to a database table. It automatically implements the
221/// `Model` trait with methods for retrieving table metadata and converting
222/// instances to/from database format.
223///
224/// # Supported Attributes
225///
226/// The macro recognizes the following `#[orm(...)]` attributes on struct fields:
227///
228/// * `primary_key` - Marks the field as a primary key
229/// * `unique` - Adds a UNIQUE constraint
230/// * `index` - Creates a database index
231/// * `create_time` - Sets default value to CURRENT_TIMESTAMP
232/// * `update_time` - Auto-updates timestamp (future feature)
233/// * `size = N` - Sets column size (VARCHAR(N))
234/// * `foreign_key = "Table::Column"` - Defines a Foreign Key relationship
235///
236/// # Type Mapping
237///
238/// The macro automatically maps Rust types to SQL types:
239///
240/// - **Primitives**: `i32` → INTEGER, `i64` → BIGINT, `bool` → BOOLEAN, etc.
241/// - **UUID**: `Uuid` → UUID (supports all versions 1-7)
242/// - **Strings**: `String` → TEXT or VARCHAR(N) with size attribute
243/// - **Date/Time**: `DateTime<Utc>` → TIMESTAMPTZ, etc.
244/// - **Nullable**: `Option<T>` → SQL type of T with NULL allowed
245///
246/// # Requirements
247///
248/// The struct must have named fields. Tuple structs and unit structs are not supported.
249///
250/// # Generated Implementation
251///
252/// The macro generates an implementation of the `Model` trait with four methods:
253///
254/// 1. `table_name()` - Returns the struct name as a static string
255/// 2. `columns()` - Returns column metadata as `Vec<ColumnInfo>`
256/// 3. `active_columns()` - Returns column names as `Vec<&'static str>`
257/// 4. `to_map()` - Serializes the instance to `HashMap<String, String>`
258///
259/// # Example
260///
261/// ```rust,ignore
262/// use bottle_orm::Model;
263/// use uuid::Uuid;
264/// use chrono::{DateTime, Utc};
265///
266/// #[derive(Model)]
267/// struct User {
268/// #[orm(primary_key)]
269/// id: Uuid,
270///
271/// #[orm(size = 50, unique)]
272/// username: String,
273///
274/// #[orm(size = 100)]
275/// email: String,
276///
277/// age: i32,
278///
279/// #[orm(create_time)]
280/// created_at: DateTime<Utc>,
281/// }
282/// ```
283///
284/// # Panics
285///
286/// The macro will panic at compile time if:
287///
288/// - The input is not a struct
289/// - The struct doesn't have named fields
290/// - An `#[orm(...)]` attribute is malformed
291/// - A `foreign_key` attribute doesn't follow the "Table::Column" format
292///
293/// # See Also
294///
295/// * [`Model`](../bottle_orm/trait.Model.html) - The trait being implemented
296/// * [`ColumnInfo`](../bottle_orm/struct.ColumnInfo.html) - Column metadata structure
297#[proc_macro_derive(Model, attributes(orm))]
298pub fn model_derive(input: TokenStream) -> TokenStream {
299 // Parse the input tokens into a syntax tree
300 let ast = parse_macro_input!(input as DeriveInput);
301
302 // Expand the macro to generate the Model trait implementation
303 let expanded = derive_model::expand(ast);
304
305 // Convert the generated code back into a TokenStream
306 TokenStream::from(expanded)
307}
308
309/// Derives the `FromRow` trait for `AnyRow` and the `AnyImpl` trait.
310///
311/// This procedural macro generates an implementation of `sqlx::FromRow<'r, sqlx::any::AnyRow>`
312/// for the target struct, allowing it to be scanned directly from database results when
313/// using `sqlx::Any` driver (which Bottle ORM uses internally).
314///
315/// It also implements the `AnyImpl` trait, which provides necessary column metadata used
316/// by the `QueryBuilder` for dynamic query construction.
317///
318/// # Features
319///
320/// - **Automatic Field Mapping**: Maps database columns to struct fields by name.
321/// - **DateTime Handling**: Includes special logic to handle `DateTime` types, often required
322/// when dealing with the `Any` driver's type erasure or JSON serialization fallback.
323/// - **Metadata Generation**: Automatically generates `AnyInfo` for each field.
324///
325/// # Requirements
326///
327/// The struct must have named fields. Tuple structs and unit structs are not supported.
328///
329/// # Example
330///
331/// ```rust,ignore
332/// use bottle_orm::{FromAnyRow, AnyImpl};
333/// use chrono::{DateTime, Utc};
334///
335/// #[derive(FromAnyRow)]
336/// struct UserCount {
337/// count: i64,
338/// last_active: DateTime<Utc>,
339/// }
340///
341/// // Usage with QueryBuilder:
342/// // let stats: UserCount = db.model::<User>().select("count(*), last_active").first().await?;
343/// ```
344#[proc_macro_derive(FromAnyRow)]
345pub fn any_derive(input: TokenStream) -> TokenStream {
346 let ast = parse_macro_input!(input as DeriveInput);
347 let expanded = derive_anyrow::expand(ast);
348 TokenStream::from(expanded)
349}