diesel/expression/functions/aggregate_expressions/
over_clause.rs

1use super::aggregate_filter::{Filter, NoFilter};
2use super::aggregate_order::NoOrder;
3use super::partition_by::NoPartition;
4use super::prefix::NoPrefix;
5use super::IsWindowFunction;
6use super::NoFrame;
7use super::WindowFunctionFragment;
8use super::{AggregateExpression, IsAggregateFunction};
9use crate::query_builder::QueryFragment;
10use crate::query_builder::{AstPass, QueryId};
11use crate::QueryResult;
12
13/// Only aggregate functions allow to use filter
14pub(super) trait ValidAggregateFilterForWindow<Fn, Window> {}
15
16impl<Fn, W> ValidAggregateFilterForWindow<Fn, W> for NoFilter {}
17empty_clause!(NoWindow);
18
19impl<F, Fn> ValidAggregateFilterForWindow<Fn, NoWindow> for Filter<F> {}
20
21impl<DB, T> WindowFunctionFragment<T, DB> for NoWindow where DB: crate::backend::Backend {}
22
23#[derive(Clone, Copy, QueryId, Debug)]
24#[doc(hidden)] // not even sure why rustc believes this is public
25#[diesel(diesel_internal_is_window = true)]
26pub struct OverClause<Partition = NoPartition, Order = NoOrder, Frame = NoFrame> {
27    pub(crate) partition_by: Partition,
28    pub(crate) order: Order,
29    pub(crate) frame_clause: Frame,
30}
31
32impl<F, Fn, Partition, Order, Frame>
33    ValidAggregateFilterForWindow<Fn, OverClause<Partition, Order, Frame>> for Filter<F>
34where
35    Fn: IsAggregateFunction,
36{
37}
38
39impl<Partition, Order, Frame, DB> QueryFragment<DB> for OverClause<Partition, Order, Frame>
40where
41    Partition: QueryFragment<DB>,
42    Order: QueryFragment<DB>,
43    Frame: QueryFragment<DB>,
44    DB: crate::backend::Backend,
45{
46    fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
47        pass.push_sql(" OVER (");
48        self.partition_by.walk_ast(pass.reborrow())?;
49        self.order.walk_ast(pass.reborrow())?;
50        self.frame_clause.walk_ast(pass.reborrow())?;
51        pass.push_sql(")");
52        Ok(())
53    }
54}
55
56pub trait OverDsl {
57    type Output;
58
59    fn over(self) -> Self::Output;
60}
61
62impl<F> OverDsl for F
63where
64    F: IsWindowFunction,
65{
66    type Output = AggregateExpression<F, NoPrefix, NoOrder, NoFilter, OverClause>;
67
68    fn over(self) -> Self::Output {
69        AggregateExpression {
70            prefix: NoPrefix,
71            function: self,
72            order: NoOrder,
73            filter: NoFilter,
74            window: OverClause {
75                partition_by: NoPartition,
76                order: NoOrder,
77                frame_clause: NoFrame,
78            },
79        }
80    }
81}
82
83impl<Fn, Filter> OverDsl for AggregateExpression<Fn, NoPrefix, NoOrder, Filter, NoWindow>
84where
85    Filter: ValidAggregateFilterForWindow<Fn, OverClause>,
86{
87    type Output = AggregateExpression<Fn, NoPrefix, NoOrder, Filter, OverClause>;
88
89    fn over(self) -> Self::Output {
90        AggregateExpression {
91            prefix: NoPrefix,
92            function: self.function,
93            order: NoOrder,
94            filter: self.filter,
95            window: OverClause {
96                partition_by: NoPartition,
97                order: NoOrder,
98                frame_clause: NoFrame,
99            },
100        }
101    }
102}