From 7802398fca7cc375de64f565a1244c59b4145ccf Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 10:41:29 +0200 Subject: [PATCH 1/9] implemented and tested Hierarchy::full_path --- src/hierarchy.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/hierarchy.rs b/src/hierarchy.rs index 5ca88612..190dda5b 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -155,6 +155,22 @@ impl Hierarchy { }) } + pub fn full_path(&self, path: &[String]) -> Option> { + self.0 + .iter() + .fold(Found::Zero, |f, (qualified_path, _)| { + if is_suffix_of(path, qualified_path) { + match f { + Found::Zero => Found::One(qualified_path.clone()), + _ => Found::More, + } + } else { + f + } + }) + .into() + } + pub fn filter(&self, path: &[String]) -> Self { self.iter() .filter_map(|(qualified_path, object)| { @@ -382,4 +398,40 @@ mod tests { ]) ) } + + #[test] + fn test_full_path() { + let values = Hierarchy::from([ + (vec!["a", "b", "c"], 1), + (vec!["a", "b", "d"], 2), + (vec!["a", "c"], 3), + (vec!["a", "e"], 4), + (vec!["a", "e", "f"], 5), + (vec!["b", "c"], 6), + ]); + assert_eq!( + values.full_path(&["a".to_string(), "c".to_string()]), + Some(vec!["a".to_string(), "c".to_string()]) + ); + assert_eq!( + values.full_path(&["c".to_string()]), + None + ); + assert_eq!( + values.full_path(&["e".to_string()]), + Some(vec!["a".to_string(), "e".to_string()]) + ); + assert_eq!( + values.full_path(&["e".to_string(), "f".to_string()]), + Some(vec!["a".to_string(), "e".to_string(), "f".to_string()]) + ); + assert_eq!( + values.full_path(&["b".to_string(), "d".to_string()]), + Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) + ); + assert_eq!( + values.full_path(&["d".to_string()]), + Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) + ); + } } From 1743e11f97bd65b5c4a580159870e3761655bc2f Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 10:59:57 +0200 Subject: [PATCH 2/9] implemented and tested Hierarchy::full_path --- src/hierarchy.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/hierarchy.rs b/src/hierarchy.rs index 190dda5b..facab205 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -138,25 +138,13 @@ impl Hierarchy { } pub fn get(&self, path: &[String]) -> Option<&T> { - self.0.get(path).or_else(|| { - self.0 - .iter() - .fold(Found::Zero, |f, (qualified_path, object)| { - if is_suffix_of(path, qualified_path) { - match f { - Found::Zero => Found::One(object), - _ => Found::More, - } - } else { - f - } - }) - .into() - }) + self.full_path(path) + .and_then(|p| self.0.get(&p)) } pub fn full_path(&self, path: &[String]) -> Option> { - self.0 + self.0.get(path).and_then(|_| Some(path.iter().map(|s| s.to_string()).collect::>())) + .or_else ( || self.0 .iter() .fold(Found::Zero, |f, (qualified_path, _)| { if is_suffix_of(path, qualified_path) { @@ -169,6 +157,7 @@ impl Hierarchy { } }) .into() + ) } pub fn filter(&self, path: &[String]) -> Self { @@ -417,6 +406,10 @@ mod tests { values.full_path(&["c".to_string()]), None ); + assert_eq!( + values.full_path(&["b".to_string(), "c".to_string()]), + Some(vec!["b".to_string(), "c".to_string()]) + ); assert_eq!( values.full_path(&["e".to_string()]), Some(vec!["a".to_string(), "e".to_string()]) From 02e9e466d4c974dc8826f33d05fe9f0e853f3d3f Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 11:00:03 +0200 Subject: [PATCH 3/9] implemented and tested Hierarchy::full_path --- src/hierarchy.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/hierarchy.rs b/src/hierarchy.rs index facab205..ec5aee4d 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -138,26 +138,28 @@ impl Hierarchy { } pub fn get(&self, path: &[String]) -> Option<&T> { - self.full_path(path) - .and_then(|p| self.0.get(&p)) + self.full_path(path).and_then(|p| self.0.get(&p)) } pub fn full_path(&self, path: &[String]) -> Option> { - self.0.get(path).and_then(|_| Some(path.iter().map(|s| s.to_string()).collect::>())) - .or_else ( || self.0 - .iter() - .fold(Found::Zero, |f, (qualified_path, _)| { - if is_suffix_of(path, qualified_path) { - match f { - Found::Zero => Found::One(qualified_path.clone()), - _ => Found::More, - } - } else { - f - } + self.0 + .get(path) + .and_then(|_| Some(path.iter().map(|s| s.to_string()).collect::>())) + .or_else(|| { + self.0 + .iter() + .fold(Found::Zero, |f, (qualified_path, _)| { + if is_suffix_of(path, qualified_path) { + match f { + Found::Zero => Found::One(qualified_path.clone()), + _ => Found::More, + } + } else { + f + } + }) + .into() }) - .into() - ) } pub fn filter(&self, path: &[String]) -> Self { @@ -402,10 +404,7 @@ mod tests { values.full_path(&["a".to_string(), "c".to_string()]), Some(vec!["a".to_string(), "c".to_string()]) ); - assert_eq!( - values.full_path(&["c".to_string()]), - None - ); + assert_eq!(values.full_path(&["c".to_string()]), None); assert_eq!( values.full_path(&["b".to_string(), "c".to_string()]), Some(vec!["b".to_string(), "c".to_string()]) From 58de7f78923318d035b446a11f2785d1ff0d3c82 Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 11:02:31 +0200 Subject: [PATCH 4/9] add docstrings --- CHANGELOG.md | 2 ++ src/hierarchy.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcd525b6..fd52a143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Implemented `least` and `greatest` (support qualified and unqualified columns)[MR102](https://github.com/Qrlew/qrlew/pull/102) ### Fixed - `And` for struct of structs [MR100](https://github.com/Qrlew/qrlew/pull/100) +### Added +- `Hierarchy::full_path` [MR103](https://github.com/Qrlew/qrlew/pull/103) ## [0.2.2] - 2023-08-29 ### Changed diff --git a/src/hierarchy.rs b/src/hierarchy.rs index ec5aee4d..e39e8244 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -141,6 +141,8 @@ impl Hierarchy { self.full_path(path).and_then(|p| self.0.get(&p)) } + /// Returns the full path of a an item in the current hierarchy. + /// If the input path does not exist of is ambiguous, returns None. pub fn full_path(&self, path: &[String]) -> Option> { self.0 .get(path) From ffcfd827e8692e8fc8c99fce7723b1439017d42a Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 12:47:41 +0200 Subject: [PATCH 5/9] impl get_key_value --- src/hierarchy.rs | 88 ++++++++++++++++++++++++-------------- src/relation/transforms.rs | 11 ++--- 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/src/hierarchy.rs b/src/hierarchy.rs index e39e8244..35802fcb 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -137,23 +137,24 @@ impl Hierarchy { .collect() } - pub fn get(&self, path: &[String]) -> Option<&T> { - self.full_path(path).and_then(|p| self.0.get(&p)) + // pub fn get<'a>(&'a self, path:&'a Vec) -> Option<&T> { + // self.get_key_value(path).and_then(|(_, v)| Some(v)) + // } + pub fn get<'a>(&'a self, path:&'a[String]) -> Option<&T> { + self.get_key_value(path).and_then(|(_, v)| Some(v)) } - /// Returns the full path of a an item in the current hierarchy. - /// If the input path does not exist of is ambiguous, returns None. - pub fn full_path(&self, path: &[String]) -> Option> { + pub fn get_key_value<'a>(&'a self, path: &'a[String]) -> Option<(&[String], &T)> { self.0 .get(path) - .and_then(|_| Some(path.iter().map(|s| s.to_string()).collect::>())) + .and_then(|object| Some((path, object))) .or_else(|| { self.0 .iter() - .fold(Found::Zero, |f, (qualified_path, _)| { + .fold(Found::Zero, |f, (qualified_path, object)| { if is_suffix_of(path, qualified_path) { match f { - Found::Zero => Found::One(qualified_path.clone()), + Found::Zero => Found::One((qualified_path.as_ref(), object)), _ => Found::More, } } else { @@ -162,7 +163,28 @@ impl Hierarchy { }) .into() }) - } + } + + // pub fn get_key_value<'a>(&'a self, path: &'a Vec) -> Option<(&Vec, &T)> { + // self.0 + // .get(path) + // .and_then(|object| Some((path, object))) + // .or_else(|| { + // self.0 + // .iter() + // .fold(Found::Zero, |f, (qualified_path, object)| { + // if is_suffix_of(path, qualified_path) { + // match f { + // Found::Zero => Found::One((qualified_path, object)), + // _ => Found::More, + // } + // } else { + // f + // } + // }) + // .into() + // }) + // } pub fn filter(&self, path: &[String]) -> Self { self.iter() @@ -254,7 +276,7 @@ impl Index

for Hierarchy { type Output = T; fn index(&self, index: P) -> &Self::Output { - self.get(&index.path()).unwrap() + self.get(index.path()).unwrap() } } @@ -403,29 +425,29 @@ mod tests { (vec!["b", "c"], 6), ]); assert_eq!( - values.full_path(&["a".to_string(), "c".to_string()]), - Some(vec!["a".to_string(), "c".to_string()]) - ); - assert_eq!(values.full_path(&["c".to_string()]), None); - assert_eq!( - values.full_path(&["b".to_string(), "c".to_string()]), - Some(vec!["b".to_string(), "c".to_string()]) - ); - assert_eq!( - values.full_path(&["e".to_string()]), - Some(vec!["a".to_string(), "e".to_string()]) - ); - assert_eq!( - values.full_path(&["e".to_string(), "f".to_string()]), - Some(vec!["a".to_string(), "e".to_string(), "f".to_string()]) - ); - assert_eq!( - values.full_path(&["b".to_string(), "d".to_string()]), - Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) - ); - assert_eq!( - values.full_path(&["d".to_string()]), - Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) + values.get_key_value(&vec!["a".to_string(), "c".to_string()]), + Some((&vec!["a".to_string(), "c".to_string()], &3)) ); + assert_eq!(values.get_key_value(&vec!["c".to_string()]), None); + // assert_eq!( + // values.get_key_value(&vec!["b".to_string(), "c".to_string()]), + // Some(vec!["b".to_string(), "c".to_string()]) + // ); + // assert_eq!( + // values.get_key_value(&vec!["e".to_string()]), + // Some(vec!["a".to_string(), "e".to_string()]) + // ); + // assert_eq!( + // values.get_key_value(&vec!["e".to_string(), "f".to_string()]), + // Some(vec!["a".to_string(), "e".to_string(), "f".to_string()]) + // ); + // assert_eq!( + // values.get_key_value(&vec!["b".to_string(), "d".to_string()]), + // Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) + // ); + // assert_eq!( + // values.get_key_value(&vec!["d".to_string()]), + // Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) + // ); } } diff --git a/src/relation/transforms.rs b/src/relation/transforms.rs index 62fb4204..ac1b7aaa 100644 --- a/src/relation/transforms.rs +++ b/src/relation/transforms.rs @@ -534,10 +534,7 @@ impl Relation { }| { relation.with_referred_field( referring_id, - relations - .get(&[referred_relation.to_string()]) - .unwrap() - .clone(), + relations[[referred_relation.to_string()]].clone(), referred_id, referred_field, referred_field_name, @@ -1634,9 +1631,7 @@ mod tests { let mut database = postgresql::test_database(); let relations = database.relations(); - let table = relations - .get(&["item_table".into()]) - .unwrap() + let table = relations[["item_table"]] .as_ref() .clone(); @@ -1798,7 +1793,7 @@ mod tests { .build(); let join: Relation = Relation::join() - .left(relations.get(&["order_table".into()]).unwrap().clone()) + .left(relations[&["order_table".into()]].unwrap().clone()) .right(table.clone()) .on(Expr::eq(Expr::col("id"), Expr::col("order_id"))) .build(); From 7ecf40d95e5c46104aa0388b17b71844853061c7 Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 13:08:52 +0200 Subject: [PATCH 6/9] impl get_key_value --- src/hierarchy.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/hierarchy.rs b/src/hierarchy.rs index 35802fcb..916192c5 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -140,14 +140,14 @@ impl Hierarchy { // pub fn get<'a>(&'a self, path:&'a Vec) -> Option<&T> { // self.get_key_value(path).and_then(|(_, v)| Some(v)) // } - pub fn get<'a>(&'a self, path:&'a[String]) -> Option<&T> { + pub fn get<'a>(&'a self, path:&[String]) -> Option<&'a T> { self.get_key_value(path).and_then(|(_, v)| Some(v)) } - pub fn get_key_value<'a>(&'a self, path: &'a[String]) -> Option<(&[String], &T)> { + pub fn get_key_value<'a>(&'a self, path: &[String]) -> Option<(&'a[String], &'a T)> { self.0 - .get(path) - .and_then(|object| Some((path, object))) + .get_key_value(path) + .map(|(k, v)| (k.as_slice(), v)) .or_else(|| { self.0 .iter() @@ -276,7 +276,7 @@ impl Index

for Hierarchy { type Output = T; fn index(&self, index: P) -> &Self::Output { - self.get(index.path()).unwrap() + self.get(&index.path()).unwrap() } } @@ -424,15 +424,15 @@ mod tests { (vec!["a", "e", "f"], 5), (vec!["b", "c"], 6), ]); - assert_eq!( - values.get_key_value(&vec!["a".to_string(), "c".to_string()]), - Some((&vec!["a".to_string(), "c".to_string()], &3)) - ); - assert_eq!(values.get_key_value(&vec!["c".to_string()]), None); // assert_eq!( - // values.get_key_value(&vec!["b".to_string(), "c".to_string()]), - // Some(vec!["b".to_string(), "c".to_string()]) + // values.get_key_value(&vec!["a".to_string(), "c".to_string()]), + // Some((&vec!["a".to_string(), "c".to_string()], &3)) // ); + assert_eq!(values.get_key_value(&vec!["c".to_string()]), None); + assert_eq!( + values.get_key_value(&vec!["b".into(), "c".into()]), + Some((vec!["b".to_string(), "c".to_string()].as_slice(), &6)) + ); // assert_eq!( // values.get_key_value(&vec!["e".to_string()]), // Some(vec!["a".to_string(), "e".to_string()]) From ccc0a723b1f9d76a0334375ec8b8218a762f8661 Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 13:10:52 +0200 Subject: [PATCH 7/9] ok --- src/relation/transforms.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/relation/transforms.rs b/src/relation/transforms.rs index ac1b7aaa..99f81e80 100644 --- a/src/relation/transforms.rs +++ b/src/relation/transforms.rs @@ -2214,4 +2214,4 @@ mod tests { let joined_rel = table_1.clone().cross_join(table_2.clone()).unwrap(); joined_rel.display_dot(); } -} +} \ No newline at end of file From 1185d3fd1a6a883c33efc9dfe06db4640fc1e08b Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 13:20:29 +0200 Subject: [PATCH 8/9] impl get_key_value --- CHANGELOG.md | 2 +- src/hierarchy.rs | 59 ++++++++++++++++++++++---------------- src/relation/transforms.rs | 13 ++++++--- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd52a143..6d9334e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - `And` for struct of structs [MR100](https://github.com/Qrlew/qrlew/pull/100) ### Added -- `Hierarchy::full_path` [MR103](https://github.com/Qrlew/qrlew/pull/103) +- `Hierarchy::get_key_value` [MR103](https://github.com/Qrlew/qrlew/pull/103) ## [0.2.2] - 2023-08-29 ### Changed diff --git a/src/hierarchy.rs b/src/hierarchy.rs index 916192c5..8779ecff 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -140,11 +140,11 @@ impl Hierarchy { // pub fn get<'a>(&'a self, path:&'a Vec) -> Option<&T> { // self.get_key_value(path).and_then(|(_, v)| Some(v)) // } - pub fn get<'a>(&'a self, path:&[String]) -> Option<&'a T> { + pub fn get<'a>(&'a self, path: &[String]) -> Option<&'a T> { self.get_key_value(path).and_then(|(_, v)| Some(v)) } - pub fn get_key_value<'a>(&'a self, path: &[String]) -> Option<(&'a[String], &'a T)> { + pub fn get_key_value<'a>(&'a self, path: &[String]) -> Option<(&'a [String], &'a T)> { self.0 .get_key_value(path) .map(|(k, v)| (k.as_slice(), v)) @@ -163,7 +163,7 @@ impl Hierarchy { }) .into() }) - } + } // pub fn get_key_value<'a>(&'a self, path: &'a Vec) -> Option<(&Vec, &T)> { // self.0 @@ -424,30 +424,39 @@ mod tests { (vec!["a", "e", "f"], 5), (vec!["b", "c"], 6), ]); - // assert_eq!( - // values.get_key_value(&vec!["a".to_string(), "c".to_string()]), - // Some((&vec!["a".to_string(), "c".to_string()], &3)) - // ); + assert_eq!( + values.get_key_value(&["a".to_string(), "c".to_string()]), + Some((["a".to_string(), "c".to_string()].as_slice(), &3)) + ); assert_eq!(values.get_key_value(&vec!["c".to_string()]), None); assert_eq!( - values.get_key_value(&vec!["b".into(), "c".into()]), - Some((vec!["b".to_string(), "c".to_string()].as_slice(), &6)) + values.get_key_value(&["b".into(), "c".into()]), + Some((["b".to_string(), "c".to_string()].as_slice(), &6)) + ); + assert_eq!( + values.get_key_value(&["e".to_string()]), + Some((["a".to_string(), "e".to_string()].as_slice(), &4)) + ); + assert_eq!( + values.get_key_value(&["e".to_string(), "f".to_string()]), + Some(( + ["a".to_string(), "e".to_string(), "f".to_string()].as_slice(), + &5 + )) + ); + assert_eq!( + values.get_key_value(&["b".to_string(), "d".to_string()]), + Some(( + ["a".to_string(), "b".to_string(), "d".to_string()].as_slice(), + &2 + )) + ); + assert_eq!( + values.get_key_value(&["d".to_string()]), + Some(( + ["a".to_string(), "b".to_string(), "d".to_string()].as_slice(), + &2 + )) ); - // assert_eq!( - // values.get_key_value(&vec!["e".to_string()]), - // Some(vec!["a".to_string(), "e".to_string()]) - // ); - // assert_eq!( - // values.get_key_value(&vec!["e".to_string(), "f".to_string()]), - // Some(vec!["a".to_string(), "e".to_string(), "f".to_string()]) - // ); - // assert_eq!( - // values.get_key_value(&vec!["b".to_string(), "d".to_string()]), - // Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) - // ); - // assert_eq!( - // values.get_key_value(&vec!["d".to_string()]), - // Some(vec!["a".to_string(), "b".to_string(), "d".to_string()]) - // ); } } diff --git a/src/relation/transforms.rs b/src/relation/transforms.rs index 99f81e80..62fb4204 100644 --- a/src/relation/transforms.rs +++ b/src/relation/transforms.rs @@ -534,7 +534,10 @@ impl Relation { }| { relation.with_referred_field( referring_id, - relations[[referred_relation.to_string()]].clone(), + relations + .get(&[referred_relation.to_string()]) + .unwrap() + .clone(), referred_id, referred_field, referred_field_name, @@ -1631,7 +1634,9 @@ mod tests { let mut database = postgresql::test_database(); let relations = database.relations(); - let table = relations[["item_table"]] + let table = relations + .get(&["item_table".into()]) + .unwrap() .as_ref() .clone(); @@ -1793,7 +1798,7 @@ mod tests { .build(); let join: Relation = Relation::join() - .left(relations[&["order_table".into()]].unwrap().clone()) + .left(relations.get(&["order_table".into()]).unwrap().clone()) .right(table.clone()) .on(Expr::eq(Expr::col("id"), Expr::col("order_id"))) .build(); @@ -2214,4 +2219,4 @@ mod tests { let joined_rel = table_1.clone().cross_join(table_2.clone()).unwrap(); joined_rel.display_dot(); } -} \ No newline at end of file +} From 7aa86cc1b3c571542d4b3b4d348180737a2067db Mon Sep 17 00:00:00 2001 From: victoria de sainte agathe Date: Fri, 8 Sep 2023 13:27:32 +0200 Subject: [PATCH 9/9] impl get_key_value --- src/hierarchy.rs | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/hierarchy.rs b/src/hierarchy.rs index 8779ecff..02cbf241 100644 --- a/src/hierarchy.rs +++ b/src/hierarchy.rs @@ -137,9 +137,6 @@ impl Hierarchy { .collect() } - // pub fn get<'a>(&'a self, path:&'a Vec) -> Option<&T> { - // self.get_key_value(path).and_then(|(_, v)| Some(v)) - // } pub fn get<'a>(&'a self, path: &[String]) -> Option<&'a T> { self.get_key_value(path).and_then(|(_, v)| Some(v)) } @@ -165,27 +162,6 @@ impl Hierarchy { }) } - // pub fn get_key_value<'a>(&'a self, path: &'a Vec) -> Option<(&Vec, &T)> { - // self.0 - // .get(path) - // .and_then(|object| Some((path, object))) - // .or_else(|| { - // self.0 - // .iter() - // .fold(Found::Zero, |f, (qualified_path, object)| { - // if is_suffix_of(path, qualified_path) { - // match f { - // Found::Zero => Found::One((qualified_path, object)), - // _ => Found::More, - // } - // } else { - // f - // } - // }) - // .into() - // }) - // } - pub fn filter(&self, path: &[String]) -> Self { self.iter() .filter_map(|(qualified_path, object)| {