crates/knut-rel2graph-bench/src/bin/export.rs
//! **rel2graph → networkx export bin (N3).** Runs the real bifröst rel2graph
//! fabric over the seeded 12-table ERP schema at a chosen scale, then writes the
//! resulting graph as a stable node-list + edge-list + correctness oracle that
//! `demo/rel2graph_networkx_demo.py` loads into a `networkx.MultiDiGraph`.
//!
//! ```text
//! cargo run -p knut-rel2graph-bench --release --bin rel2graph-export -- [SCALE] [OUT_DIR]
//! cargo run -p knut-rel2graph-bench --release --bin rel2graph-export -- [SCALE] [OUT_DIR] --parquet
//! ```
//! Defaults: `SCALE=1`, `OUT_DIR=target/rel2graph-export`. Deterministic —
//! `DEFAULT_SEED` — so the demo's assertions are reproducible run to run.
//!
//! With `--parquet` it ALSO writes the source tables as `<table>.parquet` under
//! `OUT_DIR` — the on-disk export that `knut-flight-server --parquet <OUT_DIR>`
//! then serves through its live-data seam (read parquet → same rel2graph engine →
//! Arrow Flight), so the networkx file path and the live Flight path run over the
//! identical bytes on disk.
use std::path::PathBuf;
use knut_rel2graph_bench::{
DEFAULT_SEED, build_mutation, export_networkx, generate, mapping_spec, summarize,
write_source_parquet,
};
fn main() -> std::io::Result<()> {
let mut positional = Vec::new();
let mut emit_parquet = false;
for arg in std::env::args().skip(1) {
match arg.as_str() {
"--parquet" => emit_parquet = true,
_ => positional.push(arg),
}
}
let mut args = positional.into_iter();
let scale: usize = args
.next()
.map(|s| s.parse().expect("SCALE must be a positive integer"))
.unwrap_or(1);
let out_dir = PathBuf::from(
args.next()
.unwrap_or_else(|| "target/rel2graph-export".to_string()),
);
let spec = mapping_spec();
let db = generate(scale, DEFAULT_SEED);
let mutation = build_mutation(&spec, &db);
let summary = summarize(&mutation);
let manifest = export_networkx(&mutation, &summary, &out_dir)?;
if emit_parquet {
let paths = write_source_parquet(&db, &out_dir)?;
println!(
"parquet: {} source table(s) -> {} (serve with `knut-flight-server --parquet {}`)",
paths.len(),
out_dir.display(),
out_dir.display(),
);
}
println!(
"rel2graph-export — 12-table ERP, scale {scale}x, seed {DEFAULT_SEED:#x}\n\
nodes : {:>7} -> {}\n\
edges : {:>7} -> {}\n\
oracle: -> {}\n\
totals: {} nodes, {} edges, {} dangling, {} null-endpoint rows",
manifest.nodes_written,
manifest.nodes_path,
manifest.edges_written,
manifest.edges_path,
manifest.oracle_path,
summary.total_nodes(),
summary.total_edges(),
summary.dangling,
summary.null_endpoint_rows,
);
Ok(())
}