From 922d88b177b37738c3fa0d599c2efcc22ea02ae3 Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Thu, 16 Oct 2025 12:02:29 -0400 Subject: [PATCH] Readded specific query. --- src/message.rs | 147 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 101 insertions(+), 46 deletions(-) diff --git a/src/message.rs b/src/message.rs index 2673365..335fd5a 100644 --- a/src/message.rs +++ b/src/message.rs @@ -3386,17 +3386,53 @@ mod replies { } } +#[derive(Clone, Debug)] +struct InternalRecord { + data: HashMap, +} + +impl InternalRecord { + fn new() -> Self { + Self { + data: HashMap::new(), + } + } + + fn insert(&mut self, id: Uuid, data: F) -> Option where F: Into { + self.data.insert(id, data.into()) + } + + fn get(&self, id: &Uuid) -> Option<&Field> { + self.data.get(id) + } + + fn keys(&self) -> impl Iterator { + self.data.keys() + } + + fn is_empty(&self) -> bool { + self.data.is_empty() + } +} + #[derive(Clone, Debug)] struct Record { names: Names, - data: HashMap, + data: InternalRecord, } impl Record { fn new(names: Names) -> Self { Self { names: names, - data: HashMap::new(), + data: InternalRecord::new(), + } + } + + fn with_data(names: Names, rec: InternalRecord) -> Self { + Self { + names: names, + data: rec, } } @@ -3431,7 +3467,7 @@ impl Record { #[derive(Clone, Debug)] struct RecordIter { names: Names, - records: VecDeque>, + records: VecDeque, } impl RecordIter { @@ -3442,6 +3478,13 @@ impl RecordIter { } } + fn with_names(names: Names) -> Self { + Self { + names: names, + records: VecDeque::new(), + } + } + fn push(&mut self, rec: Record) -> Result<(), MTTError> { if self.names.is_empty() { self.names = rec.names; @@ -3460,6 +3503,11 @@ impl RecordIter { } Ok(()) } + + fn insert(&mut self, rec: InternalRecord) -> Result<(), MTTError> { + self.records.push_back(rec.clone()); + Ok(()) + } } impl Iterator for RecordIter { @@ -4072,7 +4120,7 @@ mod indexes { struct DocumentFile { docdef: DocDef, - docs: HashMap>, + docs: HashMap, indexes: Indexes, queue: Queue, rx: Receiver, @@ -4211,7 +4259,7 @@ impl DocumentFile { } fn add_document(&mut self, addition: &Addition) -> MsgAction { - let mut holder: HashMap = HashMap::new(); + let mut holder = InternalRecord::new(); let doc = addition.get_document(); for (field, value) in doc.iter() { match self.validate(field, Some(value)) { @@ -4231,18 +4279,14 @@ impl DocumentFile { Err(err) => return MsgAction::Error(err), } } - let mut records = RecordIter::new(); + let mut records = RecordIter::with_names(self.docdef.get_field_names().clone()); if !holder.is_empty() { let mut oid = Oid::new(); while self.docs.contains_key(&oid) { oid = Oid::new(); } self.docs.insert(oid, holder.clone()); - let mut rec = Record::new(self.docdef.get_field_names().clone()); - for (name_id, field) in holder.iter() { - rec.insert(name_id, field.clone()); - } - records.push(rec); + records.insert(holder); } records.into() } @@ -4358,27 +4402,40 @@ impl DocumentFile { } fn query(&self, query: &Query) -> MsgAction { - let mut records = RecordIter::new(); - for rec in self.docs.values() { - let mut record = Record::new(self.docdef.get_field_names().clone()); - for (key, value) in rec.iter() { - record.insert(key, value.clone()); + let mut records = RecordIter::with_names(self.docdef.get_field_names().clone()); + let indexed_ids = self.indexes.index_ids(); + let mut indexed: HashMap = HashMap::new(); + let mut unindexed: HashMap = HashMap::new(); + for (field, data) in query.iter() { + let id = match self.docdef.get_field_id(field) { + Ok(fid) => fid, + Err(err) => return err.into(), + }; + if indexed_ids.contains(&id) { + indexed.insert(id, data.clone()); + } else { + unindexed.insert(id, data.clone()); } - records.push(record); + } + let mut oids: HashSet = self.docs.keys().cloned().collect(); + for (field_id, calculation) in indexed.iter() { + let holder = self.indexes.pull(field_id, calculation); + oids = oids.intersection(&holder).cloned().collect(); + } + for (field_id, calculation) in unindexed.iter() { + for oid in oids.clone().iter() { + let doc = self.docs.get(oid).unwrap(); + let mut calc = calculation.clone(); + calc.add_value(doc.get(field_id).unwrap().clone()); + if calc.calculate() == false.into() { + oids.remove(oid); + } + } + } + for oid in oids.iter() { + records.insert(self.docs.get(oid).unwrap().clone()); } records.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 { @@ -4771,29 +4828,26 @@ mod document_files { } } - /* #[test] fn does_query_return_related_entries() { - let mut doc = TestDocument::new([FieldType::Uuid].to_vec()); - doc.start(); - let count = 3; - let mut values: HashSet = HashSet::new(); - while values.len() < count { - values.insert(Uuid::new_v4().into()); + let mut test_doc = TestDocument::new([FieldType::Integer].to_vec()); + test_doc.start(); + let queue = test_doc.get_queue(); + let count = 5; + let expected = 3; + for i in 0..count { + test_doc.populate([i.into()].to_vec()); } - for value in values.iter() { - doc.populate([value.clone()].to_vec()); - } - let expected = values.iter().last().unwrap().clone(); + let mut query = Query::new(); let mut calc = Calculation::new(Operand::Equal); calc.add_value(expected.clone()); let mut query = Query::new(); - query.add("field0".to_string(), calc); - doc.send(query).unwrap(); - let result = doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); + query.add(Name::english("field0".to_string()), calc); + queue.send(Message::new(test_doc.get_docdef().get_document_name(), query)); + let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap(); let action = result.get_action(); match action { - MsgAction::Reply(data) => { + MsgAction::Records(data) => { assert_eq!( data.len(), 1, @@ -4801,14 +4855,15 @@ mod document_files { expected, action ); - for doc in data.iter() { - assert_eq!(doc.get_field("field0").unwrap(), expected); + for doc in data.clone() { + assert_eq!(doc.get(&Name::english("field0".to_string())).unwrap(), expected.into()); } } _ => unreachable!("got {:?}: should have been a reply", action), } } + /* #[test] fn gets_all_documents_in_query() { let mut doc = TestDocument::new([FieldType::Integer].to_vec());