|
|
@ -2,7 +2,7 @@ |
|
|
|
#[macro_use] extern crate log; |
|
|
|
#[macro_use] extern crate log; |
|
|
|
|
|
|
|
|
|
|
|
use std::borrow::Cow; |
|
|
|
use std::borrow::Cow; |
|
|
|
use std::collections::{HashMap, HashSet}; |
|
|
|
use std::collections::{HashMap}; |
|
|
|
|
|
|
|
|
|
|
|
use itertools::Itertools; |
|
|
|
use itertools::Itertools; |
|
|
|
use serde::{Deserialize, Serialize}; |
|
|
|
use serde::{Deserialize, Serialize}; |
|
|
@ -18,7 +18,7 @@ use crate::model::{PropertyModel, RelationModel}; |
|
|
|
|
|
|
|
|
|
|
|
pub use data::{TypedValue}; |
|
|
|
pub use data::{TypedValue}; |
|
|
|
pub use model::{DataType}; |
|
|
|
pub use model::{DataType}; |
|
|
|
use crate::data::{Object, Value}; |
|
|
|
use crate::data::{Object}; |
|
|
|
use crate::update::{UpdateObj, UpsertValue}; |
|
|
|
use crate::update::{UpdateObj, UpsertValue}; |
|
|
|
|
|
|
|
|
|
|
|
pub mod model; |
|
|
|
pub mod model; |
|
|
@ -138,7 +138,7 @@ impl Storage { |
|
|
|
// Ensure the default type is compatible
|
|
|
|
// Ensure the default type is compatible
|
|
|
|
prop.default = match prop.default.clone().cast_to(prop.data_type) { |
|
|
|
prop.default = match prop.default.clone().cast_to(prop.data_type) { |
|
|
|
Ok(v) => v, |
|
|
|
Ok(v) => v, |
|
|
|
Err(d) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) |
|
|
|
Err(_) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
debug!("Define property model \"{}\" of {}", prop.name, self.describe_model(prop.object)); |
|
|
|
debug!("Define property model \"{}\" of {}", prop.name, self.describe_model(prop.object)); |
|
|
@ -155,19 +155,24 @@ impl Storage { |
|
|
|
// Remove relation templates
|
|
|
|
// Remove relation templates
|
|
|
|
let removed_relation_ids = map_drain_filter(&mut self.rel_models, |_k, v| v.object == id || v.related == id) |
|
|
|
let removed_relation_ids = map_drain_filter(&mut self.rel_models, |_k, v| v.object == id || v.related == id) |
|
|
|
.keys(); |
|
|
|
.keys(); |
|
|
|
|
|
|
|
debug!("Undefined {} relation models", removed_relation_ids.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Remove related property templates
|
|
|
|
// Remove related property templates
|
|
|
|
let removed_prop_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id || removed_relation_ids.contains(&v.object)) |
|
|
|
let removed_prop_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id || removed_relation_ids.contains(&v.object)) |
|
|
|
.keys(); |
|
|
|
.keys(); |
|
|
|
|
|
|
|
debug!("Undefined {} property models", removed_prop_ids.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Remove objects
|
|
|
|
// Remove objects
|
|
|
|
let _ = map_drain_filter(&mut self.objects, |_k, v| v.model == id); |
|
|
|
let removed_objects = map_drain_filter(&mut self.objects, |_k, v| v.model == id); |
|
|
|
|
|
|
|
debug!("Deleted {} objects", removed_objects.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Remove property values
|
|
|
|
// Remove property values
|
|
|
|
let _ = map_drain_filter(&mut self.values, |_k, v| removed_prop_ids.contains(&v.model)); |
|
|
|
let removed_values = map_drain_filter(&mut self.values, |_k, v| removed_prop_ids.contains(&v.model)); |
|
|
|
|
|
|
|
debug!("Deleted {} object or relation values", removed_values.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Remove relations
|
|
|
|
// Remove relations
|
|
|
|
let _ = map_drain_filter(&mut self.relations, |_k, v| removed_relation_ids.contains(&v.model)); |
|
|
|
let removed_relations = map_drain_filter(&mut self.relations, |_k, v| removed_relation_ids.contains(&v.model)); |
|
|
|
|
|
|
|
debug!("Deleted {} object relations", removed_relations.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Related object remain untouched, so there can be a problem with orphans. This is up to the application to deal with.
|
|
|
|
// Related object remain untouched, so there can be a problem with orphans. This is up to the application to deal with.
|
|
|
|
|
|
|
|
|
|
|
@ -183,12 +188,15 @@ impl Storage { |
|
|
|
debug!("Undefine relation model \"{}\"", t.name); |
|
|
|
debug!("Undefine relation model \"{}\"", t.name); |
|
|
|
|
|
|
|
|
|
|
|
// Remove relations
|
|
|
|
// Remove relations
|
|
|
|
let _ = map_drain_filter(&mut self.relations, |_k, v| v.model == id).keys(); |
|
|
|
let removed = map_drain_filter(&mut self.relations, |_k, v| v.model == id); |
|
|
|
|
|
|
|
debug!("Deleted {} object relations", removed.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Remove related property templates
|
|
|
|
// Remove related property templates
|
|
|
|
let removed_prop_tpl_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id).keys(); |
|
|
|
let removed_prop_tpl_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id).keys(); |
|
|
|
|
|
|
|
debug!("Undefined {} relation property models", removed_prop_tpl_ids.len()); |
|
|
|
|
|
|
|
|
|
|
|
let _ = map_drain_filter(&mut self.values, |_k, v| removed_prop_tpl_ids.contains(&v.model)); |
|
|
|
let removed_values = map_drain_filter(&mut self.values, |_k, v| removed_prop_tpl_ids.contains(&v.model)); |
|
|
|
|
|
|
|
debug!("Deleted {} relation values", removed_values.len()); |
|
|
|
|
|
|
|
|
|
|
|
// Related object remain untouched, so there can be a problem with orphans. This is up to the application to deal with.
|
|
|
|
// Related object remain untouched, so there can be a problem with orphans. This is up to the application to deal with.
|
|
|
|
|
|
|
|
|
|
|
@ -203,8 +211,9 @@ impl Storage { |
|
|
|
return if let Some(t) = self.prop_models.remove(&id) { |
|
|
|
return if let Some(t) = self.prop_models.remove(&id) { |
|
|
|
debug!("Undefine property model \"{}\"", t.name); |
|
|
|
debug!("Undefine property model \"{}\"", t.name); |
|
|
|
|
|
|
|
|
|
|
|
// Remove relations
|
|
|
|
// Remove values
|
|
|
|
let _ = map_drain_filter(&mut self.values, |_k, v| v.model == id); |
|
|
|
let removed_values = map_drain_filter(&mut self.values, |_k, v| v.model == id); |
|
|
|
|
|
|
|
debug!("Deleted {} values", removed_values.len()); |
|
|
|
Ok(t) |
|
|
|
Ok(t) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
Err(StorageError::NotExist(format!("property model {}", id).into())) |
|
|
|
Err(StorageError::NotExist(format!("property model {}", id).into())) |
|
|
@ -337,10 +346,12 @@ impl Storage { |
|
|
|
|
|
|
|
|
|
|
|
self.objects.insert(object_id, object); |
|
|
|
self.objects.insert(object_id, object); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Add {} new object relations", relations_to_insert.len()); |
|
|
|
for rel in relations_to_insert { |
|
|
|
for rel in relations_to_insert { |
|
|
|
self.relations.insert(rel.id, rel); |
|
|
|
self.relations.insert(rel.id, rel); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Add {} new values", values_to_insert.len()); |
|
|
|
for value in values_to_insert { |
|
|
|
for value in values_to_insert { |
|
|
|
self.values.insert(value.id, value); |
|
|
|
self.values.insert(value.id, value); |
|
|
|
} |
|
|
|
} |
|
|
@ -561,18 +572,22 @@ impl Storage { |
|
|
|
let obj_mut = self.objects.get_mut(&updated_object_id).unwrap(); |
|
|
|
let obj_mut = self.objects.get_mut(&updated_object_id).unwrap(); |
|
|
|
obj_mut.name = updobj.name; |
|
|
|
obj_mut.name = updobj.name; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Add {} new object relations", relations_to_insert.len()); |
|
|
|
for rel in relations_to_insert { |
|
|
|
for rel in relations_to_insert { |
|
|
|
self.relations.insert(rel.id, rel); |
|
|
|
self.relations.insert(rel.id, rel); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Add {} new values", values_to_insert.len()); |
|
|
|
for value in values_to_insert { |
|
|
|
for value in values_to_insert { |
|
|
|
self.values.insert(value.id, value); |
|
|
|
self.values.insert(value.id, value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Deleted {} values", value_ids_to_delete.len()); |
|
|
|
for id in value_ids_to_delete { |
|
|
|
for id in value_ids_to_delete { |
|
|
|
self.values.remove(&id); |
|
|
|
self.values.remove(&id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Deleted {} object relations", relations_to_delete.len()); |
|
|
|
for id in relations_to_delete { |
|
|
|
for id in relations_to_delete { |
|
|
|
self.relations.remove(&id); |
|
|
|
self.relations.remove(&id); |
|
|
|
} |
|
|
|
} |
|
|
@ -650,10 +665,29 @@ impl Storage { |
|
|
|
// Ensure the default type is compatible
|
|
|
|
// Ensure the default type is compatible
|
|
|
|
prop.default = match prop.default.clone().cast_to(prop.data_type) { |
|
|
|
prop.default = match prop.default.clone().cast_to(prop.data_type) { |
|
|
|
Ok(v) => v, |
|
|
|
Ok(v) => v, |
|
|
|
Err(d) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) |
|
|
|
Err(_) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
self.prop_models.insert(prop.id, prop); |
|
|
|
self.prop_models.insert(prop.id, prop); |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Delete an object and associated data
|
|
|
|
|
|
|
|
pub fn delete_object(&mut self, id: ID) -> Result<data::Object, StorageError> { |
|
|
|
|
|
|
|
return if let Some(t) = self.objects.remove(&id) { |
|
|
|
|
|
|
|
debug!("Delete object \"{}\"", t.name); |
|
|
|
|
|
|
|
// Remove relation templates
|
|
|
|
|
|
|
|
let removed_relation_ids = map_drain_filter(&mut self.relations, |_k, v| v.object == id || v.related == id) |
|
|
|
|
|
|
|
.keys(); |
|
|
|
|
|
|
|
debug!("Deleted {} object relations", removed_relation_ids.len()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove values
|
|
|
|
|
|
|
|
let removed_values = map_drain_filter(&mut self.values, |_k, v| removed_relation_ids.contains(&v.object) || v.object == id); |
|
|
|
|
|
|
|
debug!("Deleted {} object values", removed_values.len()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(t) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
Err(StorageError::NotExist(format!("object {}", id).into())) |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|