Frees up unused unique values.
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
55297ef097
commit
f89bd8b09f
151
src/message.rs
151
src/message.rs
@ -23,7 +23,7 @@ enum MTTError {
|
|||||||
DocumentFieldNotFound(String),
|
DocumentFieldNotFound(String),
|
||||||
DocumentFieldWrongDataType(FieldType, FieldType),
|
DocumentFieldWrongDataType(FieldType, FieldType),
|
||||||
DocumentNotFound(String),
|
DocumentNotFound(String),
|
||||||
FieldDuplicate,
|
FieldDuplicate(String, Field),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
@ -1128,6 +1128,12 @@ impl FieldSetting {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_unique_value(&mut self, field: &Field) {
|
||||||
|
if self.use_unique {
|
||||||
|
self.unique.remove(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check(&self, value: Option<Field>) -> Result<Field, MTTError> {
|
fn check(&self, value: Option<Field>) -> Result<Field, MTTError> {
|
||||||
match value {
|
match value {
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
@ -1140,7 +1146,7 @@ impl FieldSetting {
|
|||||||
}
|
}
|
||||||
if self.use_unique {
|
if self.use_unique {
|
||||||
if self.unique.get(&data).is_some() {
|
if self.unique.get(&data).is_some() {
|
||||||
return Err(MTTError::FieldDuplicate);
|
return Err(MTTError::FieldDuplicate("".to_string(), data.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(data.clone())
|
Ok(data.clone())
|
||||||
@ -1228,10 +1234,13 @@ mod fieldsettings {
|
|||||||
let field: Field = Uuid::new_v4().into();
|
let field: Field = Uuid::new_v4().into();
|
||||||
fset.set_unique();
|
fset.set_unique();
|
||||||
fset.use_unique_value(field.clone());
|
fset.use_unique_value(field.clone());
|
||||||
match fset.check(Some(field)) {
|
match fset.check(Some(field.clone())) {
|
||||||
Ok(data) => unreachable!("got {:?}: should have been error", data),
|
Ok(data) => unreachable!("got {:?}: should have been error", data),
|
||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
MTTError::FieldDuplicate => {}
|
MTTError::FieldDuplicate(key, result) => {
|
||||||
|
assert_eq!(key, "");
|
||||||
|
assert_eq!(result, field);
|
||||||
|
}
|
||||||
_ => unreachable!("got {:?}: should be a duplicate field", err),
|
_ => unreachable!("got {:?}: should be a duplicate field", err),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1338,6 +1347,14 @@ impl DocDef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check(&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)
|
||||||
|
}
|
||||||
|
|
||||||
fn set_default(&mut self, field_name: &str, value: Option<Field>) -> Result<(), MTTError> {
|
fn set_default(&mut self, field_name: &str, value: Option<Field>) -> Result<(), MTTError> {
|
||||||
let setting = match self.get_field_mut(field_name) {
|
let setting = match self.get_field_mut(field_name) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
@ -1370,6 +1387,15 @@ impl DocDef {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_unique_value(&mut self, field_name: &str, field: &Field) -> Result<(), MTTError> {
|
||||||
|
let setting = match self.get_field_mut(field_name) {
|
||||||
|
Ok(data) => data,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
|
setting.remove_unique_value(field);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn iter(&self) -> impl Iterator<Item = (&String, &FieldSetting)> {
|
fn iter(&self) -> impl Iterator<Item = (&String, &FieldSetting)> {
|
||||||
self.fields.iter()
|
self.fields.iter()
|
||||||
}
|
}
|
||||||
@ -1836,18 +1862,21 @@ impl DocumentFile {
|
|||||||
self.docs.iter()
|
self.docs.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_field_to_error(key: String, err: MTTError) -> MTTError {
|
||||||
|
match err {
|
||||||
|
MTTError::DocumentFieldMissing(_) => MTTError::DocumentFieldMissing(key),
|
||||||
|
MTTError::FieldDuplicate(_, field) => MTTError::FieldDuplicate(key, field.clone()),
|
||||||
|
_ => err.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_document(&mut self, addition: &Addition) -> MsgAction {
|
fn add_document(&mut self, addition: &Addition) -> MsgAction {
|
||||||
let mut holder = Document::new();
|
let mut holder = Document::new();
|
||||||
let doc = addition.get_document();
|
let doc = addition.get_document();
|
||||||
for (key, value) in doc.iter() {
|
for (key, value) in doc.iter() {
|
||||||
match self.docdef.get_field_mut(&key) {
|
match self.docdef.check(key, Some(value.clone())) {
|
||||||
Ok(field_info) => match field_info.check(Some(value.clone())) {
|
Ok(data) => holder.add_field(key.clone(), value.clone()),
|
||||||
Ok(data) => {
|
Err(err) => return Self::add_field_to_error(key.to_string(), err).into(),
|
||||||
holder.add_field(key.clone(), value.clone());
|
|
||||||
}
|
|
||||||
Err(err) => return err.into(),
|
|
||||||
},
|
|
||||||
Err(err) => return err.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (key, value) in self.docdef.iter() {
|
for (key, value) in self.docdef.iter() {
|
||||||
@ -1855,15 +1884,7 @@ impl DocumentFile {
|
|||||||
Some(_) => {}
|
Some(_) => {}
|
||||||
None => match value.check(None) {
|
None => match value.check(None) {
|
||||||
Ok(data) => holder.add_field(key.clone(), data.clone()),
|
Ok(data) => holder.add_field(key.clone(), data.clone()),
|
||||||
Err(err) => {
|
Err(err) => return Self::add_field_to_error(key.to_string(), err).into(),
|
||||||
let error = match err {
|
|
||||||
MTTError::DocumentFieldMissing(_) => {
|
|
||||||
MTTError::DocumentFieldMissing(key.clone())
|
|
||||||
}
|
|
||||||
_ => err.clone(),
|
|
||||||
};
|
|
||||||
return error.into();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1883,12 +1904,15 @@ impl DocumentFile {
|
|||||||
fn run_query(&self, query: &Query) -> Result<Vec<Oid>, MTTError> {
|
fn run_query(&self, query: &Query) -> Result<Vec<Oid>, MTTError> {
|
||||||
let mut reply = Reply::new();
|
let mut reply = Reply::new();
|
||||||
for specifier in query.iter() {
|
for specifier in query.iter() {
|
||||||
match self.docdef.get_field(&specifier.field_name) {
|
match self
|
||||||
Ok(spec) => match spec.check(Some(specifier.value.clone())) {
|
.docdef
|
||||||
|
.check(&specifier.field_name, Some(specifier.value.clone()))
|
||||||
|
{
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => return Err(err),
|
Err(err) => match err {
|
||||||
|
MTTError::FieldDuplicate(_, _) => {}
|
||||||
|
_ => return Err(err),
|
||||||
},
|
},
|
||||||
Err(err) => return Err(err),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
@ -1929,11 +1953,12 @@ impl DocumentFile {
|
|||||||
for oid in oids.iter() {
|
for oid in oids.iter() {
|
||||||
let doc = self.docs.get_mut(oid).unwrap();
|
let doc = self.docs.get_mut(oid).unwrap();
|
||||||
for (key, value) in update.get_values().iter() {
|
for (key, value) in update.get_values().iter() {
|
||||||
match self.docdef.get_field(key) {
|
match self.docdef.check(key, Some(value.clone())) {
|
||||||
Ok(fset) => match fset.check(Some(value.clone())) {
|
Ok(field) => {
|
||||||
Ok(field) => doc.add_field(key.clone(), field.clone()),
|
self.docdef
|
||||||
Err(err) => return err.into(),
|
.remove_unique_value(key, doc.get_field(key).unwrap());
|
||||||
},
|
doc.add_field(key.clone(), field.clone());
|
||||||
|
}
|
||||||
Err(err) => return err.into(),
|
Err(err) => return err.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2751,7 +2776,11 @@ mod document_files {
|
|||||||
let action = result.get_action();
|
let action = result.get_action();
|
||||||
match action {
|
match action {
|
||||||
MsgAction::Error(err) => match err {
|
MsgAction::Error(err) => match err {
|
||||||
MTTError::FieldDuplicate => {}
|
MTTError::FieldDuplicate(key, field) => {
|
||||||
|
let expected: Field = field0.into();
|
||||||
|
assert_eq!(key, "field0");
|
||||||
|
assert_eq!(field, &expected);
|
||||||
|
}
|
||||||
_ => unreachable!("got {:?}: should have gotten an missing field", err),
|
_ => unreachable!("got {:?}: should have gotten an missing field", err),
|
||||||
},
|
},
|
||||||
_ => unreachable!("got {:?}: should have gotten an error", action),
|
_ => unreachable!("got {:?}: should have gotten an error", action),
|
||||||
@ -2782,6 +2811,66 @@ mod document_files {
|
|||||||
_ => unreachable!("got {:?}: should have gotten a reply", action),
|
_ => unreachable!("got {:?}: should have gotten a reply", action),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn updating_unique_removes_old_entry() {
|
||||||
|
let (mut docdef, doc_name) = create_docdef([FieldType::Uuid].to_vec());
|
||||||
|
docdef.set_unique("field0");
|
||||||
|
let (queue, rx) = test_doc(doc_name.as_str(), docdef, standard_routes());
|
||||||
|
let old = Uuid::new_v4();
|
||||||
|
let mut new = Uuid::new_v4();
|
||||||
|
while old == new {
|
||||||
|
new = Uuid::new_v4();
|
||||||
|
}
|
||||||
|
let fold: Field = old.into();
|
||||||
|
let fnew: Field = new.into();
|
||||||
|
let mut addition = Addition::new();
|
||||||
|
addition.add_field("field0".to_string(), old.clone());
|
||||||
|
let msg = Message::new(doc_name.clone(), addition.clone());
|
||||||
|
queue.send(msg).unwrap();
|
||||||
|
rx.recv_timeout(TIMEOUT).unwrap();
|
||||||
|
let mut update = Update::new();
|
||||||
|
let query = update.get_query_mut();
|
||||||
|
query.add_specifier("field0".to_string(), Operand::Equal, old.clone());
|
||||||
|
let values = update.get_values_mut();
|
||||||
|
values.add_field("field0".to_string(), new.clone());
|
||||||
|
let msg = Message::new(doc_name.clone(), update);
|
||||||
|
queue.send(msg).unwrap();
|
||||||
|
let result = rx.recv_timeout(TIMEOUT).unwrap();
|
||||||
|
let action = result.get_action();
|
||||||
|
match action {
|
||||||
|
MsgAction::Reply(data) => {
|
||||||
|
assert_eq!(data.len(), 1);
|
||||||
|
for doc in data.iter() {
|
||||||
|
assert_eq!(
|
||||||
|
doc.get_field("field0").unwrap(),
|
||||||
|
&fnew,
|
||||||
|
"got {:?} as a reply",
|
||||||
|
data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!("got {:?}: should have gotten a reply", action),
|
||||||
|
}
|
||||||
|
let msg = Message::new(doc_name.clone(), addition.clone());
|
||||||
|
queue.send(msg).unwrap();
|
||||||
|
let result = rx.recv_timeout(TIMEOUT).unwrap();
|
||||||
|
let action = result.get_action();
|
||||||
|
match action {
|
||||||
|
MsgAction::Reply(data) => {
|
||||||
|
assert_eq!(data.len(), 1);
|
||||||
|
for doc in data.iter() {
|
||||||
|
assert_eq!(
|
||||||
|
doc.get_field("field0").unwrap(),
|
||||||
|
&fold,
|
||||||
|
"got {:?} as a reply",
|
||||||
|
data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!("got {:?}: should have gotten a reply", action),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user