use spg_engine::{Engine, QueryResult};
fn nrows(r: &QueryResult) -> usize {
match r {
QueryResult::Rows { rows, .. } => rows.len(),
_ => panic!("not a row set"),
}
}
fn run(e: &mut Engine, sql: &str) {
e.execute(sql)
.unwrap_or_else(|err| panic!("{sql}: {err:?}"));
}
fn arm(rows: usize, with_index: bool) -> (f64, usize) {
let mut e = Engine::new();
run(&mut e, "CREATE TABLE t (k INT, s TEXT)");
for i in 0..rows {
run(&mut e, &format!("INSERT INTO t VALUES ({i}, 'X{i}')"));
}
if with_index {
run(&mut e, "CREATE INDEX t_lower ON t (lower(s))");
}
let q = "SELECT k FROM t WHERE lower(s) = 'x42'";
let n = nrows(&e.execute(q).unwrap());
let t = std::time::Instant::now();
for _ in 0..20 {
e.execute(q).unwrap();
}
(t.elapsed().as_secs_f64() * 1e3 / 20.0, n)
}
fn main() {
for rows in [10_000usize, 100_000] {
let (with, nw) = arm(rows, true);
let (without, nn) = arm(rows, false);
println!(
"rows={rows:<7} with index {with:7.3} ms ({nw} row) without {without:7.3} ms ({nn} row) ratio {:.2}x",
with / without
);
assert_eq!(nw, nn, "the index changed the ANSWER");
}
let mut e = Engine::new();
run(&mut e, "CREATE TABLE u (k INT, s TEXT)");
run(&mut e, "INSERT INTO u VALUES (1, 'Alpha')");
run(&mut e, "CREATE INDEX u_lower ON u (lower(s))");
run(&mut e, "INSERT INTO u VALUES (2, 'ALPHA'), (3, 'beta')");
let q = "SELECT k FROM u WHERE lower(s) = 'alpha' ORDER BY k";
println!(
"after INSERT -> {} rows (want 2)",
nrows(&e.execute(q).unwrap())
);
run(&mut e, "UPDATE u SET s = 'ALPHA' WHERE k = 3");
println!(
"after UPDATE -> {} rows (want 3)",
nrows(&e.execute(q).unwrap())
);
run(&mut e, "DELETE FROM u WHERE k = 1");
println!(
"after DELETE -> {} rows (want 2)",
nrows(&e.execute(q).unwrap())
);
for rows in [10_000usize, 100_000] {
let mut e = Engine::new();
run(&mut e, "CREATE TABLE w (k INT, s TEXT)");
for i in 0..rows {
run(&mut e, &format!("INSERT INTO w VALUES ({i}, 'X{i}')"));
}
run(&mut e, "CREATE INDEX w_lower ON w (lower(s))");
run(&mut e, "UPDATE w SET s = 'zz' WHERE k = 0");
run(&mut e, "DELETE FROM w WHERE k = 1");
let q = "SELECT k FROM w WHERE lower(s) = 'x42'";
let t = std::time::Instant::now();
for _ in 0..20 {
e.execute(q).unwrap();
}
println!(
"rows={rows:<7} after UPDATE+DELETE, seek {:.3} ms ({} row)",
t.elapsed().as_secs_f64() * 1e3 / 20.0,
nrows(&e.execute(q).unwrap())
);
}
}