sqlx_model/
sql_quote.rs

1/// 实现用于转义变量的trait
2pub trait SqlQuote<OUT>
3where
4    OUT: std::fmt::Display,
5{
6    fn sql_quote(&self) -> OUT;
7}
8
9/// 保留原样的变量,不自动转义,当为自定义SQL 不能当字符串串处理时使用
10pub struct SqlExpr<T: std::fmt::Display>(pub T);
11impl<T: std::fmt::Display> SqlQuote<String> for SqlExpr<T> {
12    fn sql_quote(&self) -> String {
13        format!("{}", &self.0)
14    }
15}
16macro_rules! array_join_to_str {
17    ($self:expr) => {
18        $self
19            .into_iter()
20            .map(|e| format!("{}", e.sql_quote()))
21            .collect::<Vec<String>>()
22            .join(",")
23    };
24}
25macro_rules! option_to_str {
26    ($self:expr) => {
27        match $self {
28            Some(str) => str.sql_quote().to_string(),
29            None => "NULL".to_string(),
30        }
31    };
32}
33//常用类型
34macro_rules! sql_quote_self {
35    ($in_type:ty) => {
36        impl SqlQuote<$in_type> for $in_type {
37            fn sql_quote(&self) -> $in_type {
38                *self
39            }
40        }
41    };
42}
43sql_quote_self!(i8);
44sql_quote_self!(i16);
45sql_quote_self!(i32);
46sql_quote_self!(i64);
47sql_quote_self!(i128);
48sql_quote_self!(u8);
49sql_quote_self!(u16);
50sql_quote_self!(u32);
51sql_quote_self!(u64);
52sql_quote_self!(u128);
53sql_quote_self!(f32);
54sql_quote_self!(f64);
55sql_quote_self!(usize);
56sql_quote_self!(isize);
57impl SqlQuote<String> for char {
58    fn sql_quote(&self) -> String {
59        if (*self) == '\'' {
60            "'\\''".to_string()
61        } else {
62            format!("'{self}'")
63        }
64    }
65}
66impl SqlQuote<u8> for bool {
67    fn sql_quote(&self) -> u8 {
68        (*self) as u8
69    }
70}
71impl SqlQuote<String> for &str {
72    fn sql_quote(&self) -> String {
73        format!("'{}'", self.replace('\'', "\\'"))
74    }
75}
76impl SqlQuote<String> for String {
77    fn sql_quote(&self) -> String {
78        format!("'{}'", self.replace('\'', "\\'"))
79    }
80}
81//OPTION<常用类型>
82macro_rules! sql_quote_option {
83    ($in_type:ty) => {
84        impl SqlQuote<String> for Option<$in_type> {
85            fn sql_quote(&self) -> String {
86                option_to_str!(self)
87            }
88        }
89    };
90}
91sql_quote_option!(i8);
92sql_quote_option!(i16);
93sql_quote_option!(i32);
94sql_quote_option!(i64);
95sql_quote_option!(i128);
96sql_quote_option!(u8);
97sql_quote_option!(u16);
98sql_quote_option!(u32);
99sql_quote_option!(u64);
100sql_quote_option!(u128);
101sql_quote_option!(f32);
102sql_quote_option!(f64);
103sql_quote_option!(usize);
104sql_quote_option!(isize);
105sql_quote_option!(bool);
106sql_quote_option!(char);
107sql_quote_option!(String);
108sql_quote_option!(&i8);
109sql_quote_option!(&i16);
110sql_quote_option!(&i32);
111sql_quote_option!(&i64);
112sql_quote_option!(&i128);
113sql_quote_option!(&u8);
114sql_quote_option!(&u16);
115sql_quote_option!(&u32);
116sql_quote_option!(&u64);
117sql_quote_option!(&u128);
118sql_quote_option!(&f32);
119sql_quote_option!(&f64);
120sql_quote_option!(&usize);
121sql_quote_option!(&isize);
122sql_quote_option!(&bool);
123sql_quote_option!(&char);
124sql_quote_option!(&String);
125sql_quote_option!(&str);
126
127//Vec<常用类型> or [常用类型]
128macro_rules! sql_quote_array {
129    ($in_type:ty) => {
130        impl SqlQuote<String> for Vec<$in_type> {
131            fn sql_quote(&self) -> String {
132                array_join_to_str!(self)
133            }
134        }
135        impl SqlQuote<String> for &Vec<$in_type> {
136            fn sql_quote(&self) -> String {
137                array_join_to_str!(self)
138            }
139        }
140        impl SqlQuote<String> for [$in_type] {
141            fn sql_quote(&self) -> String {
142                array_join_to_str!(self)
143            }
144        }
145        impl SqlQuote<String> for &[$in_type] {
146            fn sql_quote(&self) -> String {
147                array_join_to_str!(self)
148            }
149        }
150    };
151}
152sql_quote_array!(i8);
153sql_quote_array!(i16);
154sql_quote_array!(i32);
155sql_quote_array!(i64);
156sql_quote_array!(i128);
157sql_quote_array!(u8);
158sql_quote_array!(u16);
159sql_quote_array!(u32);
160sql_quote_array!(u64);
161sql_quote_array!(u128);
162sql_quote_array!(f32);
163sql_quote_array!(f64);
164sql_quote_array!(usize);
165sql_quote_array!(isize);
166sql_quote_array!(bool);
167sql_quote_array!(&str);
168sql_quote_array!(String);
169
170#[macro_export]
171/// 转义SQL生成,对字符串中的单引号加反斜杠
172macro_rules! sql_format {
173    ($fmt:expr) => {
174        format!($fmt)
175    };
176    ($fmt:expr,$($argsname:tt=$argsval:expr),+$(,)?) => {
177        format!($fmt,$($argsname=$argsval.sql_quote()) ,+)
178    };
179    ($fmt:expr,$($args:expr),+$(,)?) => {
180        format!($fmt,$($args.sql_quote()),+)
181    };
182}
183#[macro_export]
184/// 根据vec或[]中是否存在元素来决定是否生成SQL字符串
185/// 一般用在 in 语句生成
186macro_rules! sql_array_str {
187    ($fmt:expr,$val:expr) => {
188        if $val.len() == 0 {
189            $crate::SqlExpr("".to_string())
190        } else {
191            $crate::SqlExpr(format!($fmt, $val.sql_quote()))
192        }
193    };
194}
195#[macro_export]
196/// 根据Option中是否是NONE来生成不同的SQL
197macro_rules! sql_option_str {
198    ($some_fmt:expr,$none_fmt:expr,$val:expr) => {
199        if $val.is_none() {
200            $crate::SqlExpr(format!($none_fmt, $val.sql_quote()))
201        } else {
202            $crate::SqlExpr(format!($some_fmt, $val.sql_quote()))
203        }
204    };
205}
206
207#[test]
208fn test_sql_format_macro() {
209    assert_eq!(sql_format!("{var_i32}", var_i32 = 1), "1");
210    assert_eq!(sql_format!("{}", 1_i8), "1");
211
212    let aa = || 1;
213    assert_eq!(sql_format!("{}", aa()), "1");
214    fn bb() -> i8 {
215        1
216    }
217    assert_eq!(sql_format!("{}", bb()), "1");
218
219    assert_eq!(sql_format!("{}", "1'1'1"), "'1\\'1\\'1'");
220    assert_eq!(sql_format!("{}", "1'1'1".to_string()), "'1\\'1\\'1'");
221
222    assert_eq!(sql_format!("{}", '\''), "'\\''");
223
224    assert_eq!(
225        sql_format!("{}", vec!["1", "2'2'2'2'"]),
226        "'1','2\\'2\\'2\\'2\\''"
227    );
228
229    assert_eq!(
230        sql_format!("{}", ["1", "2'2'2'2'"]),
231        "'1','2\\'2\\'2\\'2\\''"
232    );
233
234    assert_eq!(
235        sql_format!("{}", ["1".to_string(), "2'2'2'2'".to_string()]),
236        "'1','2\\'2\\'2\\'2\\''"
237    );
238
239    assert_eq!(
240        sql_format!("{}", vec!["1".to_string(), "2'2'2'2'".to_string()]),
241        "'1','2\\'2\\'2\\'2\\''"
242    );
243
244    let a: [i8; 0] = [];
245    assert_eq!(sql_format!("{}", sql_array_str!("ddd in ({})", a)), "");
246
247    assert_eq!(
248        sql_format!("{}", sql_array_str!("ddd in ({})", [1, 2])),
249        "ddd in (1,2)"
250    );
251
252    assert_eq!(
253        sql_format!("{}", sql_option_str!("a = {}", "{}", Some(1))),
254        "a = 1"
255    );
256
257    let i: Option<i128> = None;
258    assert_eq!(
259        sql_format!("{}", sql_option_str!("{}", "a is {}", i)),
260        "a is NULL"
261    );
262
263    assert_eq!(sql_format!("{}", SqlExpr("select 1 as a")), "select 1 as a");
264}