Got unique index working, and connected to DocDef.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
This commit is contained in:
parent
7f1ce3d871
commit
32d3fbadea
173
src/message.rs
173
src/message.rs
@ -1105,7 +1105,7 @@ impl FieldSetting {
|
||||
fn set_default(&mut self, value: Option<Field>) -> Result<(), MTTError> {
|
||||
match value {
|
||||
Some(data) => {
|
||||
match self.check(Some(data.clone())) {
|
||||
match self.validate(Some(data.clone())) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
@ -1134,7 +1134,7 @@ impl FieldSetting {
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self, value: Option<Field>) -> Result<Field, MTTError> {
|
||||
fn validate(&self, value: Option<Field>) -> Result<Field, MTTError> {
|
||||
match value {
|
||||
Some(data) => {
|
||||
let vft: FieldType = (&data).into();
|
||||
@ -1170,20 +1170,20 @@ mod fieldsettings {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn checks_field_type() {
|
||||
fn validates_field_type() {
|
||||
let fset = FieldSetting::new(FieldType::Uuid);
|
||||
let value: Field = Uuid::new_v4().into();
|
||||
match fset.check(Some(value.clone())) {
|
||||
match fset.validate(Some(value.clone())) {
|
||||
Ok(data) => assert_eq!(data, value),
|
||||
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checks_for_bad_field_type() {
|
||||
fn validates_for_bad_field_type() {
|
||||
let fset = FieldSetting::new(FieldType::Uuid);
|
||||
let value: Field = "text".into();
|
||||
match fset.check(Some(value)) {
|
||||
match fset.validate(Some(value)) {
|
||||
Ok(data) => unreachable!("got {:?}: should have gotten an error", data),
|
||||
Err(err) => match err {
|
||||
MTTError::DocumentFieldWrongDataType(expected, got) => {
|
||||
@ -1198,7 +1198,7 @@ mod fieldsettings {
|
||||
#[test]
|
||||
fn no_default_returns_error() {
|
||||
let fset = FieldSetting::new(FieldType::Uuid);
|
||||
match fset.check(None) {
|
||||
match fset.validate(None) {
|
||||
Ok(data) => unreachable!("got {:?}: should have gotten an error", data),
|
||||
Err(err) => match err {
|
||||
MTTError::DocumentFieldMissing(data) => assert_eq!(data, ""),
|
||||
@ -1211,7 +1211,7 @@ mod fieldsettings {
|
||||
fn returns_value_if_default_is_set() {
|
||||
let mut fset = FieldSetting::new(FieldType::StaticString);
|
||||
fset.set_default(None);
|
||||
match fset.check(None) {
|
||||
match fset.validate(None) {
|
||||
Ok(data) => assert_eq!(data, "".into()),
|
||||
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
|
||||
}
|
||||
@ -1222,19 +1222,19 @@ mod fieldsettings {
|
||||
let mut fset = FieldSetting::new(FieldType::StaticString);
|
||||
let input = "fred";
|
||||
fset.set_default(Some(input.into()));
|
||||
match fset.check(None) {
|
||||
match fset.validate(None) {
|
||||
Ok(data) => assert_eq!(data, input.into()),
|
||||
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checks_for_unique_value() {
|
||||
fn validates_for_unique_value() {
|
||||
let mut fset = FieldSetting::new(FieldType::Uuid);
|
||||
let field: Field = Uuid::new_v4().into();
|
||||
fset.set_unique();
|
||||
fset.use_unique_value(field.clone());
|
||||
match fset.check(Some(field.clone())) {
|
||||
match fset.validate(Some(field.clone())) {
|
||||
Ok(data) => unreachable!("got {:?}: should have been error", data),
|
||||
Err(err) => match err {
|
||||
MTTError::FieldDuplicate(key, result) => {
|
||||
@ -1317,15 +1317,32 @@ mod additions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum IndexType {
|
||||
Index,
|
||||
Unique,
|
||||
}
|
||||
|
||||
impl IndexType {
|
||||
fn create_index(&self) -> Index {
|
||||
match self {
|
||||
Self::Index => Index::new(),
|
||||
Self::Unique => Index::new_unique(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct DocDef {
|
||||
fields: HashMap<String, FieldSetting>,
|
||||
indexes: HashMap<String, IndexType>,
|
||||
}
|
||||
|
||||
impl DocDef {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
fields: HashMap::new(),
|
||||
indexes: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1347,12 +1364,12 @@ impl DocDef {
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self, field_name: &str, value: Option<Field>) -> Result<Field, MTTError> {
|
||||
fn validate(&self, field_name: &str, value: Option<Field>) -> Result<Field, MTTError> {
|
||||
let setting = match self.get_field(field_name) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
setting.check(value)
|
||||
setting.validate(value)
|
||||
}
|
||||
|
||||
fn set_default(&mut self, field_name: &str, value: Option<Field>) -> Result<(), MTTError> {
|
||||
@ -1366,6 +1383,23 @@ impl DocDef {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_index(&mut self, field_name: String, index_type: IndexType) -> Result<(), MTTError> {
|
||||
let setting = match self.get_field(&field_name) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
self.indexes.insert(field_name, index_type);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_indexes(&self) -> HashMap<String, Index> {
|
||||
let mut output = HashMap::new();
|
||||
for (key, value) in self.indexes.iter() {
|
||||
output.insert(key.clone(), value.create_index());
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn set_unique(&mut self, field_name: &str) -> Result<(), MTTError> {
|
||||
let setting = match self.get_field_mut(field_name) {
|
||||
Ok(data) => data,
|
||||
@ -1380,7 +1414,7 @@ impl DocDef {
|
||||
Ok(data) => data,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
match setting.check(Some(field.clone())) {
|
||||
match setting.validate(Some(field.clone())) {
|
||||
Ok(data) => setting.use_unique_value(field),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
@ -1412,7 +1446,7 @@ mod docdefs {
|
||||
let field_type = FieldType::Uuid;
|
||||
docdef.add_field(name.clone(), field_type.clone());
|
||||
let result = docdef.get_field(name.as_str()).unwrap();
|
||||
match result.check(Some(Uuid::new_v4().into())) {
|
||||
match result.validate(Some(Uuid::new_v4().into())) {
|
||||
Ok(_) => {}
|
||||
Err(err) => unreachable!("got {:?}: should have been a value", err),
|
||||
}
|
||||
@ -1441,7 +1475,7 @@ mod docdefs {
|
||||
}
|
||||
for name in names.iter() {
|
||||
let result = docdef.get_field(name).unwrap();
|
||||
match result.check(Some("".into())) {
|
||||
match result.validate(Some("".into())) {
|
||||
Ok(_) => {}
|
||||
Err(err) => unreachable!("got {:?}: should have been a value", err),
|
||||
}
|
||||
@ -1454,7 +1488,7 @@ mod docdefs {
|
||||
let name = "defaultfunction";
|
||||
docdef.add_field(name.to_string(), FieldType::StaticString);
|
||||
docdef.set_default(name, None);
|
||||
match docdef.get_field(name).unwrap().check(None) {
|
||||
match docdef.get_field(name).unwrap().validate(None) {
|
||||
Ok(data) => match data {
|
||||
Field::StaticString(result) => assert_eq!(result, ""),
|
||||
_ => unreachable!("got {:?}: should return a static string", data),
|
||||
@ -1557,7 +1591,7 @@ enum Operand {
|
||||
}
|
||||
|
||||
impl Operand {
|
||||
fn check(&self, x: &Field, y: &Field) -> bool {
|
||||
fn validate(&self, x: &Field, y: &Field) -> bool {
|
||||
match self {
|
||||
Self::Equal => x == y,
|
||||
}
|
||||
@ -1571,7 +1605,7 @@ mod operands {
|
||||
#[test]
|
||||
fn equals_true() {
|
||||
let data: Field = Uuid::new_v4().into();
|
||||
assert!(Operand::Equal.check(&data, &data));
|
||||
assert!(Operand::Equal.validate(&data, &data));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1581,7 +1615,7 @@ mod operands {
|
||||
while x == y {
|
||||
y = Uuid::new_v4().into();
|
||||
}
|
||||
assert!(!Operand::Equal.check(&x, &y));
|
||||
assert!(!Operand::Equal.validate(&x, &y));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1608,8 +1642,8 @@ impl Specifier {
|
||||
self.field_name.clone()
|
||||
}
|
||||
|
||||
fn check(&self, field: &Field) -> bool {
|
||||
self.operation.check(field, &self.value)
|
||||
fn validate(&self, field: &Field) -> bool {
|
||||
self.operation.validate(field, &self.value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1813,31 +1847,44 @@ impl Oid {
|
||||
|
||||
struct Index {
|
||||
data: HashMap<Field, HashSet<Oid>>,
|
||||
unique: bool,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
unique: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, field: Field, oid: Oid) {
|
||||
fn new_unique() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
unique: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, field: Field, oid: Oid) -> Result<(), MTTError> {
|
||||
let oids = match self.data.get_mut(&field) {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
let mut data = HashSet::new();
|
||||
self.data.insert(field.clone(), data);
|
||||
self.data.insert(field.clone(), HashSet::new());
|
||||
self.data.get_mut(&field).unwrap()
|
||||
}
|
||||
};
|
||||
oids.insert(oid);
|
||||
if self.unique && oids.len() > 0 {
|
||||
return Err(MTTError::FieldDuplicate("".to_string(), field));
|
||||
} else {
|
||||
oids.insert(oid);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get(&self, spec: &Specifier) -> Vec<Oid> {
|
||||
let mut output = Vec::new();
|
||||
for (field, oids) in self.data.iter() {
|
||||
if spec.check(field) {
|
||||
if spec.validate(field) {
|
||||
for oid in oids.iter() {
|
||||
output.push(oid.clone());
|
||||
}
|
||||
@ -1857,6 +1904,16 @@ impl Index {
|
||||
None => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn validate(&self, field: &Field) -> Result<(), MTTError> {
|
||||
if self.unique {
|
||||
match self.data.get(field) {
|
||||
Some(_) => return Err(MTTError::FieldDuplicate("".to_string(), field.clone())),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1944,11 +2001,60 @@ mod indexes {
|
||||
index.remove(&field, &oid);
|
||||
assert_eq!(index.data.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn do_unique_indexes_error_on_duplicates() {
|
||||
let mut index = Index::new_unique();
|
||||
let field: Field = "fred".into();
|
||||
let oids = get_oids(2);
|
||||
index.add(field.clone(), oids[0].clone()).unwrap();
|
||||
match index.add(field.clone(), oids[0].clone()) {
|
||||
Ok(_) => unreachable!("should have been an error"),
|
||||
Err(err) => match err {
|
||||
MTTError::FieldDuplicate(field_name, value) => {
|
||||
assert_eq!(field_name, "");
|
||||
assert_eq!(value, field);
|
||||
}
|
||||
_ => unreachable!("got {:?}: should have been duplicate field", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn index_returns_validate() {
|
||||
let mut index = Index::new();
|
||||
let field: Field = "stuff".into();
|
||||
let oid = Oid::new();
|
||||
index.add(field.clone(), oid).unwrap();
|
||||
match index.validate(&field) {
|
||||
Ok(_) => {}
|
||||
Err(err) => unreachable!("got {:?}: should have returned without issue", err),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unique_return_duplicate_error() {
|
||||
let mut index = Index::new_unique();
|
||||
let field: Field = "fred".into();
|
||||
let oid = Oid::new();
|
||||
index.add(field.clone(), oid).unwrap();
|
||||
match index.validate(&field) {
|
||||
Ok(_) => unreachable!("should have gotten a duplication error"),
|
||||
Err(err) => match err {
|
||||
MTTError::FieldDuplicate(field_name, value) => {
|
||||
assert_eq!(field_name, "");
|
||||
assert_eq!(value, field);
|
||||
}
|
||||
_ => unreachable!("got {:?}: should have been duplicate field", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DocumentFile {
|
||||
docdef: DocDef,
|
||||
docs: HashMap<Oid, Document>,
|
||||
indexes: HashMap<String, Index>,
|
||||
queue: Queue,
|
||||
rx: Receiver<Message>,
|
||||
}
|
||||
@ -1956,8 +2062,9 @@ struct DocumentFile {
|
||||
impl DocumentFile {
|
||||
fn new(queue: Queue, rx: Receiver<Message>, docdef: DocDef) -> Self {
|
||||
Self {
|
||||
docdef: docdef,
|
||||
docdef: docdef.clone(),
|
||||
docs: HashMap::new(),
|
||||
indexes: docdef.create_indexes(),
|
||||
queue: queue,
|
||||
rx: rx,
|
||||
}
|
||||
@ -2046,7 +2153,7 @@ impl DocumentFile {
|
||||
let mut holder = Document::new();
|
||||
let doc = addition.get_document();
|
||||
for (key, value) in doc.iter() {
|
||||
match self.docdef.check(key, Some(value.clone())) {
|
||||
match self.docdef.validate(key, Some(value.clone())) {
|
||||
Ok(data) => holder.add_field(key.clone(), value.clone()),
|
||||
Err(err) => return Self::add_field_to_error(key.to_string(), err).into(),
|
||||
}
|
||||
@ -2054,7 +2161,7 @@ impl DocumentFile {
|
||||
for (key, value) in self.docdef.iter() {
|
||||
match holder.get_field(key) {
|
||||
Some(_) => {}
|
||||
None => match value.check(None) {
|
||||
None => match value.validate(None) {
|
||||
Ok(data) => holder.add_field(key.clone(), data.clone()),
|
||||
Err(err) => return Self::add_field_to_error(key.to_string(), err).into(),
|
||||
},
|
||||
@ -2078,7 +2185,7 @@ impl DocumentFile {
|
||||
for specifier in query.iter() {
|
||||
match self
|
||||
.docdef
|
||||
.check(&specifier.field_name, Some(specifier.value.clone()))
|
||||
.validate(&specifier.field_name, Some(specifier.value.clone()))
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(err) => match err {
|
||||
@ -2125,7 +2232,7 @@ impl DocumentFile {
|
||||
for oid in oids.iter() {
|
||||
let doc = self.docs.get_mut(oid).unwrap();
|
||||
for (key, value) in update.get_values().iter() {
|
||||
match self.docdef.check(key, Some(value.clone())) {
|
||||
match self.docdef.validate(key, Some(value.clone())) {
|
||||
Ok(field) => {
|
||||
self.docdef
|
||||
.remove_unique_value(key, doc.get_field(key).unwrap());
|
||||
@ -3044,7 +3151,7 @@ mod document_files {
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
//#[test]
|
||||
fn unique_available_after_bad_change() {
|
||||
let mut ids: Vec<Uuid> = Vec::new();
|
||||
while ids.len() < 3 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user