db_cores/common/
macros.rs1
2#[macro_export]
3macro_rules! define_model {
4 ($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)] #[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 #[allow(dead_code)]
29 pub fn update_time(&mut self) {
30 let now = $crate::utlis::_utc_ms_option();
32 $( if stringify!($column) == "updated_at" {
33 self.updated_at = now;
34 } )*
35 }
36 #[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 (
54 $(#[$enum_attr:meta])*
55 $vis:vis enum $name:ident {
56 $(
57 $(#[$variant_attr:meta])*
58 $variant:ident = $value:expr
59 ),* $(,)?
60 }
61 ) => {
62 $(#[$enum_attr])*
64 $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 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 impl $crate::serde::Serialize for $name { 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 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 #[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()) }
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: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:expr, $params:expr) => {{
204 use ::regex::Regex;
205 use ::sqlx::QueryBuilder;
206 let sql_str = $sql.as_ref(); let re = Regex::new(r"(\?|\$\d+)").unwrap();
208 let parts: Vec<&str> = re.split(sql_str).collect();
209 let params_ref = &$params; 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#[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}