use keelson_core::clause::{FrameMode, HasFrame};
use keelson_core::expr::{Expr, IntoExpr};
use keelson_core::{Mod, mod_fn};
fn mode<Q: HasFrame>(mode: FrameMode) -> impl Mod<Q> {
mod_fn(move |q: &mut Q| q.frame_mut().set_mode(mode))
}
fn start<Q: HasFrame>(bound: Expr) -> impl Mod<Q> {
mod_fn(move |q: &mut Q| q.frame_mut().set_start(bound))
}
fn end<Q: HasFrame>(bound: Expr) -> impl Mod<Q> {
mod_fn(move |q: &mut Q| q.frame_mut().set_end(bound))
}
fn offset_bound(offset: impl IntoExpr, keyword: &'static str) -> Expr {
Expr::join((offset, Expr::raw(keyword)))
}
pub fn range<Q: HasFrame>() -> impl Mod<Q> {
mode(FrameMode::Range)
}
pub fn rows<Q: HasFrame>() -> impl Mod<Q> {
mode(FrameMode::Rows)
}
pub fn from_unbounded_preceding<Q: HasFrame>() -> impl Mod<Q> {
start(Expr::raw("UNBOUNDED PRECEDING"))
}
pub fn from_preceding<Q: HasFrame>(offset: impl IntoExpr) -> impl Mod<Q> {
start(offset_bound(offset, "PRECEDING"))
}
pub fn from_current_row<Q: HasFrame>() -> impl Mod<Q> {
start(Expr::raw("CURRENT ROW"))
}
pub fn from_following<Q: HasFrame>(offset: impl IntoExpr) -> impl Mod<Q> {
start(offset_bound(offset, "FOLLOWING"))
}
pub fn from_unbounded_following<Q: HasFrame>() -> impl Mod<Q> {
start(Expr::raw("UNBOUNDED FOLLOWING"))
}
pub fn to_preceding<Q: HasFrame>(offset: impl IntoExpr) -> impl Mod<Q> {
end(offset_bound(offset, "PRECEDING"))
}
pub fn to_current_row<Q: HasFrame>() -> impl Mod<Q> {
end(Expr::raw("CURRENT ROW"))
}
pub fn to_following<Q: HasFrame>(offset: impl IntoExpr) -> impl Mod<Q> {
end(offset_bound(offset, "FOLLOWING"))
}
pub fn to_unbounded_following<Q: HasFrame>() -> impl Mod<Q> {
end(Expr::raw("UNBOUNDED FOLLOWING"))
}
pub fn to_unbounded_preceding<Q: HasFrame>() -> impl Mod<Q> {
end(Expr::raw("UNBOUNDED PRECEDING"))
}