added indexes to the mix.
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
f89bd8b09f
commit
7f1ce3d871
216
src/message.rs
216
src/message.rs
@ -1556,6 +1556,35 @@ enum Operand {
|
||||
Equal,
|
||||
}
|
||||
|
||||
impl Operand {
|
||||
fn check(&self, x: &Field, y: &Field) -> bool {
|
||||
match self {
|
||||
Self::Equal => x == y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod operands {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn equals_true() {
|
||||
let data: Field = Uuid::new_v4().into();
|
||||
assert!(Operand::Equal.check(&data, &data));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn equals_false() {
|
||||
let x: Field = Uuid::new_v4().into();
|
||||
let mut y: Field = Uuid::new_v4().into();
|
||||
while x == y {
|
||||
y = Uuid::new_v4().into();
|
||||
}
|
||||
assert!(!Operand::Equal.check(&x, &y));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Specifier {
|
||||
field_name: String,
|
||||
@ -1574,6 +1603,14 @@ impl Specifier {
|
||||
value: value.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn which_field(&self) -> String {
|
||||
self.field_name.clone()
|
||||
}
|
||||
|
||||
fn check(&self, field: &Field) -> bool {
|
||||
self.operation.check(field, &self.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -1774,6 +1811,141 @@ impl Oid {
|
||||
}
|
||||
}
|
||||
|
||||
struct Index {
|
||||
data: HashMap<Field, HashSet<Oid>>,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
data: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, field: Field, oid: Oid) {
|
||||
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.get_mut(&field).unwrap()
|
||||
}
|
||||
};
|
||||
oids.insert(oid);
|
||||
}
|
||||
|
||||
fn get(&self, spec: &Specifier) -> Vec<Oid> {
|
||||
let mut output = Vec::new();
|
||||
for (field, oids) in self.data.iter() {
|
||||
if spec.check(field) {
|
||||
for oid in oids.iter() {
|
||||
output.push(oid.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn remove(&mut self, field: &Field, oid: &Oid) {
|
||||
match self.data.get_mut(field) {
|
||||
Some(oids) => {
|
||||
oids.remove(oid);
|
||||
if oids.len() == 0 {
|
||||
self.data.remove(field);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod indexes {
|
||||
use super::*;
|
||||
|
||||
fn get_fields(count: usize) -> Vec<Field> {
|
||||
let mut output = Vec::new();
|
||||
while output.len() < count {
|
||||
let field: Field = Uuid::new_v4().into();
|
||||
if !output.contains(&field) {
|
||||
output.push(field);
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn get_oids(count: usize) -> Vec<Oid> {
|
||||
let mut output = Vec::new();
|
||||
while output.len() < count {
|
||||
let oid = Oid::new();
|
||||
if !output.contains(&oid) {
|
||||
output.push(oid);
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_to_index() {
|
||||
let mut index = Index::new();
|
||||
let count = 3;
|
||||
let fields = get_fields(count);
|
||||
let oids = get_oids(count);
|
||||
for i in 0..count {
|
||||
index.add(fields[i].clone(), oids[i].clone());
|
||||
}
|
||||
for i in 0..count {
|
||||
let spec = Specifier::new("stuff".to_string(), Operand::Equal, fields[i].clone());
|
||||
let result = index.get(&spec);
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0], oids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn index_can_handle_multiple_entries() {
|
||||
let mut index = Index::new();
|
||||
let count = 3;
|
||||
let fields = get_fields(1);
|
||||
let oids = get_oids(count);
|
||||
for i in 0..count {
|
||||
index.add(fields[0].clone(), oids[i].clone());
|
||||
}
|
||||
let spec = Specifier::new("unimportant".to_string(), Operand::Equal, fields[0].clone());
|
||||
let result = index.get(&spec);
|
||||
assert_eq!(result.len(), 3);
|
||||
for oid in oids {
|
||||
assert!(result.contains(&oid));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_remove_oid() {
|
||||
let mut index = Index::new();
|
||||
let count = 3;
|
||||
let pos = 1;
|
||||
let fields = get_fields(1);
|
||||
let oids = get_oids(count);
|
||||
for i in 0..count {
|
||||
index.add(fields[0].clone(), oids[i].clone());
|
||||
}
|
||||
index.remove(&fields[0], &oids[pos]);
|
||||
let spec = Specifier::new("x".to_string(), Operand::Equal, fields[0].clone());
|
||||
let result = index.get(&spec);
|
||||
assert!(!result.contains(&oids[pos]), "should have removed oid");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn are_empty_indexes_removed() {
|
||||
let mut index = Index::new();
|
||||
let field: Field = Uuid::new_v4().into();
|
||||
let oid = Oid::new();
|
||||
index.add(field.clone(), oid.clone());
|
||||
index.remove(&field, &oid);
|
||||
assert_eq!(index.data.len(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct DocumentFile {
|
||||
docdef: DocDef,
|
||||
docs: HashMap<Oid, Document>,
|
||||
@ -2871,6 +3043,50 @@ mod document_files {
|
||||
_ => unreachable!("got {:?}: should have gotten a reply", action),
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
fn unique_available_after_bad_change() {
|
||||
let mut ids: Vec<Uuid> = Vec::new();
|
||||
while ids.len() < 3 {
|
||||
let id = Uuid::new_v4();
|
||||
if !ids.contains(&id) {
|
||||
ids.push(id);
|
||||
}
|
||||
}
|
||||
let (mut docdef, doc_name) =
|
||||
create_docdef([FieldType::Uuid, FieldType::StaticString].to_vec());
|
||||
docdef.set_unique("field0");
|
||||
let (queue, rx) = test_doc(doc_name.as_str(), docdef, standard_routes());
|
||||
let field1 = "fred";
|
||||
for index in 0..2 {
|
||||
let mut addition = Addition::new();
|
||||
addition.add_field("field0".to_string(), ids[index].clone());
|
||||
addition.add_field("field1".to_string(), field1);
|
||||
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("field1".to_string(), Operand::Equal, field1);
|
||||
let values = update.get_values_mut();
|
||||
values.add_field("field0".to_string(), ids[2].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::Error(err) => match err {
|
||||
MTTError::FieldDuplicate(key, field) => {
|
||||
let expected: Field = ids[2].into();
|
||||
assert_eq!(key, "field0");
|
||||
assert_eq!(field, &expected);
|
||||
}
|
||||
_ => unreachable!("got {:?}: should have gotten an missing field", err),
|
||||
},
|
||||
_ => unreachable!("got {:?}: should have gotten an error", action),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user