1use crate::{
11 Direction, GraphLabelInfo, GraphLabelRegistry, GraphStore, GraphStoreResult, LabelKind,
12 MemoryGraphStore, PersistentGraphStore,
13};
14use std::collections::{BTreeMap, BTreeSet};
15use std::sync::Arc;
16use uqa_core::{Edge, Vertex};
17use uqa_storage::{CatalogFacade, PersistentStorageBackend};
18
19#[derive(Debug, Clone)]
20pub enum GraphStoreHandle {
21 Memory(MemoryGraphStore),
22 Persistent(PersistentGraphStore),
23}
24
25impl Default for GraphStoreHandle {
26 fn default() -> Self {
27 Self::Memory(MemoryGraphStore::new())
28 }
29}
30
31impl GraphStoreHandle {
32 pub fn from_catalog(
33 catalog: Arc<dyn CatalogFacade>,
34 backend: Arc<dyn PersistentStorageBackend>,
35 ) -> Self {
36 Self::Persistent(PersistentGraphStore::from_catalog(catalog, backend))
37 }
38
39 pub fn transaction_mapped<T, E>(
42 &mut self,
43 operation: impl FnOnce(&mut Self) -> Result<T, E>,
44 map_error: impl Fn(crate::GraphStoreError) -> E,
45 ) -> Result<T, E>
46 where
47 E: std::fmt::Display,
48 {
49 match self {
50 Self::Memory(store) => {
51 let backup = store.clone();
52 match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| operation(self))) {
53 Ok(Ok(value)) => Ok(value),
54 Ok(Err(error)) => {
55 *self = Self::Memory(backup);
56 Err(error)
57 }
58 Err(panic) => {
59 *self = Self::Memory(backup);
60 std::panic::resume_unwind(panic)
61 }
62 }
63 }
64 Self::Persistent(store) => {
65 let mut checkpoint = store.clone();
66 checkpoint.transaction_mapped(|_| operation(self), map_error)
67 }
68 }
69 }
70
71 pub fn label_registry(&self, graph: &str) -> GraphStoreResult<GraphLabelRegistry> {
72 match self {
73 Self::Memory(store) => Ok(store.label_registry(graph)),
74 Self::Persistent(store) => store.label_registry(graph),
75 }
76 }
77 pub fn graph_labels(&self, graph: &str) -> GraphStoreResult<Vec<GraphLabelInfo>> {
78 match self {
79 Self::Memory(store) => store.graph_labels(graph),
80 Self::Persistent(store) => store.graph_labels(graph),
81 }
82 }
83 pub fn graph_label_kind(
84 &self,
85 graph: &str,
86 label: &str,
87 ) -> GraphStoreResult<Option<LabelKind>> {
88 match self {
89 Self::Memory(store) => store.graph_label_kind(graph, label),
90 Self::Persistent(store) => store.graph_label_kind(graph, label),
91 }
92 }
93 pub fn create_label(
94 &mut self,
95 graph: &str,
96 label: &str,
97 kind: LabelKind,
98 ) -> GraphStoreResult<Option<u32>> {
99 match self {
100 Self::Memory(store) => store.create_label(graph, label, kind),
101 Self::Persistent(store) => store.create_label(graph, label, kind),
102 }
103 }
104 pub fn drop_label(
105 &mut self,
106 graph: &str,
107 label: &str,
108 ) -> GraphStoreResult<Option<(u32, LabelKind)>> {
109 match self {
110 Self::Memory(store) => store.drop_label(graph, label),
111 Self::Persistent(store) => store.drop_label(graph, label),
112 }
113 }
114 pub fn rename_graph(&mut self, from: &str, to: &str) -> GraphStoreResult<()> {
115 match self {
116 Self::Memory(store) => store.rename_graph(from, to),
117 Self::Persistent(store) => store.rename_graph(from, to),
118 }
119 }
120 pub fn import_label_registry(
121 &mut self,
122 graph: &str,
123 registry: &GraphLabelRegistry,
124 ) -> GraphStoreResult<()> {
125 match self {
126 Self::Memory(store) => {
127 store.import_label_registry(graph, registry);
128 Ok(())
129 }
130 Self::Persistent(store) => store.import_label_registry(graph, registry),
131 }
132 }
133 pub fn rebuild_label_registry_from_ids(&mut self, graph: &str) -> GraphStoreResult<()> {
134 match self {
135 Self::Memory(store) => {
136 store.rebuild_label_registry_from_ids(graph);
137 Ok(())
138 }
139 Self::Persistent(store) => store.rebuild_label_registry_from_ids(graph),
140 }
141 }
142}
143
144impl GraphStore for GraphStoreHandle {
145 fn vertex_id_page(
146 &self,
147 graph: &str,
148 after: Option<u64>,
149 limit: usize,
150 ) -> GraphStoreResult<Vec<u64>> {
151 match self {
152 Self::Memory(store) => store.vertex_id_page(graph, after, limit),
153 Self::Persistent(store) => store.vertex_id_page(graph, after, limit),
154 }
155 }
156 fn edge_id_page(
157 &self,
158 graph: &str,
159 after: Option<u64>,
160 limit: usize,
161 ) -> GraphStoreResult<Vec<u64>> {
162 match self {
163 Self::Memory(store) => store.edge_id_page(graph, after, limit),
164 Self::Persistent(store) => store.edge_id_page(graph, after, limit),
165 }
166 }
167 fn transaction<T>(
168 &mut self,
169 operation: impl FnOnce(&mut Self) -> GraphStoreResult<T>,
170 ) -> GraphStoreResult<T> {
171 match self {
172 Self::Memory(store) => {
173 let backup = store.clone();
174 match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| operation(self))) {
175 Ok(Ok(value)) => Ok(value),
176 Ok(Err(error)) => {
177 *self = Self::Memory(backup);
178 Err(error)
179 }
180 Err(panic) => {
181 *self = Self::Memory(backup);
182 std::panic::resume_unwind(panic)
183 }
184 }
185 }
186 Self::Persistent(store) => {
187 let mut checkpoint = store.clone();
189 checkpoint.transaction(|_| operation(self))
190 }
191 }
192 }
193 fn create_graph(&mut self, name: &str) -> GraphStoreResult<()> {
194 match self {
195 Self::Memory(store) => GraphStore::create_graph(store, name),
196 Self::Persistent(store) => GraphStore::create_graph(store, name),
197 }
198 }
199 fn drop_graph(&mut self, name: &str) -> GraphStoreResult<()> {
200 match self {
201 Self::Memory(store) => GraphStore::drop_graph(store, name),
202 Self::Persistent(store) => GraphStore::drop_graph(store, name),
203 }
204 }
205 fn graph_names(&self) -> GraphStoreResult<Vec<String>> {
206 match self {
207 Self::Memory(store) => GraphStore::graph_names(store),
208 Self::Persistent(store) => GraphStore::graph_names(store),
209 }
210 }
211 fn has_graph(&self, name: &str) -> GraphStoreResult<bool> {
212 match self {
213 Self::Memory(store) => GraphStore::has_graph(store, name),
214 Self::Persistent(store) => GraphStore::has_graph(store, name),
215 }
216 }
217 fn union_graphs(&mut self, g1: &str, g2: &str, target: &str) -> GraphStoreResult<()> {
218 match self {
219 Self::Memory(store) => GraphStore::union_graphs(store, g1, g2, target),
220 Self::Persistent(store) => GraphStore::union_graphs(store, g1, g2, target),
221 }
222 }
223 fn intersect_graphs(&mut self, g1: &str, g2: &str, target: &str) -> GraphStoreResult<()> {
224 match self {
225 Self::Memory(store) => GraphStore::intersect_graphs(store, g1, g2, target),
226 Self::Persistent(store) => GraphStore::intersect_graphs(store, g1, g2, target),
227 }
228 }
229 fn difference_graphs(&mut self, g1: &str, g2: &str, target: &str) -> GraphStoreResult<()> {
230 match self {
231 Self::Memory(store) => GraphStore::difference_graphs(store, g1, g2, target),
232 Self::Persistent(store) => GraphStore::difference_graphs(store, g1, g2, target),
233 }
234 }
235 fn copy_graph(&mut self, source: &str, target: &str) -> GraphStoreResult<()> {
236 match self {
237 Self::Memory(store) => GraphStore::copy_graph(store, source, target),
238 Self::Persistent(store) => GraphStore::copy_graph(store, source, target),
239 }
240 }
241 fn add_vertex(&mut self, vertex: Vertex, graph: &str) -> GraphStoreResult<()> {
242 match self {
243 Self::Memory(store) => GraphStore::add_vertex(store, vertex, graph),
244 Self::Persistent(store) => GraphStore::add_vertex(store, vertex, graph),
245 }
246 }
247 fn add_edge(&mut self, edge: Edge, graph: &str) -> GraphStoreResult<()> {
248 match self {
249 Self::Memory(store) => GraphStore::add_edge(store, edge, graph),
250 Self::Persistent(store) => GraphStore::add_edge(store, edge, graph),
251 }
252 }
253 fn remove_vertex(&mut self, vertex_id: u64, graph: &str) -> GraphStoreResult<()> {
254 match self {
255 Self::Memory(store) => GraphStore::remove_vertex(store, vertex_id, graph),
256 Self::Persistent(store) => GraphStore::remove_vertex(store, vertex_id, graph),
257 }
258 }
259 fn remove_edge(&mut self, edge_id: u64, graph: &str) -> GraphStoreResult<()> {
260 match self {
261 Self::Memory(store) => GraphStore::remove_edge(store, edge_id, graph),
262 Self::Persistent(store) => GraphStore::remove_edge(store, edge_id, graph),
263 }
264 }
265 fn neighbors(
266 &self,
267 vertex_id: u64,
268 label: Option<&str>,
269 direction: Direction,
270 graph: &str,
271 ) -> GraphStoreResult<Vec<u64>> {
272 match self {
273 Self::Memory(store) => GraphStore::neighbors(store, vertex_id, label, direction, graph),
274 Self::Persistent(store) => {
275 GraphStore::neighbors(store, vertex_id, label, direction, graph)
276 }
277 }
278 }
279 fn vertices_by_label(&self, label: &str, graph: &str) -> GraphStoreResult<Vec<Vertex>> {
280 match self {
281 Self::Memory(store) => GraphStore::vertices_by_label(store, label, graph),
282 Self::Persistent(store) => GraphStore::vertices_by_label(store, label, graph),
283 }
284 }
285 fn vertex_ids_by_label(&self, label: &str, graph: &str) -> GraphStoreResult<Vec<u64>> {
286 match self {
287 Self::Memory(store) => GraphStore::vertex_ids_by_label(store, label, graph),
288 Self::Persistent(store) => GraphStore::vertex_ids_by_label(store, label, graph),
289 }
290 }
291 fn vertices_in_graph(&self, graph: &str) -> GraphStoreResult<Vec<Vertex>> {
292 match self {
293 Self::Memory(store) => GraphStore::vertices_in_graph(store, graph),
294 Self::Persistent(store) => GraphStore::vertices_in_graph(store, graph),
295 }
296 }
297 fn edges_in_graph(&self, graph: &str) -> GraphStoreResult<Vec<Edge>> {
298 match self {
299 Self::Memory(store) => GraphStore::edges_in_graph(store, graph),
300 Self::Persistent(store) => GraphStore::edges_in_graph(store, graph),
301 }
302 }
303 fn vertex_graphs(&self, vertex_id: u64) -> GraphStoreResult<BTreeSet<String>> {
304 match self {
305 Self::Memory(store) => GraphStore::vertex_graphs(store, vertex_id),
306 Self::Persistent(store) => GraphStore::vertex_graphs(store, vertex_id),
307 }
308 }
309 fn edge_graphs(&self, edge_id: u64) -> GraphStoreResult<BTreeSet<String>> {
310 match self {
311 Self::Memory(store) => store.edge_graphs(edge_id),
312 Self::Persistent(store) => store.edge_graphs(edge_id),
313 }
314 }
315 fn edges_by_label(&self, label: &str, graph: &str) -> GraphStoreResult<Vec<Edge>> {
316 match self {
317 Self::Memory(store) => store.edges_by_label(label, graph),
318 Self::Persistent(store) => store.edges_by_label(label, graph),
319 }
320 }
321 fn out_edge_ids(&self, vertex_id: u64, graph: &str) -> GraphStoreResult<BTreeSet<u64>> {
322 match self {
323 Self::Memory(store) => GraphStore::out_edge_ids(store, vertex_id, graph),
324 Self::Persistent(store) => GraphStore::out_edge_ids(store, vertex_id, graph),
325 }
326 }
327 fn in_edge_ids(&self, vertex_id: u64, graph: &str) -> GraphStoreResult<BTreeSet<u64>> {
328 match self {
329 Self::Memory(store) => GraphStore::in_edge_ids(store, vertex_id, graph),
330 Self::Persistent(store) => GraphStore::in_edge_ids(store, vertex_id, graph),
331 }
332 }
333 fn edge_ids_by_label(&self, label: &str, graph: &str) -> GraphStoreResult<BTreeSet<u64>> {
334 match self {
335 Self::Memory(store) => GraphStore::edge_ids_by_label(store, label, graph),
336 Self::Persistent(store) => GraphStore::edge_ids_by_label(store, label, graph),
337 }
338 }
339 fn vertex_ids_in_graph(&self, graph: &str) -> GraphStoreResult<BTreeSet<u64>> {
340 match self {
341 Self::Memory(store) => GraphStore::vertex_ids_in_graph(store, graph),
342 Self::Persistent(store) => GraphStore::vertex_ids_in_graph(store, graph),
343 }
344 }
345 fn require_vertex_in_graph(&self, vertex_id: u64, graph: &str) -> GraphStoreResult<()> {
346 match self {
347 Self::Memory(store) => GraphStore::require_vertex_in_graph(store, vertex_id, graph),
348 Self::Persistent(store) => GraphStore::require_vertex_in_graph(store, vertex_id, graph),
349 }
350 }
351 fn degree_distribution(&self, graph: &str) -> GraphStoreResult<BTreeMap<u64, u64>> {
352 match self {
353 Self::Memory(store) => GraphStore::degree_distribution(store, graph),
354 Self::Persistent(store) => GraphStore::degree_distribution(store, graph),
355 }
356 }
357 fn label_degree(&self, label: &str, graph: &str) -> GraphStoreResult<f64> {
358 match self {
359 Self::Memory(store) => GraphStore::label_degree(store, label, graph),
360 Self::Persistent(store) => GraphStore::label_degree(store, label, graph),
361 }
362 }
363 fn vertex_label_counts(&self, graph: &str) -> GraphStoreResult<BTreeMap<String, u64>> {
364 match self {
365 Self::Memory(store) => GraphStore::vertex_label_counts(store, graph),
366 Self::Persistent(store) => GraphStore::vertex_label_counts(store, graph),
367 }
368 }
369 fn get_vertex(&self, vertex_id: u64) -> GraphStoreResult<Option<Vertex>> {
370 match self {
371 Self::Memory(store) => GraphStore::get_vertex(store, vertex_id),
372 Self::Persistent(store) => GraphStore::get_vertex(store, vertex_id),
373 }
374 }
375 fn get_edge(&self, edge_id: u64) -> GraphStoreResult<Option<Edge>> {
376 match self {
377 Self::Memory(store) => GraphStore::get_edge(store, edge_id),
378 Self::Persistent(store) => GraphStore::get_edge(store, edge_id),
379 }
380 }
381 fn next_vertex_id(&mut self) -> GraphStoreResult<u64> {
382 match self {
383 Self::Memory(store) => GraphStore::next_vertex_id(store),
384 Self::Persistent(store) => GraphStore::next_vertex_id(store),
385 }
386 }
387 fn next_edge_id(&mut self) -> GraphStoreResult<u64> {
388 match self {
389 Self::Memory(store) => GraphStore::next_edge_id(store),
390 Self::Persistent(store) => GraphStore::next_edge_id(store),
391 }
392 }
393 fn allocate_vertex_id(&mut self, label: &str, graph: &str) -> GraphStoreResult<u64> {
394 match self {
395 Self::Memory(store) => GraphStore::allocate_vertex_id(store, label, graph),
396 Self::Persistent(store) => GraphStore::allocate_vertex_id(store, label, graph),
397 }
398 }
399 fn allocate_edge_id(&mut self, label: &str, graph: &str) -> GraphStoreResult<u64> {
400 match self {
401 Self::Memory(store) => GraphStore::allocate_edge_id(store, label, graph),
402 Self::Persistent(store) => GraphStore::allocate_edge_id(store, label, graph),
403 }
404 }
405 fn clear(&mut self) -> GraphStoreResult<()> {
406 match self {
407 Self::Memory(store) => GraphStore::clear(store),
408 Self::Persistent(store) => GraphStore::clear(store),
409 }
410 }
411 fn vertices(&self) -> GraphStoreResult<BTreeMap<u64, Vertex>> {
412 match self {
413 Self::Memory(store) => GraphStore::vertices(store),
414 Self::Persistent(store) => GraphStore::vertices(store),
415 }
416 }
417 fn edges(&self) -> GraphStoreResult<BTreeMap<u64, Edge>> {
418 match self {
419 Self::Memory(store) => GraphStore::edges(store),
420 Self::Persistent(store) => GraphStore::edges(store),
421 }
422 }
423}