use spg_engine::{Engine, QueryResult};
fn text_of(e: &mut Engine, sql: &str) -> String {
match e.execute(sql).unwrap() {
QueryResult::Rows { rows, .. } => spg_engine::eval::value_to_text(&rows[0].values[0]),
other => panic!("{sql}: {other:?}"),
}
}
fn col_of(e: &mut Engine, sql: &str) -> Vec<String> {
match e.execute(sql).unwrap() {
QueryResult::Rows { rows, .. } => rows
.iter()
.map(|r| spg_engine::eval::value_to_text(&r.values[0]))
.collect(),
other => panic!("{sql}: {other:?}"),
}
}
fn setup(e: &mut Engine) {
e.execute("CREATE TYPE mood AS ENUM ('sad','ok','happy')")
.unwrap();
e.execute("ALTER TYPE mood ADD VALUE 'meh' BEFORE 'ok'")
.unwrap();
e.execute("CREATE TABLE em (id INT, m mood)").unwrap();
e.execute("INSERT INTO em VALUES (1,'happy'),(2,'sad'),(3,'meh'),(4,'ok'),(5,NULL),(6,'meh')")
.unwrap();
}
#[test]
fn comparisons_use_member_order() {
let mut e = Engine::new();
setup(&mut e);
assert_eq!(
col_of(
&mut e,
"SELECT ('sad'::mood < 'meh'::mood) OR false" ),
vec!["true"]
);
assert_eq!(text_of(&mut e, "SELECT 'happy'::mood > 'ok'::mood"), "true");
assert_eq!(text_of(&mut e, "SELECT 'sad'::mood < 'meh'"), "true");
assert_eq!(
col_of(&mut e, "SELECT m FROM em WHERE m > 'meh' ORDER BY m"),
vec!["ok", "happy"]
);
assert_eq!(
col_of(
&mut e,
"SELECT m FROM em WHERE m BETWEEN 'sad' AND 'ok' ORDER BY m, id"
),
vec!["sad", "meh", "meh", "ok"]
);
}
#[test]
fn min_max_and_greatest_least() {
let mut e = Engine::new();
setup(&mut e);
assert_eq!(col_of(&mut e, "SELECT min(m) FROM em"), vec!["sad"]);
assert_eq!(col_of(&mut e, "SELECT max(m) FROM em"), vec!["happy"]);
assert_eq!(
text_of(&mut e, "SELECT min(m) FROM em WHERE m > 'sad'"),
"meh"
);
assert_eq!(
text_of(&mut e, "SELECT greatest('sad'::mood, 'meh'::mood)"),
"meh"
);
assert_eq!(
text_of(&mut e, "SELECT least('ok'::mood, 'happy'::mood)"),
"ok"
);
assert_eq!(
text_of(&mut e, "SELECT greatest(m, 'meh') FROM em WHERE id = 2"),
"meh"
);
}
#[test]
fn ordered_collection_and_grouped_output() {
let mut e = Engine::new();
setup(&mut e);
assert_eq!(
text_of(
&mut e,
"SELECT array_agg(m ORDER BY m) FROM em WHERE m IS NOT NULL"
),
"{sad,meh,meh,ok,happy}"
);
assert_eq!(
text_of(
&mut e,
"SELECT array_agg(m ORDER BY m DESC) FROM em WHERE m IS NOT NULL"
),
"{happy,ok,meh,meh,sad}"
);
assert_eq!(
col_of(
&mut e,
"SELECT m FROM em WHERE m IS NOT NULL GROUP BY m ORDER BY m"
),
vec!["sad", "meh", "ok", "happy"]
);
assert_eq!(
col_of(
&mut e,
"SELECT m FROM em GROUP BY m HAVING m > 'meh' ORDER BY m"
),
vec!["ok", "happy"]
);
}
#[test]
fn index_backed_scans_stay_member_ordered() {
let mut e = Engine::new();
setup(&mut e);
e.execute("CREATE INDEX em_m ON em (m)").unwrap();
assert_eq!(
col_of(&mut e, "SELECT m FROM em WHERE m > 'meh' ORDER BY m"),
vec!["ok", "happy"]
);
assert_eq!(
col_of(
&mut e,
"SELECT m FROM em WHERE m >= 'meh' AND m <= 'ok' ORDER BY m, id"
),
vec!["meh", "meh", "ok"]
);
assert_eq!(
text_of(
&mut e,
"SELECT count(*) FROM em WHERE m >= 'meh' AND m <= 'ok'"
),
"3"
);
assert_eq!(
col_of(&mut e, "SELECT id FROM em WHERE m = 'meh' ORDER BY id"),
vec!["3", "6"]
);
}