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