style: apply rustfmt, fix clippy warnings, and minor code cleanup

Reformat Rust code with rustfmt, suppress clippy::too_many_arguments
for Tauri IPC commands, derive Default for AppSettings, fix unused
variable pattern in TableDataView, and add unit tests for utils.
This commit is contained in:
2026-04-06 13:12:52 +03:00
parent 1e002d801a
commit 6b925d6260
11 changed files with 186 additions and 53 deletions

View File

@@ -34,7 +34,11 @@ pub fn topological_sort_tables(
continue;
}
if graph.entry(parent.clone()).or_default().insert(child.clone()) {
if graph
.entry(parent.clone())
.or_default()
.insert(child.clone())
{
*in_degree.entry(child).or_insert(0) += 1;
}
}
@@ -73,3 +77,136 @@ pub fn topological_sort_tables(
result
}
#[cfg(test)]
mod tests {
use super::*;
// ── escape_ident ──────────────────────────────────────────
#[test]
fn escape_ident_simple_name() {
assert_eq!(escape_ident("users"), "\"users\"");
}
#[test]
fn escape_ident_with_double_quotes() {
assert_eq!(escape_ident(r#"my"table"#), r#""my""table""#);
}
#[test]
fn escape_ident_empty_string() {
assert_eq!(escape_ident(""), r#""""#);
}
#[test]
fn escape_ident_with_spaces() {
assert_eq!(escape_ident("my table"), "\"my table\"");
}
#[test]
fn escape_ident_with_semicolon() {
assert_eq!(escape_ident("users; DROP TABLE"), "\"users; DROP TABLE\"");
}
#[test]
fn escape_ident_with_single_quotes() {
assert_eq!(escape_ident("it's"), "\"it's\"");
}
#[test]
fn escape_ident_with_backslash() {
assert_eq!(escape_ident(r"back\slash"), r#""back\slash""#);
}
#[test]
fn escape_ident_unicode() {
assert_eq!(escape_ident("таблица"), "\"таблица\"");
}
#[test]
fn escape_ident_multiple_double_quotes() {
assert_eq!(escape_ident(r#"a""b"#), r#""a""""b""#);
}
#[test]
fn escape_ident_reserved_word() {
assert_eq!(escape_ident("select"), "\"select\"");
}
#[test]
fn escape_ident_null_byte() {
assert_eq!(escape_ident("a\0b"), "\"a\0b\"");
}
#[test]
fn escape_ident_newline() {
assert_eq!(escape_ident("a\nb"), "\"a\nb\"");
}
// ── topological_sort_tables ───────────────────────────────
#[test]
fn topo_sort_no_edges() {
let tables = vec![("public".into(), "b".into()), ("public".into(), "a".into())];
let result = topological_sort_tables(&[], &tables);
assert_eq!(result.len(), 2);
assert!(result.contains(&("public".into(), "a".into())));
assert!(result.contains(&("public".into(), "b".into())));
}
#[test]
fn topo_sort_simple_dependency() {
let edges = vec![(
"public".into(),
"orders".into(),
"public".into(),
"users".into(),
)];
let tables = vec![
("public".into(), "orders".into()),
("public".into(), "users".into()),
];
let result = topological_sort_tables(&edges, &tables);
let user_pos = result.iter().position(|t| t.1 == "users").unwrap();
let order_pos = result.iter().position(|t| t.1 == "orders").unwrap();
assert!(user_pos < order_pos, "users must come before orders");
}
#[test]
fn topo_sort_self_reference() {
let edges = vec![(
"public".into(),
"employees".into(),
"public".into(),
"employees".into(),
)];
let tables = vec![("public".into(), "employees".into())];
let result = topological_sort_tables(&edges, &tables);
assert_eq!(result.len(), 1);
}
#[test]
fn topo_sort_cycle() {
let edges = vec![
("public".into(), "a".into(), "public".into(), "b".into()),
("public".into(), "b".into(), "public".into(), "a".into()),
];
let tables = vec![("public".into(), "a".into()), ("public".into(), "b".into())];
let result = topological_sort_tables(&edges, &tables);
assert_eq!(result.len(), 2);
}
#[test]
fn topo_sort_edge_outside_target_set_ignored() {
let edges = vec![(
"public".into(),
"orders".into(),
"public".into(),
"external".into(),
)];
let tables = vec![("public".into(), "orders".into())];
let result = topological_sort_tables(&edges, &tables);
assert_eq!(result.len(), 1);
}
}