#![cfg(feature = "std")]
use graphitesql::{Connection, Value};
fn setup() -> Connection {
let mut c = Connection::open_memory().unwrap();
c.execute("CREATE TABLE t(id INTEGER PRIMARY KEY, kind TEXT, amount INT)")
.unwrap();
c.execute(
"INSERT INTO t(kind, amount) VALUES \
('a', 10), ('b', 20), ('a', 30), ('b', 40), ('a', 50)",
)
.unwrap();
c
}
#[test]
fn query_view_with_filter() {
let mut c = setup();
c.execute("CREATE VIEW a_only AS SELECT id, amount FROM t WHERE kind = 'a'")
.unwrap();
let r = c
.query("SELECT amount FROM a_only ORDER BY amount")
.unwrap();
let amounts: Vec<i64> = r
.rows
.iter()
.map(|row| match row[0] {
Value::Integer(v) => v,
_ => panic!(),
})
.collect();
assert_eq!(amounts, vec![10, 30, 50]);
let r = c
.query("SELECT count(*), sum(amount) FROM a_only WHERE amount > 10")
.unwrap();
assert_eq!(r.rows[0][0], Value::Integer(2));
assert_eq!(r.rows[0][1], Value::Integer(80));
}
#[test]
fn view_with_explicit_columns_and_drop() {
let mut c = setup();
c.execute("CREATE VIEW totals(k, total) AS SELECT kind, sum(amount) FROM t GROUP BY kind")
.unwrap();
let r = c.query("SELECT k, total FROM totals ORDER BY k").unwrap();
assert_eq!(r.columns, vec!["k", "total"]);
assert_eq!(r.rows[0][0], Value::Text("a".into()));
assert_eq!(r.rows[0][1], Value::Integer(90)); assert_eq!(r.rows[1][0], Value::Text("b".into()));
assert_eq!(r.rows[1][1], Value::Integer(60));
c.execute("DROP VIEW totals").unwrap();
assert!(c.query("SELECT * FROM totals").is_err());
}
#[test]
fn view_in_join() {
let mut c = setup();
c.execute("CREATE TABLE k(kind TEXT, label TEXT)").unwrap();
c.execute("INSERT INTO k VALUES ('a','Apple'),('b','Banana')")
.unwrap();
c.execute("CREATE VIEW a_only AS SELECT id, kind, amount FROM t WHERE kind = 'a'")
.unwrap();
let r = c
.query(
"SELECT a_only.amount, k.label FROM a_only \
JOIN k ON a_only.kind = k.kind ORDER BY a_only.amount",
)
.unwrap();
assert_eq!(r.rows.len(), 3);
assert_eq!(r.rows[0][0], Value::Integer(10));
assert_eq!(r.rows[0][1], Value::Text("Apple".into()));
let r = c
.query("SELECT count(*) FROM k JOIN a_only ON k.kind = a_only.kind")
.unwrap();
assert_eq!(r.rows[0][0], Value::Integer(3));
}
#[test]
fn create_view_if_not_exists() {
let mut c = setup();
c.execute("CREATE VIEW v AS SELECT id FROM t").unwrap();
assert!(c.execute("CREATE VIEW v AS SELECT id FROM t").is_err());
c.execute("CREATE VIEW IF NOT EXISTS v AS SELECT id FROM t")
.unwrap();
}
#[test]
fn drop_if_exists_still_rejects_wrong_object_kind() {
let mut c = setup();
c.execute("CREATE VIEW v AS SELECT id FROM t").unwrap();
assert!(c.execute("DROP VIEW IF EXISTS t").is_err());
assert!(c.execute("DROP TABLE IF EXISTS v").is_err());
c.execute("DROP VIEW IF EXISTS nope").unwrap();
c.execute("DROP TABLE IF EXISTS nope").unwrap();
assert!(c.query("SELECT * FROM t").is_ok());
assert!(c.query("SELECT * FROM v").is_ok());
c.execute("DROP VIEW IF EXISTS v").unwrap();
assert!(c.query("SELECT * FROM v").is_err());
}
#[test]
fn view_column_inherits_base_collation_and_affinity() {
let mut c = Connection::open_memory().unwrap();
c.execute("CREATE TABLE t(a TEXT COLLATE NOCASE, n INTEGER)")
.unwrap();
c.execute("INSERT INTO t VALUES('B',1),('a',2),('C',3)")
.unwrap();
c.execute("CREATE VIEW v AS SELECT a, n FROM t").unwrap();
assert_eq!(
c.query("SELECT a FROM v ORDER BY a").unwrap().rows,
vec![
vec![Value::Text("a".into())],
vec![Value::Text("B".into())],
vec![Value::Text("C".into())],
]
);
assert_eq!(
c.query("SELECT count(*) FROM v WHERE a='A'").unwrap().rows[0][0],
Value::Integer(1)
);
assert_eq!(
c.query("SELECT min(a), max(a) FROM v").unwrap().rows[0],
vec![Value::Text("a".into()), Value::Text("C".into())]
);
assert_eq!(
c.query("SELECT count(*) FROM v WHERE n='1'").unwrap().rows[0][0],
Value::Integer(1)
);
c.execute("CREATE VIEW w AS SELECT a||'' AS a FROM t")
.unwrap();
assert_eq!(
c.query("SELECT a FROM w ORDER BY a").unwrap().rows,
vec![
vec![Value::Text("B".into())],
vec![Value::Text("C".into())],
vec![Value::Text("a".into())],
]
);
}