#![cfg(feature = "std")]
use graphitesql::Connection;
fn run(frame: &str) -> Result<(), String> {
let mut c = Connection::open_memory().unwrap();
c.execute("CREATE TABLE t(a)").unwrap();
c.query(&format!("SELECT count(*) OVER (ORDER BY a {frame}) FROM t"))
.map(|_| ())
.map_err(|e| {
e.to_string()
.trim_start_matches("error: ")
.trim_start_matches("SQL error: ")
.to_string()
})
}
fn ok(frame: &str) {
run(frame).unwrap_or_else(|e| panic!("expected {frame:?} to parse, got: {e}"));
}
fn err(frame: &str, msg: &str) {
assert_eq!(run(frame).unwrap_err(), msg, "{frame:?}");
}
const UNSUPPORTED: &str = "unsupported frame specification";
#[test]
fn start_after_end_is_unsupported() {
err("ROWS BETWEEN CURRENT ROW AND 1 PRECEDING", UNSUPPORTED);
err("ROWS BETWEEN 1 FOLLOWING AND 1 PRECEDING", UNSUPPORTED);
err("ROWS BETWEEN 1 FOLLOWING AND CURRENT ROW", UNSUPPORTED);
err("RANGE BETWEEN 1 FOLLOWING AND 1 PRECEDING", UNSUPPORTED);
err("GROUPS BETWEEN 1 FOLLOWING AND CURRENT ROW", UNSUPPORTED);
}
#[test]
fn unbounded_following_start_is_a_syntax_error() {
err(
"ROWS BETWEEN UNBOUNDED FOLLOWING AND UNBOUNDED FOLLOWING",
"near \"FOLLOWING\": syntax error",
);
err(
"ROWS BETWEEN UNBOUNDED FOLLOWING AND 1 PRECEDING",
"near \"FOLLOWING\": syntax error",
);
err(
"ROWS UNBOUNDED FOLLOWING",
"near \"FOLLOWING\": syntax error",
);
}
#[test]
fn unbounded_preceding_end_is_a_syntax_error() {
err(
"ROWS BETWEEN CURRENT ROW AND UNBOUNDED PRECEDING",
"near \"PRECEDING\": syntax error",
);
err(
"ROWS BETWEEN 1 PRECEDING AND UNBOUNDED PRECEDING",
"near \"PRECEDING\": syntax error",
);
}
#[test]
fn valid_frames_still_parse() {
ok("ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING");
ok("ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW");
ok("ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING");
ok("ROWS BETWEEN CURRENT ROW AND CURRENT ROW");
ok("ROWS UNBOUNDED PRECEDING");
ok("ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING");
ok("ROWS BETWEEN 2 FOLLOWING AND 1 FOLLOWING");
}