mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-26 23:04:26 +01:00
Introduce a basic schema diff function
This commit is contained in:
parent
32d8b4b83f
commit
e86a547e93
@ -215,11 +215,155 @@ impl fmt::Display for SchemaAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum Diff {
|
||||||
|
IdentChange {
|
||||||
|
old: String,
|
||||||
|
new: String,
|
||||||
|
},
|
||||||
|
AttrMove {
|
||||||
|
name: String,
|
||||||
|
old: usize,
|
||||||
|
new: usize,
|
||||||
|
},
|
||||||
|
AttrPropsChange {
|
||||||
|
name: String,
|
||||||
|
old: SchemaProps,
|
||||||
|
new: SchemaProps,
|
||||||
|
},
|
||||||
|
NewAttr {
|
||||||
|
name: String,
|
||||||
|
pos: usize,
|
||||||
|
props: SchemaProps,
|
||||||
|
},
|
||||||
|
RemovedAttr {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn diff(old: &Schema, new: &Schema) -> Vec<Diff> {
|
||||||
|
use Diff::{AttrMove, AttrPropsChange, IdentChange, NewAttr, RemovedAttr};
|
||||||
|
|
||||||
|
let mut differences = Vec::new();
|
||||||
|
let old = old.to_builder();
|
||||||
|
let new = new.to_builder();
|
||||||
|
|
||||||
|
// check if the old identifier differs from the new one
|
||||||
|
if old.identifier != new.identifier {
|
||||||
|
let old = old.identifier;
|
||||||
|
let new = new.identifier;
|
||||||
|
differences.push(IdentChange { old, new });
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare all old attributes positions
|
||||||
|
// and properties with the new ones
|
||||||
|
for (pos, (name, props)) in old.attributes.iter().enumerate() {
|
||||||
|
match new.attributes.get_full(name) {
|
||||||
|
Some((npos, _, nprops)) => {
|
||||||
|
if pos != npos {
|
||||||
|
let name = name.clone();
|
||||||
|
differences.push(AttrMove {
|
||||||
|
name,
|
||||||
|
old: pos,
|
||||||
|
new: npos,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if props != nprops {
|
||||||
|
let name = name.clone();
|
||||||
|
differences.push(AttrPropsChange {
|
||||||
|
name,
|
||||||
|
old: *props,
|
||||||
|
new: *nprops,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => differences.push(RemovedAttr { name: name.clone() }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve all attributes that
|
||||||
|
// were not present in the old schema
|
||||||
|
for (pos, (name, props)) in new.attributes.iter().enumerate() {
|
||||||
|
if !old.attributes.contains_key(name) {
|
||||||
|
let name = name.clone();
|
||||||
|
differences.push(NewAttr {
|
||||||
|
name,
|
||||||
|
pos,
|
||||||
|
props: *props,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
differences
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn difference() {
|
||||||
|
use Diff::{AttrMove, AttrPropsChange, IdentChange, NewAttr, RemovedAttr};
|
||||||
|
|
||||||
|
let mut builder = SchemaBuilder::with_identifier("id");
|
||||||
|
builder.new_attribute("alpha", DISPLAYED);
|
||||||
|
builder.new_attribute("beta", DISPLAYED | INDEXED);
|
||||||
|
builder.new_attribute("gamma", INDEXED);
|
||||||
|
builder.new_attribute("omega", INDEXED);
|
||||||
|
let old = builder.build();
|
||||||
|
|
||||||
|
let mut builder = SchemaBuilder::with_identifier("kiki");
|
||||||
|
builder.new_attribute("beta", DISPLAYED | INDEXED);
|
||||||
|
builder.new_attribute("alpha", DISPLAYED | INDEXED);
|
||||||
|
builder.new_attribute("delta", RANKED);
|
||||||
|
builder.new_attribute("gamma", DISPLAYED);
|
||||||
|
let new = builder.build();
|
||||||
|
|
||||||
|
let differences = diff(&old, &new);
|
||||||
|
let expected = &[
|
||||||
|
IdentChange {
|
||||||
|
old: format!("id"),
|
||||||
|
new: format!("kiki"),
|
||||||
|
},
|
||||||
|
AttrMove {
|
||||||
|
name: format!("alpha"),
|
||||||
|
old: 0,
|
||||||
|
new: 1,
|
||||||
|
},
|
||||||
|
AttrPropsChange {
|
||||||
|
name: format!("alpha"),
|
||||||
|
old: DISPLAYED,
|
||||||
|
new: DISPLAYED | INDEXED,
|
||||||
|
},
|
||||||
|
AttrMove {
|
||||||
|
name: format!("beta"),
|
||||||
|
old: 1,
|
||||||
|
new: 0,
|
||||||
|
},
|
||||||
|
AttrMove {
|
||||||
|
name: format!("gamma"),
|
||||||
|
old: 2,
|
||||||
|
new: 3,
|
||||||
|
},
|
||||||
|
AttrPropsChange {
|
||||||
|
name: format!("gamma"),
|
||||||
|
old: INDEXED,
|
||||||
|
new: DISPLAYED,
|
||||||
|
},
|
||||||
|
RemovedAttr {
|
||||||
|
name: format!("omega"),
|
||||||
|
},
|
||||||
|
NewAttr {
|
||||||
|
name: format!("delta"),
|
||||||
|
pos: 2,
|
||||||
|
props: RANKED,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(&differences, expected)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_deserialize() -> bincode::Result<()> {
|
fn serialize_deserialize() -> bincode::Result<()> {
|
||||||
let mut builder = SchemaBuilder::with_identifier("id");
|
let mut builder = SchemaBuilder::with_identifier("id");
|
||||||
|
Loading…
Reference in New Issue
Block a user