use rudb::Database;
use rudb_common::Value;
fn parquet(name: &str) -> String {
format!("'{}/../rudb-parquet/testdata/parts/{name}'", env!("CARGO_MANIFEST_DIR"))
}
fn csv(name: &str) -> String {
format!("'{}/../rudb-csv/testdata/parts/{name}'", env!("CARGO_MANIFEST_DIR"))
}
fn one(what: &str, from: &str) -> Value {
let database = Database::new();
let sql = format!("SELECT {what} FROM {from}");
database.value(&sql).unwrap_or_else(|error| panic!("{sql} failed: {error}"))
}
fn refusal(sql: &str) -> String {
let database = Database::new();
database.query(sql).unwrap_err().message().to_string()
}
#[test]
fn a_list_of_paths_reads_every_one_of_them() {
let from = format!("read_parquet([{}, {}])", parquet("p1.parquet"), parquet("p2.parquet"));
assert_eq!(one("count(*)", &from), Value::BigInt(7));
assert_eq!(one("sum(a)", &from), Value::HugeInt(49));
}
#[test]
fn a_list_is_read_in_the_order_it_was_written_and_not_in_sorted_order() {
let database = Database::new();
let sql = format!(
"SELECT a FROM read_parquet([{}, {}]) LIMIT 5",
parquet("p2.parquet"),
parquet("p1.parquet")
);
let result = database.query(&sql).expect("runs");
let rows: Vec<Value> = (0..result.len()).map(|row| result.value_at(row, 0)).collect();
assert_eq!(
rows,
vec![
Value::Integer(10),
Value::Integer(11),
Value::Integer(12),
Value::Integer(13),
Value::Integer(0)
]
);
}
#[test]
fn a_file_named_twice_is_read_twice() {
let from = format!("read_parquet([{}, {}])", parquet("p1.parquet"), parquet("p1.parquet"));
assert_eq!(one("count(*)", &from), Value::BigInt(6));
}
#[test]
fn an_item_of_a_list_can_itself_be_a_pattern() {
let from = format!("read_parquet([{}])", parquet("p*.parquet"));
assert_eq!(one("count(*)", &from), Value::BigInt(7));
}
#[test]
fn every_item_has_to_find_a_file_of_its_own() {
let sql = format!(
"SELECT count(*) FROM read_parquet([{}, {}])",
parquet("p1.parquet"),
parquet("zz*.parquet")
);
let message = refusal(&sql);
assert!(message.starts_with("No files found that match the pattern"), "{message}");
assert!(message.ends_with("zz*.parquet\""), "{message}");
}
#[test]
fn an_empty_list_is_the_message_about_overloads_because_it_has_no_element_type() {
let message = refusal("SELECT * FROM read_parquet([])");
assert!(
message.starts_with(
"No function matches the given name and argument types 'read_parquet(INTEGER[])'"
),
"{message}"
);
assert!(message.contains("read_parquet(VARCHAR[])"), "{message}");
}
#[test]
fn a_null_inside_a_list_and_a_null_instead_of_one_are_two_different_sentences() {
let sql = format!("SELECT * FROM read_parquet([{}, NULL])", parquet("p1.parquet"));
assert_eq!(refusal(&sql), "read_parquet reader cannot take NULL input as parameter");
assert_eq!(
refusal("SELECT * FROM read_csv(NULL)"),
"read_csv cannot take NULL list as parameter"
);
}
#[test]
fn the_csv_reader_takes_a_list_the_same_way() {
let from = format!("read_csv([{}, {}])", csv("c1.csv"), csv("c2.csv"));
assert_eq!(one("count(*)", &from), Value::BigInt(3));
assert_eq!(one("sum(a)", &from), Value::HugeInt(13));
}
#[test]
fn a_list_call_answers_to_the_function_name_when_nothing_aliased_it() {
let database = Database::new();
let sql =
format!("SELECT read_parquet.a FROM read_parquet([{}]) LIMIT 1", parquet("p1.parquet"));
assert_eq!(database.value(&sql).expect("runs"), Value::Integer(0));
}
#[test]
fn a_list_where_an_expression_goes_is_a_gap_that_says_so() {
let message = refusal("SELECT [1, 2, 3]");
assert!(message.contains("List"), "{message}");
}