halo/
macros.rs

1//! 宏集合:为 builder 提供 Go 式的可变参数调用封装。
2//! 通过 `select_cols!` / `where_exprs!` 等宏,可以使用不定长字符串参数而无需手动创建 `Vec`。
3
4#[doc(hidden)]
5#[macro_export]
6macro_rules! __collect_strings {
7    () => {
8        Vec::<String>::new()
9    };
10    ($($value:expr),+ $(,)?) => {{
11        let mut values = Vec::<String>::new();
12        $(
13        crate::macros::__collect_strings_helper($value, &mut values);
14        )*
15        values
16    }};
17}
18
19#[doc(hidden)]
20#[macro_export]
21macro_rules! __collect_static_strs {
22    () => {
23        Vec::<&'static str>::new()
24    };
25    ($($value:expr),+ $(,)?) => {{
26        let mut values = Vec::<&'static str>::new();
27        $(
28            values.push($value);
29        )*
30        values
31    }};
32}
33
34#[doc(hidden)]
35#[macro_export]
36macro_rules! __builder_with_strings {
37    ($builder:expr, $method:ident $(, $arg:expr)* $(,)?) => {
38        $builder.$method(crate::__collect_strings!($($arg),*))
39    };
40}
41
42pub(crate) trait __IntoStrings {
43    fn extend_into_strings(self, dst: &mut Vec<String>);
44}
45
46impl __IntoStrings for String {
47    fn extend_into_strings(self, dst: &mut Vec<String>) {
48        dst.push(self);
49    }
50}
51
52impl<'a> __IntoStrings for &'a str {
53    fn extend_into_strings(self, dst: &mut Vec<String>) {
54        dst.push(self.to_string());
55    }
56}
57
58impl<'a, const N: usize> __IntoStrings for [&'a str; N] {
59    fn extend_into_strings(self, dst: &mut Vec<String>) {
60        for item in self {
61            dst.push(item.to_string());
62        }
63    }
64}
65
66impl<'a, T> __IntoStrings for &'a [T]
67where
68    T: Into<String> + Clone,
69{
70    fn extend_into_strings(self, dst: &mut Vec<String>) {
71        for item in self {
72            dst.push(item.clone().into());
73        }
74    }
75}
76
77impl<T> __IntoStrings for Vec<T>
78where
79    T: Into<String>,
80{
81    fn extend_into_strings(self, dst: &mut Vec<String>) {
82        for item in self {
83            dst.push(item.into());
84        }
85    }
86}
87
88#[doc(hidden)]
89pub fn __collect_strings_helper<T>(value: T, dst: &mut Vec<String>)
90where
91    T: __IntoStrings,
92{
93    value.extend_into_strings(dst);
94}
95
96#[doc(hidden)]
97#[macro_export]
98macro_rules! __builder_with_strings_after {
99    ($builder:expr, $method:ident, $first:expr $(, $arg:expr)* $(,)?) => {
100        $builder.$method($first, crate::__collect_strings!($($arg),*))
101    };
102}
103
104#[doc(hidden)]
105#[macro_export]
106macro_rules! __builder_with_strings_after_two {
107    ($builder:expr, $method:ident, $first:expr, $second:expr $(, $arg:expr)* $(,)?) => {
108        $builder.$method($first, $second, crate::__collect_strings!($($arg),*))
109    };
110}
111
112/// 为 `SelectBuilder::select` 提供 Go 风格的可变参数调用。
113#[macro_export]
114macro_rules! select_cols {
115    ($builder:expr $(, $col:expr)* $(,)?) => {
116        crate::__builder_with_strings!($builder, select $(, $col)*)
117    };
118}
119
120/// 为 `SelectBuilder::select_more` 提供 Go 风格的可变参数调用。
121#[macro_export]
122macro_rules! select_more_cols {
123    ($builder:expr $(, $col:expr)* $(,)?) => {
124        crate::__builder_with_strings!($builder, select_more $(, $col)*)
125    };
126}
127
128/// 为 `SelectBuilder::from` 提供 Go 风格的可变参数调用。
129#[macro_export]
130macro_rules! from_tables {
131    ($builder:expr $(, $table:expr)* $(,)?) => {
132        crate::__builder_with_strings!($builder, from $(, $table)*)
133    };
134}
135
136/// 为 `SelectBuilder::join` 提供 Go 风格的可变参数调用。
137#[macro_export]
138macro_rules! join_on {
139    ($builder:expr, $table:expr $(, $expr:expr)* $(,)?) => {
140        crate::__builder_with_strings_after!($builder, join, $table $(, $expr)*)
141    };
142}
143
144/// 为 `SelectBuilder::join_with_option` 提供 Go 风格的可变参数调用。
145#[macro_export]
146macro_rules! join_with_option {
147    ($builder:expr, $option:expr, $table:expr $(, $expr:expr)* $(,)?) => {
148        crate::__builder_with_strings_after_two!($builder, join_with_option, $option, $table $(, $expr)*)
149    };
150}
151
152/// 为所有 `where_` 调用提供 Go 风格的可变参数调用(Select/Update/Delete)。
153#[macro_export]
154macro_rules! where_exprs {
155    ($builder:expr $(, $expr:expr)* $(,)?) => {
156        crate::__builder_with_strings!($builder, where_ $(, $expr)*)
157    };
158}
159
160/// 为 `having` 提供 Go 风格的可变参数调用。
161#[macro_export]
162macro_rules! having_exprs {
163    ($builder:expr $(, $expr:expr)* $(,)?) => {
164        crate::__builder_with_strings!($builder, having $(, $expr)*)
165    };
166}
167
168/// 为 `group_by` 提供 Go 风格的可变参数调用。
169#[macro_export]
170macro_rules! group_by_cols {
171    ($builder:expr $(, $col:expr)* $(,)?) => {
172        crate::__builder_with_strings!($builder, group_by $(, $col)*)
173    };
174}
175
176/// 为 `order_by` 提供 Go 风格的可变参数调用。
177#[macro_export]
178macro_rules! order_by_cols {
179    ($builder:expr $(, $col:expr)* $(,)?) => {
180        crate::__builder_with_strings!($builder, order_by $(, $col)*)
181    };
182}
183
184/// 为 `InsertBuilder::cols` 提供 Go 风格的可变参数调用。
185#[macro_export]
186macro_rules! insert_cols {
187    ($builder:expr $(, $col:expr)* $(,)?) => {
188        crate::__builder_with_strings!($builder, cols $(, $col)*)
189    };
190}
191
192/// 为 `InsertBuilder::select` 提供 Go 风格的可变参数调用。
193#[macro_export]
194macro_rules! insert_select_cols {
195    ($builder:expr $(, $col:expr)* $(,)?) => {
196        crate::__builder_with_strings!($builder, select $(, $col)*)
197    };
198}
199
200/// 为所有 `returning` 调用提供 Go 风格的可变参数调用。
201#[macro_export]
202macro_rules! returning_cols {
203    ($builder:expr $(, $col:expr)* $(,)?) => {
204        crate::__builder_with_strings!($builder, returning $(, $col)*)
205    };
206}
207
208/// 为 `DeleteBuilder::delete_from` 提供 Go 风格的可变参数调用。
209#[macro_export]
210macro_rules! delete_from_tables {
211    ($builder:expr $(, $table:expr)* $(,)?) => {
212        crate::__builder_with_strings!($builder, delete_from $(, $table)*)
213    };
214}
215
216/// 为 `UpdateBuilder::update` 提供 Go 风格的可变参数调用。
217#[macro_export]
218macro_rules! update_tables {
219    ($builder:expr $(, $table:expr)* $(,)?) => {
220        crate::__builder_with_strings!($builder, update $(, $table)*)
221    };
222}
223
224/// 为 `UpdateBuilder::set` 提供 Go 风格的可变参数调用。
225#[macro_export]
226macro_rules! update_set {
227    ($builder:expr $(, $assignment:expr)* $(,)?) => {
228        crate::__builder_with_strings!($builder, set $(, $assignment)*)
229    };
230}
231
232/// 为 `UpdateBuilder::set_more` 提供 Go 风格的可变参数调用。
233#[macro_export]
234macro_rules! update_set_more {
235    ($builder:expr $(, $assignment:expr)* $(,)?) => {
236        crate::__builder_with_strings!($builder, set_more $(, $assignment)*)
237    };
238}
239
240/// 为 `CTEBuilder::select` 提供 Go 风格的可变参数调用。
241#[macro_export]
242macro_rules! cte_select_cols {
243    ($builder:expr $(, $col:expr)* $(,)?) => {
244        crate::__builder_with_strings!($builder, select $(, $col)*)
245    };
246}
247
248/// 为 `CTEBuilder::delete_from` 提供 Go 风格的可变参数调用。
249#[macro_export]
250macro_rules! cte_delete_from {
251    ($builder:expr $(, $table:expr)* $(,)?) => {
252        crate::__builder_with_strings!($builder, delete_from $(, $table)*)
253    };
254}
255
256/// 为 `CTEBuilder::update` 提供 Go 风格的可变参数调用。
257#[macro_export]
258macro_rules! cte_update_tables {
259    ($builder:expr $(, $table:expr)* $(,)?) => {
260        crate::__builder_with_strings!($builder, update $(, $table)*)
261    };
262}
263
264/// 为 `CTEQueryBuilder::table` 提供 Go 风格的列名参数。
265#[macro_export]
266macro_rules! cte_query_table {
267    ($builder:expr, $name:expr $(, $col:expr)* $(,)?) => {
268        crate::__builder_with_strings_after!($builder, table, $name $(, $col)*)
269    };
270}
271
272/// 为 `CreateTableBuilder::define` 提供 Go 风格的可变参数调用。
273#[macro_export]
274macro_rules! create_table_define {
275    ($builder:expr $(, $def:expr)* $(,)?) => {
276        crate::__builder_with_strings!($builder, define $(, $def)*)
277    };
278}
279
280/// 为 `CreateTableBuilder::option` 提供 Go 风格的可变参数调用。
281#[macro_export]
282macro_rules! create_table_option {
283    ($builder:expr $(, $opt:expr)* $(,)?) => {
284        crate::__builder_with_strings!($builder, option $(, $opt)*)
285    };
286}
287
288/// 为 `Struct::with_tag` 提供 Go 风格的可变参数调用。
289#[macro_export]
290macro_rules! struct_with_tag {
291    ($builder:expr $(, $tag:expr)* $(,)?) => {
292        $builder.with_tag(crate::__collect_static_strs!($($tag),*))
293    };
294}
295
296/// 为 `Struct::without_tag` 提供 Go 风格的可变参数调用。
297#[macro_export]
298macro_rules! struct_without_tag {
299    ($builder:expr $(, $tag:expr)* $(,)?) => {
300        $builder.without_tag(crate::__collect_static_strs!($($tag),*))
301    };
302}