tensorlogic_adapters/database/
memory.rs1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6
7use super::{SchemaDatabase, SchemaId, SchemaMetadata, SchemaVersion};
8use crate::{AdapterError, SymbolTable};
9
10pub struct MemoryDatabase {
19 schemas: HashMap<SchemaId, StoredSchema>,
20 next_id: u64,
21 name_index: HashMap<String, Vec<SchemaId>>,
22}
23
24#[derive(Clone, Debug, Serialize, Deserialize)]
25struct StoredSchema {
26 id: SchemaId,
27 name: String,
28 version: u32,
29 table: SymbolTable,
30 created_at: u64,
31 updated_at: u64,
32 description: Option<String>,
33}
34
35impl MemoryDatabase {
36 pub fn new() -> Self {
38 Self {
39 schemas: HashMap::new(),
40 next_id: 1,
41 name_index: HashMap::new(),
42 }
43 }
44
45 fn current_timestamp() -> u64 {
47 std::time::SystemTime::now()
48 .duration_since(std::time::UNIX_EPOCH)
49 .expect("SystemTime after UNIX_EPOCH")
50 .as_secs()
51 }
52
53 fn find_latest_version(&self, name: &str) -> Option<SchemaId> {
55 self.name_index.get(name).and_then(|ids| {
56 ids.iter()
57 .filter_map(|id| self.schemas.get(id))
58 .max_by_key(|s| s.version)
59 .map(|s| s.id)
60 })
61 }
62}
63
64impl Default for MemoryDatabase {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl SchemaDatabase for MemoryDatabase {
71 fn store_schema(&mut self, name: &str, table: &SymbolTable) -> Result<SchemaId, AdapterError> {
72 let now = Self::current_timestamp();
73
74 let version = if let Some(existing_id) = self.find_latest_version(name) {
76 if let Some(existing) = self.schemas.get(&existing_id) {
77 existing.version + 1
78 } else {
79 1
80 }
81 } else {
82 1
83 };
84
85 let id = SchemaId(self.next_id);
86 self.next_id += 1;
87
88 let stored = StoredSchema {
89 id,
90 name: name.to_string(),
91 version,
92 table: table.clone(),
93 created_at: now,
94 updated_at: now,
95 description: None,
96 };
97
98 self.schemas.insert(id, stored);
99
100 self.name_index
102 .entry(name.to_string())
103 .or_default()
104 .push(id);
105
106 Ok(id)
107 }
108
109 fn load_schema(&self, id: SchemaId) -> Result<SymbolTable, AdapterError> {
110 self.schemas
111 .get(&id)
112 .map(|s| s.table.clone())
113 .ok_or_else(|| {
114 AdapterError::InvalidOperation(format!("Schema with ID {:?} not found", id))
115 })
116 }
117
118 fn load_schema_by_name(&self, name: &str) -> Result<SymbolTable, AdapterError> {
119 let id = self.find_latest_version(name).ok_or_else(|| {
120 AdapterError::InvalidOperation(format!("Schema '{}' not found", name))
121 })?;
122
123 self.load_schema(id)
124 }
125
126 fn list_schemas(&self) -> Result<Vec<SchemaMetadata>, AdapterError> {
127 let mut metadata: Vec<SchemaMetadata> = self
128 .schemas
129 .values()
130 .map(|s| SchemaMetadata {
131 id: s.id,
132 name: s.name.clone(),
133 version: s.version,
134 created_at: s.created_at,
135 updated_at: s.updated_at,
136 num_domains: s.table.domains.len(),
137 num_predicates: s.table.predicates.len(),
138 num_variables: s.table.variables.len(),
139 description: s.description.clone(),
140 })
141 .collect();
142
143 metadata.sort_by_key(|m| m.name.clone());
144 Ok(metadata)
145 }
146
147 fn delete_schema(&mut self, id: SchemaId) -> Result<(), AdapterError> {
148 if let Some(schema) = self.schemas.remove(&id) {
149 if let Some(ids) = self.name_index.get_mut(&schema.name) {
151 ids.retain(|&i| i != id);
152 if ids.is_empty() {
153 self.name_index.remove(&schema.name);
154 }
155 }
156 Ok(())
157 } else {
158 Err(AdapterError::InvalidOperation(format!(
159 "Schema with ID {:?} not found",
160 id
161 )))
162 }
163 }
164
165 fn search_schemas(&self, pattern: &str) -> Result<Vec<SchemaMetadata>, AdapterError> {
166 let pattern_lower = pattern.to_lowercase();
167 let mut results: Vec<SchemaMetadata> = self
168 .schemas
169 .values()
170 .filter(|s| s.name.to_lowercase().contains(&pattern_lower))
171 .map(|s| SchemaMetadata {
172 id: s.id,
173 name: s.name.clone(),
174 version: s.version,
175 created_at: s.created_at,
176 updated_at: s.updated_at,
177 num_domains: s.table.domains.len(),
178 num_predicates: s.table.predicates.len(),
179 num_variables: s.table.variables.len(),
180 description: s.description.clone(),
181 })
182 .collect();
183
184 results.sort_by_key(|m| m.name.clone());
185 Ok(results)
186 }
187
188 fn get_schema_history(&self, name: &str) -> Result<Vec<SchemaVersion>, AdapterError> {
189 let ids = self.name_index.get(name).ok_or_else(|| {
190 AdapterError::InvalidOperation(format!("Schema '{}' not found", name))
191 })?;
192
193 let mut versions: Vec<SchemaVersion> = ids
194 .iter()
195 .filter_map(|id| {
196 self.schemas.get(id).map(|s| SchemaVersion {
197 version: s.version,
198 timestamp: s.created_at,
199 description: format!("Version {}", s.version),
200 schema_id: s.id,
201 })
202 })
203 .collect();
204
205 versions.sort_by_key(|v| v.version);
206 Ok(versions)
207 }
208}