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}