#![cfg(feature = "std")]
use std::process::Command;
fn run(sql: &str) -> (String, bool) {
let out = Command::new(env!("CARGO_BIN_EXE_graphitesql"))
.arg(":memory:")
.arg(sql)
.output()
.expect("run graphitesql shell");
let mut s = String::from_utf8_lossy(&out.stdout).into_owned();
s.push_str(&String::from_utf8_lossy(&out.stderr));
(s, out.status.success())
}
#[test]
fn pragma_setter_persists_in_batch() {
let (out, ok) = run("PRAGMA foreign_keys=ON; PRAGMA foreign_keys");
assert!(ok, "batch should succeed: {out}");
assert_eq!(out.trim(), "1");
let (out, _) = run("PRAGMA foreign_keys = ON; PRAGMA foreign_keys");
assert_eq!(out.trim(), "1");
let (out, _) = run("PRAGMA user_version=42; PRAGMA user_version");
assert_eq!(out.trim(), "42");
}
#[test]
fn foreign_keys_enforced_through_the_shell() {
let (out, ok) = run("PRAGMA foreign_keys=ON; CREATE TABLE u(x PRIMARY KEY); \
CREATE TABLE t(a REFERENCES u(x)); INSERT INTO t VALUES(99)");
assert!(!ok, "orphan insert should fail with FKs on: {out}");
assert!(
out.contains("FOREIGN KEY constraint failed"),
"unexpected output: {out}"
);
}
#[test]
fn getter_pragmas_still_print_rows() {
let (out, _) = run("PRAGMA foreign_keys");
assert_eq!(out.trim(), "0");
let (out, _) = run("CREATE TABLE t(a INT, b TEXT); PRAGMA table_info(t)");
assert!(out.contains("a") && out.contains("b"), "got: {out}");
}
#[test]
fn arg_taking_query_pragmas_route_via_eq_form() {
let setup = "CREATE TABLE foo(a INT PRIMARY KEY, b TEXT REFERENCES bar(id)); \
CREATE TABLE bar(id INT PRIMARY KEY); CREATE INDEX ix ON foo(b); ";
for (eq, paren) in [
("PRAGMA table_info=foo", "PRAGMA table_info(foo)"),
("PRAGMA table_xinfo=foo", "PRAGMA table_xinfo(foo)"),
("PRAGMA index_list=foo", "PRAGMA index_list(foo)"),
("PRAGMA index_info=ix", "PRAGMA index_info(ix)"),
("PRAGMA index_xinfo=ix", "PRAGMA index_xinfo(ix)"),
(
"PRAGMA foreign_key_list=foo",
"PRAGMA foreign_key_list(foo)",
),
] {
let (a, _) = run(&format!("{setup}{eq}"));
let (b, _) = run(&format!("{setup}{paren}"));
assert_eq!(a, b, "`{eq}` should equal `{paren}`");
assert!(!a.trim().is_empty(), "`{eq}` should print rows, got empty");
}
if Command::new("sqlite3").arg("--version").output().is_ok() {
for tail in [
"PRAGMA table_info=foo",
"PRAGMA table_xinfo=foo",
"PRAGMA index_list=foo",
"PRAGMA index_info=ix",
"PRAGMA index_xinfo=ix",
"PRAGMA foreign_key_list=foo",
"PRAGMA foreign_key_check=foo",
] {
let sql = format!("{setup}{tail}");
let (g, _) = run(&sql);
let s = Command::new("sqlite3")
.arg(":memory:")
.arg(&sql)
.output()
.expect("run sqlite3");
let s = String::from_utf8_lossy(&s.stdout).into_owned();
assert_eq!(g.trim_end(), s.trim_end(), "mismatch for `{tail}`");
}
}
}
#[test]
fn trigger_bodies_and_returning() {
let (out, ok) = run(
"CREATE TABLE t(a); CREATE TABLE c(n); INSERT INTO c VALUES(0); \
CREATE TRIGGER tr AFTER INSERT ON t BEGIN UPDATE c SET n=n+1; END; \
INSERT INTO t VALUES(1),(2),(3); SELECT n FROM c",
);
assert!(ok, "trigger script should run: {out}");
assert_eq!(out.trim(), "3");
let (out, ok) =
run("BEGIN; CREATE TABLE t(x); INSERT INTO t VALUES(1); COMMIT; SELECT x FROM t");
assert!(ok, "transaction script should run: {out}");
assert_eq!(out.trim(), "1");
let (out, ok) = run("CREATE TABLE t(a INTEGER PRIMARY KEY, b); \
INSERT INTO t(b) VALUES('x') RETURNING a,b");
assert!(ok, "RETURNING should print rows: {out}");
assert_eq!(out.trim(), "1|x");
}
#[test]
fn explain_and_with_dml_route_correctly() {
let (out, ok) = run("CREATE TABLE t(a,b); CREATE INDEX i ON t(a); \
EXPLAIN QUERY PLAN SELECT * FROM t WHERE a=1");
assert!(ok, "EXPLAIN should succeed: {out}");
assert_eq!(out.trim(), "QUERY PLAN\n`--SEARCH t USING INDEX i (a=?)");
let (out, _) = run("CREATE TABLE t(a,b); EXPLAIN QUERY PLAN SELECT * FROM t");
assert_eq!(out.trim(), "QUERY PLAN\n`--SCAN t");
let (out, ok) = run(
"CREATE TABLE t(a); WITH s(v) AS (VALUES(1),(2),(3)) INSERT INTO t SELECT v FROM s; \
SELECT group_concat(a) FROM (SELECT a FROM t ORDER BY a)",
);
assert!(ok, "WITH+INSERT should succeed: {out}");
assert_eq!(out.trim(), "1,2,3");
}