use spg_engine::{Engine, QueryResult};
fn ok(e: &mut Engine, sql: &str) {
e.execute(sql)
.unwrap_or_else(|err| panic!("{sql}: {err:?}"));
}
fn err(e: &mut Engine, sql: &str) {
assert!(e.execute(sql).is_err(), "{sql} should have been rejected");
}
fn count(e: &mut Engine, sql: &str) -> usize {
match e.execute(sql).unwrap() {
QueryResult::Rows { rows, .. } => rows.len(),
_ => panic!("expected rows"),
}
}
#[test]
fn update_to_duplicate_unique_constraint_is_rejected() {
let mut e = Engine::new();
ok(&mut e, "CREATE TABLE u(x int UNIQUE)");
ok(&mut e, "INSERT INTO u VALUES(1),(2)");
err(&mut e, "UPDATE u SET x=1 WHERE x=2");
assert_eq!(count(&mut e, "SELECT * FROM u WHERE x=2"), 1);
}
#[test]
fn update_to_duplicate_plain_unique_index_is_rejected() {
let mut e = Engine::new();
ok(&mut e, "CREATE TABLE u(x int)");
ok(&mut e, "CREATE UNIQUE INDEX ux ON u(x)");
ok(&mut e, "INSERT INTO u VALUES(1),(2)");
err(&mut e, "UPDATE u SET x=1 WHERE x=2");
}
#[test]
fn update_to_duplicate_expression_unique_index_is_rejected() {
let mut e = Engine::new();
ok(&mut e, "CREATE TABLE u(email text, note text)");
ok(&mut e, "CREATE UNIQUE INDEX u_le ON u(lower(email))");
ok(
&mut e,
"INSERT INTO u VALUES('A@x.com','a'),('b@y.com','b')",
);
err(&mut e, "UPDATE u SET email='A@X.COM' WHERE email='b@y.com'");
ok(&mut e, "UPDATE u SET email='c@z.com' WHERE email='b@y.com'");
ok(&mut e, "UPDATE u SET note='z' WHERE email='A@x.com'");
}
#[test]
fn update_no_op_and_free_reassign_pass() {
let mut e = Engine::new();
ok(&mut e, "CREATE TABLE u(x int)");
ok(&mut e, "CREATE UNIQUE INDEX ux ON u(x)");
ok(&mut e, "INSERT INTO u VALUES(1),(2),(3)");
ok(&mut e, "UPDATE u SET x=x"); ok(&mut e, "UPDATE u SET x=x+10"); assert_eq!(count(&mut e, "SELECT * FROM u"), 3);
}
#[test]
fn update_swap_and_shift_are_rejected_like_pg() {
let mut e = Engine::new();
ok(&mut e, "CREATE TABLE u(x int)");
ok(&mut e, "CREATE UNIQUE INDEX ux ON u(x)");
ok(&mut e, "INSERT INTO u VALUES(1),(2),(3)");
err(
&mut e,
"UPDATE u SET x=CASE WHEN x=1 THEN 2 WHEN x=2 THEN 1 ELSE x END",
);
err(&mut e, "UPDATE u SET x=x+1");
}
#[test]
fn update_unique_column_to_null_allows_multiple() {
let mut e = Engine::new();
ok(&mut e, "CREATE TABLE u(x int UNIQUE)");
ok(&mut e, "INSERT INTO u VALUES(1),(2)");
ok(&mut e, "UPDATE u SET x=NULL WHERE x=1");
ok(&mut e, "UPDATE u SET x=NULL WHERE x=2");
assert_eq!(count(&mut e, "SELECT * FROM u WHERE x IS NULL"), 2);
}