Got unique index working, and connected to DocDef.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s

This commit is contained in:
Jeff Baskin 2025-09-14 10:53:47 -04:00
parent 7f1ce3d871
commit 32d3fbadea

View File

@ -1105,7 +1105,7 @@ impl FieldSetting {
fn set_default(&mut self, value: Option<Field>) -> Result<(), MTTError> {
match value {
Some(data) => {
match self.check(Some(data.clone())) {
match self.validate(Some(data.clone())) {
Ok(_) => {}
Err(err) => return Err(err),
}
@ -1134,7 +1134,7 @@ impl FieldSetting {
}
}
fn check(&self, value: Option<Field>) -> Result<Field, MTTError> {
fn validate(&self, value: Option<Field>) -> Result<Field, MTTError> {
match value {
Some(data) => {
let vft: FieldType = (&data).into();
@ -1170,20 +1170,20 @@ mod fieldsettings {
use super::*;
#[test]
fn checks_field_type() {
fn validates_field_type() {
let fset = FieldSetting::new(FieldType::Uuid);
let value: Field = Uuid::new_v4().into();
match fset.check(Some(value.clone())) {
match fset.validate(Some(value.clone())) {
Ok(data) => assert_eq!(data, value),
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
}
}
#[test]
fn checks_for_bad_field_type() {
fn validates_for_bad_field_type() {
let fset = FieldSetting::new(FieldType::Uuid);
let value: Field = "text".into();
match fset.check(Some(value)) {
match fset.validate(Some(value)) {
Ok(data) => unreachable!("got {:?}: should have gotten an error", data),
Err(err) => match err {
MTTError::DocumentFieldWrongDataType(expected, got) => {
@ -1198,7 +1198,7 @@ mod fieldsettings {
#[test]
fn no_default_returns_error() {
let fset = FieldSetting::new(FieldType::Uuid);
match fset.check(None) {
match fset.validate(None) {
Ok(data) => unreachable!("got {:?}: should have gotten an error", data),
Err(err) => match err {
MTTError::DocumentFieldMissing(data) => assert_eq!(data, ""),
@ -1211,7 +1211,7 @@ mod fieldsettings {
fn returns_value_if_default_is_set() {
let mut fset = FieldSetting::new(FieldType::StaticString);
fset.set_default(None);
match fset.check(None) {
match fset.validate(None) {
Ok(data) => assert_eq!(data, "".into()),
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
}
@ -1222,19 +1222,19 @@ mod fieldsettings {
let mut fset = FieldSetting::new(FieldType::StaticString);
let input = "fred";
fset.set_default(Some(input.into()));
match fset.check(None) {
match fset.validate(None) {
Ok(data) => assert_eq!(data, input.into()),
Err(err) => unreachable!("got {:?}: should have gotten a value", err),
}
}
#[test]
fn checks_for_unique_value() {
fn validates_for_unique_value() {
let mut fset = FieldSetting::new(FieldType::Uuid);
let field: Field = Uuid::new_v4().into();
fset.set_unique();
fset.use_unique_value(field.clone());
match fset.check(Some(field.clone())) {
match fset.validate(Some(field.clone())) {
Ok(data) => unreachable!("got {:?}: should have been error", data),
Err(err) => match err {
MTTError::FieldDuplicate(key, result) => {
@ -1317,15 +1317,32 @@ mod additions {
}
}
#[derive(Clone, Debug)]
enum IndexType {
Index,
Unique,
}
impl IndexType {
fn create_index(&self) -> Index {
match self {
Self::Index => Index::new(),
Self::Unique => Index::new_unique(),
}
}
}
#[derive(Clone, Debug)]
struct DocDef {
fields: HashMap<String, FieldSetting>,
indexes: HashMap<String, IndexType>,
}
impl DocDef {
fn new() -> Self {
Self {
fields: HashMap::new(),
indexes: HashMap::new(),
}
}
@ -1347,12 +1364,12 @@ impl DocDef {
}
}
fn check(&self, field_name: &str, value: Option<Field>) -> Result<Field, MTTError> {
fn validate(&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)
setting.validate(value)
}
fn set_default(&mut self, field_name: &str, value: Option<Field>) -> Result<(), MTTError> {
@ -1366,6 +1383,23 @@ impl DocDef {
}
}
fn add_index(&mut self, field_name: String, index_type: IndexType) -> Result<(), MTTError> {
let setting = match self.get_field(&field_name) {
Ok(_) => {}
Err(err) => return Err(err),
};
self.indexes.insert(field_name, index_type);
Ok(())
}
fn create_indexes(&self) -> HashMap<String, Index> {
let mut output = HashMap::new();
for (key, value) in self.indexes.iter() {
output.insert(key.clone(), value.create_index());
}
output
}
fn set_unique(&mut self, field_name: &str) -> Result<(), MTTError> {
let setting = match self.get_field_mut(field_name) {
Ok(data) => data,
@ -1380,7 +1414,7 @@ impl DocDef {
Ok(data) => data,
Err(err) => return Err(err),
};
match setting.check(Some(field.clone())) {
match setting.validate(Some(field.clone())) {
Ok(data) => setting.use_unique_value(field),
Err(err) => return Err(err),
}
@ -1412,7 +1446,7 @@ mod docdefs {
let field_type = FieldType::Uuid;
docdef.add_field(name.clone(), field_type.clone());
let result = docdef.get_field(name.as_str()).unwrap();
match result.check(Some(Uuid::new_v4().into())) {
match result.validate(Some(Uuid::new_v4().into())) {
Ok(_) => {}
Err(err) => unreachable!("got {:?}: should have been a value", err),
}
@ -1441,7 +1475,7 @@ mod docdefs {
}
for name in names.iter() {
let result = docdef.get_field(name).unwrap();
match result.check(Some("".into())) {
match result.validate(Some("".into())) {
Ok(_) => {}
Err(err) => unreachable!("got {:?}: should have been a value", err),
}
@ -1454,7 +1488,7 @@ mod docdefs {
let name = "defaultfunction";
docdef.add_field(name.to_string(), FieldType::StaticString);
docdef.set_default(name, None);
match docdef.get_field(name).unwrap().check(None) {
match docdef.get_field(name).unwrap().validate(None) {
Ok(data) => match data {
Field::StaticString(result) => assert_eq!(result, ""),
_ => unreachable!("got {:?}: should return a static string", data),
@ -1557,7 +1591,7 @@ enum Operand {
}
impl Operand {
fn check(&self, x: &Field, y: &Field) -> bool {
fn validate(&self, x: &Field, y: &Field) -> bool {
match self {
Self::Equal => x == y,
}
@ -1571,7 +1605,7 @@ mod operands {
#[test]
fn equals_true() {
let data: Field = Uuid::new_v4().into();
assert!(Operand::Equal.check(&data, &data));
assert!(Operand::Equal.validate(&data, &data));
}
#[test]
@ -1581,7 +1615,7 @@ mod operands {
while x == y {
y = Uuid::new_v4().into();
}
assert!(!Operand::Equal.check(&x, &y));
assert!(!Operand::Equal.validate(&x, &y));
}
}
@ -1608,8 +1642,8 @@ impl Specifier {
self.field_name.clone()
}
fn check(&self, field: &Field) -> bool {
self.operation.check(field, &self.value)
fn validate(&self, field: &Field) -> bool {
self.operation.validate(field, &self.value)
}
}
@ -1813,31 +1847,44 @@ impl Oid {
struct Index {
data: HashMap<Field, HashSet<Oid>>,
unique: bool,
}
impl Index {
fn new() -> Self {
Self {
data: HashMap::new(),
unique: false,
}
}
fn add(&mut self, field: Field, oid: Oid) {
fn new_unique() -> Self {
Self {
data: HashMap::new(),
unique: true,
}
}
fn add(&mut self, field: Field, oid: Oid) -> Result<(), MTTError> {
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.insert(field.clone(), HashSet::new());
self.data.get_mut(&field).unwrap()
}
};
oids.insert(oid);
if self.unique && oids.len() > 0 {
return Err(MTTError::FieldDuplicate("".to_string(), field));
} else {
oids.insert(oid);
}
Ok(())
}
fn get(&self, spec: &Specifier) -> Vec<Oid> {
let mut output = Vec::new();
for (field, oids) in self.data.iter() {
if spec.check(field) {
if spec.validate(field) {
for oid in oids.iter() {
output.push(oid.clone());
}
@ -1857,6 +1904,16 @@ impl Index {
None => {}
};
}
fn validate(&self, field: &Field) -> Result<(), MTTError> {
if self.unique {
match self.data.get(field) {
Some(_) => return Err(MTTError::FieldDuplicate("".to_string(), field.clone())),
None => {}
}
}
Ok(())
}
}
#[cfg(test)]
@ -1944,11 +2001,60 @@ mod indexes {
index.remove(&field, &oid);
assert_eq!(index.data.len(), 0);
}
#[test]
fn do_unique_indexes_error_on_duplicates() {
let mut index = Index::new_unique();
let field: Field = "fred".into();
let oids = get_oids(2);
index.add(field.clone(), oids[0].clone()).unwrap();
match index.add(field.clone(), oids[0].clone()) {
Ok(_) => unreachable!("should have been an error"),
Err(err) => match err {
MTTError::FieldDuplicate(field_name, value) => {
assert_eq!(field_name, "");
assert_eq!(value, field);
}
_ => unreachable!("got {:?}: should have been duplicate field", err),
},
}
}
#[test]
fn index_returns_validate() {
let mut index = Index::new();
let field: Field = "stuff".into();
let oid = Oid::new();
index.add(field.clone(), oid).unwrap();
match index.validate(&field) {
Ok(_) => {}
Err(err) => unreachable!("got {:?}: should have returned without issue", err),
}
}
#[test]
fn unique_return_duplicate_error() {
let mut index = Index::new_unique();
let field: Field = "fred".into();
let oid = Oid::new();
index.add(field.clone(), oid).unwrap();
match index.validate(&field) {
Ok(_) => unreachable!("should have gotten a duplication error"),
Err(err) => match err {
MTTError::FieldDuplicate(field_name, value) => {
assert_eq!(field_name, "");
assert_eq!(value, field);
}
_ => unreachable!("got {:?}: should have been duplicate field", err),
},
}
}
}
struct DocumentFile {
docdef: DocDef,
docs: HashMap<Oid, Document>,
indexes: HashMap<String, Index>,
queue: Queue,
rx: Receiver<Message>,
}
@ -1956,8 +2062,9 @@ struct DocumentFile {
impl DocumentFile {
fn new(queue: Queue, rx: Receiver<Message>, docdef: DocDef) -> Self {
Self {
docdef: docdef,
docdef: docdef.clone(),
docs: HashMap::new(),
indexes: docdef.create_indexes(),
queue: queue,
rx: rx,
}
@ -2046,7 +2153,7 @@ impl DocumentFile {
let mut holder = Document::new();
let doc = addition.get_document();
for (key, value) in doc.iter() {
match self.docdef.check(key, Some(value.clone())) {
match self.docdef.validate(key, Some(value.clone())) {
Ok(data) => holder.add_field(key.clone(), value.clone()),
Err(err) => return Self::add_field_to_error(key.to_string(), err).into(),
}
@ -2054,7 +2161,7 @@ impl DocumentFile {
for (key, value) in self.docdef.iter() {
match holder.get_field(key) {
Some(_) => {}
None => match value.check(None) {
None => match value.validate(None) {
Ok(data) => holder.add_field(key.clone(), data.clone()),
Err(err) => return Self::add_field_to_error(key.to_string(), err).into(),
},
@ -2078,7 +2185,7 @@ impl DocumentFile {
for specifier in query.iter() {
match self
.docdef
.check(&specifier.field_name, Some(specifier.value.clone()))
.validate(&specifier.field_name, Some(specifier.value.clone()))
{
Ok(_) => {}
Err(err) => match err {
@ -2125,7 +2232,7 @@ impl DocumentFile {
for oid in oids.iter() {
let doc = self.docs.get_mut(oid).unwrap();
for (key, value) in update.get_values().iter() {
match self.docdef.check(key, Some(value.clone())) {
match self.docdef.validate(key, Some(value.clone())) {
Ok(field) => {
self.docdef
.remove_unique_value(key, doc.get_field(key).unwrap());
@ -3044,7 +3151,7 @@ mod document_files {
}
}
// #[test]
//#[test]
fn unique_available_after_bad_change() {
let mut ids: Vec<Uuid> = Vec::new();
while ids.len() < 3 {