lorm_macros/lib.rs
1use proc_macro::TokenStream;
2use syn::{DeriveInput, parse_macro_input};
3
4mod models;
5mod orm;
6mod utils;
7
8/// `#[derive(ToLOrm)]`
9/// generate methods for Object Relational Mapping.
10///
11/// attributes:
12///
13/// `#[lorm(pk)]`
14/// Annotated field is marked as being the primary key and can only be generated at insertion time.
15/// This field is also automatically considered as a `#[lorm(by)]` field.
16/// - If `#[lorm(new)]` is specified, it will use its struct method to generate a new pk at insertion time
17/// - If `#[lorm(is_set)]` is specified, it will use its instance method against `self` to check if the pk is set. Otherwise it compares the pk value with its <struct>::default() (assuming the Default trait is set)
18/// - If `#[lorm(readonly)]` is specified, it will ignore is_set `#[lorm(new)]` and `#[lorm(is_set)]` and let the database handles the field
19///
20/// `#[lorm(rename="name")]`
21/// - at struct level to rename at table name
22/// - at field level to rename at column name
23///
24/// by default, a table name is the struct name pluralized and converted to table case: UserDetail => user_details.
25/// by default, a field name is converted to snake_case: UserDetail => user_detail.
26///
27/// `#[lorm(skip)]`
28/// Ignore field for persistence operations. Using sqlx::FromRow, skip needs `#[lorm(skip)]` and `#[sqlx(skip)]`
29///
30/// `#[lorm(readonly)]`
31/// readonly attribute. Cannot be updated not inserted.
32/// Special cases to consider:
33/// - If applied to the primary key, key generation is left to the database. No update possible as it is the primary key.
34/// - If applied to create_at or updated_at field, timestamp generation is left to the database. No update possible.
35///
36/// `#[lorm(by)]`
37/// Generates query methods for this field:
38/// - `by_<field>(executor, value)` - Find single record by field value
39/// - `with_<field>(executor, value)` - Find all records matching field value
40/// - `where_<field>(Where, value)` - Filter in select() query builder
41/// - `where_between_<field>(start, end)` - Range filter in select() query builder
42/// - `order_by_<field>()` - Order results by this field (chain with `.asc()` or `.desc()`)
43/// - `group_by_<field>()` - Group results by this field
44///
45/// `#[lorm(created_at)]`
46/// Add the `#[lorm(created_at)]` annotation to mark the field as the `created_at` field.
47/// - If `#[lorm(new)]` is specified, it will use its method to update the time upon insertion
48/// - If `#[lorm(readonly)]` is specified, it will ignore is_set `#[lorm(new)]` and let the database handles the field
49///
50/// `#[lorm(updated_at)]`
51/// Add the `#[lorm(updated_at)]` annotation to mark the field as the `updated_at` field.
52/// - If `#[lorm(new)]` is specified, it will use its method to update the time upon insertion and update
53/// - If `#[lorm(readonly)]` is specified, it will ignore is_set `#[lorm(new)]` and let the database handles the field
54///
55/// `#[lorm(new="module::path::class::new_custom()")]`
56/// Add the `#[lorm(new="module::path::class::new_custom()")]` annotation to use a custom creation method.
57/// - The function call is expected to return an instance
58/// - When not provided, the type::new() method is called
59///
60/// `#[lorm(is_set="is_nil()")]`
61/// Uses a specific function call to check if the returned value if the default value.
62/// The function call is expected to return bool.
63/// Defaults to class_type::default() which assumes both the Default and PartialEq trait are implemented.
64///
65#[proc_macro_derive(ToLOrm,
66 attributes(
67 lorm,
68 // lorm(pk),
69 // lorm(by),
70 // lorm(skip),
71 // lorm(readonly),
72 // lorm(new="module::path::class::new_custom()"),
73 // lorm(is_set="is_nil()"),
74 // lorm(rename="name"),
75 // lorm(created_at),
76 // lorm(updated_at),
77 )
78)]
79pub fn sql_derive_to_orm(input: TokenStream) -> TokenStream {
80 let input = parse_macro_input!(input as DeriveInput);
81 match orm::expand_derive_to_orm(&input) {
82 Ok(ts) => ts,
83 Err(e) => e.to_compile_error().into(),
84 }
85}