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