Skip to main content

tensorlogic_adapters/database/
mod.rs

1//! Database integration for schema persistence.
2//!
3//! This module provides functionality to store and retrieve symbol tables
4//! from relational databases. Supported databases:
5//! - SQLite (via rusqlite) - embedded, file-based
6//! - PostgreSQL (via tokio-postgres) - server-based, multi-user
7//!
8//! The database schema includes tables for:
9//! - Domains (with cardinality and metadata)
10//! - Predicates (with arity, argument domains, and constraints)
11//! - Variables (with domain bindings)
12//! - Schema versioning and change history
13
14use serde::{Deserialize, Serialize};
15
16use crate::{AdapterError, SymbolTable};
17
18mod memory;
19mod sql;
20
21#[cfg(feature = "sqlite")]
22mod sqlite_backend;
23
24#[cfg(feature = "postgres")]
25mod postgres_backend;
26
27pub use memory::MemoryDatabase;
28pub use sql::{DatabaseStats, SchemaDatabaseSQL};
29
30#[cfg(feature = "sqlite")]
31pub use sqlite_backend::SQLiteDatabase;
32
33#[cfg(feature = "postgres")]
34pub use postgres_backend::PostgreSQLDatabase;
35
36/// Database storage trait for symbol tables.
37///
38/// Implementations handle the specifics of different database backends.
39pub trait SchemaDatabase {
40    /// Store a complete symbol table in the database.
41    ///
42    /// If a schema with the same name exists, it is updated.
43    fn store_schema(&mut self, name: &str, table: &SymbolTable) -> Result<SchemaId, AdapterError>;
44
45    /// Load a symbol table by schema ID.
46    fn load_schema(&self, id: SchemaId) -> Result<SymbolTable, AdapterError>;
47
48    /// Load a symbol table by name (returns most recent version).
49    fn load_schema_by_name(&self, name: &str) -> Result<SymbolTable, AdapterError>;
50
51    /// List all available schemas.
52    fn list_schemas(&self) -> Result<Vec<SchemaMetadata>, AdapterError>;
53
54    /// Delete a schema by ID.
55    fn delete_schema(&mut self, id: SchemaId) -> Result<(), AdapterError>;
56
57    /// Search schemas by name pattern.
58    fn search_schemas(&self, pattern: &str) -> Result<Vec<SchemaMetadata>, AdapterError>;
59
60    /// Get schema history (all versions).
61    fn get_schema_history(&self, name: &str) -> Result<Vec<SchemaVersion>, AdapterError>;
62}
63
64/// Unique identifier for a stored schema.
65#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
66pub struct SchemaId(pub u64);
67
68/// Metadata about a stored schema.
69#[derive(Clone, Debug, Serialize, Deserialize)]
70pub struct SchemaMetadata {
71    /// Unique identifier
72    pub id: SchemaId,
73    /// Schema name
74    pub name: String,
75    /// Version number
76    pub version: u32,
77    /// Creation timestamp (Unix epoch)
78    pub created_at: u64,
79    /// Last modification timestamp
80    pub updated_at: u64,
81    /// Number of domains
82    pub num_domains: usize,
83    /// Number of predicates
84    pub num_predicates: usize,
85    /// Number of variables
86    pub num_variables: usize,
87    /// Optional description
88    pub description: Option<String>,
89}
90
91/// Version information for a schema.
92#[derive(Clone, Debug, Serialize, Deserialize)]
93pub struct SchemaVersion {
94    /// Version number
95    pub version: u32,
96    /// Timestamp
97    pub timestamp: u64,
98    /// Change description
99    pub description: String,
100    /// Schema ID for this version
101    pub schema_id: SchemaId,
102}
103
104// Tests are in a separate module to keep this file under 2000 lines
105#[cfg(test)]
106#[path = "../database_tests.rs"]
107mod tests;