use rstest::rstest;
use vortex_buffer::buffer;
use vortex_error::VortexResult;
use crate::IntoArray;
use crate::ToCanonical;
use crate::array::DynArray;
use crate::arrays::PrimitiveArray;
use crate::arrays::TemporalArray;
use crate::assert_arrays_eq;
use crate::expr::gt;
use crate::expr::lit;
use crate::expr::root;
use crate::extension::datetime::TemporalMetadata;
use crate::extension::datetime::TimeUnit;
use crate::extension::datetime::Timestamp;
use crate::extension::datetime::TimestampOptions;
use crate::scalar::Scalar;
use crate::validity::Validity;
use crate::vtable::ValidityHelper;
macro_rules! test_temporal_roundtrip {
($prim:ty, $constructor:expr, $unit:expr) => {{
let array = buffer![100 as $prim].into_array();
let temporal: TemporalArray = $constructor(array, $unit);
assert_arrays_eq!(
temporal.temporal_values(),
PrimitiveArray::from_iter([100 as $prim])
);
assert_eq!(temporal.temporal_metadata().time_unit(), $unit);
}};
}
macro_rules! test_success_case {
($name:ident, $prim:ty, $constructor:expr, $unit:expr) => {
#[test]
fn $name() {
test_temporal_roundtrip!($prim, $constructor, $unit);
}
};
}
macro_rules! test_fail_case {
($name:ident, $prim:ty, $constructor:expr, $unit:expr) => {
#[test]
#[should_panic]
fn $name() {
test_temporal_roundtrip!($prim, $constructor, $unit)
}
};
}
test_success_case!(
test_roundtrip_time32_second,
i32,
TemporalArray::new_time,
TimeUnit::Seconds
);
test_success_case!(
test_roundtrip_time32_millisecond,
i32,
TemporalArray::new_time,
TimeUnit::Milliseconds
);
test_fail_case!(
test_fail_time32_micro,
i32,
TemporalArray::new_time,
TimeUnit::Microseconds
);
test_fail_case!(
test_fail_time32_nano,
i32,
TemporalArray::new_time,
TimeUnit::Nanoseconds
);
test_success_case!(
test_roundtrip_time64_us,
i64,
TemporalArray::new_time,
TimeUnit::Microseconds
);
test_success_case!(
test_roundtrip_time64_ns,
i64,
TemporalArray::new_time,
TimeUnit::Nanoseconds
);
test_fail_case!(
test_fail_time64_ms,
i64,
TemporalArray::new_time,
TimeUnit::Milliseconds
);
test_fail_case!(
test_fail_time64_s,
i64,
TemporalArray::new_time,
TimeUnit::Seconds
);
test_fail_case!(
test_fail_time64_i32,
i32,
TemporalArray::new_time,
TimeUnit::Nanoseconds
);
test_success_case!(
test_roundtrip_date32,
i32,
TemporalArray::new_date,
TimeUnit::Days
);
test_fail_case!(
test_fail_date32,
i64,
TemporalArray::new_date,
TimeUnit::Days
);
test_success_case!(
test_roundtrip_date64,
i64,
TemporalArray::new_date,
TimeUnit::Milliseconds
);
test_fail_case!(
test_fail_date64,
i32,
TemporalArray::new_date,
TimeUnit::Milliseconds
);
#[test]
fn test_timestamp() {
let ts = buffer![100i64].into_array();
let ts_array = ts.into_array();
for unit in [
TimeUnit::Seconds,
TimeUnit::Milliseconds,
TimeUnit::Microseconds,
TimeUnit::Nanoseconds,
] {
for tz in [Some("UTC".into()), None] {
let temporal_array =
TemporalArray::new_timestamp(ts_array.to_array(), unit, tz.clone());
assert_arrays_eq!(
temporal_array.temporal_values(),
PrimitiveArray::from_iter([100i64])
);
assert_eq!(
temporal_array.temporal_metadata(),
TemporalMetadata::Timestamp(&unit, &tz)
);
}
}
}
#[test]
#[should_panic]
fn test_timestamp_fails_i32() {
let ts = buffer![100i32].into_array();
let ts_array = ts.into_array();
TemporalArray::new_timestamp(ts_array, TimeUnit::Seconds, None);
}
#[rstest]
#[case(Validity::NonNullable)]
#[case(Validity::AllValid)]
#[case(Validity::AllInvalid)]
#[case(Validity::from_iter([true, false, true]))]
fn test_validity_preservation(#[case] validity: Validity) {
let milliseconds = PrimitiveArray::new(
buffer![
86_400i64, 86_400i64 + 1000, 86_400i64 + 1000 + 1, ],
validity.clone(),
)
.into_array();
let temporal_array =
TemporalArray::new_timestamp(milliseconds, TimeUnit::Milliseconds, Some("UTC".into()));
assert_eq!(
temporal_array.temporal_values().to_primitive().validity(),
&validity
);
}
#[test]
fn test222() -> VortexResult<()> {
let ts_array = PrimitiveArray::from_iter(vec![1704067200000i64, 1704153600000, 1704240000000])
.into_array();
let temporal = TemporalArray::new_timestamp(ts_array, TimeUnit::Milliseconds, None);
let filter_expr = gt(
root(),
lit(Scalar::extension::<Timestamp>(
TimestampOptions {
unit: TimeUnit::Seconds,
tz: None,
},
Scalar::from(1704153600i64),
)),
);
let _result = temporal.as_ref().apply(&filter_expr);
Ok(())
}