1use crate::{
2 common::Join,
3 traits::{SQLiteSQL, SQLiteTable, ToSQLiteSQL},
4};
5use drizzle_core::{
6 SQL, ToSQL, Token, helpers as core_helpers,
7 traits::{SQLColumnInfo, SQLModel},
8};
9
10pub(crate) use core_helpers::{
12 delete, from, group_by, having, insert, limit, offset, order_by, select, set, update, r#where,
13};
14
15fn columns_info_to_sql<'a>(columns: &[&'static dyn SQLColumnInfo]) -> SQLiteSQL<'a> {
17 let joined_names = columns
19 .iter()
20 .map(|col| col.name())
21 .collect::<Vec<_>>()
22 .join(", ");
23 SQL::raw(joined_names)
24}
25
26fn join_internal<'a, Table>(
27 table: Table,
28 join: Join,
29 condition: impl ToSQLiteSQL<'a>,
30) -> SQLiteSQL<'a>
31where
32 Table: SQLiteTable<'a>,
33{
34 join.to_sql()
35 .append(&table)
36 .push(Token::ON)
37 .append(&condition)
38}
39
40pub fn natural_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
42where
43 Table: SQLiteTable<'a>,
44{
45 join_internal(table, Join::default().natural(), condition)
46}
47
48pub fn join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
50where
51 Table: SQLiteTable<'a>,
52{
53 join_internal(table, Join::default(), condition)
54}
55
56pub fn natural_left_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
57where
58 Table: SQLiteTable<'a>,
59{
60 join_internal(table, Join::new().natural().left(), condition)
61}
62
63pub fn left_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
65where
66 Table: SQLiteTable<'a>,
67{
68 join_internal(table, Join::new().left(), condition)
69}
70
71pub fn left_outer_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
72where
73 Table: SQLiteTable<'a>,
74{
75 join_internal(table, Join::new().left().outer(), condition)
76}
77
78pub fn natural_left_outer_join<'a, Table>(
79 table: Table,
80 condition: impl ToSQLiteSQL<'a>,
81) -> SQLiteSQL<'a>
82where
83 Table: SQLiteTable<'a>,
84{
85 join_internal(table, Join::new().natural().left().outer(), condition)
86}
87
88pub fn natural_right_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
89where
90 Table: SQLiteTable<'a>,
91{
92 join_internal(table, Join::new().natural().right(), condition)
93}
94
95pub fn right_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
97where
98 Table: SQLiteTable<'a>,
99{
100 join_internal(table, Join::new().right(), condition)
101}
102
103pub fn right_outer_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
104where
105 Table: SQLiteTable<'a>,
106{
107 join_internal(table, Join::new().right().outer(), condition)
108}
109
110pub fn natural_right_outer_join<'a, Table>(
111 table: Table,
112 condition: impl ToSQLiteSQL<'a>,
113) -> SQLiteSQL<'a>
114where
115 Table: SQLiteTable<'a>,
116{
117 join_internal(table, Join::new().natural().right().outer(), condition)
118}
119
120pub fn natural_full_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
121where
122 Table: SQLiteTable<'a>,
123{
124 join_internal(table, Join::new().natural().full(), condition)
125}
126
127pub fn full_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
129where
130 Table: SQLiteTable<'a>,
131{
132 join_internal(table, Join::new().full(), condition)
133}
134
135pub fn full_outer_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
136where
137 Table: SQLiteTable<'a>,
138{
139 join_internal(table, Join::new().full().outer(), condition)
140}
141
142pub fn natural_full_outer_join<'a, Table>(
143 table: Table,
144 condition: impl ToSQLiteSQL<'a>,
145) -> SQLiteSQL<'a>
146where
147 Table: SQLiteTable<'a>,
148{
149 join_internal(table, Join::new().natural().full().outer(), condition)
150}
151
152pub fn natural_inner_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
153where
154 Table: SQLiteTable<'a>,
155{
156 join_internal(table, Join::new().natural().inner(), condition)
157}
158
159pub fn inner_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
161where
162 Table: SQLiteTable<'a>,
163{
164 join_internal(table, Join::new().inner(), condition)
165}
166
167pub fn cross_join<'a, Table>(table: Table, condition: impl ToSQLiteSQL<'a>) -> SQLiteSQL<'a>
169where
170 Table: SQLiteTable<'a>,
171{
172 join_internal(table, Join::new().cross(), condition)
173}
174
175pub(crate) fn values<'a, Table, T>(
178 rows: impl IntoIterator<Item = Table::Insert<T>>,
179) -> SQLiteSQL<'a>
180where
181 Table: SQLiteTable<'a> + Default,
182{
183 let rows: Vec<_> = rows.into_iter().collect();
184
185 if rows.is_empty() {
186 return SQL::from(Token::VALUES);
187 }
188
189 let columns_info = rows[0].columns();
192
193 if columns_info.is_empty() {
195 return SQL::from_iter([Token::DEFAULT, Token::VALUES]);
196 }
197
198 let columns_sql = columns_info_to_sql(&columns_info);
199 let value_clauses = rows.iter().map(|row| {
200 SQL::from(Token::LPAREN)
201 .append(row.values())
202 .push(Token::RPAREN)
203 });
204
205 columns_sql
206 .parens()
207 .push(Token::VALUES)
208 .append(SQL::join(value_clauses, Token::COMMA))
209}
210
211pub(crate) fn returning<'a, 'b, I>(columns: I) -> SQLiteSQL<'a>
213where
214 I: ToSQLiteSQL<'a>,
215{
216 SQL::from(Token::RETURNING).append(&columns)
217}