1use reifydb_core::{
5 CommitVersion,
6 interface::{NamespaceId, ViewDef, ViewId},
7};
8
9use crate::materialized::{MaterializedCatalog, MultiVersionViewDef};
10
11impl MaterializedCatalog {
12 pub fn find_view(&self, view: ViewId, version: CommitVersion) -> Option<ViewDef> {
14 self.views.get(&view).and_then(|entry| {
15 let multi = entry.value();
16 multi.get(version)
17 })
18 }
19
20 pub fn find_view_by_name(&self, namespace: NamespaceId, name: &str, version: CommitVersion) -> Option<ViewDef> {
22 self.views_by_name.get(&(namespace, name.to_string())).and_then(|entry| {
23 let view_id = *entry.value();
24 self.find_view(view_id, version)
25 })
26 }
27
28 pub fn set_view(&self, id: ViewId, version: CommitVersion, view: Option<ViewDef>) {
29 if let Some(entry) = self.views.get(&id) {
31 if let Some(pre) = entry.value().get_latest() {
32 self.views_by_name.remove(&(pre.namespace, pre.name.clone()));
33 }
34 }
35
36 let multi = self.views.get_or_insert_with(id, MultiVersionViewDef::new);
37 if let Some(new) = view {
38 self.views_by_name.insert((new.namespace, new.name.clone()), id);
39 multi.value().insert(version, new);
40 } else {
41 multi.value().remove(version);
42 }
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use reifydb_core::interface::{ColumnDef, ColumnId, ColumnIndex, ViewKind};
49 use reifydb_type::{Type, TypeConstraint};
50
51 use super::*;
52
53 fn create_test_view(id: ViewId, namespace: NamespaceId, name: &str) -> ViewDef {
54 ViewDef {
55 id,
56 namespace,
57 name: name.to_string(),
58 kind: ViewKind::Deferred,
59 columns: vec![
60 ColumnDef {
61 id: ColumnId(1),
62 name: "id".to_string(),
63 constraint: TypeConstraint::unconstrained(Type::Int1),
64 policies: vec![],
65 index: ColumnIndex(0),
66 auto_increment: false,
67 dictionary_id: None,
68 },
69 ColumnDef {
70 id: ColumnId(2),
71 name: "name".to_string(),
72 constraint: TypeConstraint::unconstrained(Type::Utf8),
73 policies: vec![],
74 index: ColumnIndex(1),
75 auto_increment: false,
76 dictionary_id: None,
77 },
78 ],
79 primary_key: None,
80 }
81 }
82
83 #[test]
84 fn test_set_and_find_view() {
85 let catalog = MaterializedCatalog::new();
86 let view_id = ViewId(1);
87 let namespace_id = NamespaceId(1);
88 let view = create_test_view(view_id, namespace_id, "test_view");
89
90 catalog.set_view(view_id, CommitVersion(1), Some(view.clone()));
92
93 let found = catalog.find_view(view_id, CommitVersion(1));
95 assert_eq!(found, Some(view.clone()));
96
97 let found = catalog.find_view(view_id, CommitVersion(5));
99 assert_eq!(found, Some(view));
100
101 let found = catalog.find_view(view_id, CommitVersion(0));
103 assert_eq!(found, None);
104 }
105
106 #[test]
107 fn test_find_view_by_name() {
108 let catalog = MaterializedCatalog::new();
109 let view_id = ViewId(1);
110 let namespace_id = NamespaceId(1);
111 let view = create_test_view(view_id, namespace_id, "named_view");
112
113 catalog.set_view(view_id, CommitVersion(1), Some(view.clone()));
115
116 let found = catalog.find_view_by_name(namespace_id, "named_view", CommitVersion(1));
118 assert_eq!(found, Some(view));
119
120 let found = catalog.find_view_by_name(namespace_id, "wrong_name", CommitVersion(1));
122 assert_eq!(found, None);
123
124 let found = catalog.find_view_by_name(NamespaceId(2), "named_view", CommitVersion(1));
126 assert_eq!(found, None);
127 }
128
129 #[test]
130 fn test_view_rename() {
131 let catalog = MaterializedCatalog::new();
132 let view_id = ViewId(1);
133 let namespace_id = NamespaceId(1);
134
135 let view_v1 = create_test_view(view_id, namespace_id, "old_name");
137 catalog.set_view(view_id, CommitVersion(1), Some(view_v1.clone()));
138
139 assert!(catalog.find_view_by_name(namespace_id, "old_name", CommitVersion(1)).is_some());
141 assert!(catalog.find_view_by_name(namespace_id, "new_name", CommitVersion(1)).is_none());
142
143 let mut view_v2 = view_v1.clone();
145 view_v2.name = "new_name".to_string();
146 catalog.set_view(view_id, CommitVersion(2), Some(view_v2.clone()));
147
148 assert!(catalog.find_view_by_name(namespace_id, "old_name", CommitVersion(2)).is_none());
150
151 assert_eq!(
153 catalog.find_view_by_name(namespace_id, "new_name", CommitVersion(2)),
154 Some(view_v2.clone())
155 );
156
157 assert_eq!(catalog.find_view(view_id, CommitVersion(1)), Some(view_v1));
159
160 assert_eq!(catalog.find_view(view_id, CommitVersion(2)), Some(view_v2));
162 }
163
164 #[test]
165 fn test_view_move_between_namespaces() {
166 let catalog = MaterializedCatalog::new();
167 let view_id = ViewId(1);
168 let namespace1 = NamespaceId(1);
169 let namespace2 = NamespaceId(2);
170
171 let view_v1 = create_test_view(view_id, namespace1, "movable_view");
173 catalog.set_view(view_id, CommitVersion(1), Some(view_v1.clone()));
174
175 assert!(catalog.find_view_by_name(namespace1, "movable_view", CommitVersion(1)).is_some());
177 assert!(catalog.find_view_by_name(namespace2, "movable_view", CommitVersion(1)).is_none());
178
179 let mut view_v2 = view_v1.clone();
181 view_v2.namespace = namespace2;
182 catalog.set_view(view_id, CommitVersion(2), Some(view_v2.clone()));
183
184 assert!(catalog.find_view_by_name(namespace1, "movable_view", CommitVersion(2)).is_none());
186
187 assert!(catalog.find_view_by_name(namespace2, "movable_view", CommitVersion(2)).is_some());
189 }
190
191 #[test]
192 fn test_view_deletion() {
193 let catalog = MaterializedCatalog::new();
194 let view_id = ViewId(1);
195 let namespace_id = NamespaceId(1);
196
197 let view = create_test_view(view_id, namespace_id, "deletable_view");
199 catalog.set_view(view_id, CommitVersion(1), Some(view.clone()));
200
201 assert_eq!(catalog.find_view(view_id, CommitVersion(1)), Some(view.clone()));
203 assert!(catalog.find_view_by_name(namespace_id, "deletable_view", CommitVersion(1)).is_some());
204
205 catalog.set_view(view_id, CommitVersion(2), None);
207
208 assert_eq!(catalog.find_view(view_id, CommitVersion(2)), None);
210 assert!(catalog.find_view_by_name(namespace_id, "deletable_view", CommitVersion(2)).is_none());
211
212 assert_eq!(catalog.find_view(view_id, CommitVersion(1)), Some(view));
214 }
215
216 #[test]
217 fn test_multiple_views_in_namespace() {
218 let catalog = MaterializedCatalog::new();
219 let namespace_id = NamespaceId(1);
220
221 let view1 = create_test_view(ViewId(1), namespace_id, "view1");
222 let view2 = create_test_view(ViewId(2), namespace_id, "view2");
223 let view3 = create_test_view(ViewId(3), namespace_id, "view3");
224
225 catalog.set_view(ViewId(1), CommitVersion(1), Some(view1.clone()));
227 catalog.set_view(ViewId(2), CommitVersion(1), Some(view2.clone()));
228 catalog.set_view(ViewId(3), CommitVersion(1), Some(view3.clone()));
229
230 assert_eq!(catalog.find_view_by_name(namespace_id, "view1", CommitVersion(1)), Some(view1));
232 assert_eq!(catalog.find_view_by_name(namespace_id, "view2", CommitVersion(1)), Some(view2));
233 assert_eq!(catalog.find_view_by_name(namespace_id, "view3", CommitVersion(1)), Some(view3));
234 }
235
236 #[test]
237 fn test_view_versioning() {
238 let catalog = MaterializedCatalog::new();
239 let view_id = ViewId(1);
240 let namespace_id = NamespaceId(1);
241
242 let view_v1 = create_test_view(view_id, namespace_id, "view_v1");
244 let mut view_v2 = view_v1.clone();
245 view_v2.name = "view_v2".to_string();
246 let mut view_v3 = view_v2.clone();
247 view_v3.name = "view_v3".to_string();
248
249 catalog.set_view(view_id, CommitVersion(10), Some(view_v1.clone()));
251 catalog.set_view(view_id, CommitVersion(20), Some(view_v2.clone()));
252 catalog.set_view(view_id, CommitVersion(30), Some(view_v3.clone()));
253
254 assert_eq!(catalog.find_view(view_id, CommitVersion(5)), None);
256 assert_eq!(catalog.find_view(view_id, CommitVersion(10)), Some(view_v1.clone()));
257 assert_eq!(catalog.find_view(view_id, CommitVersion(15)), Some(view_v1));
258 assert_eq!(catalog.find_view(view_id, CommitVersion(20)), Some(view_v2.clone()));
259 assert_eq!(catalog.find_view(view_id, CommitVersion(25)), Some(view_v2));
260 assert_eq!(catalog.find_view(view_id, CommitVersion(30)), Some(view_v3.clone()));
261 assert_eq!(catalog.find_view(view_id, CommitVersion(100)), Some(view_v3));
262 }
263}