1#[cfg(not(feature = "std"))]
2use crate::prelude::*;
3use crate::traits::PostgresTable;
4use crate::values::PostgresValue;
5use drizzle_core::{ColumnRef, SQL, SQLTableInfo, ToSQL, Token, helpers, traits::SQLModel};
6
7pub(crate) use helpers::{
9 delete, except, except_all, from, group_by_expr, having, intersect, intersect_all, limit,
10 offset, order_by, select, select_distinct, set, union, union_all, update, r#where,
11};
12
13pub use drizzle_core::Join;
15
16drizzle_core::impl_join_arg_trait!(
17 table_trait: PostgresTable<'a>,
18 table_info_trait: SQLTableInfo,
19 condition_trait: ToSQL<'a, PostgresValue<'a>>,
20 value_type: PostgresValue<'a>,
21);
22
23fn columns_info_to_sql<'a>(columns: &[ColumnRef]) -> SQL<'a, PostgresValue<'a>> {
25 let mut sql = SQL::with_capacity_chunks(columns.len().saturating_mul(2));
26 for (idx, col) in columns.iter().enumerate() {
27 if idx > 0 {
28 sql.push_mut(Token::COMMA);
29 }
30 sql.append_mut(SQL::ident(col.name));
31 }
32 sql
33}
34
35drizzle_core::impl_join_helpers!(
37 table_trait: PostgresTable<'a>,
38 condition_trait: ToSQL<'a, PostgresValue<'a>>,
39 sql_type: SQL<'a, PostgresValue<'a>>,
40);
41
42pub(crate) fn select_distinct_on<'a, On, Columns>(
44 on: On,
45 columns: Columns,
46) -> SQL<'a, PostgresValue<'a>>
47where
48 On: ToSQL<'a, PostgresValue<'a>>,
49 Columns: ToSQL<'a, PostgresValue<'a>>,
50{
51 SQL::from_iter([Token::SELECT, Token::DISTINCT, Token::ON, Token::LPAREN])
52 .append(on.to_sql())
53 .push(Token::RPAREN)
54 .append(columns.to_sql())
55}
56
57fn join_using_internal<'a, Table>(
62 table: Table,
63 join: Join,
64 columns: impl ToSQL<'a, PostgresValue<'a>>,
65) -> SQL<'a, PostgresValue<'a>>
66where
67 Table: PostgresTable<'a>,
68{
69 join.to_sql()
70 .append(table.to_sql())
71 .push(Token::USING)
72 .push(Token::LPAREN)
73 .append(columns.to_sql())
74 .push(Token::RPAREN)
75}
76
77pub fn join_using<'a, Table>(
83 table: Table,
84 columns: impl ToSQL<'a, PostgresValue<'a>>,
85) -> SQL<'a, PostgresValue<'a>>
86where
87 Table: PostgresTable<'a>,
88{
89 join_using_internal(table, Join::new(), columns)
90}
91
92pub fn inner_join_using<'a, Table>(
94 table: Table,
95 columns: impl ToSQL<'a, PostgresValue<'a>>,
96) -> SQL<'a, PostgresValue<'a>>
97where
98 Table: PostgresTable<'a>,
99{
100 join_using_internal(table, Join::new().inner(), columns)
101}
102
103pub fn left_join_using<'a, Table>(
105 table: Table,
106 columns: impl ToSQL<'a, PostgresValue<'a>>,
107) -> SQL<'a, PostgresValue<'a>>
108where
109 Table: PostgresTable<'a>,
110{
111 join_using_internal(table, Join::new().left(), columns)
112}
113
114pub fn left_outer_join_using<'a, Table>(
116 table: Table,
117 columns: impl ToSQL<'a, PostgresValue<'a>>,
118) -> SQL<'a, PostgresValue<'a>>
119where
120 Table: PostgresTable<'a>,
121{
122 join_using_internal(table, Join::new().left().outer(), columns)
123}
124
125pub fn right_join_using<'a, Table>(
127 table: Table,
128 columns: impl ToSQL<'a, PostgresValue<'a>>,
129) -> SQL<'a, PostgresValue<'a>>
130where
131 Table: PostgresTable<'a>,
132{
133 join_using_internal(table, Join::new().right(), columns)
134}
135
136pub fn right_outer_join_using<'a, Table>(
138 table: Table,
139 columns: impl ToSQL<'a, PostgresValue<'a>>,
140) -> SQL<'a, PostgresValue<'a>>
141where
142 Table: PostgresTable<'a>,
143{
144 join_using_internal(table, Join::new().right().outer(), columns)
145}
146
147pub fn full_join_using<'a, Table>(
149 table: Table,
150 columns: impl ToSQL<'a, PostgresValue<'a>>,
151) -> SQL<'a, PostgresValue<'a>>
152where
153 Table: PostgresTable<'a>,
154{
155 join_using_internal(table, Join::new().full(), columns)
156}
157
158pub fn full_outer_join_using<'a, Table>(
160 table: Table,
161 columns: impl ToSQL<'a, PostgresValue<'a>>,
162) -> SQL<'a, PostgresValue<'a>>
163where
164 Table: PostgresTable<'a>,
165{
166 join_using_internal(table, Join::new().full().outer(), columns)
167}
168
169pub(crate) fn insert<'a, Table>(table: &Table) -> SQL<'a, PostgresValue<'a>>
174where
175 Table: PostgresTable<'a>,
176{
177 SQL::from_iter([Token::INSERT, Token::INTO]).append(table)
178}
179
180pub(crate) fn values<'a, Table, T>(
183 rows: impl IntoIterator<Item = Table::Insert<T>>,
184) -> SQL<'a, PostgresValue<'a>>
185where
186 Table: PostgresTable<'a>,
187{
188 let rows: Vec<_> = rows.into_iter().collect();
189
190 if rows.is_empty() {
191 return SQL::from(Token::VALUES);
192 }
193
194 let columns_info = rows[0].columns();
197 let columns_slice = columns_info.as_ref();
198 if columns_slice.is_empty() {
200 return SQL::from_iter([Token::DEFAULT, Token::VALUES]);
201 }
202
203 let columns_sql = columns_info_to_sql(columns_slice);
204 let mut values_sql = SQL::with_capacity_chunks(rows.len().saturating_mul(4));
205 for (idx, row) in rows.iter().enumerate() {
206 if idx > 0 {
207 values_sql.push_mut(Token::COMMA);
208 }
209 values_sql.push_mut(Token::LPAREN);
210 values_sql.append_mut(row.values());
211 values_sql.push_mut(Token::RPAREN);
212 }
213
214 columns_sql.parens().push(Token::VALUES).append(values_sql)
215}
216
217pub(crate) fn returning<'a, 'b, I>(columns: I) -> SQL<'a, PostgresValue<'a>>
219where
220 I: ToSQL<'a, PostgresValue<'a>>,
221{
222 SQL::from(Token::RETURNING).append(columns.to_sql())
223}
224
225pub(crate) fn for_update<'a>() -> SQL<'a, PostgresValue<'a>> {
231 SQL::from_iter([Token::FOR, Token::UPDATE])
232}
233
234pub(crate) fn for_share<'a>() -> SQL<'a, PostgresValue<'a>> {
236 SQL::from_iter([Token::FOR, Token::SHARE])
237}
238
239pub(crate) fn for_no_key_update<'a>() -> SQL<'a, PostgresValue<'a>> {
241 SQL::from_iter([Token::FOR, Token::NO, Token::KEY, Token::UPDATE])
242}
243
244pub(crate) fn for_key_share<'a>() -> SQL<'a, PostgresValue<'a>> {
246 SQL::from_iter([Token::FOR, Token::KEY, Token::SHARE])
247}
248
249pub(crate) fn for_update_of<'a>(table_name: &str) -> SQL<'a, PostgresValue<'a>> {
252 SQL::from_iter([Token::FOR, Token::UPDATE, Token::OF])
253 .append(SQL::ident(String::from(table_name)))
254}
255
256pub(crate) fn for_share_of<'a>(table_name: &str) -> SQL<'a, PostgresValue<'a>> {
259 SQL::from_iter([Token::FOR, Token::SHARE, Token::OF])
260 .append(SQL::ident(String::from(table_name)))
261}
262
263pub(crate) fn nowait<'a>() -> SQL<'a, PostgresValue<'a>> {
265 SQL::from(Token::NOWAIT)
266}
267
268pub(crate) fn skip_locked<'a>() -> SQL<'a, PostgresValue<'a>> {
270 SQL::from_iter([Token::SKIP, Token::LOCKED])
271}