use spg_engine::{Engine, QueryResult};
fn col1(e: &mut Engine, sql: &str) -> Vec<i64> {
let r = e
.execute(sql)
.unwrap_or_else(|err| panic!("{sql}: {err:?}"));
let QueryResult::Rows { rows, .. } = r else {
panic!("expected Rows");
};
rows.iter()
.map(|row| match row.values[row.values.len() - 1] {
spg_storage::Value::Int(n) => i64::from(n),
spg_storage::Value::BigInt(n) => n,
spg_storage::Value::Float(f) => f as i64,
spg_storage::Value::Null => -1,
ref other => panic!("unexpected {other:?}"),
})
.collect()
}
fn setup() -> Engine {
let mut e = Engine::new();
e.execute("CREATE TABLE fx (id INT, v INT)").unwrap();
e.execute("INSERT INTO fx VALUES (1,10),(2,20),(3,30)")
.unwrap();
e
}
#[test]
fn exclude_current_row() {
let mut e = setup();
let got = col1(
&mut e,
"SELECT id, sum(v) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING \
AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW) FROM fx ORDER BY id",
);
assert_eq!(got, vec![50, 40, 30]);
}
#[test]
fn exclude_no_others_is_default() {
let mut e = setup();
let got = col1(
&mut e,
"SELECT id, sum(v) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING \
AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS) FROM fx ORDER BY id",
);
assert_eq!(got, vec![60, 60, 60]);
}
#[test]
fn exclude_current_row_count() {
let mut e = setup();
let got = col1(
&mut e,
"SELECT id, count(*) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING \
AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW) FROM fx ORDER BY id",
);
assert_eq!(got, vec![2, 2, 2]);
let out = match e
.execute(
"SELECT sum(v) OVER (ORDER BY id ROWS UNBOUNDED PRECEDING EXCLUDE GROUP) \
FROM fx ORDER BY id",
)
.unwrap()
{
spg_engine::QueryResult::Rows { rows, .. } => rows
.iter()
.map(|r| match &r.values[0] {
spg_storage::Value::Null => "NULL".to_string(),
v => spg_engine::eval::value_to_text(v),
})
.collect::<Vec<_>>(),
other => panic!("{other:?}"),
};
assert_eq!(out, vec!["NULL", "10", "30"]);
}