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!("expected Rows"),
}
}
fn one_cell(eng: &mut Engine, sql: &str) -> Value<'static> {
let row = one_row(eng.execute(sql).unwrap());
assert_eq!(row.len(), 1, "{sql}");
row.into_iter().next().unwrap()
}
fn text_of(v: Value) -> String {
match v {
Value::Text(s) => s.into_owned(),
other => panic!("expected Value::Text, got {other:?}"),
}
}
fn bigint_of(v: Value) -> i64 {
match v {
Value::BigInt(n) => n,
Value::Int(n) => i64::from(n),
other => panic!("expected Value::BigInt, got {other:?}"),
}
}
#[test]
fn date_format_iso_date_layout() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%Y-%m-%d')",
));
assert_eq!(s, "2025-06-08");
}
#[test]
fn date_format_iso_datetime_layout() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%Y-%m-%d %H:%i:%s')",
));
assert_eq!(s, "2025-06-08 14:30:45");
}
#[test]
fn date_format_percent_i_is_minute_not_month() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%i')",
));
assert_eq!(s, "30");
}
#[test]
fn date_format_percent_capital_m_is_month_name() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%M')",
));
assert_eq!(s, "June");
}
#[test]
fn date_format_percent_b_is_abbrev_month() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%b')",
));
assert_eq!(s, "Jun");
}
#[test]
fn date_format_percent_p_renders_ampm() {
let mut e = Engine::new();
let am = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 09:30:45'::TIMESTAMP, '%p')",
));
assert_eq!(am, "AM");
let pm = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%p')",
));
assert_eq!(pm, "PM");
}
#[test]
fn date_format_percent_f_microsecond_zero_pad_6() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45.123456'::TIMESTAMP, '%f')",
));
assert_eq!(s, "123456");
}
#[test]
fn date_format_double_percent_emits_literal_percent() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT date_format('2025-06-08 14:30:45'::TIMESTAMP, '%Y%%')",
));
assert_eq!(s, "2025%");
}
#[test]
fn date_format_null_input_returns_null() {
let mut e = Engine::new();
assert!(matches!(
one_cell(&mut e, "SELECT date_format(NULL, '%Y')"),
Value::Null
));
}
#[test]
fn unix_timestamp_of_known_timestamp() {
let mut e = Engine::new();
let n = bigint_of(one_cell(
&mut e,
"SELECT unix_timestamp('2025-06-08 14:30:45'::TIMESTAMP)",
));
assert_eq!(n, 1_749_393_045);
}
#[test]
fn unix_timestamp_of_date_is_midnight_utc() {
let mut e = Engine::new();
let n = bigint_of(one_cell(
&mut e,
"SELECT unix_timestamp('2025-06-08'::DATE)",
));
assert_eq!(n, 1_749_340_800);
}
#[test]
fn unix_timestamp_null_returns_null() {
let mut e = Engine::new();
assert!(matches!(
one_cell(&mut e, "SELECT unix_timestamp(NULL)"),
Value::Null
));
}
#[test]
fn unix_timestamp_bare_call_returns_bigint() {
const FROZEN_NOW_US: i64 = 1_749_393_045_000_000;
fn frozen_clock() -> i64 {
FROZEN_NOW_US
}
let mut e = Engine::new().with_clock(frozen_clock);
let n = bigint_of(one_cell(&mut e, "SELECT unix_timestamp()"));
assert_eq!(n, 1_749_393_045);
}
#[test]
fn from_unixtime_seconds_to_timestamp() {
let mut e = Engine::new();
let v = one_cell(&mut e, "SELECT from_unixtime(1749393045)");
let Value::Timestamp(t) = v else {
panic!("expected Timestamp, got {v:?}");
};
assert_eq!(t, 1_749_393_045 * 1_000_000);
}
#[test]
fn from_unixtime_two_arg_formats_text() {
let mut e = Engine::new();
let s = text_of(one_cell(
&mut e,
"SELECT from_unixtime(1749393045, '%Y-%m-%d %H:%i:%s')",
));
assert_eq!(s, "2025-06-08 14:30:45");
}
#[test]
fn from_unixtime_null_returns_null() {
let mut e = Engine::new();
assert!(matches!(
one_cell(&mut e, "SELECT from_unixtime(NULL)"),
Value::Null
));
}