quaint_forked/
macros.rs

1/// Convert given set of tuples into `Values`.
2///
3/// ```rust
4/// # use quaint::{col, values, ast::*, visitor::{Visitor, Sqlite}};
5/// # fn main() -> Result<(), quaint::error::Error> {
6///
7/// let condition = Row::from((col!("id"), col!("name")))
8///     .in_selection(values!((1, "Musti"), (2, "Naukio")));
9///
10/// let query = Select::from_table("cats").so_that(condition);
11/// let (sql, _) = Sqlite::build(query)?;
12///
13/// assert_eq!(
14///     "SELECT `cats`.* FROM `cats` WHERE (`id`,`name`) IN (VALUES (?,?),(?,?))",
15///     sql
16/// );
17/// # Ok(())
18/// # }
19/// ```
20#[macro_export]
21macro_rules! values {
22    ($($x:expr),*) => (
23        Values::from(std::iter::empty() $(.chain(std::iter::once(Row::from($x))))*)
24    );
25}
26
27/// Marks a given string or a tuple as a column. Useful when using a column in
28/// calculations, e.g.
29///
30/// ``` rust
31/// # use quaint::{col, val, ast::*, visitor::{Visitor, Sqlite}};
32/// # fn main() -> Result<(), quaint::error::Error> {
33/// let join = "dogs".on(("dogs", "slave_id").equals(Column::from(("cats", "master_id"))));
34///
35/// let query = Select::from_table("cats")
36///     .value(Table::from("cats").asterisk())
37///     .value(col!("dogs", "age") - val!(4))
38///     .inner_join(join);
39///
40/// let (sql, params) = Sqlite::build(query)?;
41///
42/// assert_eq!(
43///     "SELECT `cats`.*, (`dogs`.`age` - ?) FROM `cats` INNER JOIN `dogs` ON `dogs`.`slave_id` = `cats`.`master_id`",
44///     sql
45/// );
46/// # Ok(())
47/// # }
48/// ```
49#[macro_export]
50macro_rules! col {
51    ($e1:expr) => {
52        Expression::from(Column::from($e1))
53    };
54
55    ($e1:expr, $e2:expr) => {
56        Expression::from(Column::from(($e1, $e2)))
57    };
58}
59
60/// Marks a given string as a value. Useful when using a value in calculations,
61/// e.g.
62///
63/// ``` rust
64/// # use quaint::{col, val, ast::*, visitor::{Visitor, Sqlite}};
65/// # fn main() -> Result<(), quaint::error::Error> {
66/// let join = "dogs".on(("dogs", "slave_id").equals(Column::from(("cats", "master_id"))));
67///
68/// let query = Select::from_table("cats")
69///     .value(Table::from("cats").asterisk())
70///     .value(col!("dogs", "age") - val!(4))
71///     .inner_join(join);
72///
73/// let (sql, params) = Sqlite::build(query)?;
74///
75/// assert_eq!(
76///     "SELECT `cats`.*, (`dogs`.`age` - ?) FROM `cats` INNER JOIN `dogs` ON `dogs`.`slave_id` = `cats`.`master_id`",
77///     sql
78/// );
79/// # Ok(())
80/// # }
81/// ```
82#[macro_export]
83macro_rules! val {
84    ($val:expr) => {
85        Expression::from($val)
86    };
87}
88
89macro_rules! value {
90    ($target:ident: $kind:ty,$paramkind:ident,$that:expr) => {
91        impl<'a> From<$kind> for crate::ast::Value<'a> {
92            fn from(that: $kind) -> Self {
93                let $target = that;
94                crate::ast::Value::$paramkind(Some($that))
95            }
96        }
97
98        impl<'a> From<Option<$kind>> for crate::ast::Value<'a> {
99            fn from(that: Option<$kind>) -> Self {
100                match that {
101                    Some(val) => crate::ast::Value::from(val),
102                    None => crate::ast::Value::$paramkind(None),
103                }
104            }
105        }
106    };
107}
108
109macro_rules! aliasable {
110    ($($kind:ty),*) => (
111        $(
112            impl<'a> Aliasable<'a> for $kind {
113                type Target = Table<'a>;
114
115                fn alias<T>(self, alias: T) -> Self::Target
116                where
117                    T: Into<Cow<'a, str>>,
118                {
119                    let table: Table = self.into();
120                    table.alias(alias)
121                }
122            }
123        )*
124    );
125}
126
127macro_rules! function {
128    ($($kind:ident),*) => (
129        $(
130            impl<'a> From<$kind<'a>> for Function<'a> {
131                fn from(f: $kind<'a>) -> Self {
132                    Function {
133                        typ_: FunctionType::$kind(f),
134                        alias: None,
135                    }
136                }
137            }
138
139            impl<'a> From<$kind<'a>> for Expression<'a> {
140                fn from(f: $kind<'a>) -> Self {
141                    Function::from(f).into()
142                }
143            }
144        )*
145    );
146}
147
148macro_rules! expression {
149    ($kind:ident,$paramkind:ident) => {
150        impl<'a> From<$kind<'a>> for Expression<'a> {
151            fn from(that: $kind<'a>) -> Self {
152                Expression {
153                    kind: ExpressionKind::$paramkind(that),
154                    alias: None,
155                }
156            }
157        }
158    };
159}
160
161/// A test-generator to test types in the defined database.
162#[cfg(test)]
163macro_rules! test_type {
164    ($name:ident($db:ident, $sql_type:literal, $(($input:expr, $output:expr)),+ $(,)?)) => {
165        paste::item! {
166            #[test]
167            fn [< test_type_ $name >] () -> crate::Result<()> {
168                use crate::ast::*;
169                use crate::connector::Queryable;
170                use crate::tests::test_api::TestApi;
171                use tokio::runtime::Builder;
172
173                let rt = Builder::new_multi_thread().enable_all().build().unwrap();
174
175                rt.block_on(async {
176                    let mut setup = [< $db _test_api >]().await?;
177                    let table = setup.create_type_table($sql_type).await?;
178
179                    $(
180                        let input = $input;
181                        let output = $output;
182
183                        let insert = Insert::single_into(&table).value("value", input);
184                        setup.conn().insert(insert.into()).await?;
185
186                        let select = Select::from_table(&table).column("value").order_by("id".descend());
187                        let res = setup.conn().select(select).await?.into_single()?;
188
189                        assert_eq!(Some(&output), res.at(0));
190                    )+
191
192                    Result::<(), crate::error::Error>::Ok(())
193                }).unwrap();
194
195                Ok(())
196            }
197        }
198    };
199
200    ($name:ident($db:ident, $sql_type:literal, $($value:expr),+ $(,)?)) => {
201        paste::item! {
202            #[test]
203            fn [< test_type_ $name >] () -> crate::Result<()> {
204                use crate::ast::*;
205                use crate::connector::Queryable;
206                use crate::tests::test_api::TestApi;
207                use tokio::runtime::Builder;
208
209                let rt = Builder::new_multi_thread().enable_all().build().unwrap();
210
211                rt.block_on(async {
212                    let mut setup = [< $db _test_api >]().await?;
213                    let table = setup.create_type_table($sql_type).await?;
214
215                    $(
216                        let value = $value;
217                        let insert = Insert::single_into(&table).value("value", value.clone());
218                        setup.conn().insert(insert.into()).await?;
219
220                        let select = Select::from_table(&table).column("value").order_by("id".descend());
221                        let res = setup.conn().select(select).await?.into_single()?;
222
223                        assert_eq!(Some(&value), res.at(0));
224                    )+
225
226                    Result::<(), crate::error::Error>::Ok(())
227                }).unwrap();
228
229                Ok(())
230            }
231        }
232    };
233}