Skip to main content

rorm_sql/
select_column.rs

1use std::fmt::Write;
2
3use crate::aggregation::SelectAggregator;
4
5/**
6Trait representing a column builder.
7*/
8pub trait SelectColumn {
9    /**
10    Build the column selector in the provided String.
11    */
12    fn build(&self, s: &mut String);
13}
14
15/**
16Representation of a select identifier.
17
18This is due to the presence of join expressions and some reserved keywords in postgres.
19 */
20#[derive(Debug, Clone, Copy)]
21pub struct SelectColumnData<'until_build> {
22    /// Optional name of the table
23    pub table_name: Option<&'until_build str>,
24    /// Name of the column
25    pub column_name: &'until_build str,
26    /// Optional alias to set for the column
27    pub select_alias: Option<&'until_build str>,
28    /// Optional aggregation function
29    pub aggregation: Option<SelectAggregator>,
30}
31
32/**
33Representation of the column selector and implementation of the [SelectColumn] trait.
34
35Should only be constructed via [DBImpl::select_column](crate::DBImpl::select_column).
36 */
37#[derive(Clone, Debug)]
38pub enum SelectColumnImpl<'until_build> {
39    /// SQLite representation of a column selector expression.
40    #[cfg(feature = "sqlite")]
41    SQLite(SelectColumnData<'until_build>),
42    /// Postgres representation of a column selector expression.
43    #[cfg(feature = "postgres")]
44    Postgres(SelectColumnData<'until_build>),
45}
46
47impl SelectColumn for SelectColumnImpl<'_> {
48    fn build(&self, s: &mut String) {
49        match self {
50            #[cfg(feature = "sqlite")]
51            SelectColumnImpl::SQLite(d) => {
52                if let Some(aggregation) = d.aggregation {
53                    match aggregation {
54                        SelectAggregator::Avg => write!(s, "AVG("),
55                        SelectAggregator::Count => write!(s, "COUNT("),
56                        SelectAggregator::Sum => write!(s, "SUM("),
57                        SelectAggregator::Max => write!(s, "MAX("),
58                        SelectAggregator::Min => write!(s, "MIN("),
59                    }
60                    .unwrap();
61                }
62
63                if let Some(table_name) = d.table_name {
64                    write!(s, "\"{table_name}\".").unwrap();
65                }
66
67                write!(s, "\"{}\"", d.column_name).unwrap();
68
69                if d.aggregation.is_some() {
70                    write!(s, ")").unwrap();
71                }
72
73                if let Some(alias) = d.select_alias {
74                    write!(s, " AS {alias}").unwrap();
75                }
76            }
77            #[cfg(feature = "postgres")]
78            SelectColumnImpl::Postgres(d) => {
79                if let Some(aggregation) = d.aggregation {
80                    match aggregation {
81                        SelectAggregator::Avg => write!(s, "AVG("),
82                        SelectAggregator::Count => write!(s, "COUNT("),
83                        SelectAggregator::Sum => write!(s, "SUM("),
84                        SelectAggregator::Max => write!(s, "MAX("),
85                        SelectAggregator::Min => write!(s, "MIN("),
86                    }
87                    .unwrap();
88                }
89                if let Some(table_name) = d.table_name {
90                    write!(s, "\"{table_name}\".").unwrap();
91                }
92
93                write!(s, "\"{}\"", d.column_name).unwrap();
94
95                if d.aggregation.is_some() {
96                    write!(s, ")").unwrap();
97                }
98
99                if let Some(alias) = d.select_alias {
100                    write!(s, " AS {alias}").unwrap();
101                }
102            }
103        }
104    }
105}