alopex_sql/catalog/
memory.rs1use std::collections::HashMap;
7
8use super::{Catalog, IndexMetadata, TableMetadata};
9use crate::planner::PlannerError;
10
11#[derive(Debug, Default)]
42pub struct MemoryCatalog {
43 tables: HashMap<String, TableMetadata>,
45 indexes: HashMap<String, IndexMetadata>,
47 table_id_counter: u32,
49 index_id_counter: u32,
51}
52
53impl MemoryCatalog {
54 pub fn new() -> Self {
56 Self::default()
57 }
58
59 pub fn table_count(&self) -> usize {
61 self.tables.len()
62 }
63
64 pub fn index_count(&self) -> usize {
66 self.indexes.len()
67 }
68
69 pub fn table_names(&self) -> Vec<&str> {
71 self.tables.keys().map(|s| s.as_str()).collect()
72 }
73
74 pub fn index_names(&self) -> Vec<&str> {
76 self.indexes.keys().map(|s| s.as_str()).collect()
77 }
78
79 pub fn clear(&mut self) {
81 self.tables.clear();
82 self.indexes.clear();
83 }
84
85 pub(crate) fn counters(&self) -> (u32, u32) {
86 (self.table_id_counter, self.index_id_counter)
87 }
88
89 pub(crate) fn set_counters(&mut self, table_id_counter: u32, index_id_counter: u32) {
90 self.table_id_counter = table_id_counter;
91 self.index_id_counter = index_id_counter;
92 }
93
94 pub(crate) fn insert_table_unchecked(&mut self, table: TableMetadata) {
95 self.tables.insert(table.name.clone(), table);
96 }
97
98 pub(crate) fn remove_table_unchecked(&mut self, name: &str) {
99 self.tables.remove(name);
100 self.indexes.retain(|_, idx| idx.table != name);
101 }
102
103 pub(crate) fn insert_index_unchecked(&mut self, index: IndexMetadata) {
104 self.indexes.insert(index.name.clone(), index);
105 }
106
107 pub(crate) fn remove_index_unchecked(&mut self, name: &str) {
108 self.indexes.remove(name);
109 }
110}
111
112impl Catalog for MemoryCatalog {
113 fn create_table(&mut self, table: TableMetadata) -> Result<(), PlannerError> {
114 if self.tables.contains_key(&table.name) {
115 return Err(PlannerError::table_already_exists(&table.name));
116 }
117 self.tables.insert(table.name.clone(), table);
118 Ok(())
119 }
120
121 fn get_table(&self, name: &str) -> Option<&TableMetadata> {
122 self.tables.get(name)
123 }
124
125 fn drop_table(&mut self, name: &str) -> Result<(), PlannerError> {
126 if self.tables.remove(name).is_none() {
127 return Err(PlannerError::TableNotFound {
128 name: name.to_string(),
129 line: 0,
130 column: 0,
131 });
132 }
133 self.indexes.retain(|_, idx| idx.table != name);
135 Ok(())
136 }
137
138 fn create_index(&mut self, index: IndexMetadata) -> Result<(), PlannerError> {
139 if self.indexes.contains_key(&index.name) {
141 return Err(PlannerError::index_already_exists(&index.name));
142 }
143
144 let table = self
146 .tables
147 .get(&index.table)
148 .ok_or_else(|| PlannerError::TableNotFound {
149 name: index.table.clone(),
150 line: 0,
151 column: 0,
152 })?;
153
154 for column in &index.columns {
156 if table.get_column(column).is_none() {
157 return Err(PlannerError::ColumnNotFound {
158 column: column.clone(),
159 table: index.table.clone(),
160 line: 0,
161 col: 0,
162 });
163 }
164 }
165
166 self.indexes.insert(index.name.clone(), index);
167 Ok(())
168 }
169
170 fn get_index(&self, name: &str) -> Option<&IndexMetadata> {
171 self.indexes.get(name)
172 }
173
174 fn get_indexes_for_table(&self, table: &str) -> Vec<&IndexMetadata> {
175 self.indexes
176 .values()
177 .filter(|idx| idx.table == table)
178 .collect()
179 }
180
181 fn drop_index(&mut self, name: &str) -> Result<(), PlannerError> {
182 if self.indexes.remove(name).is_none() {
183 return Err(PlannerError::index_not_found(name));
184 }
185 Ok(())
186 }
187
188 fn table_exists(&self, name: &str) -> bool {
189 self.tables.contains_key(name)
190 }
191
192 fn index_exists(&self, name: &str) -> bool {
193 self.indexes.contains_key(name)
194 }
195
196 fn next_table_id(&mut self) -> u32 {
197 self.table_id_counter += 1;
198 self.table_id_counter
199 }
200
201 fn next_index_id(&mut self) -> u32 {
202 self.index_id_counter += 1;
203 self.index_id_counter
204 }
205}