Skip to main content

solidb/storage/collection/
schema.rs

1use super::*;
2use crate::error::{DbError, DbResult};
3use crate::storage::schema::CollectionSchema;
4use seahash::SeaHasher;
5use std::hash::Hasher;
6
7impl Collection {
8    // ==================== Schema Management ====================
9
10    /// Compute hash of schema for cache invalidation
11    fn compute_schema_hash(schema: &CollectionSchema) -> u64 {
12        let serialized = serde_json::to_vec(schema).unwrap_or_default();
13        let mut hasher = SeaHasher::new();
14        hasher.write(&serialized);
15        hasher.finish()
16    }
17
18    /// Get or create cached schema validator
19    pub fn get_cached_schema_validator(&self) -> Result<Option<SchemaValidator>, DbError> {
20        if let Some(schema) = self.get_json_schema() {
21            let schema_hash = Self::compute_schema_hash(&schema);
22
23            let mut cached_hash = self.schema_hash.write().unwrap();
24            let mut cached_validator = self.schema_validator.write().unwrap();
25
26            if let Some(ref current_hash) = *cached_hash {
27                if *current_hash == schema_hash {
28                    if let Some(ref validator) = *cached_validator {
29                        return Ok(Some(validator.clone()));
30                    }
31                }
32            }
33
34            let validator = SchemaValidator::new(schema).map_err(|e| {
35                DbError::InvalidDocument(format!("Schema compilation error: {}", e))
36            })?;
37
38            *cached_hash = Some(schema_hash);
39            *cached_validator = Some(validator.clone());
40
41            Ok(Some(validator))
42        } else {
43            Ok(None)
44        }
45    }
46
47    /// Invalidate schema cache (called when schema changes)
48    fn invalidate_schema_cache(&self) {
49        let mut cached_hash = self.schema_hash.write().unwrap();
50        let mut cached_validator = self.schema_validator.write().unwrap();
51        *cached_hash = None;
52        *cached_validator = None;
53    }
54
55    /// Set JSON schema for collection validation
56    /// Set JSON schema for collection validation
57    pub fn set_json_schema(&self, schema: CollectionSchema) -> DbResult<()> {
58        self.invalidate_schema_cache();
59
60        // Validate the schema itself if enabled
61        if schema.is_enabled() {
62            jsonschema::validator_for(&schema.schema)
63                .map_err(|e| DbError::InvalidDocument(format!("Invalid JSON Schema: {}", e)))?;
64        }
65
66        let db = &self.db;
67        let cf = db
68            .cf_handle(&self.name)
69            .expect("Column family should exist");
70
71        let schema_bytes = serde_json::to_vec(&schema)?;
72        db.put_cf(cf, SCHEMA_KEY.as_bytes(), &schema_bytes)
73            .map_err(|e| DbError::InternalError(format!("Failed to set schema: {}", e)))?;
74
75        Ok(())
76    }
77
78    /// Get JSON schema
79    pub fn get_json_schema(&self) -> Option<CollectionSchema> {
80        let db = &self.db;
81        let cf = db.cf_handle(&self.name)?;
82
83        db.get_cf(cf, SCHEMA_KEY.as_bytes())
84            .ok()
85            .flatten()
86            .and_then(|bytes| serde_json::from_slice(&bytes).ok())
87    }
88
89    /// Remove JSON schema
90    pub fn remove_json_schema(&self) -> DbResult<()> {
91        self.invalidate_schema_cache();
92
93        let db = &self.db;
94        let cf = db
95            .cf_handle(&self.name)
96            .expect("Column family should exist");
97
98        db.delete_cf(cf, SCHEMA_KEY.as_bytes())
99            .map_err(|e| DbError::InternalError(format!("Failed to remove schema: {}", e)))?;
100
101        Ok(())
102    }
103}