velesdb_core/database/
collection_ops.rs1use crate::collection::AnyCollection;
9use crate::{CollectionType, DistanceMetric, Error, Result, StorageMode};
10
11use super::Database;
12
13impl Database {
14 pub(super) fn ensure_collection_name_available(&self, name: &str) -> Result<()> {
23 crate::validation::validate_collection_name(name)?;
24
25 if self.collection_exists_in_registry(name) {
26 return Err(Error::CollectionExists(name.to_string()));
27 }
28
29 let collection_path = self.data_dir.join(name);
30 if collection_path.exists() {
31 return Err(Error::CollectionExists(name.to_string()));
32 }
33
34 let total_collections = self.vector_colls.read().len()
43 + self.graph_colls.read().len()
44 + self.metadata_colls.read().len();
45 let cap = self.config.limits.max_collections;
46 if total_collections >= cap {
47 return Err(Error::GuardRail(format!(
48 "max_collections limit reached ({total_collections} / {cap}); \
49 raise `limits.max_collections` in VelesConfig to create more"
50 )));
51 }
52
53 Ok(())
54 }
55
56 fn collection_exists_in_registry(&self, name: &str) -> bool {
58 self.vector_colls.read().contains_key(name)
59 || self.graph_colls.read().contains_key(name)
60 || self.metadata_colls.read().contains_key(name)
61 }
62
63 pub(super) fn enforce_vector_dimension_limit(&self, dimension: usize) -> Result<()> {
77 if dimension == 0 {
78 return Ok(());
79 }
80 let cap = self.config.limits.max_dimensions;
81 if dimension > cap {
82 return Err(Error::GuardRail(format!(
83 "vector dimension {dimension} exceeds configured max_dimensions cap of {cap}; \
84 raise `limits.max_dimensions` in VelesConfig to allow larger vectors"
85 )));
86 }
87 Ok(())
88 }
89
90 pub fn create_collection(
112 &self,
113 name: &str,
114 dimension: usize,
115 metric: DistanceMetric,
116 ) -> Result<()> {
117 self.create_collection_with_options(name, dimension, metric, StorageMode::default())
118 }
119
120 pub fn create_collection_with_options(
126 &self,
127 name: &str,
128 dimension: usize,
129 metric: DistanceMetric,
130 storage_mode: StorageMode,
131 ) -> Result<()> {
132 self.create_vector_collection_with_options(name, dimension, metric, storage_mode)
133 }
134
135 #[must_use]
140 pub fn get_any_collection(&self, name: &str) -> Option<AnyCollection> {
141 if let Some(c) = self.get_vector_collection(name) {
142 return Some(AnyCollection::Vector(c));
143 }
144 if let Some(c) = self.get_graph_collection(name) {
145 return Some(AnyCollection::Graph(c));
146 }
147 if let Some(c) = self.get_metadata_collection(name) {
148 return Some(AnyCollection::Metadata(c));
149 }
150 None
151 }
152
153 #[must_use]
155 pub fn collection_write_generation(&self, name: &str) -> Option<u64> {
156 if let Some(vc) = self.vector_colls.read().get(name) {
157 return Some(vc.inner.write_generation());
158 }
159 if let Some(gc) = self.graph_colls.read().get(name) {
160 return Some(gc.inner.write_generation());
161 }
162 if let Some(mc) = self.metadata_colls.read().get(name) {
163 return Some(mc.inner.write_generation());
164 }
165 None
166 }
167
168 #[must_use]
177 pub fn indexed_fields_for(&self, name: &str) -> std::collections::HashSet<String> {
178 if let Some(vc) = self.vector_colls.read().get(name) {
179 return vc.inner.indexed_field_names();
180 }
181 if let Some(gc) = self.graph_colls.read().get(name) {
182 return gc.inner.indexed_field_names();
183 }
184 if let Some(mc) = self.metadata_colls.read().get(name) {
185 return mc.inner.indexed_field_names();
186 }
187 std::collections::HashSet::new()
188 }
189
190 #[must_use]
198 pub fn collection_analyze_generation(&self, name: &str) -> Option<u64> {
199 if let Some(vc) = self.vector_colls.read().get(name) {
200 return Some(vc.inner.analyze_generation());
201 }
202 if let Some(gc) = self.graph_colls.read().get(name) {
203 return Some(gc.inner.analyze_generation());
204 }
205 if let Some(mc) = self.metadata_colls.read().get(name) {
206 return Some(mc.inner.analyze_generation());
207 }
208 None
209 }
210
211 pub fn list_collections(&self) -> Vec<String> {
215 let vector_colls = self.vector_colls.read();
216 let graph_colls = self.graph_colls.read();
217 let metadata_colls = self.metadata_colls.read();
218
219 let mut names: std::collections::HashSet<String> = vector_colls.keys().cloned().collect();
220 for k in graph_colls.keys() {
221 names.insert(k.clone());
222 }
223 for k in metadata_colls.keys() {
224 names.insert(k.clone());
225 }
226 let mut result: Vec<String> = names.into_iter().collect();
227 result.sort();
228 result
229 }
230
231 pub fn delete_collection(&self, name: &str) -> Result<()> {
238 crate::validation::validate_collection_name(name)?;
239
240 if !self.collection_exists_in_registry(name) {
241 return Err(Error::CollectionNotFound(name.to_string()));
242 }
243
244 let collection_path = self.data_dir.join(name);
245 if collection_path.exists() {
246 std::fs::remove_dir_all(&collection_path)?;
247 }
248
249 self.remove_from_all_registries(name);
250
251 if let Some(ref obs) = self.observer {
252 obs.on_collection_deleted(name);
253 }
254
255 self.schema_version
256 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
257
258 Ok(())
259 }
260
261 fn remove_from_all_registries(&self, name: &str) {
263 self.vector_colls.write().remove(name);
264 self.graph_colls.write().remove(name);
265 self.metadata_colls.write().remove(name);
266 self.collection_stats.write().remove(name);
267 }
268
269 pub fn create_collection_typed(
275 &self,
276 name: &str,
277 collection_type: &CollectionType,
278 ) -> Result<()> {
279 match collection_type {
280 CollectionType::Vector {
281 dimension,
282 metric,
283 storage_mode,
284 } => {
285 self.create_vector_collection_with_options(name, *dimension, *metric, *storage_mode)
286 }
287 CollectionType::MetadataOnly => self.create_metadata_collection(name),
288 CollectionType::Graph {
289 dimension,
290 metric,
291 schema,
292 } => self.create_graph_collection_from_type(name, *dimension, *metric, schema),
293 }
294 }
295
296 pub(super) fn read_collection_config(
301 &self,
302 name: &str,
303 ) -> Option<crate::collection::CollectionConfig> {
304 if crate::validation::validate_collection_name(name).is_err() {
305 return None;
306 }
307 let path = self.data_dir.join(name);
308 let config_path = path.join("config.json");
309 if !config_path.exists() {
310 return None;
311 }
312 let data = std::fs::read_to_string(&config_path).ok()?;
313 serde_json::from_str(&data).ok()
314 }
315
316 pub fn update_guardrails(&self, limits: &crate::guardrails::QueryLimits) {
318 for vc in self.vector_colls.read().values() {
319 vc.guard_rails().update_limits(limits);
320 }
321 for gc in self.graph_colls.read().values() {
322 gc.inner.guard_rails().update_limits(limits);
323 }
324 for mc in self.metadata_colls.read().values() {
325 mc.inner.guard_rails().update_limits(limits);
326 }
327 }
328
329 pub fn collection_diagnostics(
335 &self,
336 name: &str,
337 ) -> Result<crate::collection::CollectionDiagnostics> {
338 if let Some(c) = self.get_vector_collection(name) {
339 return Ok(c.diagnostics());
340 }
341 if let Some(c) = self.get_graph_collection(name) {
342 return Ok(c.diagnostics());
343 }
344 if let Some(c) = self.get_metadata_collection(name) {
345 return Ok(c.diagnostics());
346 }
347 Err(Error::CollectionNotFound(name.to_string()))
348 }
349}