1use crate::common::PostgresSchemaType;
2use crate::values::PostgresValue;
3use core::fmt::Debug;
4use core::marker::PhantomData;
5use drizzle_core::{SQLTable, ToSQL};
6
7use super::ExecutableState;
9
10#[derive(Debug, Clone, Copy, Default)]
16pub struct UpdateInitial;
17
18#[derive(Debug, Clone, Copy, Default)]
20pub struct UpdateSetClauseSet;
21
22#[derive(Debug, Clone, Copy, Default)]
24pub struct UpdateFromSet;
25
26#[derive(Debug, Clone, Copy, Default)]
28pub struct UpdateWhereSet;
29
30#[derive(Debug, Clone, Copy, Default)]
32pub struct UpdateReturningSet;
33
34impl ExecutableState for UpdateSetClauseSet {}
36impl ExecutableState for UpdateFromSet {}
37impl ExecutableState for UpdateWhereSet {}
38impl ExecutableState for UpdateReturningSet {}
39
40pub type UpdateBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
46 super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
47
48type ReturningMarker<Table, Columns> = drizzle_core::Scoped<
49 <Columns as drizzle_core::IntoSelectTarget>::Marker,
50 drizzle_core::Cons<Table, drizzle_core::Nil>,
51>;
52
53type ReturningRow<Table, Columns> =
54 <<Columns as drizzle_core::IntoSelectTarget>::Marker as drizzle_core::ResolveRow<Table>>::Row;
55
56type ReturningBuilder<'a, S, T, Columns> = UpdateBuilder<
57 'a,
58 S,
59 UpdateReturningSet,
60 T,
61 ReturningMarker<T, Columns>,
62 ReturningRow<T, Columns>,
63>;
64
65impl<'a, Schema, Table> UpdateBuilder<'a, Schema, UpdateInitial, Table>
70where
71 Table: SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>,
72{
73 #[inline]
75 pub fn set(
76 self,
77 values: Table::Update,
78 ) -> UpdateBuilder<'a, Schema, UpdateSetClauseSet, Table> {
79 let sql = crate::helpers::set::<Table, PostgresSchemaType, PostgresValue<'a>>(&values);
80 drop(values);
81 UpdateBuilder {
82 sql: self.sql.append(sql),
83 schema: PhantomData,
84 state: PhantomData,
85 table: PhantomData,
86 marker: PhantomData,
87 row: PhantomData,
88 grouped: PhantomData,
89 }
90 }
91}
92
93impl<'a, S, T> UpdateBuilder<'a, S, UpdateSetClauseSet, T> {
98 #[inline]
100 pub fn from(
101 self,
102 source: impl ToSQL<'a, PostgresValue<'a>>,
103 ) -> UpdateBuilder<'a, S, UpdateFromSet, T> {
104 let from_sql = crate::helpers::from(source);
105 UpdateBuilder {
106 sql: self.sql.append(from_sql),
107 schema: PhantomData,
108 state: PhantomData,
109 table: PhantomData,
110 marker: PhantomData,
111 row: PhantomData,
112 grouped: PhantomData,
113 }
114 }
115
116 #[inline]
118 pub fn r#where<E>(self, condition: E) -> UpdateBuilder<'a, S, UpdateWhereSet, T>
119 where
120 E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
121 E::SQLType: drizzle_core::types::BooleanLike,
122 {
123 let where_sql = crate::helpers::r#where(condition);
124 UpdateBuilder {
125 sql: self.sql.append(where_sql),
126 schema: PhantomData,
127 state: PhantomData,
128 table: PhantomData,
129 marker: PhantomData,
130 row: PhantomData,
131 grouped: PhantomData,
132 }
133 }
134
135 #[inline]
137 pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
138 where
139 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
140 Columns::Marker: drizzle_core::ResolveRow<T>,
141 {
142 let returning_sql = crate::helpers::returning(columns);
143 UpdateBuilder {
144 sql: self.sql.append(returning_sql),
145 schema: PhantomData,
146 state: PhantomData,
147 table: PhantomData,
148 marker: PhantomData,
149 row: PhantomData,
150 grouped: PhantomData,
151 }
152 }
153}
154
155impl<'a, S, T> UpdateBuilder<'a, S, UpdateFromSet, T> {
160 #[inline]
162 pub fn r#where<E>(self, condition: E) -> UpdateBuilder<'a, S, UpdateWhereSet, T>
163 where
164 E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
165 E::SQLType: drizzle_core::types::BooleanLike,
166 {
167 let where_sql = crate::helpers::r#where(condition);
168 UpdateBuilder {
169 sql: self.sql.append(where_sql),
170 schema: PhantomData,
171 state: PhantomData,
172 table: PhantomData,
173 marker: PhantomData,
174 row: PhantomData,
175 grouped: PhantomData,
176 }
177 }
178
179 #[inline]
181 pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
182 where
183 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
184 Columns::Marker: drizzle_core::ResolveRow<T>,
185 {
186 let returning_sql = crate::helpers::returning(columns);
187 UpdateBuilder {
188 sql: self.sql.append(returning_sql),
189 schema: PhantomData,
190 state: PhantomData,
191 table: PhantomData,
192 marker: PhantomData,
193 row: PhantomData,
194 grouped: PhantomData,
195 }
196 }
197}
198
199impl<'a, S, T> UpdateBuilder<'a, S, UpdateWhereSet, T> {
204 #[inline]
206 pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
207 where
208 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
209 Columns::Marker: drizzle_core::ResolveRow<T>,
210 {
211 let returning_sql = crate::helpers::returning(columns);
212 UpdateBuilder {
213 sql: self.sql.append(returning_sql),
214 schema: PhantomData,
215 state: PhantomData,
216 table: PhantomData,
217 marker: PhantomData,
218 row: PhantomData,
219 grouped: PhantomData,
220 }
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227 use drizzle_core::{SQL, ToSQL};
228
229 #[test]
230 fn test_update_builder_creation() {
231 let builder = UpdateBuilder::<(), UpdateInitial, ()> {
232 sql: SQL::raw("UPDATE test"),
233 schema: PhantomData,
234 state: PhantomData,
235 table: PhantomData,
236 marker: PhantomData,
237 row: PhantomData,
238 grouped: PhantomData,
239 };
240
241 assert_eq!(builder.to_sql().sql(), "UPDATE test");
242 }
243}