#![cfg(feature = "std")]
use graphitesql::{Connection, Value};
use std::process::Command;
fn cell(c: &Connection, sql: &str) -> Result<Value, String> {
c.query(sql)
.map(|r| {
r.rows
.into_iter()
.next()
.map(|mut row| row.remove(0))
.unwrap()
})
.map_err(|e| {
let s = e.to_string();
s.strip_prefix("error: ").unwrap_or(&s).to_string()
})
}
#[test]
fn sum_result_type_follows_numeric_affinity() {
for &vdbe in &[true, false] {
let c = Connection::open_memory().unwrap();
c.set_use_vdbe(vdbe);
assert_eq!(
cell(&c, "SELECT sum(a) FROM (SELECT '1' a UNION ALL SELECT 10)"),
Ok(Value::Integer(11)),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) FROM (SELECT ' 10 ' a UNION ALL SELECT 5)"
),
Ok(Value::Integer(15)),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) FROM (SELECT '+5' a UNION ALL SELECT '-2')"
),
Ok(Value::Integer(3)),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) FROM (SELECT '1.0' a UNION ALL SELECT 10)"
),
Ok(Value::Real(11.0)),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) FROM (SELECT '1e2' a UNION ALL SELECT 10)"
),
Ok(Value::Real(110.0)),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) FROM (SELECT 'abc' a UNION ALL SELECT 10)"
),
Ok(Value::Real(10.0)),
"vdbe={vdbe}"
);
assert!(
matches!(
cell(
&c,
"SELECT sum(a) FROM (SELECT '9999999999999999999' a UNION ALL SELECT 1)"
),
Ok(Value::Real(_))
),
"vdbe={vdbe}"
);
assert_eq!(
cell(&c, "SELECT sum(a) FROM (SELECT 1.0 a UNION ALL SELECT 2)"),
Ok(Value::Real(3.0)),
"vdbe={vdbe}"
);
assert_eq!(
cell(&c, "SELECT sum(a) FROM (SELECT 1 a UNION ALL SELECT 2)"),
Ok(Value::Integer(3)),
"vdbe={vdbe}"
);
assert_eq!(
cell(&c, "SELECT sum(a) FROM (SELECT 1 a WHERE 0)"),
Ok(Value::Null),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT typeof(sum(a) OVER ()) FROM (SELECT '1' a UNION ALL SELECT 10)"
),
Ok(Value::Text("integer".into())),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) FROM (SELECT 9223372036854775807 a UNION ALL SELECT 1)"
),
Err("integer overflow".into()),
"vdbe={vdbe}"
);
assert_eq!(
cell(
&c,
"SELECT sum(a) OVER () FROM (SELECT 9223372036854775807 a UNION ALL SELECT 1)"
),
Err("integer overflow".into()),
"vdbe={vdbe}"
);
}
}
#[test]
fn matches_sqlite_cli() {
if Command::new("sqlite3").arg("--version").output().is_err() {
eprintln!("sqlite3 CLI not found; skipping");
return;
}
let run = |bin: &str, sql: &str| -> String {
let out = Command::new(bin).arg(":memory:").arg(sql).output().unwrap();
let s = String::from_utf8_lossy(&out.stdout);
let e = String::from_utf8_lossy(&out.stderr);
let et = e.trim();
if !et.is_empty() {
return et
.lines()
.next()
.unwrap_or("")
.trim_start_matches("Error: in prepare, ")
.trim_start_matches("Error: ")
.trim_start_matches("error: ")
.trim_start_matches("stepping, ")
.to_string();
}
s.lines().collect::<Vec<_>>().join("|")
};
let g = env!("CARGO_BIN_EXE_graphitesql");
for sql in [
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '1' a UNION ALL SELECT 10);",
"SELECT a, sum(a) OVER (ORDER BY a) FROM (SELECT '1' a UNION ALL SELECT 10);",
"SELECT typeof(sum(a) OVER ()) FROM (SELECT '1' a UNION ALL SELECT 10);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '1.5' a UNION ALL SELECT 10);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '1.0' a UNION ALL SELECT 10);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '1e2' a UNION ALL SELECT 10);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT 'abc' a UNION ALL SELECT 10);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '1abc' a UNION ALL SELECT 10);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT ' 10 ' a UNION ALL SELECT 5);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '+5' a UNION ALL SELECT 5);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT '-5' a UNION ALL SELECT 5);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT 1 a UNION ALL SELECT 2);",
"SELECT sum(a), typeof(sum(a)) FROM (SELECT 1.0 a UNION ALL SELECT 2);",
"SELECT sum(a) FROM (SELECT 1 a WHERE 0);",
"SELECT sum(a) FROM (SELECT 9223372036854775807 a UNION ALL SELECT 1);",
"SELECT sum(a) FROM (SELECT 9223372036854775807 a UNION ALL SELECT 1.0);",
"SELECT sum(a) OVER () FROM (SELECT 9223372036854775807 a UNION ALL SELECT 1);",
"SELECT a, sum(a) OVER (ORDER BY a) FROM (SELECT '9999999999999999999' a UNION ALL SELECT 1);",
] {
assert_eq!(run("sqlite3", sql), run(g, sql), "for {sql}");
}
}