Skip to main content

db_cores/common/
macros.rs

1
2#[macro_export]
3macro_rules! define_model {
4    // ident为标识符, expr是表达式,
5    ($struct:ident,
6     $table_name:expr,
7    $(
8        $(#[$field_attr:meta])*
9        $column:ident : $type:ty
10    ),* $(,)?
11
12    ) => {
13        
14        #[allow(unused_attributes)]
15        #[derive(Debug, $crate::serde::Serialize, $crate::serde::Deserialize, $crate::db_proc_macro::ToFields, $crate::db_proc_macro::ToOption, Clone)] //::app_macro::ToOption,
16        #[cfg_attr(any(feature = "postgres", feature = "mysql", feature = "sqlite"), derive($crate::sqlx::FromRow))]
17        pub struct $struct {
18            $(
19                $(#[$field_attr])*
20                pub $column: $type,
21            )*
22        }
23
24        impl $struct {
25            #[allow(dead_code)]
26            pub const NAME: &'static str = $table_name;
27            /// 系统字段:更新时间戳
28            #[allow(dead_code)]
29            pub fn update_time(&mut self) {
30                //  前端一律不上传 created_at, 由数据库自动生成
31                let now = $crate::utlis::_utc_ms_option();
32                $( if stringify!($column) == "updated_at" {
33                    self.updated_at = now;
34                } )*
35            }
36            // 返加postgres 加上 schema的table名
37            #[allow(dead_code)]
38            pub fn pg_table(schema:&str)->String{
39                if !schema.is_empty() {
40                    format!("\"{}\".\"{}\"" , schema, Self::NAME)
41                } else {
42                    format!("\"{}\"" , Self::NAME)
43                }
44            }
45        }
46    }
47}
48
49
50#[macro_export]
51macro_rules! define_enum {
52    // 定义宏规则
53    (
54        $(#[$enum_attr:meta])*
55        $vis:vis enum $name:ident {
56            $(
57                $(#[$variant_attr:meta])*
58                $variant:ident = $value:expr
59            ),* $(,)?
60        }
61    ) => {
62        // 定义枚举
63        $(#[$enum_attr])*
64        // #[derive(Debug, Clone)]
65        $vis enum $name {
66            $(
67                $(#[$variant_attr])*
68                $variant,
69            )*
70        }
71
72        impl $name {
73            pub fn to_str(&self) -> &'static str {
74                match self {
75                    $(
76                        $name::$variant => $value,
77                    )*
78                }
79            }
80        }
81
82        // 实现 FromStr  s.parse() 就是调用了 FromStr trait 的 from_str 方法
83        impl ::std::str::FromStr for $name {
84            type Err = String;
85            fn from_str(s: &str) -> Result<Self, Self::Err> {
86                match s {
87                    $(
88                        $value => Ok($name::$variant),
89                    )*
90                    _ => Err(format!("Invalid value for {}: {}", stringify!($name), s)),
91                }
92            }
93        }
94
95        // 实现 Serialize
96        impl $crate::serde::Serialize for $name {  // 从结构 序列化 成 json时才会调用
97            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
98            where
99                S: $crate::serde::Serializer,
100            {
101                let value = match self {
102                    $(
103                        $name::$variant => $value,
104                    )*
105                };
106                serializer.serialize_str(value)
107            }
108        }
109
110
111        // 实现 Deserialize  当sqlx 解析son内容时会调用
112        impl<'de> $crate::serde::Deserialize<'de> for $name {
113            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
114            where
115                D: $crate::serde::Deserializer<'de>,
116            {
117                let s = String::deserialize(deserializer)?;
118                match s.as_str() {
119                    $(
120                        $value => Ok($name::$variant),
121                    )*
122                    _ => Err(::serde::de::Error::custom(
123                        format!(concat!("Invalid value for ", stringify!($name), ": {}"), s))),
124                }
125            }
126        }
127
128
129        // $crate::sqlx  前提是lib 有  pub use sqlx;
130        #[cfg(feature = "sqlite")]
131        impl<'r> $crate::sqlx::Decode<'r, $crate::sqlx::Sqlite> for $name {
132            fn decode(value: $crate::sqlx::sqlite::SqliteValueRef<'r>) -> Result<Self, $crate::sqlx::error::BoxDynError> {
133                let value_str = <String as $crate::sqlx::Decode<$crate::sqlx::Sqlite>>::decode(value)?;
134                $name::from_str(&value_str).map_err(|e| e.into()) //
135            }
136        }
137
138        #[cfg(feature = "mysql")]
139        impl<'r> $crate::sqlx::Decode<'r, $crate::sqlx::MySql> for $name {
140            fn decode(value: $crate::sqlx::mysql::MySqlValueRef<'r>) -> Result<Self, $crate::sqlx::error::BoxDynError> {
141                let value_str = <String as $crate::sqlx::Decode<$crate::sqlx::MySql>>::decode(value)?;
142                $name::from_str(&value_str).map_err(|e| e.into())
143            }
144        }
145
146        #[cfg(feature = "postgres")]
147        impl<'r> $crate::sqlx::Decode<'r, $crate::sqlx::Postgres> for $name {
148            fn decode(value: $crate::sqlx::postgres::PgValueRef<'r>) -> Result<Self, $crate::sqlx::error::BoxDynError> {
149                let value_str = <String as $crate::sqlx::Decode<$crate::sqlx::Postgres>>::decode(value)?;
150                $name::from_str(&value_str).map_err(|e| e.into())
151            }
152        }
153
154        #[cfg(feature = "sqlite")]
155        impl $crate::sqlx::Type<$crate::sqlx::Sqlite> for $name {
156            fn type_info() -> $crate::sqlx::sqlite::SqliteTypeInfo {
157                <String as $crate::sqlx::Type<$crate::sqlx::Sqlite>>::type_info()
158            }
159        }
160
161        #[cfg(feature = "postgres")]
162        impl $crate::sqlx::Type<$crate::sqlx::Postgres> for $name {
163            fn type_info() -> $crate::sqlx::postgres::PgTypeInfo  {
164                <String as $crate::sqlx::Type<$crate::sqlx::Postgres>>::type_info()
165            }
166        }
167
168        #[cfg(feature = "mysql")]
169        impl $crate::sqlx::Type<$crate::sqlx::MySql> for $name {
170            fn type_info() -> $crate::sqlx::mysql::MySqlTypeInfo{
171                <String as $crate::sqlx::Type<$crate::sqlx::MySql>>::type_info()
172            }
173        }
174    };
175}
176
177
178
179#[cfg(feature = "postgres")]
180#[macro_export]
181macro_rules! pg_builder {
182    //  第一个参数为Sql str,  第二个参数 匹配方括号写法: 编译期已知参数列表 [expr, expr, ...]
183    ($sql:expr, [$($param:expr),* $(,)?]) => {{
184        use ::regex::Regex;
185        use ::sqlx::QueryBuilder;
186        let sql_str = $sql.as_ref();
187        let re = Regex::new(r"(\?|\$\d+)").unwrap();
188        let parts: Vec<&str> = re.split(sql_str).collect();
189        let param_count = 0 $( + { let _ = &$param; 1 } )*;
190        if parts.len() != param_count + 1 {panic!("参数数量与 SQL 占位符数量不匹配: 发现 {} 个占位符, 提供了 {} 个参数",parts.len() - 1, param_count ); }
191        let mut builder: QueryBuilder<'_, ::sqlx::postgres::Postgres> = QueryBuilder::new("");
192        let mut _i = 0;
193        $(
194            builder.push(parts[_i]);
195            builder.push_bind(&$param);
196            _i += 1;
197        )*
198        builder.push(parts[_i]);
199        builder
200    }};
201
202    //  第一个参数为Sql str,  第二参数 匹配运行时参数容器:Vec<T> 或 &[T]
203    ($sql:expr, $params:expr) => {{
204        use ::regex::Regex;
205        use ::sqlx::QueryBuilder;
206        let sql_str = $sql.as_ref(); // 这样可以兼容String和 &str
207        let re = Regex::new(r"(\?|\$\d+)").unwrap();
208        let parts: Vec<&str> = re.split(sql_str).collect();
209        let params_ref = &$params; // 引用 Vec/切片
210        let param_count = params_ref.len();
211        if parts.len() != param_count + 1 {
212            panic!( "参数数量与 SQL 占位符数量不匹配: 发现 {} 个占位符, 提供了 {} 个参数", parts.len() - 1, param_count);
213        }
214        let mut builder: QueryBuilder<'_, ::sqlx::postgres::Postgres> = QueryBuilder::new("");
215        for (i, value) in params_ref.iter().enumerate() {
216            builder.push(parts[i]);
217            builder.push_bind(&*value);
218        }
219        builder.push(parts[param_count]);
220        builder
221    }};
222}
223
224// 这个怎么实现     let a = pg_builder!(sql, [b,aa]);  []作用是为了与 sql区别,并不是要传入一个数组切版
225#[cfg(feature = "postgres")]
226#[test]
227fn dev() {
228    let sql = "select * from talbe where id=$1 and  stre=$2";
229    let _b = 34;
230
231    let _aa = "adsb".to_string();
232    let veca = [34, 3434];
233    let a = pg_builder!(sql, veca);
234    let a = a.sql();
235
236    println!("asfd {a}");
237}