use crate::graph::GraphStorage;
use crate::traversal::step::map_steps::temporal::{
ZoneArg, check_zone, computed, incoming_temporal, replaced, temporal_error, zone_of,
};
use crate::value::dt::DT;
use crate::value::literal::TokenLiteral;
use crate::value::temporal::arith;
use crate::*;
#[derive(Clone)]
struct StepDateTrunc {
unit: DT,
zone: Option<ZoneArg>,
}
impl fmt::Display for StepDateTrunc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "date_trunc({}", self.unit.token_literal())?;
if let Some(zone) = &self.zone {
write!(f, ", {}", zone.literal())?;
}
f.write_str(")")
}
}
fn step<'g, S: GraphStorage + 'g>(unit: DT, zone: Option<&str>) -> GraphStep<'g, S> {
GraphStep::Map(
"date_trunc",
Box::new(StepDateTrunc {
unit,
zone: zone.map(ZoneArg::parse),
}),
)
}
macro_rules! date_trunc_builders {
() => {
pub fn date_trunc(self, unit: DT) -> Self {
self.push_step(step(unit, None))
}
pub fn date_trunc_in(self, unit: DT, zone: &str) -> Self {
self.push_step(step(unit, Some(zone)))
}
};
}
impl<'g, S: GraphStorage + 'g> GraphTraversalSource<'g, S> {
date_trunc_builders!();
}
impl<'g, S: GraphStorage + 'g> AnonymousTraversal<'g, S> {
date_trunc_builders!();
}
impl __ {
pub fn date_trunc<'g, S: GraphStorage + 'g>(unit: DT) -> AnonymousTraversal<'g, S> {
AnonymousTraversal::new().date_trunc(unit)
}
}
impl<'g, S: GraphStorage + 'g> GraphStepMap<'g, S> for StepDateTrunc {
fn process(
&self,
context: &mut TraverserContext<'_, S>,
source: Traverser<S>,
) -> TraverserResult<Traverser<S>> {
let value = incoming_temporal(context, &source.value, "date_trunc", "a date or time")?;
let zone = zone_of(&self.zone, "date_trunc")?;
let result = arith::trunc(value, self.unit, zone)
.map_err(|error| temporal_error("date_trunc", error))?;
Ok(replaced(source, computed(result)))
}
fn may_filter(&self) -> bool {
true
}
fn plan_check(&self) -> TraverserResult<()> {
check_zone(&self.zone, "date_trunc")
}
fn clone_box(&self) -> Box<dyn GraphStepMap<'g, S> + 'g> {
Box::new(self.clone())
}
}