1use crate::row_store::RowStore;
6use alloc::collections::BTreeMap;
7use alloc::format;
8use alloc::rc::Rc;
9use alloc::string::{String, ToString};
10use alloc::vec::Vec;
11use cynos_core::schema::Table;
12use cynos_core::{Error, Result, Row, RowId};
13
14pub struct TableCache {
16 tables: BTreeMap<String, RowStore>,
18}
19
20impl TableCache {
21 pub fn new() -> Self {
23 Self {
24 tables: BTreeMap::new(),
25 }
26 }
27
28 pub fn create_table(&mut self, schema: Table) -> Result<()> {
30 let name = schema.name().to_string();
31 if self.tables.contains_key(&name) {
32 return Err(Error::invalid_schema(format!(
33 "Table already exists: {}",
34 name
35 )));
36 }
37 self.tables.insert(name, RowStore::new(schema));
38 Ok(())
39 }
40
41 pub fn drop_table(&mut self, name: &str) -> Result<()> {
43 if self.tables.remove(name).is_none() {
44 return Err(Error::table_not_found(name));
45 }
46 Ok(())
47 }
48
49 pub fn get_table(&self, name: &str) -> Option<&RowStore> {
51 self.tables.get(name)
52 }
53
54 pub fn get_table_mut(&mut self, name: &str) -> Option<&mut RowStore> {
56 self.tables.get_mut(name)
57 }
58
59 pub fn table_count(&self) -> usize {
61 self.tables.len()
62 }
63
64 pub fn table_names(&self) -> Vec<&str> {
66 self.tables.keys().map(|s| s.as_str()).collect()
67 }
68
69 pub fn total_row_count(&self) -> usize {
71 self.tables.values().map(|t| t.len()).sum()
72 }
73
74 pub fn get_row(&self, table: &str, row_id: RowId) -> Option<Rc<Row>> {
76 self.tables.get(table).and_then(|t| t.get(row_id))
77 }
78
79 pub fn get_many(&self, table: &str, row_ids: &[RowId]) -> Vec<Option<Rc<Row>>> {
81 if let Some(store) = self.tables.get(table) {
82 store.get_many(row_ids)
83 } else {
84 row_ids.iter().map(|_| None).collect()
85 }
86 }
87
88 pub fn has_table(&self, name: &str) -> bool {
90 self.tables.contains_key(name)
91 }
92
93 pub fn clear(&mut self) {
95 for store in self.tables.values_mut() {
96 store.clear();
97 }
98 }
99
100 pub fn clear_table(&mut self, name: &str) -> Result<()> {
102 if let Some(store) = self.tables.get_mut(name) {
103 store.clear();
104 Ok(())
105 } else {
106 Err(Error::table_not_found(name))
107 }
108 }
109}
110
111impl Default for TableCache {
112 fn default() -> Self {
113 Self::new()
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use cynos_core::schema::TableBuilder;
121 use cynos_core::{DataType, Value};
122 use alloc::vec;
123
124 fn test_schema(name: &str) -> Table {
125 TableBuilder::new(name)
126 .unwrap()
127 .add_column("id", DataType::Int64)
128 .unwrap()
129 .add_column("name", DataType::String)
130 .unwrap()
131 .add_primary_key(&["id"], false)
132 .unwrap()
133 .build()
134 .unwrap()
135 }
136
137 #[test]
138 fn test_cache_create_table() {
139 let mut cache = TableCache::new();
140 let result = cache.create_table(test_schema("users"));
141 assert!(result.is_ok());
142 assert!(cache.has_table("users"));
143 }
144
145 #[test]
146 fn test_cache_create_duplicate_table() {
147 let mut cache = TableCache::new();
148 cache.create_table(test_schema("users")).unwrap();
149 let result = cache.create_table(test_schema("users"));
150 assert!(result.is_err());
151 }
152
153 #[test]
154 fn test_cache_drop_table() {
155 let mut cache = TableCache::new();
156 cache.create_table(test_schema("users")).unwrap();
157 let result = cache.drop_table("users");
158 assert!(result.is_ok());
159 assert!(!cache.has_table("users"));
160 }
161
162 #[test]
163 fn test_cache_drop_nonexistent_table() {
164 let mut cache = TableCache::new();
165 let result = cache.drop_table("nonexistent");
166 assert!(result.is_err());
167 }
168
169 #[test]
170 fn test_cache_get_table() {
171 let mut cache = TableCache::new();
172 cache.create_table(test_schema("users")).unwrap();
173
174 assert!(cache.get_table("users").is_some());
175 assert!(cache.get_table("nonexistent").is_none());
176 }
177
178 #[test]
179 fn test_cache_insert_and_get() {
180 let mut cache = TableCache::new();
181 cache.create_table(test_schema("users")).unwrap();
182
183 let row = Row::new(1, vec![Value::Int64(1), Value::String("Alice".into())]);
184 cache.get_table_mut("users").unwrap().insert(row).unwrap();
185
186 let retrieved = cache.get_row("users", 1);
187 assert!(retrieved.is_some());
188 }
189
190 #[test]
191 fn test_cache_total_row_count() {
192 let mut cache = TableCache::new();
193 cache.create_table(test_schema("users")).unwrap();
194 cache.create_table(test_schema("orders")).unwrap();
195
196 cache.get_table_mut("users").unwrap()
197 .insert(Row::new(1, vec![Value::Int64(1), Value::String("Alice".into())]))
198 .unwrap();
199 cache.get_table_mut("users").unwrap()
200 .insert(Row::new(2, vec![Value::Int64(2), Value::String("Bob".into())]))
201 .unwrap();
202 cache.get_table_mut("orders").unwrap()
203 .insert(Row::new(3, vec![Value::Int64(1), Value::String("Order1".into())]))
204 .unwrap();
205
206 assert_eq!(cache.total_row_count(), 3);
207 }
208
209 #[test]
210 fn test_cache_clear() {
211 let mut cache = TableCache::new();
212 cache.create_table(test_schema("users")).unwrap();
213 cache.get_table_mut("users").unwrap()
214 .insert(Row::new(1, vec![Value::Int64(1), Value::String("Alice".into())]))
215 .unwrap();
216
217 cache.clear();
218 assert_eq!(cache.total_row_count(), 0);
219 assert!(cache.has_table("users"));
221 }
222}