rbatis_macro_driver/lib.rs
1#![allow(unused_assignments)]
2extern crate proc_macro;
3extern crate rbatis_codegen;
4
5use syn::parse::{Parse, ParseStream};
6use syn::punctuated::Punctuated;
7use syn::{parse_macro_input, ItemFn, Token};
8
9use crate::macros::html_sql_impl::impl_macro_html_sql;
10use crate::macros::py_sql_impl::impl_macro_py_sql;
11use crate::macros::sql_impl::impl_macro_sql;
12use crate::proc_macro::TokenStream;
13
14mod macros;
15mod util;
16
17struct ParseArgs {
18 pub sqls: Vec<syn::LitStr>,
19}
20
21impl Parse for ParseArgs {
22 fn parse(input: ParseStream) -> syn::Result<Self> {
23 let r = Punctuated::<syn::LitStr, Token![,]>::parse_terminated(input)?;
24 Ok(Self {
25 sqls: r.into_iter().collect(),
26 })
27 }
28}
29
30/// auto create sql macro,this macro use RB.query_prepare and RB.exec_prepare
31/// for example:
32///```log
33/// use rbatis::plugin;
34/// use rbatis::executor::Executor;
35/// #[derive(serde::Serialize,serde::Deserialize)]
36/// pub struct MockTable{}
37///
38/// #[sql("select * from biz_activity where id = ?")]
39/// async fn select(rb:&dyn Executor, name: &str) -> MockTable {}
40///```
41#[proc_macro_attribute]
42pub fn sql(args: TokenStream, func: TokenStream) -> TokenStream {
43 let args = parse_macro_input!(args as ParseArgs);
44 let target_fn: ItemFn = syn::parse(func).unwrap();
45 let stream = impl_macro_sql(&target_fn, &args);
46 #[cfg(feature = "println_gen")]
47 if cfg!(debug_assertions) {
48 use quote::ToTokens;
49 let func_name_ident = target_fn.sig.ident.to_token_stream();
50 println!("............#[sql] '{}'...................\n {}", func_name_ident, stream);
51 println!(".......................................................");
52 }
53
54 stream
55}
56
57/// py sql create macro,this macro use RB.py_query and RB.py_exec
58///```log
59/// use rbatis::executor::Executor;
60/// use rbatis::py_sql;
61/// #[derive(serde::Serialize,serde::Deserialize)]
62/// pub struct MockTable{}
63///
64/// #[py_sql("select * from biz_activity where delete_flag = 0")]
65/// async fn py_select_page(rb: &dyn Executor, name: &str) -> Vec<MockTable> { }
66///```
67/// or more example:
68///```log
69/// use rbatis::executor::Executor;
70/// use rbatis::py_sql;
71/// #[derive(serde::Serialize,serde::Deserialize)]
72/// pub struct MockTable{}
73///
74/// #[py_sql("
75/// SELECT * FROM biz_activity
76/// if name != null:
77/// AND delete_flag = #{del}
78/// AND version = 1
79/// if age!=1:
80/// AND version = 1
81/// AND version = 1
82/// AND a = 0
83/// AND version = 1
84/// and id in (
85/// trim ',': for item in ids:
86/// #{item},
87/// )
88/// and id in (
89/// trim ',': for index,item in ids:
90/// #{item},
91/// )
92/// trim 'AND':
93/// AND delete_flag = #{del2}
94/// choose:
95/// when age==27:
96/// AND age = 27
97/// otherwise:
98/// AND age = 0
99/// WHERE id = '2'")]
100/// pub async fn py_select_rb(rb: &dyn Executor, name: &str) -> Option<MockTable> {}
101/// ```
102/// or read from file
103/// ```rust
104/// //#[rbatis::py_sql(r#"include!("C:/rs/rbatis/target/debug/xx.py_sql")"#)]
105/// //pub async fn test_same_id(rb: &dyn Executor, id: &u64) -> Result<Value, Error> { impled!() }
106/// ```
107#[proc_macro_attribute]
108pub fn py_sql(args: TokenStream, func: TokenStream) -> TokenStream {
109 let args = parse_macro_input!(args as ParseArgs);
110 let target_fn: ItemFn = syn::parse(func).unwrap();
111 let stream = impl_macro_py_sql(&target_fn, args);
112 #[cfg(feature = "println_gen")]
113 if cfg!(debug_assertions) {
114 use quote::ToTokens;
115 use rust_format::{Formatter, RustFmt};
116 let func_name_ident = target_fn.sig.ident.to_token_stream();
117 let stream_str = stream.to_string().replace("$crate", "rbatis");
118 let code = RustFmt::default()
119 .format_str(&stream_str)
120 .unwrap_or_else(|_e| stream_str.to_string());
121 println!("............#[py_sql] '{}'............\n {}", func_name_ident, code);
122 println!(".......................................................");
123 }
124 stream
125}
126
127/// html sql create macro,this macro use RB.py_query and RB.py_exec
128/// for example:
129/// ```log
130/// use rbatis::executor::Executor;
131/// use rbatis::html_sql;
132/// #[derive(serde::Serialize,serde::Deserialize)]
133/// pub struct MockTable{}
134///
135/// #[html_sql(r#"
136/// <select id="select_by_condition">
137/// `select * from activity`
138/// <where>
139/// <if test="name != ''">
140/// ` and name like #{name}`
141/// </if>
142/// <if test="dt >= '2023-11-03T21:13:09.9357266+08:00'">
143/// ` and create_time < #{dt}`
144/// </if>
145/// <choose>
146/// <when test="true">
147/// ` and id != '-1'`
148/// </when>
149/// <otherwise>and id != -2</otherwise>
150/// </choose>
151/// ` and `
152/// <trim prefixOverrides=" and">
153/// ` and name != '' `
154/// </trim>
155/// </where>
156/// </select>"#)]
157/// pub async fn select_by_name(rbatis: &dyn Executor, name: &str) -> Option<MockTable> {}
158/// ```
159/// or from file
160/// ```log
161/// #[html_sql("xxxx.html")]
162/// pub async fn select_by_name(rbatis: &dyn Executor, name: &str) -> Option<MockTable> {}
163/// ```
164#[proc_macro_attribute]
165pub fn html_sql(args: TokenStream, func: TokenStream) -> TokenStream {
166 let args = parse_macro_input!(args as ParseArgs);
167 let target_fn: ItemFn = syn::parse(func).unwrap();
168 let stream = impl_macro_html_sql(&target_fn, &args);
169 #[cfg(feature = "println_gen")]
170 if cfg!(debug_assertions) {
171 use quote::ToTokens;
172 use rust_format::{Formatter, RustFmt};
173 let func_name_ident = target_fn.sig.ident.to_token_stream();
174 let stream_str = stream.to_string().replace("$crate", "rbatis");
175 let code = RustFmt::default()
176 .format_str(&stream_str)
177 .unwrap_or_else(|_e| stream_str.to_string());
178 println!("............#[html_sql] '{}'............\n {}", func_name_ident, code);
179 println!(".......................................................");
180 }
181 stream
182}
183
184/// proxy rbatis_codegen rb_py
185#[proc_macro_attribute]
186pub fn rb_py(args: TokenStream, func: TokenStream) -> TokenStream {
187 rbatis_codegen::rb_py(args, func)
188}
189
190/// proxy rbatis_codegen rb_html
191#[proc_macro_attribute]
192pub fn rb_html(args: TokenStream, func: TokenStream) -> TokenStream {
193 rbatis_codegen::rb_html(args, func)
194}
195
196#[proc_macro_attribute]
197pub fn snake_name(args: TokenStream, func: TokenStream) -> TokenStream {
198 macros::snake_name::snake_name(args, func)
199}