#![cfg(feature = "std")]
use std::process::Command;
fn sqlite3_available() -> bool {
Command::new("sqlite3").arg("--version").output().is_ok()
}
fn rows(bin: &str, sql: &str) -> String {
let o = Command::new(bin).arg(":memory:").arg(sql).output().unwrap();
let mut v: Vec<String> = String::from_utf8_lossy(&o.stdout)
.lines()
.map(String::from)
.collect();
v.sort();
v.join("\n")
}
#[test]
fn cross_type_index_join_seek_matches_sqlite() {
if !sqlite3_available() {
eprintln!("sqlite3 CLI not found; skipping");
return;
}
let g = env!("CARGO_BIN_EXE_graphitesql");
let bug = "CREATE TABLE a(x0 INTEGER PRIMARY KEY, v0);\
CREATE TABLE b(x1 INTEGER, v1 REAL);CREATE INDEX i1 ON b(x1);\
CREATE TABLE c(x2, v2);CREATE INDEX i2 ON c(x2);\
INSERT INTO a VALUES('2',1),('4',5);\
INSERT INTO b VALUES('2',8),('2',2),(2,5),('3',2),('2',5);\
INSERT INTO c VALUES('1',6),('3',1),('2',6),('4',5),('2',3);";
let cases: &[&str] = &[
&format!("{bug}SELECT a.v0,b.v1,c.v2 FROM a JOIN b ON a.x0=b.x1 JOIN c ON a.x0=c.x2"),
"CREATE TABLE t(k INTEGER, v);CREATE TABLE u(k, w);CREATE INDEX iu ON u(k);\
INSERT INTO t VALUES(1,'a'),(2,'b'),(3,'c');\
INSERT INTO u VALUES('1','p'),('2','q'),('1','r'),('9','s');\
SELECT t.v,u.w FROM t JOIN u ON t.k=u.k",
"CREATE TABLE t(k INTEGER, v);CREATE TABLE u(k TEXT, w);CREATE INDEX iu ON u(k);\
INSERT INTO t VALUES(1,'a'),(2,'b');INSERT INTO u VALUES('1','p'),('2','q'),('1','r');\
SELECT t.v,u.w FROM t JOIN u ON t.k=u.k",
"CREATE TABLE a(x, v);CREATE INDEX ia ON a(x);CREATE TABLE d(y INTEGER, w);\
INSERT INTO a VALUES('1','p'),('2','q'),('1','r');INSERT INTO d VALUES(1,'m'),(2,'n');\
SELECT a.v,d.w FROM a JOIN d ON a.x=d.y",
"CREATE TABLE t(k);CREATE TABLE u(k INTEGER, w);CREATE INDEX iu ON u(k);\
INSERT INTO t VALUES(1),(2),(1);INSERT INTO u VALUES(1,'m'),(2,'n'),(1,'z');\
SELECT t.k,u.w FROM t JOIN u ON t.k=u.k",
"CREATE TABLE t(k TEXT);CREATE TABLE u(k TEXT, w);CREATE INDEX iu ON u(k);\
INSERT INTO t VALUES('x'),('y');INSERT INTO u VALUES('x','m'),('y','n'),('x','z');\
SELECT t.k,u.w FROM t JOIN u ON t.k=u.k",
"CREATE TABLE t(k);CREATE TABLE u(k, w);CREATE INDEX iu ON u(k);\
INSERT INTO t VALUES(1),('2');INSERT INTO u VALUES(1,'m'),('2','n');\
SELECT t.k,u.w FROM t JOIN u ON t.k=u.k",
];
for q in cases {
let sql = if q.trim_end().ends_with(';') {
q.to_string()
} else {
format!("{q};")
};
assert_eq!(rows("sqlite3", &sql), rows(g, &sql), "mismatch for `{q}`");
}
}