use spg_engine::{Engine, QueryResult};
use spg_storage::Value;
fn rows(r: QueryResult) -> Vec<Vec<Value<'static>>> {
match r {
QueryResult::Rows { rows, .. } => rows.into_iter().map(|r| r.values).collect(),
_ => panic!("expected rows"),
}
}
#[test]
fn interval_text_cast_via_double_colon() {
let mut e = Engine::new();
let r = rows(e.execute("SELECT '30 days'::INTERVAL").unwrap());
assert_eq!(r.len(), 1);
let Value::Interval {
months,
days,
micros,
} = r[0][0]
else {
panic!("expected Interval, got {:?}", r[0][0]);
};
assert_eq!(months, 0);
assert_eq!(days, 30);
assert_eq!(micros, 0);
}
#[test]
fn interval_literal_in_expression_position() {
let mut e = Engine::new();
e.execute("CREATE TABLE t (id INT NOT NULL, created_at TIMESTAMP NOT NULL)")
.unwrap();
e.execute(
"INSERT INTO t VALUES \
(1, '2024-01-01 00:00:00'::TIMESTAMP), \
(2, '2024-06-01 00:00:00'::TIMESTAMP)",
)
.unwrap();
let r = rows(
e.execute(
"SELECT id FROM t WHERE created_at > '2024-03-01 00:00:00'::TIMESTAMP - INTERVAL '60 days'",
)
.unwrap(),
);
assert!(!r.is_empty());
}
#[test]
fn interval_with_compound_units() {
let mut e = Engine::new();
let r = rows(
e.execute("SELECT '1 day 2 hours 3 minutes'::INTERVAL")
.unwrap(),
);
let Value::Interval {
months,
days,
micros,
} = r[0][0]
else {
panic!();
};
assert_eq!(months, 0);
assert_eq!(days, 1);
let expected = (2 * 3600 + 3 * 60) * 1_000_000;
assert_eq!(micros, expected);
}
#[test]
fn interval_with_months_and_years() {
let mut e = Engine::new();
let r = rows(e.execute("SELECT '1 year 2 months'::INTERVAL").unwrap());
let Value::Interval {
months,
days,
micros,
} = r[0][0]
else {
panic!();
};
assert_eq!(months, 14);
assert_eq!(days, 0);
assert_eq!(micros, 0);
}
#[test]
fn interval_negative_value() {
let mut e = Engine::new();
let r = rows(e.execute("SELECT '-7 days'::INTERVAL").unwrap());
let Value::Interval {
months,
days,
micros,
} = r[0][0]
else {
panic!();
};
assert_eq!(months, 0);
assert_eq!(days, -7);
assert_eq!(micros, 0);
}
#[test]
fn timestamp_plus_interval_via_cast() {
let mut e = Engine::new();
e.execute("CREATE TABLE t (when_ TIMESTAMP NOT NULL)")
.unwrap();
e.execute("INSERT INTO t VALUES ('2024-01-01 12:00:00'::TIMESTAMP)")
.unwrap();
let r = rows(
e.execute("SELECT when_ + '1 day'::INTERVAL FROM t")
.unwrap(),
);
let Value::Timestamp(t) = r[0][0] else {
panic!();
};
let day_us = 86_400 * 1_000_000_i64;
let base = 19723_i64 * day_us + 12 * 3600 * 1_000_000;
assert_eq!(t, base + day_us);
}
#[test]
fn interval_in_generate_series_step() {
let mut e = Engine::new();
let r = rows(
e.execute(
"SELECT * FROM generate_series(\
'2024-01-01'::TIMESTAMP, \
'2024-01-03'::TIMESTAMP, \
'1 day'::INTERVAL\
)",
)
.unwrap(),
);
assert_eq!(r.len(), 3);
}