tardis_macros/lib.rs
1//! # Tardis-Macros
2//!
3//! Tardis-Macros is a macro support library for the Tardis framework, providing additional macros to simplify code generation for DTO (Data Transfer Object) with sea_orm.
4//!
5//! ## Main Macros
6//!
7//! - [`TardisCreateEntity`]: Generates code to create entities, combining `TardisCreateIndex` and `TardisCreateTable`.
8//!
9//! ## Features
10//!
11//! Tardis-Macros supports the following features, which enable the usage of specific macros:
12//!
13//! | Feature | Macro |
14//! |-------------------------------------------------|-------------------------|
15//! | `reldb-postgres`or`reldb-mysql`or`reldb-sqlite` | `TardisCreateTable` |
16//! | `reldb-postgres`or`reldb-mysql`or`reldb-sqlite` | `TardisCreateIndex` |
17//! | `reldb-postgres`or`reldb-mysql`or`reldb-sqlite` | `TardisCreateEntity` |
18//! | `reldb-postgres`or`reldb-mysql`or`reldb-sqlite` | `TardisEmptyBehavior` |
19//! | `reldb-postgres`or`reldb-mysql`or`reldb-sqlite` | `TardisEmptyRelation` |
20//!
21//!
22//! Please note that the availability of each macro depends on the enabled features. Make sure to enable the corresponding feature to use the desired macro.
23//!
24//! ## How to Use
25//!
26//! ### Best Practices
27//!
28//! Add the `TardisCreateEntity` macro to your struct definition, along with other necessary derive macros like `DeriveEntityModel`, `TardisEmptyBehavior`, and `TardisEmptyRelation`.
29//!
30//! Example usage:
31//!
32//! ```rust ignore
33//! #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, TardisCreateEntity, TardisEmptyBehavior, TardisEmptyRelation)]
34//! #[sea_orm(table_name = "examples")]
35//! pub struct Model {
36//! #[sea_orm(primary_key, auto_increment = false)]
37//! pub id: String,
38//! #[index]
39//! #[fill_ctx(own_paths)]
40//! pub aaa: String,
41//! }
42//! ```
43//! You also can refer to the example code and test cases for the best practices on using the Tardis-Macros library.
44//!
45//!
46//! For more examples and detailed usage, please refer to the documentation of each specific macro.
47//!
48//! [TardisCreateEntity]
49
50#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
51use proc_macro::TokenStream;
52#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
53use syn::{parse_macro_input, DeriveInput};
54
55/// # TardisCreateTable
56/// Generate table creation statement, compatible with `tardis_entity`.
57/// see [TardisActiveModel::create_table_statement](https://docs.rs/tardis/latest/tardis/db/reldb_client/trait.TardisActiveModel.html#method.create_table_statement).
58///
59/// According to tardis_entity automatically generates `tardis_create_table_statement(db: DbBackend)`
60/// method, you can be directly called in the `TardisActiveModel::create_table_statement` method. \
61/// example see [macros_examples::example_for_derive_create_tabled].
62///
63/// ## tardis_entity attribute
64///
65/// - `custom_len`: Custom length for the table columns. (optional)
66///
67/// [`sea-query::tabled::column::ColumnDef`]: https://docs.rs/sea-query/latest/sea_query/table/struct.ColumnDef.html
68#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
69#[proc_macro_derive(TardisCreateTable, attributes(tardis_entity))]
70pub fn tardis_create_table(input: TokenStream) -> TokenStream {
71 let DeriveInput { ident, data, attrs, .. } = parse_macro_input!(input as DeriveInput);
72 match tardis_create_table::create_table(ident, data, attrs) {
73 Ok(stream) => stream.into(),
74 Err(err) => err.to_compile_error().into(),
75 }
76}
77
78/// # TardisCreateIndex
79/// Generate index creation statement, compatible with `tardis_entity`.
80/// see [create_index_statement](https://docs.rs/tardis/latest/tardis/db/reldb_client/trait.TardisActiveModel.html#method.create_index_statement).
81///
82/// According to tardis_entity automatically generates `tardis_create_index_statement()` method,
83/// you can be directly called in the `TardisActiveModel::create_index_statement` method. \
84/// example see [macros_examples::example_for_derive_create_index].
85///
86/// ## index attribute
87///
88/// - `index_id`: ID of the index. (default: Random id)
89/// - `name`: Name of the index. (optional)
90/// - `primary`: Specifies if the index is a primary index. (default: `false`)
91/// - `unique`: Specifies if the index is a unique index. (default: `false`)
92/// - `full_text`: Specifies if the index is a full-text index. (default: `false`)
93/// - `if_not_exists`: Specifies if the index should be created if it doesn't exist. (default: `false`)
94/// - `index_type`: Type of the index. See "Index Types" section for possible values. (optional)
95///
96/// ### index_id parameter
97///
98/// Each default index will be a separate index statement. \
99/// If you want to add multiple properties to a single index statement, you must set the `index_id` to the same value.
100///
101/// Same index_id, if there are different variable assignments, only the first one will take effect. \
102/// For example,the name of the generated statement is name1 instead of name2.
103/// ```ignore
104/// #[index(index_id="1",name="name1")]
105/// name1:String,
106/// #[index(index_id="1",name="name2")]
107/// name2:String,
108/// ```
109///
110/// ### Index Types
111///
112/// The `index_type` value needs to be one of the following:
113///
114/// - BTree
115/// - FullText
116/// - Gin
117/// - Hash
118/// - Custom
119///
120/// Example for custom:
121/// ```ignore
122/// #[derive(Clone, Debug, DeriveEntityModel, TardisCreateIndex)]
123/// #[sea_orm(table_name = "examples")]
124/// pub struct Model {
125/// #[sea_orm(primary_key)]
126/// #[tardis_entity(primary_key)]
127/// pub id: String,
128/// #[index(index_id = "index_id_1", index_type = "Custom(Test)")]
129/// pub custom_index_col: String,
130/// }
131///
132/// struct Test;
133/// impl Iden for Test {
134/// todo!()
135/// }
136/// ```
137///
138///
139#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
140#[proc_macro_derive(TardisCreateIndex, attributes(index))]
141pub fn tardis_create_index(input: TokenStream) -> TokenStream {
142 let DeriveInput { ident, data, attrs, .. } = parse_macro_input!(input as DeriveInput);
143 match tardis_create_index::create_index(ident, data, attrs) {
144 Ok(stream) => stream.into(),
145 Err(err) => err.to_compile_error().into(),
146 }
147}
148
149/// # TardisCreateEntity
150/// The functionality of `TardisCreateEntity` is equivalent to `TardisCreateIndex` combined with `TardisCreateTable`.
151/// Additionally, it introduces a new attribute called fill_ctx, and automatically implements `ActiveModelBehavior`. \
152/// see [TardisCreateIndex] and [TardisCreateTable]
153#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
154#[proc_macro_derive(TardisCreateEntity, attributes(tardis_entity, index, fill_ctx))]
155pub fn tardis_create_entity(input: TokenStream) -> TokenStream {
156 let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);
157
158 match tardis_create_entity::create_entity(ident, data) {
159 Ok(stream) => stream.into(),
160 Err(err) => err.to_compile_error().into(),
161 }
162}
163/// # TardisEmptyBehavior
164/// Generates an empty implementation of `ActiveModelBehavior` for `ActiveModel`.
165#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
166#[proc_macro_derive(TardisEmptyBehavior)]
167pub fn tardis_empty_behavior(input: TokenStream) -> TokenStream {
168 let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);
169
170 match tardis_empty_impl::create_empty_behavior(ident, data) {
171 Ok(stream) => stream.into(),
172 Err(err) => err.to_compile_error().into(),
173 }
174}
175/// #TardisEmptyRelation
176/// Generates an empty `Relation`.
177#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
178#[proc_macro_derive(TardisEmptyRelation)]
179pub fn tardis_empty_relation(input: TokenStream) -> TokenStream {
180 let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);
181
182 match tardis_empty_impl::create_empty_relation(ident, data) {
183 Ok(stream) => stream.into(),
184 Err(err) => err.to_compile_error().into(),
185 }
186}
187
188#[allow(dead_code)]
189pub(crate) mod macro_helpers;
190#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
191mod tardis_create_entity;
192#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
193mod tardis_create_index;
194#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
195mod tardis_create_table;
196#[cfg(any(feature = "reldb-postgres", feature = "reldb-mysql", feature = "reldb-sqlite"))]
197mod tardis_empty_impl;