1use crate::prelude::*;
2use crate::{SQL, SQLSchemaType, SQLTable, ToSQL, Token, traits::SQLParam};
3
4pub fn select<'a, Value, T>(columns: T) -> SQL<'a, Value>
6where
7 Value: SQLParam,
8 T: ToSQL<'a, Value>,
9{
10 SQL::from(Token::SELECT).append(&columns)
11}
12
13pub fn select_distinct<'a, Value, T>(columns: T) -> SQL<'a, Value>
15where
16 Value: SQLParam,
17 T: ToSQL<'a, Value>,
18{
19 SQL::from_iter([Token::SELECT, Token::DISTINCT]).append(&columns)
20}
21
22fn set_op<'a, Value, L, R>(left: L, op: Token, all: bool, right: R) -> SQL<'a, Value>
23where
24 Value: SQLParam,
25 L: ToSQL<'a, Value>,
26 R: ToSQL<'a, Value>,
27{
28 let left = left.to_sql().parens();
29 let right = right.to_sql().parens();
30 let op_sql = if all {
31 SQL::from(op).push(Token::ALL)
32 } else {
33 SQL::from(op)
34 };
35
36 left.append(op_sql).append(right)
37}
38
39pub fn union<'a, Value, L, R>(left: L, right: R) -> SQL<'a, Value>
41where
42 Value: SQLParam,
43 L: ToSQL<'a, Value>,
44 R: ToSQL<'a, Value>,
45{
46 set_op(left, Token::UNION, false, right)
47}
48
49pub fn union_all<'a, Value, L, R>(left: L, right: R) -> SQL<'a, Value>
51where
52 Value: SQLParam,
53 L: ToSQL<'a, Value>,
54 R: ToSQL<'a, Value>,
55{
56 set_op(left, Token::UNION, true, right)
57}
58
59pub fn intersect<'a, Value, L, R>(left: L, right: R) -> SQL<'a, Value>
61where
62 Value: SQLParam,
63 L: ToSQL<'a, Value>,
64 R: ToSQL<'a, Value>,
65{
66 set_op(left, Token::INTERSECT, false, right)
67}
68
69pub fn intersect_all<'a, Value, L, R>(left: L, right: R) -> SQL<'a, Value>
71where
72 Value: SQLParam,
73 L: ToSQL<'a, Value>,
74 R: ToSQL<'a, Value>,
75{
76 set_op(left, Token::INTERSECT, true, right)
77}
78
79pub fn except<'a, Value, L, R>(left: L, right: R) -> SQL<'a, Value>
81where
82 Value: SQLParam,
83 L: ToSQL<'a, Value>,
84 R: ToSQL<'a, Value>,
85{
86 set_op(left, Token::EXCEPT, false, right)
87}
88
89pub fn except_all<'a, Value, L, R>(left: L, right: R) -> SQL<'a, Value>
91where
92 Value: SQLParam,
93 L: ToSQL<'a, Value>,
94 R: ToSQL<'a, Value>,
95{
96 set_op(left, Token::EXCEPT, true, right)
97}
98
99pub fn insert<'a, Table, Type, Value>(table: Table) -> SQL<'a, Value>
101where
102 Type: SQLSchemaType,
103 Value: SQLParam,
104 Table: SQLTable<'a, Type, Value>,
105{
106 SQL::from_iter([Token::INSERT, Token::INTO]).append(&table)
107}
108
109pub fn from<'a, T, Value>(query: T) -> SQL<'a, Value>
111where
112 T: ToSQL<'a, Value>,
113 Value: SQLParam,
114{
115 SQL::from(Token::FROM).append(&query)
116}
117
118pub fn r#where<'a, V>(condition: impl ToSQL<'a, V>) -> SQL<'a, V>
120where
121 V: SQLParam + 'a,
122{
123 SQL::from(Token::WHERE).append(&condition)
124}
125
126pub fn group_by<'a, V, I, T>(expressions: I) -> SQL<'a, V>
128where
129 V: SQLParam + 'a,
130 I: IntoIterator<Item = T>,
131 T: ToSQL<'a, V>,
132{
133 SQL::from_iter([Token::GROUP, Token::BY]).append(SQL::join(
134 expressions.into_iter().map(|e| e.to_sql()),
135 Token::COMMA,
136 ))
137}
138
139pub fn having<'a, V>(condition: impl ToSQL<'a, V>) -> SQL<'a, V>
141where
142 V: SQLParam + 'a,
143{
144 SQL::from(Token::HAVING).append(&condition)
145}
146
147pub fn order_by<'a, T, V>(expressions: T) -> SQL<'a, V>
149where
150 T: ToSQL<'a, V>,
151 V: SQLParam + 'a,
152{
153 SQL::from_iter([Token::ORDER, Token::BY]).append(expressions.to_sql())
154}
155
156pub fn limit<'a, V>(value: usize) -> SQL<'a, V>
158where
159 V: SQLParam + 'a,
160{
161 SQL::from(Token::LIMIT).append(SQL::raw(value.to_string()))
162}
163
164pub fn offset<'a, V>(value: usize) -> SQL<'a, V>
166where
167 V: SQLParam + 'a,
168{
169 SQL::from(Token::OFFSET).append(SQL::raw(value.to_string()))
170}
171
172pub fn update<'a, Table, Type, Value>(table: Table) -> SQL<'a, Value>
174where
175 Table: SQLTable<'a, Type, Value>,
176 Type: SQLSchemaType,
177 Value: SQLParam + 'a,
178{
179 SQL::from(Token::UPDATE).append(&table)
180}
181
182pub fn set<'a, Table, Type, Value>(assignments: Table::Update) -> SQL<'a, Value>
184where
185 Value: SQLParam + 'a,
186 Table: SQLTable<'a, Type, Value>,
187 Type: SQLSchemaType,
188{
189 SQL::from(Token::SET).append(assignments.to_sql())
190}
191
192pub fn delete<'a, Table, Type, Value>(table: Table) -> SQL<'a, Value>
194where
195 Table: SQLTable<'a, Type, Value>,
196 Type: SQLSchemaType,
197 Value: SQLParam + 'a,
198{
199 SQL::from_iter([Token::DELETE, Token::FROM]).append(&table)
200}