use std::collections::BTreeMap;
use crate::record::RowValue;
pub(crate) fn merge_non_pk_into_full_map(
full_map: &mut BTreeMap<String, RowValue>,
parts: &[String],
v: &RowValue,
) {
let mut cur: &mut RowValue = full_map
.entry(parts[0].clone())
.or_insert_with(|| RowValue::Object(BTreeMap::new()));
for seg in parts.iter().skip(1).take(parts.len().saturating_sub(2)) {
loop {
match cur {
RowValue::Object(m) => {
cur = m
.entry(seg.clone())
.or_insert_with(|| RowValue::Object(BTreeMap::new()));
break;
}
_ => {
*cur = RowValue::Object(BTreeMap::new());
}
}
}
}
if let RowValue::Object(m) = cur {
m.insert(parts[parts.len() - 1].clone(), v.clone());
}
}
#[cfg(test)]
mod tests {
use super::merge_non_pk_into_full_map;
use crate::record::RowValue;
use std::collections::BTreeMap;
#[test]
fn merge_turns_scalar_prefix_into_object_for_deeper_path() {
let mut m = BTreeMap::new();
m.insert("a".into(), RowValue::Int64(7));
merge_non_pk_into_full_map(
&mut m,
&["a".into(), "b".into(), "c".into()],
&RowValue::String("leaf".into()),
);
let inner = m.get("a").unwrap().as_object_map().unwrap();
let mid = inner.get("b").unwrap().as_object_map().unwrap();
assert_eq!(mid.get("c"), Some(&RowValue::String("leaf".into())));
}
#[test]
fn merge_three_segments_overwrites_leaf() {
let mut m = BTreeMap::new();
merge_non_pk_into_full_map(
&mut m,
&["x".into(), "y".into(), "z".into()],
&RowValue::Bool(true),
);
merge_non_pk_into_full_map(
&mut m,
&["x".into(), "y".into(), "z".into()],
&RowValue::Bool(false),
);
let x = m.get("x").unwrap().as_object_map().unwrap();
let y = x.get("y").unwrap().as_object_map().unwrap();
assert_eq!(y.get("z"), Some(&RowValue::Bool(false)));
}
#[test]
fn merge_reuses_existing_intermediate_segment() {
let mut m = BTreeMap::new();
merge_non_pk_into_full_map(
&mut m,
&["a".into(), "b".into(), "c".into()],
&RowValue::Int64(1),
);
merge_non_pk_into_full_map(
&mut m,
&["a".into(), "b".into(), "d".into()],
&RowValue::Int64(2),
);
let a = m.get("a").unwrap().as_object_map().unwrap();
let b = a.get("b").unwrap().as_object_map().unwrap();
assert_eq!(b.get("c"), Some(&RowValue::Int64(1)));
assert_eq!(b.get("d"), Some(&RowValue::Int64(2)));
}
#[test]
fn merge_two_segments_inserts_leaf_value() {
let mut m = BTreeMap::new();
merge_non_pk_into_full_map(&mut m, &["a".into(), "b".into()], &RowValue::Int64(7));
let a = m.get("a").unwrap().as_object_map().unwrap();
assert_eq!(a.get("b"), Some(&RowValue::Int64(7)));
}
}