1use crate::error::Result;
2use meshdb_core::{Edge, EdgeId, Node, NodeId};
3use meshdb_storage::{
4 ConstraintScope, PropertyConstraintKind, PropertyConstraintSpec, StorageEngine,
5};
6
7pub type NodeIndexSpec = (String, String);
15
16pub type EdgeIndexSpec = (String, String);
21
22pub trait GraphWriter {
32 fn put_node(&self, node: &Node) -> Result<()>;
33 fn put_edge(&self, edge: &Edge) -> Result<()>;
34 fn delete_edge(&self, id: EdgeId) -> Result<()>;
35 fn detach_delete_node(&self, id: NodeId) -> Result<()>;
36
37 fn create_property_index(&self, _label: &str, _property: &str) -> Result<()> {
42 Err(crate::error::Error::Unsupported(
43 "property-index DDL is not supported by this writer".into(),
44 ))
45 }
46
47 fn drop_property_index(&self, _label: &str, _property: &str) -> Result<()> {
49 Err(crate::error::Error::Unsupported(
50 "property-index DDL is not supported by this writer".into(),
51 ))
52 }
53
54 fn list_property_indexes(&self) -> Result<Vec<NodeIndexSpec>> {
59 Ok(Vec::new())
60 }
61
62 fn create_edge_property_index(&self, _edge_type: &str, _property: &str) -> Result<()> {
68 Err(crate::error::Error::Unsupported(
69 "edge-property-index DDL is not supported by this writer".into(),
70 ))
71 }
72
73 fn drop_edge_property_index(&self, _edge_type: &str, _property: &str) -> Result<()> {
76 Err(crate::error::Error::Unsupported(
77 "edge-property-index DDL is not supported by this writer".into(),
78 ))
79 }
80
81 fn list_edge_property_indexes(&self) -> Result<Vec<EdgeIndexSpec>> {
85 Ok(Vec::new())
86 }
87
88 fn create_property_constraint(
95 &self,
96 _name: Option<&str>,
97 _scope: &ConstraintScope,
98 _properties: &[String],
99 _kind: PropertyConstraintKind,
100 _if_not_exists: bool,
101 ) -> Result<PropertyConstraintSpec> {
102 Err(crate::error::Error::Unsupported(
103 "constraint DDL is not supported by this writer".into(),
104 ))
105 }
106
107 fn drop_property_constraint(&self, _name: &str, _if_exists: bool) -> Result<()> {
110 Err(crate::error::Error::Unsupported(
111 "constraint DDL is not supported by this writer".into(),
112 ))
113 }
114
115 fn list_property_constraints(&self) -> Result<Vec<PropertyConstraintSpec>> {
118 Ok(Vec::new())
119 }
120}
121
122impl<T: StorageEngine> GraphWriter for T {
127 fn put_node(&self, node: &Node) -> Result<()> {
128 StorageEngine::put_node(self, node)?;
129 Ok(())
130 }
131
132 fn put_edge(&self, edge: &Edge) -> Result<()> {
133 StorageEngine::put_edge(self, edge)?;
134 Ok(())
135 }
136
137 fn delete_edge(&self, id: EdgeId) -> Result<()> {
138 if StorageEngine::get_edge(self, id)?.is_some() {
139 StorageEngine::delete_edge(self, id)?;
140 }
141 Ok(())
142 }
143
144 fn detach_delete_node(&self, id: NodeId) -> Result<()> {
145 StorageEngine::detach_delete_node(self, id)?;
146 Ok(())
147 }
148
149 fn create_property_index(&self, label: &str, property: &str) -> Result<()> {
150 StorageEngine::create_property_index(self, label, property)?;
151 Ok(())
152 }
153
154 fn drop_property_index(&self, label: &str, property: &str) -> Result<()> {
155 StorageEngine::drop_property_index(self, label, property)?;
156 Ok(())
157 }
158
159 fn list_property_indexes(&self) -> Result<Vec<NodeIndexSpec>> {
160 Ok(StorageEngine::list_property_indexes(self)
161 .into_iter()
162 .map(|s| (s.label, s.property))
163 .collect())
164 }
165
166 fn create_edge_property_index(&self, edge_type: &str, property: &str) -> Result<()> {
167 StorageEngine::create_edge_property_index(self, edge_type, property)?;
168 Ok(())
169 }
170
171 fn drop_edge_property_index(&self, edge_type: &str, property: &str) -> Result<()> {
172 StorageEngine::drop_edge_property_index(self, edge_type, property)?;
173 Ok(())
174 }
175
176 fn list_edge_property_indexes(&self) -> Result<Vec<EdgeIndexSpec>> {
177 Ok(StorageEngine::list_edge_property_indexes(self)
178 .into_iter()
179 .map(|s| (s.edge_type, s.property))
180 .collect())
181 }
182
183 fn create_property_constraint(
184 &self,
185 name: Option<&str>,
186 scope: &ConstraintScope,
187 properties: &[String],
188 kind: PropertyConstraintKind,
189 if_not_exists: bool,
190 ) -> Result<PropertyConstraintSpec> {
191 Ok(StorageEngine::create_property_constraint(
192 self,
193 name,
194 scope,
195 properties,
196 kind,
197 if_not_exists,
198 )?)
199 }
200
201 fn drop_property_constraint(&self, name: &str, if_exists: bool) -> Result<()> {
202 StorageEngine::drop_property_constraint(self, name, if_exists)?;
203 Ok(())
204 }
205
206 fn list_property_constraints(&self) -> Result<Vec<PropertyConstraintSpec>> {
207 Ok(StorageEngine::list_property_constraints(self))
208 }
209}
210
211pub struct StorageWriterAdapter<'a>(pub &'a dyn StorageEngine);
214
215impl GraphWriter for StorageWriterAdapter<'_> {
216 fn put_node(&self, node: &Node) -> Result<()> {
217 self.0.put_node(node)?;
218 Ok(())
219 }
220
221 fn put_edge(&self, edge: &Edge) -> Result<()> {
222 self.0.put_edge(edge)?;
223 Ok(())
224 }
225
226 fn delete_edge(&self, id: EdgeId) -> Result<()> {
227 if self.0.get_edge(id)?.is_some() {
228 self.0.delete_edge(id)?;
229 }
230 Ok(())
231 }
232
233 fn detach_delete_node(&self, id: NodeId) -> Result<()> {
234 self.0.detach_delete_node(id)?;
235 Ok(())
236 }
237
238 fn create_property_index(&self, label: &str, property: &str) -> Result<()> {
239 self.0.create_property_index(label, property)?;
240 Ok(())
241 }
242
243 fn drop_property_index(&self, label: &str, property: &str) -> Result<()> {
244 self.0.drop_property_index(label, property)?;
245 Ok(())
246 }
247
248 fn list_property_indexes(&self) -> Result<Vec<NodeIndexSpec>> {
249 Ok(self
250 .0
251 .list_property_indexes()
252 .into_iter()
253 .map(|s| (s.label, s.property))
254 .collect())
255 }
256
257 fn create_edge_property_index(&self, edge_type: &str, property: &str) -> Result<()> {
258 self.0.create_edge_property_index(edge_type, property)?;
259 Ok(())
260 }
261
262 fn drop_edge_property_index(&self, edge_type: &str, property: &str) -> Result<()> {
263 self.0.drop_edge_property_index(edge_type, property)?;
264 Ok(())
265 }
266
267 fn list_edge_property_indexes(&self) -> Result<Vec<EdgeIndexSpec>> {
268 Ok(self
269 .0
270 .list_edge_property_indexes()
271 .into_iter()
272 .map(|s| (s.edge_type, s.property))
273 .collect())
274 }
275
276 fn create_property_constraint(
277 &self,
278 name: Option<&str>,
279 scope: &ConstraintScope,
280 properties: &[String],
281 kind: PropertyConstraintKind,
282 if_not_exists: bool,
283 ) -> Result<PropertyConstraintSpec> {
284 Ok(self
285 .0
286 .create_property_constraint(name, scope, properties, kind, if_not_exists)?)
287 }
288
289 fn drop_property_constraint(&self, name: &str, if_exists: bool) -> Result<()> {
290 self.0.drop_property_constraint(name, if_exists)?;
291 Ok(())
292 }
293
294 fn list_property_constraints(&self) -> Result<Vec<PropertyConstraintSpec>> {
295 Ok(self.0.list_property_constraints())
296 }
297}