improve diff check

This commit is contained in:
Dull Bananas 2024-05-20 21:15:08 +00:00
parent 9a528fb38a
commit 5596cb79cb

View File

@ -22,7 +22,7 @@ pub fn get_dump(conn: &mut PgConnection) -> String {
.expect("pg_export_snapshot failed");
let snapshot_arg = format!("--snapshot={snapshot}");*/
let output = Command::new("pg_dump")
.args(["--schema-only"])
.args(["--schema-only", "--no-owner", "--no-privileges", "--no-comments", "--no-publications", "--no-security-labels", "--no-subscriptions", "--no-table-access-method", "--no-tablespaces"])
.env("DATABASE_URL", SETTINGS.get_database_url())
.stderr(Stdio::inherit())
.output()
@ -45,6 +45,8 @@ pub fn check_dump_diff(conn: &mut PgConnection, mut before: String, name: &str)
// Ignore timestamp differences by removing timestamps
for dump in [&mut before, &mut after] {
for index in 0.. {
let Some(byte)=dump.as_bytes().get(index) else{break};
if !byte.is_ascii_digit() {continue;}
// Check for this pattern: 0000-00-00 00:00:00
let Some((
&[a0, a1, a2, a3, b0, a4, a5, b1, a6, a7, b2, a8, a9, b3, a10, a11, b4, a12, a13],
@ -78,11 +80,13 @@ pub fn check_dump_diff(conn: &mut PgConnection, mut before: String, name: &str)
let [before_chunks, after_chunks] =
[&before, &after].map(|dump| chunks(dump).collect::<BTreeSet<_>>());
let only_b = before_chunks.difference(&after_chunks).copied().map(process_chunk).collect::<BTreeSet<_>>();
let only_a = after_chunks.difference(&before_chunks).copied().map(process_chunk).collect::<BTreeSet<_>>();
// todo dont collect only_in_before?
let [mut only_in_before, mut only_in_after] = [
before_chunks.difference(&after_chunks),
after_chunks.difference(&before_chunks),
only_b.difference(&only_a),
only_a.difference(&only_b),
]
.map(|chunks| {
chunks
@ -121,12 +125,15 @@ pub fn check_dump_diff(conn: &mut PgConnection, mut before: String, name: &str)
.iter()
.enumerate()
.max_by_key(|(_, (after_chunk, after_chunk_filtered))| {
if
after_chunk.split_once(|c:char|c.is_lowercase()).unwrap_or_default().0 !=
before_chunk.split_once(|c:char|c.is_lowercase()).unwrap_or_default().0 {0}else{
diff::chars(after_chunk_filtered, &before_chunk_filtered)
.into_iter()
.filter(|i| matches!(i, diff::Result::Both(c, _)
// `is_lowercase` increases accuracy for some trigger function diffs
if c.is_lowercase() || c.is_numeric()))
.count()
.count()}
})
.unwrap_or((0,&default));
@ -151,18 +158,8 @@ pub fn check_dump_diff(conn: &mut PgConnection, mut before: String, name: &str)
panic!("{output}");
}
// todo inline?
fn chunks<'a>(dump: &'a str) -> impl Iterator<Item = Cow<'a, str>> {
let mut remaining = dump;
std::iter::from_fn(move || {
remaining = remaining.trim_start();
while let Some(s) = remove_skipped_item_from_beginning(remaining) {
remaining = s.trim_start();
}
// `a` can't be empty because of trim_start
let (result, after_result) = remaining.split_once("\n\n")?;
remaining = after_result;
Some(if result.starts_with("CREATE TABLE ") {
fn process_chunk<'a>(result: &'a str) -> Cow<'a, str> {
if result.starts_with("CREATE TABLE ") {
// Allow column order to change
let mut lines = result
.lines()
@ -211,7 +208,20 @@ fn chunks<'a>(dump: &'a str) -> impl Iterator<Item = Cow<'a, str>> {
}else{Cow::Borrowed(result)}
} else {
Cow::Borrowed(result)
})
}
}
fn chunks(dump: &str) -> impl Iterator<Item = &str> {
let mut remaining = dump;
std::iter::from_fn(move || {
remaining = remaining.trim_start();
while let Some(s) = remove_skipped_item_from_beginning(remaining) {
remaining = s.trim_start();
}
// `a` can't be empty because of trim_start
let (result, after_result) = remaining.split_once("\n\n")?;
remaining = after_result;
Some(result)
})
}