#![cfg(feature = "std")]
use std::process::Command;
fn sqlite3_available() -> bool {
Command::new("sqlite3").arg("--version").output().is_ok()
}
fn plan(bin: &str, base: &str, sql: &str) -> String {
let full = format!("{base} EXPLAIN QUERY PLAN {sql}");
let out = Command::new(bin)
.arg(":memory:")
.arg(&full)
.output()
.unwrap();
String::from_utf8_lossy(&out.stdout)
.lines()
.filter(|l| !l.trim().is_empty() && !l.starts_with("QUERY PLAN"))
.map(|l| l.trim_start_matches(|c: char| " |`*+_-".contains(c)))
.collect::<Vec<_>>()
.join("#")
}
const BASE: &str = "CREATE TABLE t(a INTEGER PRIMARY KEY, b, c);\
CREATE INDEX tb ON t(b);\
INSERT INTO t VALUES(1,10,100),(2,20,200),(3,30,300);\
CREATE TABLE u(x, y); CREATE INDEX ux ON u(x); INSERT INTO u VALUES(10,1),(30,3);\
CREATE TABLE w(p, q); INSERT INTO w VALUES(10,1),(20,2),(99,3);";
#[test]
fn for_in_operator_plan_matches_sqlite() {
if !sqlite3_available() {
eprintln!("sqlite3 CLI not found; skipping");
return;
}
let g = env!("CARGO_BIN_EXE_graphitesql");
for q in [
"SELECT * FROM w WHERE p IN (SELECT b FROM t)",
"SELECT * FROM w WHERE p NOT IN (SELECT b FROM t)",
"SELECT * FROM w WHERE p IN (SELECT b FROM t ORDER BY b)",
"SELECT * FROM w WHERE p IN (SELECT (b) FROM t)",
"SELECT * FROM w WHERE p IN (SELECT b AS bb FROM t)",
"SELECT * FROM w WHERE p IN (SELECT t.b FROM t)",
"SELECT * FROM w WHERE p IN (SELECT a FROM t)",
"SELECT * FROM w WHERE p IN (SELECT rowid FROM t)",
"SELECT * FROM w WHERE p NOT IN (SELECT a FROM t)",
"SELECT * FROM w WHERE p IN (SELECT c FROM t)", "SELECT * FROM w WHERE p IN (SELECT b FROM t WHERE c > 0)", "SELECT * FROM w WHERE p IN (SELECT b FROM t LIMIT 2)", "SELECT * FROM w WHERE p IN (SELECT DISTINCT b FROM t)", "SELECT * FROM w WHERE p IN (SELECT b + 1 FROM t)", "SELECT * FROM u WHERE x IN (SELECT b FROM t)",
"SELECT * FROM t WHERE b IN (SELECT x FROM u)",
] {
assert_eq!(plan("sqlite3", BASE, q), plan(g, BASE, q), "plan for {q}");
}
}
#[test]
fn for_in_operator_rows_match() {
if !sqlite3_available() {
eprintln!("sqlite3 CLI not found; skipping");
return;
}
let g = env!("CARGO_BIN_EXE_graphitesql");
for q in [
"SELECT p FROM w WHERE p IN (SELECT b FROM t) ORDER BY p",
"SELECT p FROM w WHERE p NOT IN (SELECT b FROM t) ORDER BY p",
"SELECT p FROM w WHERE p IN (SELECT a FROM t) ORDER BY p",
] {
let full = format!("{BASE} {q}");
let sq = Command::new("sqlite3")
.arg(":memory:")
.arg(&full)
.output()
.unwrap();
let gr = Command::new(g).arg(":memory:").arg(&full).output().unwrap();
assert_eq!(
String::from_utf8_lossy(&sq.stdout),
String::from_utf8_lossy(&gr.stdout),
"rows for {q}"
);
}
}