#![cfg(feature = "std")]
use graphitesql::{Connection, Value};
use std::process::Command;
fn sqlite3(setup: &[&str], query: &str) -> String {
let mut script = String::new();
for s in setup {
script.push_str(s);
script.push_str(";\n");
}
script.push_str(query);
script.push(';');
let o = Command::new("sqlite3")
.arg(":memory:")
.arg(&script)
.output()
.unwrap();
String::from_utf8_lossy(&o.stdout).trim_end().to_string()
}
fn render(result: &graphitesql::QueryResult) -> String {
result
.rows
.iter()
.map(|row| {
row.iter()
.map(|v| match v {
Value::Null => String::new(),
Value::Integer(i) => i.to_string(),
Value::Text(s) => String::from(s.as_str()),
Value::Real(r) => graphitesql::exec::eval::format_real(*r),
Value::Blob(b) => b.iter().map(|x| format!("{x:02x}")).collect(),
})
.collect::<Vec<_>>()
.join("|")
})
.collect::<Vec<_>>()
.join("\n")
}
#[test]
fn without_rowid_live_scan_matches_sqlite3() {
if Command::new("sqlite3").arg("--version").output().is_err() {
eprintln!("sqlite3 not found; skipping");
return;
}
let setup = [
"CREATE TABLE wr(k TEXT PRIMARY KEY, v INTEGER, g INTEGER GENERATED ALWAYS AS (v*2)) WITHOUT ROWID",
"INSERT INTO wr(k,v) VALUES('banana',3),('apple',1),('cherry',2),('date',2)",
];
let mut g = Connection::open_memory().unwrap();
for s in &setup {
g.execute(s).unwrap();
}
let queries = [
"SELECT k, v, g FROM wr", "SELECT v, k FROM wr WHERE v >= 2", "SELECT k FROM wr ORDER BY v DESC, k", "SELECT k FROM wr LIMIT 2 OFFSET 1", "SELECT count(*), sum(v), min(k), max(k) FROM wr", "SELECT DISTINCT v FROM wr ORDER BY 1", "SELECT k || ':' || g FROM wr", "SELECT k, (SELECT count(*) FROM wr b WHERE b.v < wr.v) FROM wr",
"SELECT k FROM wr WHERE v = (SELECT max(v) FROM wr)",
];
for q in queries {
let want = sqlite3(&setup, q);
let got = render(&g.query(q).unwrap());
assert_eq!(got, want, "WITHOUT ROWID scan diverged: {q}");
}
}