use std::time::Instant;
use spg_engine::Engine;
const N_BIG: usize = 40;
const N_FACT: usize = 3;
fn setup_engine(with_stats: bool) -> Engine {
let mut e = Engine::new();
e.execute("CREATE TABLE fact (id INT NOT NULL, k1 INT NOT NULL, k2 INT NOT NULL, k3 INT NOT NULL, k4 INT NOT NULL)").unwrap();
for tag in ["big1", "big2", "big3", "big4"] {
e.execute(&format!("CREATE TABLE {tag} (k INT NOT NULL)"))
.unwrap();
}
for i in 0..N_FACT {
e.execute(&format!(
"INSERT INTO fact VALUES ({i}, {i}, {i}, {i}, {i})"
))
.unwrap();
}
for tag in ["big1", "big2", "big3", "big4"] {
for i in 0..N_BIG {
e.execute(&format!("INSERT INTO {tag} VALUES ({i})"))
.unwrap();
}
}
if with_stats {
e.execute("ANALYZE").unwrap();
}
e
}
fn five_table_join_sql() -> &'static str {
"SELECT fact.id FROM big1 \
INNER JOIN big2 ON 1 = 1 \
INNER JOIN big3 ON 1 = 1 \
INNER JOIN big4 ON 1 = 1 \
INNER JOIN fact \
ON fact.k1 = big1.k \
AND fact.k2 = big2.k \
AND fact.k3 = big3.k \
AND fact.k4 = big4.k"
}
#[test]
fn five_table_join_speedup_vs_source_order() {
let _lock = crate::perf_lock();
let mut eng_with_stats = setup_engine(true);
let mut eng_no_stats = setup_engine(false);
let sql = five_table_join_sql();
let _ = eng_with_stats.execute(sql).expect("warmup reordered");
let _ = eng_no_stats.execute(sql).expect("warmup baseline");
let t0 = Instant::now();
let r = eng_with_stats.execute(sql).expect("reordered SELECT");
let reordered_ns = t0.elapsed().as_nanos();
std::hint::black_box(r);
let t0 = Instant::now();
let r = eng_no_stats.execute(sql).expect("baseline SELECT");
let baseline_ns = t0.elapsed().as_nanos();
std::hint::black_box(r);
let speedup = baseline_ns as f64 / reordered_ns.max(1) as f64;
eprintln!(
"five_table_join: baseline={baseline_ns} ns, reordered={reordered_ns} ns, speedup={speedup:.1}×"
);
assert!(
speedup >= 10.0,
"v6.2.3 ship-gate: 5-table JOIN reorder speedup must be ≥ 10×; got {speedup:.1}×"
);
}