mysql_connector/model/
into_query.rs

1use super::ModelData;
2
3macro_rules! append {
4    ($str: expr; $($part:expr),* $(,)?) => {
5        $(
6            $str += $part;
7        )*
8    };
9}
10
11/// Data for column that contains a reference.
12///
13/// As foreign key this would look like: `foreign key (<column>) references <table>(<key>)`
14pub struct QueryColumnReference {
15    /// Column in which the reference is stored
16    pub column: &'static str,
17    /// Referenced table
18    pub table: &'static str,
19    /// Referenced key
20    pub key: &'static str,
21    /// Columns of referenced table
22    pub columns: &'static [QueryColumn],
23}
24
25impl QueryColumnReference {
26    /// Join the referenced table and append all columns to the select,
27    /// which may include some more joins.
28    fn join(&self, namespace: &str, select: &mut String, join: &mut String) {
29        let new_namespace = namespace.to_owned() + "." + self.column;
30        append!(*join; " join `", self.table, "` as `", &new_namespace, "` on (`", namespace, "`.`", self.column, "` = `", &new_namespace, "`.`", self.key, "`)");
31
32        for (i, column) in self.columns.iter().enumerate() {
33            if i != 0 {
34                *select += ", ";
35            }
36            column.append_to_select(&new_namespace, select, join);
37        }
38    }
39}
40
41pub enum QueryColumn {
42    Column(&'static str),
43    Reference(QueryColumnReference),
44}
45
46impl QueryColumn {
47    fn append_to_select(&self, namespace: &str, select: &mut String, join: &mut String) {
48        match self {
49            Self::Column(column) => {
50                append!(*select; "`", namespace, "`.`", *column, "`");
51            }
52            Self::Reference(r#struct) => {
53                r#struct.join(namespace, select, join);
54            }
55        }
56    }
57}
58
59pub trait IntoQuery: ModelData {
60    const COLUMNS: &'static [QueryColumn];
61
62    fn build_query() -> String {
63        let mut select = String::from("select ");
64        let mut join = String::new();
65        for (i, column) in Self::COLUMNS.iter().enumerate() {
66            if i != 0 {
67                select += ", ";
68            }
69            column.append_to_select(Self::TABLE, &mut select, &mut join);
70        }
71        append!(select; " from `", Self::TABLE, "`");
72        select += &join;
73        select
74    }
75}