Made query selective.

This commit is contained in:
Jeff Baskin 2025-08-11 12:17:37 -04:00
parent 50481c18ad
commit 73b4b866d4

View File

@ -959,7 +959,16 @@ enum FieldType {
Uuid,
}
#[derive(Clone, Debug)]
impl From<&Field> for FieldType {
fn from(value: &Field) -> Self {
match value {
Field::StaticString(_) => Self::StaticString,
Field::Uuid(_) => Self::Uuid,
}
}
}
#[derive(Clone, Debug, PartialEq)]
enum Field {
StaticString(String),
Uuid(Uuid),
@ -967,10 +976,7 @@ enum Field {
impl Field {
fn get_type(&self) -> FieldType {
match self {
Self::StaticString(_) => FieldType::StaticString,
Self::Uuid(_) => FieldType::Uuid,
}
self.into()
}
}
@ -1209,11 +1215,65 @@ mod docdefs {
}
#[derive(Clone, Debug)]
struct Query;
enum Operand {
Equal,
}
#[derive(Clone, Debug)]
struct Specifier {
field_name: String,
operation: Operand,
value: Field,
}
impl Specifier {
fn new<F>(name: String, op: Operand, value: F) -> Self
where
F: Into<Field>,
{
Self {
field_name: name,
operation: op,
value: value.into(),
}
}
}
#[derive(Clone, Debug)]
struct Query {
specifiers: Vec<Specifier>,
}
impl Query {
fn new() -> Self {
Self {}
Self {
specifiers: Vec::new(),
}
}
fn add_specifier<F>(&mut self, name: String, op: Operand, value: F)
where
F: Into<Field>,
{
let spec = Specifier::new(name, op, value);
self.specifiers.push(spec);
}
fn run(&self, docs: &DocumentFile) -> Reply {
let mut reply = Reply::new();
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());
}
}
reply
}
}
@ -1234,14 +1294,9 @@ impl Reply {
fn len(&self) -> usize {
self.data.len()
}
}
impl IntoIterator for Reply {
type Item = Document;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
fn iter(&self) -> impl Iterator<Item = &Document> {
self.data.iter()
}
}
@ -1275,7 +1330,7 @@ mod replies {
let mut reply = Reply::new();
reply.add(doc1);
reply.add(doc2);
let mut reply_iter = reply.into_iter();
let mut reply_iter = reply.iter();
let mut result1 = reply_iter.next().unwrap();
match result1.get_field(&fieldname).unwrap() {
Field::StaticString(output) => assert_eq!(output, "one"),
@ -1432,6 +1487,10 @@ impl DocumentFile {
}
}
fn get_documents<'a>(&self) -> impl Iterator<Item = &Document> {
self.docs.iter()
}
fn add_document(&mut self, addition: &Addition) -> MsgAction {
let mut holder = Document::new();
let doc = addition.get_document();
@ -1464,11 +1523,7 @@ impl DocumentFile {
}
fn query(&self, query: &Query) -> MsgAction {
let mut reply = Reply::new();
for doc in self.docs.iter() {
reply.add(doc.clone());
}
reply.into()
query.run(self).into()
}
}
@ -1609,7 +1664,7 @@ mod document_files {
match result.get_action() {
MsgAction::Reply(output) => {
assert_eq!(output.len(), 1);
let holder = output.clone().into_iter().next().unwrap();
let holder = output.iter().next().unwrap();
match holder.get_field(name) {
Some(field) => match field {
Field::Uuid(store) => assert_eq!(store, &data),
@ -1630,7 +1685,7 @@ mod document_files {
match result.get_action() {
MsgAction::Reply(output) => {
assert_eq!(output.len(), 1);
let holder = output.clone().into_iter().next().unwrap();
let holder = output.iter().next().unwrap();
match holder.get_field(name) {
Some(field) => match field {
Field::Uuid(store) => assert_eq!(store, &data),
@ -1750,6 +1805,48 @@ mod document_files {
_ => unreachable!("got {:?}: should have been an error", result.get_action()),
}
}
#[test]
fn does_query_return_related_entries() {
let doc_name = "query";
let (queue, rx) = test_doc(doc_name, create_docdef(2), standard_routes());
let field0 = Uuid::new_v4();
let field1 = Uuid::new_v4();
for _ in 0..3 {
let mut addition = Addition::new();
addition.add_field("field0".to_string(), Uuid::new_v4());
addition.add_field("field1".to_string(), Uuid::new_v4());
let msg = Message::new(doc_name, addition);
queue.send(msg).unwrap();
rx.recv_timeout(TIMEOUT).unwrap();
}
let mut addition = Addition::new();
addition.add_field("field0".to_string(), field0.clone());
addition.add_field("field1".to_string(), field1.clone());
let msg = Message::new(doc_name, addition);
queue.send(msg).unwrap();
rx.recv_timeout(TIMEOUT).unwrap();
for _ in 0..3 {
let mut addition = Addition::new();
addition.add_field("field0".to_string(), Uuid::new_v4());
addition.add_field("field1".to_string(), Uuid::new_v4());
let msg = Message::new(doc_name, addition);
queue.send(msg).unwrap();
rx.recv_timeout(TIMEOUT).unwrap();
}
let mut query = Query::new();
query.add_specifier("field0".to_string(), Operand::Equal, field0.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(data) => {
assert_eq!(data.len(), 1, "should return one entry");
}
_ => unreachable!("got {:?}: should have been a reply", action),
}
}
}
#[cfg(test)]