use chrono::{DateTime, Utc};
use datafusion::logical_expr::Operator;
use crate::ts_table_provider::{IntervalTruth, TimePred};
pub(crate) fn eval_cmp_on_interval(
op: Operator,
dt: DateTime<Utc>,
seg_min: DateTime<Utc>,
seg_max: DateTime<Utc>,
) -> IntervalTruth {
use IntervalTruth::*;
match op {
Operator::Lt => {
if seg_max < dt {
AlwaysTrue
} else if seg_min >= dt {
AlwaysFalse
} else {
MaybeTrue
}
}
Operator::LtEq => {
if seg_max <= dt {
AlwaysTrue
} else if seg_min > dt {
AlwaysFalse
} else {
MaybeTrue
}
}
Operator::Gt => {
if seg_min > dt {
AlwaysTrue
} else if seg_max <= dt {
AlwaysFalse
} else {
MaybeTrue
}
}
Operator::GtEq => {
if seg_min >= dt {
AlwaysTrue
} else if seg_max < dt {
AlwaysFalse
} else {
MaybeTrue
}
}
Operator::Eq => {
if dt < seg_min || dt > seg_max {
AlwaysFalse
} else if seg_min == seg_max && seg_min == dt {
AlwaysTrue
} else {
MaybeTrue
}
}
Operator::NotEq => {
if seg_min == seg_max && seg_min == dt {
AlwaysFalse
} else if dt < seg_min || dt > seg_max {
AlwaysTrue
} else {
MaybeTrue
}
}
_ => MaybeTrue,
}
}
pub(crate) fn eval_time_pred_on_segment(
pred: &TimePred,
seg_min: DateTime<Utc>,
seg_max: DateTime<Utc>,
) -> IntervalTruth {
use IntervalTruth::*;
use TimePred::*;
match pred {
True => AlwaysTrue,
False => AlwaysFalse,
Unknown => MaybeTrue,
NonTime => MaybeTrue,
Cmp { op, ts } => eval_cmp_on_interval(*op, *ts, seg_min, seg_max),
And(a, b) => eval_time_pred_on_segment(a, seg_min, seg_max)
.and(eval_time_pred_on_segment(b, seg_min, seg_max)),
Or(a, b) => eval_time_pred_on_segment(a, seg_min, seg_max)
.or(eval_time_pred_on_segment(b, seg_min, seg_max)),
Not(x) => eval_time_pred_on_segment(x, seg_min, seg_max).not(),
}
}