1use std::marker::PhantomData;
13
14use crate::expr::{BigInt, ExprKind, IntoExpr, Keyed, SortDir};
15use crate::scope::{Concat, Nil};
16use crate::select::OrderKey;
17
18pub struct Window<Req> {
23 partition_by: Vec<ExprKind>,
24 order_by: Vec<(ExprKind, SortDir)>,
25 _marker: PhantomData<fn() -> Req>,
26}
27
28pub fn window() -> Window<Nil> {
31 Window {
32 partition_by: Vec::new(),
33 order_by: Vec::new(),
34 _marker: PhantomData,
35 }
36}
37
38impl<Req> Window<Req> {
39 pub fn partition_by<Req2>(
40 self,
41 key: impl IntoExpr<Req = Req2>,
42 ) -> Window<<Req as Concat<Req2>>::Output>
43 where
44 Req: Concat<Req2>,
45 {
46 let mut partition_by = self.partition_by;
47 partition_by.push(key.into_expr().kind);
48 Window {
49 partition_by,
50 order_by: self.order_by,
51 _marker: PhantomData,
52 }
53 }
54
55 pub fn order_by<Req2>(self, key: OrderKey<Req2>) -> Window<<Req as Concat<Req2>>::Output>
56 where
57 Req: Concat<Req2>,
58 {
59 let mut order_by = self.order_by;
60 order_by.push(key.into_parts());
61 Window {
62 partition_by: self.partition_by,
63 order_by,
64 _marker: PhantomData,
65 }
66 }
67}
68
69pub struct WindowFunc<K> {
78 sql: &'static str,
79 _marker: PhantomData<fn() -> K>,
80}
81
82impl<K> crate::row::RowKey for WindowFunc<K> {
83 type Key = K;
84}
85
86impl<K: crate::row::Spelled> crate::row::LookupKey for WindowFunc<K> {}
89
90impl<K> WindowFunc<K> {
91 pub fn over<WindowReq>(self, window: Window<WindowReq>) -> Keyed<K, WindowReq, BigInt> {
95 Keyed::from_kind(ExprKind::Window {
96 func: self.sql,
97 partition_by: window.partition_by,
98 order_by: window.order_by,
99 })
100 }
101}
102
103fn window_func<K>(sql: &'static str) -> WindowFunc<K> {
104 WindowFunc {
105 sql,
106 _marker: PhantomData,
107 }
108}
109
110crate::row::expr_key!(
111 RowNumber,
112 HasRowNumber,
113 row_number,
114 "The identity a selected `row_number() OVER (..)` is filed under in a row.",
115 'r',
116 'o',
117 'w',
118 '_',
119 'n',
120 'u',
121 'm',
122 'b',
123 'e',
124 'r'
125);
126crate::row::expr_key!(
127 Rank,
128 HasRank,
129 rank,
130 "The identity a selected `rank() OVER (..)` is filed under in a row.",
131 'r',
132 'a',
133 'n',
134 'k'
135);
136crate::row::expr_key!(
137 DenseRank,
138 HasDenseRank,
139 dense_rank,
140 "The identity a selected `dense_rank() OVER (..)` is filed under in a row.",
141 'd',
142 'e',
143 'n',
144 's',
145 'e',
146 '_',
147 'r',
148 'a',
149 'n',
150 'k'
151);
152
153pub fn row_number() -> WindowFunc<RowNumber> {
156 window_func("row_number()")
157}
158
159pub fn rank() -> WindowFunc<Rank> {
162 window_func("rank()")
163}
164
165pub fn dense_rank() -> WindowFunc<DenseRank> {
168 window_func("dense_rank()")
169}