diff --git a/src/message.rs b/src/message.rs index e21efa3..9ff1425 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1417,37 +1417,8 @@ impl Query { self.specifiers.push(spec); } - fn run(&self, docs: &DocumentFile) -> Result { - let mut reply = Reply::new(); - let docdef = docs.get_docdef(); - for specifier in self.specifiers.iter() { - match docdef.get_field(&specifier.field_name) { - Ok(spec) => { - let value_type: FieldType = (&specifier.value).into(); - let wanted_type = spec.get_type(); - if &value_type != wanted_type { - return Err(MTTError::DocumentFieldWrongDataType( - wanted_type.clone(), - value_type.clone(), - )); - } - } - Err(err) => return Err(err), - } - } - for doc in docs.get_documents() { - let mut output = true; - for specifier in self.specifiers.iter() { - let value = doc.get_field(&specifier.field_name).unwrap(); - if value != &specifier.value { - output = false; - } - } - if output { - reply.add(doc.clone()); - } - } - Ok(reply) + fn iter(&self) -> impl Iterator { + self.specifiers.iter() } } @@ -1594,18 +1565,39 @@ impl Update { } } + fn get_query(&self) -> &Query { + &self.query + } + fn get_query_mut(&mut self) -> &mut Query { &mut self.query } + fn get_values(&self) -> &Document { + &self.values + } + fn get_values_mut(&mut self) -> &mut Document { &mut self.values } } +#[derive(Clone, Eq, Hash, PartialEq)] +struct Oid { + oid: Uuid, +} + +impl Oid { + fn new() -> Self { + Self { + oid: Uuid::new_v4(), + } + } +} + struct DocumentFile { docdef: DocDef, - docs: Vec, + docs: HashMap, queue: Queue, rx: Receiver, } @@ -1614,7 +1606,7 @@ impl DocumentFile { fn new(queue: Queue, rx: Receiver, docdef: DocDef) -> Self { Self { docdef: docdef, - docs: Vec::new(), + docs: HashMap::new(), queue: queue, rx: rx, } @@ -1676,6 +1668,7 @@ impl DocumentFile { let result = match msg.get_action() { MsgAction::Addition(data) => self.add_document(data), MsgAction::Query(query) => self.query(query), + MsgAction::Update(update) => self.update(update), _ => Reply::new().into(), }; self.queue.send(msg.response(result)).unwrap(); @@ -1686,7 +1679,7 @@ impl DocumentFile { &self.docdef } - fn get_documents<'a>(&self) -> impl Iterator { + fn get_documents<'a>(&self) -> impl Iterator { self.docs.iter() } @@ -1723,18 +1716,77 @@ impl DocumentFile { }, } } - self.docs.push(holder.clone()); + let mut oid = Oid::new(); + while self.docs.contains_key(&oid) { + oid = Oid::new(); + } + self.docs.insert(oid, holder.clone()); let mut reply = Reply::new(); reply.add(holder); reply.into() } + fn run_query(&self, query: &Query) -> Result, MTTError> { + let mut reply = Reply::new(); + for specifier in query.iter() { + match self.docdef.get_field(&specifier.field_name) { + Ok(spec) => { + let value_type: FieldType = (&specifier.value).into(); + let wanted_type = spec.get_type(); + if &value_type != wanted_type { + return Err(MTTError::DocumentFieldWrongDataType( + wanted_type.clone(), + value_type.clone(), + )); + } + } + Err(err) => return Err(err), + } + } + let mut result = Vec::new(); + for (oid, doc) in self.get_documents() { + let mut output = true; + for specifier in query.iter() { + let value = doc.get_field(&specifier.field_name).unwrap(); + if value != &specifier.value { + output = false; + } + } + if output { + result.push(oid.clone()); + } + } + Ok(result) + } + fn query(&self, query: &Query) -> MsgAction { - match query.run(self) { - Ok(reply) => reply.into(), + match self.run_query(query) { + Ok(result) => { + let mut reply = Reply::new(); + for oid in result.iter() { + reply.add(self.docs.get(oid).unwrap().clone()); + } + reply.into() + } Err(err) => err.into(), } } + + fn update(&mut self, update: &Update) -> MsgAction { + let oids = match self.run_query(update.get_query()) { + Ok(result) => result, + Err(err) => return err.into(), + }; + let mut reply = Reply::new(); + for oid in oids.iter() { + let doc = self.docs.get_mut(oid).unwrap(); + for (key, value) in update.get_values().iter() { + doc.add_field(key.clone(), value.clone()); + } + reply.add(doc.clone()); + } + reply.into() + } } #[cfg(test)] @@ -2303,6 +2355,61 @@ mod document_files { }, } } + + #[test] + fn changes_information_requested() { + let (mut docdef, doc_name) = + create_docdef([FieldType::Uuid, FieldType::StaticString].to_vec()); + let (mut queue, rx) = test_doc(doc_name.as_str(), docdef, standard_routes()); + let id = Uuid::new_v4(); + let old = "old"; + let new = "new"; + let mut addition = Addition::new(); + addition.add_field("field0".to_string(), id.clone()); + addition.add_field("field1".to_string(), old); + let msg = Message::new(doc_name.clone(), addition); + queue.send(msg).unwrap(); + rx.recv_timeout(TIMEOUT).unwrap(); + let mut update = Update::new(); + update + .get_query_mut() + .add_specifier("field0".to_string(), Operand::Equal, id.clone()); + update.get_values_mut().add_field("field1".to_string(), new); + 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(docs) => { + assert_eq!(docs.len(), 1); + let expected_id: Field = id.into(); + let output: Field = new.into(); + for doc in docs.iter() { + assert_eq!(doc.get_field("field0").unwrap(), &expected_id); + assert_eq!(doc.get_field("field1").unwrap(), &output); + } + } + _ => unreachable!("got {:?}: should have gotten a reply", action), + } + let mut query = Query::new(); + query.add_specifier("field0".to_string(), Operand::Equal, id.clone()); + let msg = Message::new(doc_name, query); + queue.send(msg).unwrap(); + let result = rx.recv_timeout(TIMEOUT).unwrap(); + let action = result.get_action(); + match action { + MsgAction::Reply(docs) => { + assert_eq!(docs.len(), 1); + let expected_id: Field = id.into(); + let output: Field = new.into(); + for doc in docs.iter() { + assert_eq!(doc.get_field("field0").unwrap(), &expected_id); + assert_eq!(doc.get_field("field1").unwrap(), &output); + } + } + _ => unreachable!("got {:?}: should have gotten a reply", action), + } + } } #[cfg(test)]