Skip to main content

a3s_orm/
window.rs

1use std::marker::PhantomData;
2
3use crate::expression::{
4    Expression, OrderDirection, Selection, SelectionExt, WindowBoundary, WindowFrame,
5    WindowFrameUnits,
6};
7use crate::Column;
8
9#[derive(Clone, Debug)]
10pub struct WindowExpression<V> {
11    expression: Expression,
12    partition_by: Vec<Expression>,
13    order_by: Vec<(Expression, OrderDirection)>,
14    frame: Option<WindowFrame>,
15    marker: PhantomData<fn() -> V>,
16}
17
18impl<V> WindowExpression<V> {
19    pub(crate) fn new(expression: Expression) -> Self {
20        Self {
21            expression,
22            partition_by: Vec::new(),
23            order_by: Vec::new(),
24            frame: None,
25            marker: PhantomData,
26        }
27    }
28
29    pub fn partition_by<T, C>(mut self, column: Column<T, C>) -> Self {
30        self.partition_by.push(column.expression());
31        self
32    }
33
34    pub fn order_by<T, C>(mut self, column: Column<T, C>, direction: OrderDirection) -> Self {
35        self.order_by.push((column.expression(), direction));
36        self
37    }
38
39    pub fn frame(
40        mut self,
41        units: WindowFrameUnits,
42        start: WindowBoundary,
43        end: WindowBoundary,
44    ) -> Self {
45        self.frame = Some(WindowFrame { units, start, end });
46        self
47    }
48}
49
50impl<V> Selection for WindowExpression<V> {
51    type Output = V;
52
53    fn expressions(self) -> Vec<Expression> {
54        vec![Expression::Window {
55            expression: Box::new(self.expression),
56            partition_by: self.partition_by,
57            order_by: self.order_by,
58            frame: self.frame,
59        }]
60    }
61}
62
63impl<V> SelectionExt for WindowExpression<V> {}
64
65pub fn row_number() -> WindowExpression<i64> {
66    rank_function("row_number")
67}
68
69pub fn rank() -> WindowExpression<i64> {
70    rank_function("rank")
71}
72
73pub fn dense_rank() -> WindowExpression<i64> {
74    rank_function("dense_rank")
75}
76
77fn rank_function(name: &'static str) -> WindowExpression<i64> {
78    WindowExpression::new(Expression::Function {
79        name,
80        arguments: Vec::new(),
81    })
82}