use spg_engine::{Engine, QueryResult};
use spg_storage::Value;
fn one_row(r: QueryResult) -> Vec<Value<'static>> {
match r {
QueryResult::Rows { rows, .. } => {
assert_eq!(rows.len(), 1);
rows.into_iter().next().unwrap().values
}
_ => panic!(),
}
}
fn text(e: &mut Engine, sql: &str) -> String {
let row = one_row(
e.execute(sql)
.unwrap_or_else(|err| panic!("{sql}: {err:?}")),
);
match &row[0] {
Value::Text(s) => s.to_string(),
other => panic!("expected Text, got {other:?}"),
}
}
#[test]
fn translate_simple_char_swap() {
let mut e = Engine::new();
assert_eq!(text(&mut e, "SELECT translate('hello', 'l', 'L')"), "heLLo");
}
#[test]
fn translate_positional_mapping() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('aabbcc', 'abc', 'XYZ')"),
"XXYYZZ"
);
}
#[test]
fn translate_chars_not_in_from_pass_through() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('hello world', 'lo', 'L0')"),
"heLL0 w0rLd"
);
}
#[test]
fn translate_extra_from_chars_deleted() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('abcdef', 'abc', 'X')"),
"Xdef"
);
}
#[test]
fn translate_empty_to_deletes_all_from_chars() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('hello world', 'lo', '')"),
"he wrd"
);
}
#[test]
fn translate_empty_from_passes_through_unchanged() {
let mut e = Engine::new();
assert_eq!(text(&mut e, "SELECT translate('hello', '', 'X')"), "hello");
}
#[test]
fn translate_empty_input() {
let mut e = Engine::new();
assert_eq!(text(&mut e, "SELECT translate('', 'a', 'b')"), "");
}
#[test]
fn translate_duplicate_chars_in_from_first_match_wins() {
let mut e = Engine::new();
assert_eq!(text(&mut e, "SELECT translate('aaa', 'aaa', 'XYZ')"), "XXX");
}
#[test]
fn translate_multibyte_input() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('日本aaa', 'a', '*')"),
"日本***"
);
}
#[test]
fn translate_multibyte_in_from_set() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('日本語', '日本', 'JP')"),
"JP語"
);
}
#[test]
fn translate_null_input_returns_null() {
let mut e = Engine::new();
let row = one_row(e.execute("SELECT translate(NULL, 'a', 'b')").unwrap());
assert_eq!(row[0], Value::Null);
}
#[test]
fn translate_null_from_returns_null() {
let mut e = Engine::new();
let row = one_row(e.execute("SELECT translate('hi', NULL, 'b')").unwrap());
assert_eq!(row[0], Value::Null);
}
#[test]
fn translate_null_to_returns_null() {
let mut e = Engine::new();
let row = one_row(e.execute("SELECT translate('hi', 'a', NULL)").unwrap());
assert_eq!(row[0], Value::Null);
}
#[test]
fn translate_arity_too_few_errors() {
let mut e = Engine::new();
assert!(e.execute("SELECT translate('a', 'b')").is_err());
}
#[test]
fn translate_arity_too_many_errors() {
let mut e = Engine::new();
assert!(e.execute("SELECT translate('a', 'b', 'c', 'd')").is_err());
}
#[test]
fn translate_normalize_phone_number() {
let mut e = Engine::new();
assert_eq!(
text(&mut e, "SELECT translate('(555) 123-4567', ' ()-', '')"),
"5551234567"
);
}
#[test]
fn translate_inside_where() {
let mut e = Engine::new();
e.execute("CREATE TABLE u (id INT NOT NULL, code TEXT NOT NULL)")
.unwrap();
e.execute("INSERT INTO u VALUES (1, 'ABC-123'), (2, 'XYZ-456')")
.unwrap();
let r = e
.execute("SELECT id FROM u WHERE translate(code, '-', '') = 'ABC123'")
.unwrap();
let QueryResult::Rows { rows, .. } = r else {
panic!()
};
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].values[0], Value::Int(1));
}
#[test]
fn translate_column_type_is_text() {
let mut e = Engine::new();
let r = e.execute("SELECT translate('a', 'a', 'b')").unwrap();
let QueryResult::Rows { columns, .. } = r else {
panic!()
};
assert_eq!(columns[0].ty, spg_storage::DataType::Text);
}