reifydb_catalog/transaction/
view.rs1use reifydb_core::{
5 interface::{
6 CommandTransaction, NamespaceId, QueryTransaction, TransactionalChanges, TransactionalViewChanges,
7 ViewDef, ViewId,
8 interceptor::{ViewDefInterceptor, WithInterceptors},
9 },
10 log_warn,
11};
12use reifydb_type::{
13 IntoFragment,
14 diagnostic::catalog::{view_already_exists, view_not_found},
15 error, internal, return_error,
16};
17
18use crate::{
19 CatalogNamespaceQueryOperations, CatalogStore, store::view::ViewToCreate,
20 transaction::MaterializedCatalogTransaction,
21};
22
23pub trait CatalogViewCommandOperations {
24 fn create_view(&mut self, view: ViewToCreate) -> crate::Result<ViewDef>;
25
26 }
31
32pub trait CatalogTrackViewChangeOperations {
33 fn track_view_def_created(&mut self, view: ViewDef) -> crate::Result<()>;
34
35 fn track_view_def_updated(&mut self, pre: ViewDef, post: ViewDef) -> crate::Result<()>;
36
37 fn track_view_def_deleted(&mut self, view: ViewDef) -> crate::Result<()>;
38}
39
40pub trait CatalogViewQueryOperations: CatalogNamespaceQueryOperations {
41 fn find_view(&mut self, id: ViewId) -> crate::Result<Option<ViewDef>>;
42
43 fn find_view_by_name<'a>(
44 &mut self,
45 namespace: NamespaceId,
46 name: impl IntoFragment<'a>,
47 ) -> crate::Result<Option<ViewDef>>;
48
49 fn get_view(&mut self, id: ViewId) -> crate::Result<ViewDef>;
50
51 fn get_view_by_name<'a>(
52 &mut self,
53 namespace: NamespaceId,
54 name: impl IntoFragment<'a>,
55 ) -> crate::Result<ViewDef>;
56}
57
58impl<
59 CT: CommandTransaction
60 + MaterializedCatalogTransaction
61 + CatalogTrackViewChangeOperations
62 + WithInterceptors<CT>
63 + TransactionalChanges,
64> CatalogViewCommandOperations for CT
65{
66 fn create_view(&mut self, to_create: ViewToCreate) -> reifydb_core::Result<ViewDef> {
67 if let Some(view) = self.find_view_by_name(to_create.namespace, &to_create.name)? {
68 let namespace = self.get_namespace(to_create.namespace)?;
69 return_error!(view_already_exists(to_create.fragment, &namespace.name, &view.name));
70 }
71 let result = CatalogStore::create_deferred_view(self, to_create)?;
72 self.track_view_def_created(result.clone())?;
73 ViewDefInterceptor::post_create(self, &result)?;
74 Ok(result)
75 }
76}
77
78impl<QT: QueryTransaction + MaterializedCatalogTransaction + TransactionalChanges> CatalogViewQueryOperations for QT {
79 fn find_view(&mut self, id: ViewId) -> reifydb_core::Result<Option<ViewDef>> {
80 if let Some(view) = TransactionalViewChanges::find_view(self, id) {
83 return Ok(Some(view.clone()));
84 }
85
86 if TransactionalViewChanges::is_view_deleted(self, id) {
89 return Ok(None);
90 }
91
92 if let Some(view) = self.catalog().find_view(id, self.version()) {
94 return Ok(Some(view));
95 }
96
97 if let Some(view) = CatalogStore::find_view(self, id)? {
99 log_warn!("View with ID {:?} found in storage but not in MaterializedCatalog", id);
100 return Ok(Some(view));
101 }
102
103 Ok(None)
104 }
105
106 fn find_view_by_name<'a>(
107 &mut self,
108 namespace: NamespaceId,
109 name: impl IntoFragment<'a>,
110 ) -> reifydb_core::Result<Option<ViewDef>> {
111 let name = name.into_fragment();
112
113 if let Some(view) = TransactionalViewChanges::find_view_by_name(self, namespace, name.as_borrowed()) {
116 return Ok(Some(view.clone()));
117 }
118
119 if TransactionalViewChanges::is_view_deleted_by_name(self, namespace, name.as_borrowed()) {
122 return Ok(None);
123 }
124
125 if let Some(view) = self.catalog().find_view_by_name(namespace, name.text(), self.version()) {
127 return Ok(Some(view));
128 }
129
130 if let Some(view) = CatalogStore::find_view_by_name(self, namespace, name.text())? {
132 log_warn!(
133 "View '{}' in namespace {:?} found in storage but not in MaterializedCatalog",
134 name.text(),
135 namespace
136 );
137 return Ok(Some(view));
138 }
139
140 Ok(None)
141 }
142
143 fn get_view(&mut self, id: ViewId) -> reifydb_core::Result<ViewDef> {
144 self.find_view(id)?.ok_or_else(|| {
145 error!(internal!(
146 "View with ID {:?} not found in catalog. This indicates a critical catalog inconsistency.",
147 id
148 ))
149 })
150 }
151
152 fn get_view_by_name<'a>(
153 &mut self,
154 namespace: NamespaceId,
155 name: impl IntoFragment<'a>,
156 ) -> reifydb_core::Result<ViewDef> {
157 let name = name.into_fragment();
158
159 let namespace_name = self.get_namespace(namespace)?.name;
160
161 self.find_view_by_name(namespace, name.as_borrowed())?
162 .ok_or_else(|| error!(view_not_found(name.as_borrowed(), &namespace_name, name.text())))
163 }
164}