drizzle_postgres/builder/
refresh.rs1use crate::values::PostgresValue;
23use core::marker::PhantomData;
24use drizzle_core::traits::{SQLTableInfo, SQLViewInfo};
25use drizzle_core::{SQL, ToSQL, Token};
26
27#[derive(Debug, Clone, Copy, Default)]
33pub struct RefreshInitial;
34
35#[derive(Debug, Clone, Copy, Default)]
37pub struct RefreshConcurrently;
38
39#[derive(Debug, Clone, Copy, Default)]
41pub struct RefreshWithNoData;
42
43#[derive(Debug, Clone)]
57pub struct RefreshMaterializedView<'a, State = RefreshInitial> {
58 sql: SQL<'a, PostgresValue<'a>>,
59 _state: PhantomData<State>,
60}
61
62impl<'a> RefreshMaterializedView<'a, RefreshInitial> {
63 #[must_use]
65 pub fn new<V: SQLViewInfo>(view: &'a V) -> Self {
66 let schema = SQLTableInfo::schema(view).unwrap_or("public");
67 let name = view.name();
68
69 let sql = SQL::from_iter([Token::REFRESH, Token::MATERIALIZED, Token::VIEW])
71 .append(SQL::ident(schema))
72 .push(Token::DOT)
73 .append(SQL::ident(name));
74
75 Self {
76 sql,
77 _state: PhantomData,
78 }
79 }
80
81 #[must_use]
88 pub fn concurrently(self) -> RefreshMaterializedView<'a, RefreshConcurrently> {
89 let chunks = self.sql.chunks;
95 let schema_name_start = 3; let mut new_sql = SQL::from_iter([
98 Token::REFRESH,
99 Token::MATERIALIZED,
100 Token::VIEW,
101 Token::CONCURRENTLY,
102 ]);
103
104 for chunk in chunks.into_iter().skip(schema_name_start) {
106 new_sql = new_sql.push(chunk);
107 }
108
109 RefreshMaterializedView {
110 sql: new_sql,
111 _state: PhantomData,
112 }
113 }
114
115 #[must_use]
122 pub fn with_no_data(self) -> RefreshMaterializedView<'a, RefreshWithNoData> {
123 RefreshMaterializedView {
124 sql: self.sql.push(Token::WITH).push(Token::NO).push(Token::DATA),
125 _state: PhantomData,
126 }
127 }
128
129 #[must_use]
131 pub fn with_data(self) -> Self {
132 Self {
133 sql: self.sql.push(Token::WITH).push(Token::DATA),
134 _state: PhantomData,
135 }
136 }
137}
138
139impl<'a, State> ToSQL<'a, PostgresValue<'a>> for RefreshMaterializedView<'a, State> {
144 fn to_sql(&self) -> SQL<'a, PostgresValue<'a>> {
145 self.sql.clone()
146 }
147}
148
149pub fn refresh_materialized_view<V: SQLViewInfo>(
155 view: &V,
156) -> RefreshMaterializedView<'_, RefreshInitial> {
157 RefreshMaterializedView::new(view)
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 struct TestView;
166
167 impl drizzle_core::traits::SQLTableInfo for TestView {
168 fn name(&self) -> &'static str {
169 "user_stats"
170 }
171
172 fn schema(&self) -> Option<&'static str> {
173 Some("public")
174 }
175 }
176
177 impl SQLViewInfo for TestView {
178 fn definition_sql(&self) -> std::borrow::Cow<'static, str> {
179 "SELECT * FROM users".into()
180 }
181
182 fn is_materialized(&self) -> bool {
183 true
184 }
185 }
186
187 #[test]
188 fn test_basic_refresh() {
189 let view = TestView;
190 let refresh = RefreshMaterializedView::new(&view);
191 let sql = refresh.to_sql();
192
193 assert_eq!(
194 sql.sql(),
195 r#"REFRESH MATERIALIZED VIEW "public"."user_stats""#
196 );
197 }
198
199 #[test]
200 fn test_concurrent_refresh() {
201 let view = TestView;
202 let refresh = RefreshMaterializedView::new(&view).concurrently();
203 let sql = refresh.to_sql();
204
205 assert_eq!(
206 sql.sql(),
207 r#"REFRESH MATERIALIZED VIEW CONCURRENTLY "public"."user_stats""#
208 );
209 }
210
211 #[test]
212 fn test_refresh_with_no_data() {
213 let view = TestView;
214 let refresh = RefreshMaterializedView::new(&view).with_no_data();
215 let sql = refresh.to_sql();
216
217 assert_eq!(
218 sql.sql(),
219 r#"REFRESH MATERIALIZED VIEW "public"."user_stats" WITH NO DATA"#
220 );
221 }
222
223 #[test]
224 fn test_refresh_with_data() {
225 let view = TestView;
226 let refresh = RefreshMaterializedView::new(&view).with_data();
227 let sql = refresh.to_sql();
228
229 assert_eq!(
230 sql.sql(),
231 r#"REFRESH MATERIALIZED VIEW "public"."user_stats" WITH DATA"#
232 );
233 }
234
235 #[test]
236 fn test_helper_function() {
237 let view = TestView;
238 let refresh = refresh_materialized_view(&view);
239 let sql = refresh.to_sql();
240
241 assert_eq!(
242 sql.sql(),
243 r#"REFRESH MATERIALIZED VIEW "public"."user_stats""#
244 );
245 }
246}