Skip to main content

uqa_storage_sqlite/catalog/
facade.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Storage-backend facade delegation for the `SQLite` catalog.
8
9use super::{
10    Catalog, CatalogFacade, CatalogIndexRow, ColumnStatsInput, ColumnStatsRow, EdgeRow,
11    ForeignTableRow, GraphSnapshot, OptionalExtension, RelationIdentity, Result, SQLiteError,
12    SequenceReservationResult, SequenceRow, StorageBackendError, StorageBackendResult,
13    TableAclEntry, TableSchema, ViewRow,
14};
15
16fn into_storage_result<T>(result: Result<T>) -> StorageBackendResult<T> {
17    result.map_err(StorageBackendError::from)
18}
19
20impl CatalogFacade for Catalog {
21    fn clear_path_index_data(&self, index: &str) -> StorageBackendResult<()> {
22        into_storage_result(Catalog::clear_path_index_data(self, index))
23    }
24
25    fn save_path_index_pairs(
26        &self,
27        index: &str,
28        sequence: &str,
29        pairs: &[(u64, u64)],
30    ) -> StorageBackendResult<()> {
31        into_storage_result(Catalog::save_path_index_pairs(self, index, sequence, pairs))
32    }
33
34    fn finish_path_index_data(
35        &self,
36        index: &str,
37        graph: &str,
38        definition: &str,
39    ) -> StorageBackendResult<()> {
40        into_storage_result(Catalog::finish_path_index_data(
41            self, index, graph, definition,
42        ))
43    }
44
45    fn path_index_data_is_current(
46        &self,
47        index: &str,
48        definition: &str,
49    ) -> StorageBackendResult<bool> {
50        into_storage_result(Catalog::path_index_data_is_current(self, index, definition))
51    }
52
53    fn path_index_pairs(
54        &self,
55        index: &str,
56        sequence: &str,
57        after: Option<(u64, u64)>,
58        limit: usize,
59    ) -> StorageBackendResult<Vec<(u64, u64)>> {
60        into_storage_result(Catalog::path_index_pairs(
61            self, index, sequence, after, limit,
62        ))
63    }
64
65    fn graph_vertex(&self, id: u64) -> StorageBackendResult<Option<uqa_storage::GraphVertexRow>> {
66        into_storage_result(Catalog::graph_vertex(self, id))
67    }
68
69    fn graph_edge(&self, id: u64) -> StorageBackendResult<Option<EdgeRow>> {
70        into_storage_result(Catalog::graph_edge(self, id))
71    }
72
73    fn graph_entity_ids(
74        &self,
75        filter: uqa_storage::GraphEntityFilter<'_>,
76        after: Option<u64>,
77        limit: usize,
78    ) -> StorageBackendResult<Vec<u64>> {
79        into_storage_result(Catalog::graph_entity_ids(self, filter, after, limit))
80    }
81
82    fn graph_entity_count(
83        &self,
84        filter: uqa_storage::GraphEntityFilter<'_>,
85    ) -> StorageBackendResult<u64> {
86        into_storage_result(Catalog::graph_entity_count(self, filter))
87    }
88
89    fn graph_entity_max_id(
90        &self,
91        kind: uqa_storage::GraphEntityKind,
92    ) -> StorageBackendResult<Option<u64>> {
93        into_storage_result(Catalog::graph_entity_max_id(self, kind))
94    }
95
96    fn graph_entity_memberships(
97        &self,
98        kind: uqa_storage::GraphEntityKind,
99        id: u64,
100    ) -> StorageBackendResult<Vec<String>> {
101        into_storage_result(Catalog::graph_entity_memberships(self, kind, id))
102    }
103
104    fn graph_has_membership(
105        &self,
106        kind: uqa_storage::GraphEntityKind,
107        id: u64,
108        graph: &str,
109    ) -> StorageBackendResult<bool> {
110        into_storage_result(Catalog::graph_has_membership(self, kind, id, graph))
111    }
112
113    fn initialize_storage(&self) -> StorageBackendResult<()> {
114        into_storage_result(Catalog::initialize_storage(self))
115    }
116
117    fn cache_revisions(&self) -> StorageBackendResult<Option<uqa_storage::CatalogCacheRevisions>> {
118        into_storage_result(Catalog::cache_revisions(self)).map(Some)
119    }
120
121    fn set_metadata(&self, key: &str, value: &str) -> StorageBackendResult<()> {
122        into_storage_result(Catalog::set_metadata(self, key, value))
123    }
124
125    fn get_metadata(&self, key: &str) -> StorageBackendResult<Option<String>> {
126        into_storage_result(Catalog::get_metadata(self, key))
127    }
128
129    fn migrate_relation_namespace(&self) -> StorageBackendResult<()> {
130        into_storage_result(self.conn.with(|connection| {
131            let foreign_key_violation = connection
132                .query_row("PRAGMA foreign_key_check", [], |row| {
133                    Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
134                })
135                .optional()?;
136            if let Some((table, row_id)) = foreign_key_violation {
137                return Err(SQLiteError::StorageBackend(format!(
138                    "relation catalog foreign-key violation in `{table}` row {row_id}"
139                )));
140            }
141            let orphan = connection
142                .query_row(
143                    "SELECT r.schema_name, r.relation_name, r.kind
144                       FROM _relations AS r
145                       LEFT JOIN (
146                           SELECT schema_name, relation_name, 'table' AS kind FROM _tables
147                           UNION ALL
148                           SELECT schema_name, relation_name, 'view' AS kind FROM _views
149                           UNION ALL
150                           SELECT schema_name, relation_name, 'sequence' AS kind FROM _sequences
151                           UNION ALL
152                           SELECT schema_name, relation_name, 'foreign_table' AS kind
153                             FROM _foreign_tables
154                           UNION ALL
155                           SELECT schema_name, relation_name, 'index' AS kind
156                             FROM _catalog_indexes
157                       ) AS child
158                         ON child.schema_name = r.schema_name
159                        AND child.relation_name = r.relation_name
160                        AND child.kind = r.kind
161                      WHERE child.relation_name IS NULL
162                      LIMIT 1",
163                    [],
164                    |row| {
165                        Ok((
166                            row.get::<_, String>(0)?,
167                            row.get::<_, String>(1)?,
168                            row.get::<_, String>(2)?,
169                        ))
170                    },
171                )
172                .optional()?;
173            if let Some((schema, name, kind)) = orphan {
174                return Err(SQLiteError::StorageBackend(format!(
175                    "catalog relation `{schema}.{name}` has no {kind} child"
176                )));
177            }
178            Ok(())
179        }))
180    }
181
182    fn save_schema_row(
183        &self,
184        schema: &uqa_storage::catalog::SchemaRow,
185    ) -> StorageBackendResult<()> {
186        into_storage_result(Catalog::save_schema_row(self, schema))
187    }
188
189    fn drop_schema(&self, name: &str) -> StorageBackendResult<()> {
190        into_storage_result(Catalog::drop_schema(self, name))
191    }
192
193    fn load_schema_rows(&self) -> StorageBackendResult<Vec<uqa_storage::catalog::SchemaRow>> {
194        into_storage_result(Catalog::load_schema_rows(self))
195    }
196
197    fn save_table(&self, schema: &TableSchema) -> StorageBackendResult<()> {
198        into_storage_result(Catalog::save_table(self, schema))
199    }
200
201    fn load_tables(&self) -> StorageBackendResult<Vec<TableSchema>> {
202        into_storage_result(Catalog::load_tables(self))
203    }
204
205    fn drop_table(&self, name: &str) -> StorageBackendResult<()> {
206        into_storage_result(Catalog::drop_table(self, name))
207    }
208
209    fn drop_table_and_data(&self, name: &str) -> StorageBackendResult<()> {
210        into_storage_result(Catalog::drop_table_and_data(self, name))
211    }
212
213    fn purge_table_data(&self, name: &str) -> StorageBackendResult<()> {
214        into_storage_result(Catalog::purge_table_data(self, name))
215    }
216
217    fn rename_table_data(&self, from: &str, to: &str) -> StorageBackendResult<()> {
218        into_storage_result(Catalog::rename_table_data(self, from, to))
219    }
220
221    fn drop_column_data(&self, table_name: &str, column_name: &str) -> StorageBackendResult<()> {
222        into_storage_result(Catalog::drop_column_data(self, table_name, column_name))
223    }
224
225    fn rename_column_data(
226        &self,
227        table_name: &str,
228        from: &str,
229        to: &str,
230    ) -> StorageBackendResult<()> {
231        into_storage_result(Catalog::rename_column_data(self, table_name, from, to))
232    }
233
234    fn save_model(&self, name: &str, json: &str) -> StorageBackendResult<()> {
235        into_storage_result(Catalog::save_model(self, name, json))
236    }
237
238    fn load_models(&self) -> StorageBackendResult<Vec<(String, String)>> {
239        into_storage_result(Catalog::load_models(self))
240    }
241
242    fn load_model(&self, name: &str) -> StorageBackendResult<Option<String>> {
243        into_storage_result(Catalog::load_model(self, name))
244    }
245
246    fn drop_model(&self, name: &str) -> StorageBackendResult<()> {
247        into_storage_result(Catalog::drop_model(self, name))
248    }
249
250    fn save_scoring_params(&self, name: &str, params_json: &str) -> StorageBackendResult<()> {
251        into_storage_result(Catalog::save_scoring_params(self, name, params_json))
252    }
253
254    fn load_scoring_params(&self, name: &str) -> StorageBackendResult<Option<String>> {
255        into_storage_result(Catalog::load_scoring_params(self, name))
256    }
257
258    fn load_all_scoring_params(&self) -> StorageBackendResult<Vec<(String, String)>> {
259        into_storage_result(Catalog::load_all_scoring_params(self))
260    }
261
262    fn drop_scoring_params(&self, name: &str) -> StorageBackendResult<()> {
263        into_storage_result(Catalog::drop_scoring_params(self, name))
264    }
265
266    fn create_sequence_row(&self, sequence: &SequenceRow) -> StorageBackendResult<bool> {
267        into_storage_result(Catalog::create_sequence_row(self, sequence))
268    }
269
270    fn replace_sequence_row(&self, sequence: &SequenceRow) -> StorageBackendResult<bool> {
271        into_storage_result(Catalog::replace_sequence_row(self, sequence))
272    }
273
274    fn rename_sequence_row(&self, from: &str, to: &str) -> StorageBackendResult<bool> {
275        into_storage_result(Catalog::rename_sequence_row(self, from, to))
276    }
277
278    fn drop_sequence_row(&self, name: &str) -> StorageBackendResult<bool> {
279        into_storage_result(Catalog::drop_sequence_row(self, name))
280    }
281
282    fn load_sequence_rows(&self) -> StorageBackendResult<Vec<SequenceRow>> {
283        into_storage_result(Catalog::load_sequence_rows(self))
284    }
285
286    fn reserve_sequence_values(
287        &self,
288        name: &str,
289        object_id: [u8; 16],
290        definition_generation: [u8; 16],
291    ) -> StorageBackendResult<SequenceReservationResult> {
292        into_storage_result(Catalog::reserve_sequence_values(
293            self,
294            name,
295            object_id,
296            definition_generation,
297        ))
298    }
299
300    fn set_sequence_value(
301        &self,
302        name: &str,
303        object_id: [u8; 16],
304        value: i64,
305        called: bool,
306        log_count: i64,
307    ) -> StorageBackendResult<Option<i64>> {
308        into_storage_result(Catalog::set_sequence_value(
309            self, name, object_id, value, called, log_count,
310        ))
311    }
312
313    fn save_view(&self, view: &ViewRow) -> StorageBackendResult<()> {
314        into_storage_result(Catalog::save_view(self, view))
315    }
316
317    fn rename_view(
318        &self,
319        from: &RelationIdentity,
320        to: &RelationIdentity,
321    ) -> StorageBackendResult<bool> {
322        into_storage_result(Catalog::rename_view(self, from, to))
323    }
324
325    fn drop_view(&self, relation: &RelationIdentity) -> StorageBackendResult<bool> {
326        into_storage_result(Catalog::drop_view(self, relation))
327    }
328
329    fn load_views(&self) -> StorageBackendResult<Vec<ViewRow>> {
330        into_storage_result(Catalog::load_views(self))
331    }
332
333    fn save_named_graph(&self, name: &str) -> StorageBackendResult<()> {
334        into_storage_result(Catalog::save_named_graph(self, name))
335    }
336
337    fn drop_named_graph(&self, name: &str) -> StorageBackendResult<()> {
338        into_storage_result(Catalog::drop_named_graph(self, name))
339    }
340
341    fn load_named_graphs(&self) -> StorageBackendResult<Vec<String>> {
342        into_storage_result(Catalog::load_named_graphs(self))
343    }
344    fn named_graph_exists(&self, name: &str) -> StorageBackendResult<bool> {
345        into_storage_result(Catalog::named_graph_exists(self, name))
346    }
347
348    fn load_named_graph_snapshot(&self, name: &str) -> StorageBackendResult<Option<GraphSnapshot>> {
349        into_storage_result(Catalog::load_named_graph_snapshot(self, name))
350    }
351
352    fn save_vertex(
353        &self,
354        vertex_id: u64,
355        label: &str,
356        properties_json: &str,
357    ) -> StorageBackendResult<()> {
358        into_storage_result(Catalog::save_vertex(
359            self,
360            vertex_id,
361            label,
362            properties_json,
363        ))
364    }
365
366    fn delete_vertex(&self, vertex_id: u64) -> StorageBackendResult<()> {
367        into_storage_result(Catalog::delete_vertex(self, vertex_id))
368    }
369
370    fn load_vertices(&self) -> StorageBackendResult<Vec<(u64, String, String)>> {
371        into_storage_result(Catalog::load_vertices(self))
372    }
373
374    fn save_edge(
375        &self,
376        edge_id: u64,
377        source_id: u64,
378        target_id: u64,
379        label: &str,
380        properties_json: &str,
381    ) -> StorageBackendResult<()> {
382        into_storage_result(Catalog::save_edge(
383            self,
384            edge_id,
385            source_id,
386            target_id,
387            label,
388            properties_json,
389        ))
390    }
391
392    fn delete_edge(&self, edge_id: u64) -> StorageBackendResult<()> {
393        into_storage_result(Catalog::delete_edge(self, edge_id))
394    }
395
396    fn load_edges(&self) -> StorageBackendResult<Vec<EdgeRow>> {
397        into_storage_result(Catalog::load_edges(self))
398    }
399
400    fn save_graph_membership(
401        &self,
402        entity_type: &str,
403        entity_id: u64,
404        graph_name: &str,
405    ) -> StorageBackendResult<()> {
406        into_storage_result(Catalog::save_graph_membership(
407            self,
408            entity_type,
409            entity_id,
410            graph_name,
411        ))
412    }
413
414    fn delete_graph_membership(
415        &self,
416        entity_type: &str,
417        entity_id: u64,
418        graph_name: &str,
419    ) -> StorageBackendResult<()> {
420        into_storage_result(Catalog::delete_graph_membership(
421            self,
422            entity_type,
423            entity_id,
424            graph_name,
425        ))
426    }
427
428    fn delete_graph_membership_for_graph(&self, graph_name: &str) -> StorageBackendResult<()> {
429        into_storage_result(Catalog::delete_graph_membership_for_graph(self, graph_name))
430    }
431
432    fn load_graph_memberships(&self) -> StorageBackendResult<Vec<(String, u64, String)>> {
433        into_storage_result(Catalog::load_graph_memberships(self))
434    }
435
436    fn purge_orphan_graph_entities(&self) -> StorageBackendResult<()> {
437        into_storage_result(Catalog::purge_orphan_graph_entities(self))
438    }
439
440    fn replace_named_graph(
441        &self,
442        graph_name: &str,
443        snapshot: &GraphSnapshot,
444    ) -> StorageBackendResult<()> {
445        into_storage_result(Catalog::replace_named_graph(self, graph_name, snapshot))
446    }
447
448    fn drop_named_graph_data(&self, graph_name: &str) -> StorageBackendResult<()> {
449        into_storage_result(Catalog::drop_named_graph_data(self, graph_name))
450    }
451
452    fn save_analyzer(&self, name: &str, config_json: &str) -> StorageBackendResult<()> {
453        into_storage_result(Catalog::save_analyzer(self, name, config_json))
454    }
455
456    fn drop_analyzer(&self, name: &str) -> StorageBackendResult<()> {
457        into_storage_result(Catalog::drop_analyzer(self, name))
458    }
459
460    fn load_analyzers(&self) -> StorageBackendResult<Vec<(String, String)>> {
461        into_storage_result(Catalog::load_analyzers(self))
462    }
463
464    fn save_analyzer_revision(
465        &self,
466        name: &str,
467        config_json: &str,
468        descriptor_json: &str,
469    ) -> StorageBackendResult<()> {
470        into_storage_result(Catalog::save_analyzer_revision(
471            self,
472            name,
473            config_json,
474            descriptor_json,
475        ))
476    }
477
478    fn load_analyzer_descriptors(&self) -> StorageBackendResult<Vec<(String, String)>> {
479        into_storage_result(Catalog::load_analyzer_descriptors(self))
480    }
481
482    fn replace_table_field_analyzer_binding(
483        &self,
484        table: &str,
485        field: &str,
486        phase: &str,
487        name: &str,
488        binding_json: &str,
489    ) -> StorageBackendResult<()> {
490        into_storage_result(Catalog::replace_table_field_analyzer_binding(
491            self,
492            table,
493            field,
494            phase,
495            name,
496            binding_json,
497        ))
498    }
499
500    fn load_table_field_analyzer_bindings(
501        &self,
502    ) -> StorageBackendResult<Vec<(String, String, String)>> {
503        into_storage_result(Catalog::load_table_field_analyzer_bindings(self))
504    }
505
506    fn save_table_field_analyzer(
507        &self,
508        table_name: &str,
509        field: &str,
510        phase: &str,
511        analyzer_name: &str,
512    ) -> StorageBackendResult<()> {
513        into_storage_result(Catalog::save_table_field_analyzer(
514            self,
515            table_name,
516            field,
517            phase,
518            analyzer_name,
519        ))
520    }
521
522    fn replace_table_field_analyzer(
523        &self,
524        table_name: &str,
525        field: &str,
526        phase: &str,
527        analyzer_name: &str,
528    ) -> StorageBackendResult<()> {
529        into_storage_result(Catalog::replace_table_field_analyzer(
530            self,
531            table_name,
532            field,
533            phase,
534            analyzer_name,
535        ))
536    }
537
538    fn drop_table_field_analyzer_field(
539        &self,
540        table_name: &str,
541        field: &str,
542    ) -> StorageBackendResult<()> {
543        into_storage_result(Catalog::drop_table_field_analyzer_field(
544            self, table_name, field,
545        ))
546    }
547
548    fn drop_table_field_analyzers(&self, table_name: &str) -> StorageBackendResult<()> {
549        into_storage_result(Catalog::drop_table_field_analyzers(self, table_name))
550    }
551
552    fn load_table_field_analyzers(
553        &self,
554    ) -> StorageBackendResult<Vec<(String, String, String, String)>> {
555        into_storage_result(Catalog::load_table_field_analyzers(self))
556    }
557
558    fn save_foreign_server(
559        &self,
560        name: &str,
561        fdw_type: &str,
562        options_json: &str,
563    ) -> StorageBackendResult<()> {
564        into_storage_result(Catalog::save_foreign_server(
565            self,
566            name,
567            fdw_type,
568            options_json,
569        ))
570    }
571
572    fn drop_foreign_server(&self, name: &str) -> StorageBackendResult<()> {
573        into_storage_result(Catalog::drop_foreign_server(self, name))
574    }
575
576    fn load_foreign_servers(&self) -> StorageBackendResult<Vec<(String, String, String)>> {
577        into_storage_result(Catalog::load_foreign_servers(self))
578    }
579
580    fn save_foreign_table(&self, row: &ForeignTableRow) -> StorageBackendResult<()> {
581        into_storage_result(Catalog::save_foreign_table(self, row))
582    }
583
584    fn rename_foreign_table(
585        &self,
586        from: &RelationIdentity,
587        to: &RelationIdentity,
588    ) -> StorageBackendResult<bool> {
589        into_storage_result(Catalog::rename_foreign_table(self, from, to))
590    }
591
592    fn update_foreign_table_security(
593        &self,
594        relation: &RelationIdentity,
595        role_owner: &str,
596        acl: Option<&[TableAclEntry]>,
597        column_acls: &std::collections::BTreeMap<String, Vec<TableAclEntry>>,
598    ) -> StorageBackendResult<bool> {
599        into_storage_result(Catalog::update_foreign_table_security(
600            self,
601            relation,
602            role_owner,
603            acl,
604            column_acls,
605        ))
606    }
607
608    fn drop_foreign_table(&self, relation: &RelationIdentity) -> StorageBackendResult<()> {
609        into_storage_result(Catalog::drop_foreign_table(self, relation))
610    }
611
612    fn load_foreign_tables(&self) -> StorageBackendResult<Vec<ForeignTableRow>> {
613        into_storage_result(Catalog::load_foreign_tables(self))
614    }
615
616    fn save_catalog_index_row(&self, index: &CatalogIndexRow) -> StorageBackendResult<()> {
617        into_storage_result(Catalog::save_catalog_index_row(self, index))
618    }
619
620    fn drop_catalog_index(&self, relation: &RelationIdentity) -> StorageBackendResult<()> {
621        into_storage_result(Catalog::drop_catalog_index(self, relation))
622    }
623
624    fn drop_catalog_indexes_for_table(&self, table_name: &str) -> StorageBackendResult<()> {
625        into_storage_result(Catalog::drop_catalog_indexes_for_table(self, table_name))
626    }
627
628    fn load_catalog_indexes(&self) -> StorageBackendResult<Vec<CatalogIndexRow>> {
629        into_storage_result(Catalog::load_catalog_indexes(self))
630    }
631
632    fn save_path_index(
633        &self,
634        graph_name: &str,
635        label_sequences_json: &str,
636    ) -> StorageBackendResult<()> {
637        into_storage_result(Catalog::save_path_index(
638            self,
639            graph_name,
640            label_sequences_json,
641        ))
642    }
643
644    fn drop_path_index(&self, graph_name: &str) -> StorageBackendResult<()> {
645        into_storage_result(Catalog::drop_path_index(self, graph_name))
646    }
647
648    fn load_path_indexes(&self) -> StorageBackendResult<Vec<(String, String)>> {
649        into_storage_result(Catalog::load_path_indexes(self))
650    }
651
652    fn save_column_stats(&self, stats: ColumnStatsInput<'_>) -> StorageBackendResult<()> {
653        into_storage_result(Catalog::save_column_stats(self, stats))
654    }
655
656    fn replace_column_stats(
657        &self,
658        table_name: &str,
659        stats: &[ColumnStatsInput<'_>],
660    ) -> StorageBackendResult<()> {
661        into_storage_result(Catalog::replace_column_stats(self, table_name, stats))
662    }
663
664    fn load_column_stats(&self, table_name: &str) -> StorageBackendResult<Vec<ColumnStatsRow>> {
665        into_storage_result(Catalog::load_column_stats(self, table_name))
666    }
667
668    fn delete_column_stats(&self, table_name: &str) -> StorageBackendResult<()> {
669        into_storage_result(Catalog::delete_column_stats(self, table_name))
670    }
671}