Skip to main content

diesel/expression/functions/aggregate_expressions/
frame_clause.rs

1use super::aggregate_filter::NoFilter;
2use super::aggregate_order::{NoOrder, Order};
3use super::over_clause::{NoWindow, OverClause, ValidAggregateFilterForWindow};
4use super::partition_by::NoPartition;
5use super::prefix::NoPrefix;
6use super::{AggregateExpression, IsWindowFunction};
7use crate::backend::sql_dialect;
8use crate::query_builder::{QueryFragment, QueryId};
9use alloc::string::ToString;
10
11pub struct NoFrame;
#[automatically_derived]impl ::core::fmt::Debug for NoFrame {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "NoFrame")
    }
}
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for NoFrame {
}
#[automatically_derived]impl ::core::clone::Clone for NoFrame {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for NoFrame { }
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for NoFrame {
            type QueryId = NoFrame<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
impl<DB> crate::query_builder::QueryFragment<DB> for NoFrame where
    DB: crate::backend::Backend + crate::backend::DieselReserveSpecialization
    {
    fn walk_ast<'b>(&'b self,
        _pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        Ok(())
    }
}empty_clause!(NoFrame);
12
13#[derive(const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<F: diesel::query_builder::QueryId> diesel::query_builder::QueryId
            for FrameClause<F> {
            type QueryId =
                FrameClause<<F as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <F as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <F as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                    false;
        }
    };QueryId, #[automatically_derived]impl<F: ::core::marker::Copy> ::core::marker::Copy for
    FrameClause<F> {
}Copy, #[automatically_derived]impl<F: ::core::clone::Clone> ::core::clone::Clone for
    FrameClause<F> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self {
        FrameClause(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]impl<F: ::core::fmt::Debug> ::core::fmt::Debug for
    FrameClause<F> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "FrameClause",
            &&self.0)
    }
}Debug)]
14pub struct FrameClause<F>(F);
15
16impl<F, DB> QueryFragment<DB> for FrameClause<F>
17where
18    F: QueryFragment<DB>,
19    DB: crate::backend::Backend,
20{
21    fn walk_ast<'b>(
22        &'b self,
23        pass: crate::query_builder::AstPass<'_, 'b, DB>,
24    ) -> crate::QueryResult<()> {
25        self.0.walk_ast(pass)?;
26        Ok(())
27    }
28}
29
30macro_rules! simple_frame_expr {
31    ($(#[doc = $doc: literal])* $name: ident, $kind: expr_2021) => {
32        #[derive(QueryId, Clone, Copy, Debug)]
33        $(#[doc = $doc])*
34        pub struct $name;
35
36        impl<DB> QueryFragment<DB> for $name
37        where
38            DB: crate::backend::Backend,
39        {
40            fn walk_ast<'b>(
41                &'b self,
42                mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
43            ) -> crate::QueryResult<()> {
44                pass.push_sql($kind);
45                Ok(())
46            }
47        }
48    };
49}
50
51macro_rules! simple_frame_expr_with_bound {
52    ($(#[doc = $doc:literal])* $name: ident, $option: ident, $bound: ty, $kind: expr_2021) => {
53        #[derive(QueryId, Clone, Copy, Debug)]
54        $(#[doc = $doc])*
55        pub struct $name;
56
57        impl<DB> QueryFragment<DB> for $name
58        where
59            DB: crate::backend::Backend,
60            Self: QueryFragment<DB, DB::$option>,
61        {
62            fn walk_ast<'b>(
63                &'b self,
64                pass: crate::query_builder::AstPass<'_, 'b, DB>,
65            ) -> crate::QueryResult<()> {
66                <Self as QueryFragment<DB, DB::$option>>::walk_ast(self, pass)
67            }
68        }
69        impl<DB> QueryFragment<DB, $bound> for $name
70        where
71            DB: crate::backend::Backend<$option = $bound>,
72        {
73            fn walk_ast<'b>(
74                &'b self,
75                mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
76            ) -> crate::QueryResult<()> {
77                pass.push_sql($kind);
78                Ok(())
79            }
80        }
81    };
82}
83
84// kinds
85#[doc = r" Range frame mode"]
#[doc = r""]
#[doc = r" Requires to set a `ORDER BY` clause set via `window_order`"]
#[doc = r" for the current window function call"]
pub struct Range;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for Range {
            type QueryId = Range<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Range {
}
#[automatically_derived]impl ::core::clone::Clone for Range {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for Range { }
#[automatically_derived]impl ::core::fmt::Debug for Range {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Range")
    }
}
impl<DB> QueryFragment<DB> for Range where DB: crate::backend::Backend {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql(" RANGE ");
        Ok(())
    }
}simple_frame_expr!(
86    /// Range frame mode
87    ///
88    /// Requires to set a `ORDER BY` clause set via `window_order`
89    /// for the current window function call
90    Range,
91    " RANGE "
92);
93#[doc = r" Rows frame mode"]
#[doc = r""]
#[doc = r" This options specifies that the offset starts/ends"]
#[doc = r" a certain number of rows before/after the current row"]
pub struct Rows;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for Rows {
            type QueryId = Rows<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Rows {
}
#[automatically_derived]impl ::core::clone::Clone for Rows {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for Rows { }
#[automatically_derived]impl ::core::fmt::Debug for Rows {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Rows")
    }
}
impl<DB> QueryFragment<DB> for Rows where DB: crate::backend::Backend {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql(" ROWS ");
        Ok(())
    }
}simple_frame_expr!(
94    /// Rows frame mode
95    ///
96    /// This options specifies that the offset starts/ends
97    /// a certain number of rows before/after the current row
98    Rows,
99    " ROWS "
100);
101#[doc = r" Groups frame mode"]
#[doc = r""]
#[doc = r" This options specifies that the offset starts/ends"]
#[doc = r" a certain number of peer groups before or after"]
#[doc = r" the current row. A peer group is a set of rows that are"]
#[doc = r" equivalent in the `ORDER BY` ordering"]
#[doc = r""]
#[doc = r" There must be a `ORDER BY` clause set via `window_order`"]
#[doc = r" for the current window function call"]
pub struct Groups;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for Groups {
            type QueryId = Groups<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Groups {
}
#[automatically_derived]impl ::core::clone::Clone for Groups {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for Groups { }
#[automatically_derived]impl ::core::fmt::Debug for Groups {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Groups")
    }
}
impl<DB> QueryFragment<DB> for Groups where DB: crate::backend::Backend,
    Self: QueryFragment<DB, DB::WindowFrameClauseGroupSupport> {
    fn walk_ast<'b>(&'b self, pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        <Self as
                QueryFragment<DB,
                DB::WindowFrameClauseGroupSupport>>::walk_ast(self, pass)
    }
}
impl<DB>
    QueryFragment<DB,
    sql_dialect::window_frame_clause_group_support::IsoGroupWindowFrameUnit>
    for Groups where
    DB: crate::backend::Backend<WindowFrameClauseGroupSupport =
    sql_dialect::window_frame_clause_group_support::IsoGroupWindowFrameUnit> {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql(" GROUPS ");
        Ok(())
    }
}simple_frame_expr_with_bound!(
102    /// Groups frame mode
103    ///
104    /// This options specifies that the offset starts/ends
105    /// a certain number of peer groups before or after
106    /// the current row. A peer group is a set of rows that are
107    /// equivalent in the `ORDER BY` ordering
108    ///
109    /// There must be a `ORDER BY` clause set via `window_order`
110    /// for the current window function call
111    Groups,
112    WindowFrameClauseGroupSupport,
113    sql_dialect::window_frame_clause_group_support::IsoGroupWindowFrameUnit,
114    " GROUPS "
115);
116
117// start & end
118#[doc = r" A `UNBOUNDED PRECEDING` frame bound"]
#[doc = r""]
#[doc = r" This bound specifies that the frame starts with"]
#[doc = r" the first row of the partition"]
#[doc = r""]
#[doc = r" This option can be used as frame start"]
pub struct UnboundedPreceding;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for UnboundedPreceding {
            type QueryId = UnboundedPreceding<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for UnboundedPreceding {
}
#[automatically_derived]impl ::core::clone::Clone for UnboundedPreceding {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for UnboundedPreceding { }
#[automatically_derived]impl ::core::fmt::Debug for UnboundedPreceding {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "UnboundedPreceding")
    }
}
impl<DB> QueryFragment<DB> for UnboundedPreceding where
    DB: crate::backend::Backend {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("UNBOUNDED PRECEDING ");
        Ok(())
    }
}simple_frame_expr!(
119    /// A `UNBOUNDED PRECEDING` frame bound
120    ///
121    /// This bound specifies that the frame starts with
122    /// the first row of the partition
123    ///
124    /// This option can be used as frame start
125    UnboundedPreceding,
126    "UNBOUNDED PRECEDING "
127);
128#[doc = r" A `CURRENT ROW` frame bound"]
#[doc = r""]
#[doc = r" For the `RANGE` and `GROUP` frame mode this bound"]
#[doc = r" specifies that the current frame starts with the current"]
#[doc = r" rows first peer groups row. A peer group is defined as a"]
#[doc = r" set of rows with an equivalent `ORDER BY` ordering."]
#[doc = r""]
#[doc = r" For the `ROWS` mode `CURRENT ROW` simply means the current"]
#[doc = r" row"]
#[doc = r""]
#[doc = r" This option can be used as frame start and end"]
pub struct CurrentRow;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for CurrentRow {
            type QueryId = CurrentRow<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for CurrentRow {
}
#[automatically_derived]impl ::core::clone::Clone for CurrentRow {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for CurrentRow { }
#[automatically_derived]impl ::core::fmt::Debug for CurrentRow {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "CurrentRow")
    }
}
impl<DB> QueryFragment<DB> for CurrentRow where DB: crate::backend::Backend {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("CURRENT ROW ");
        Ok(())
    }
}simple_frame_expr!(
129    /// A `CURRENT ROW` frame bound
130    ///
131    /// For the `RANGE` and `GROUP` frame mode this bound
132    /// specifies that the current frame starts with the current
133    /// rows first peer groups row. A peer group is defined as a
134    /// set of rows with an equivalent `ORDER BY` ordering.
135    ///
136    /// For the `ROWS` mode `CURRENT ROW` simply means the current
137    /// row
138    ///
139    /// This option can be used as frame start and end
140    CurrentRow,
141    "CURRENT ROW "
142);
143#[doc = r" A `UNBOUNDED FOLLOWING` frame bound"]
#[doc = r""]
#[doc = r" This bound specifies that the frame ends with"]
#[doc = r" the last row of the partition"]
#[doc = r""]
#[doc = r" This option can be used as frame end"]
pub struct UnboundedFollowing;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for UnboundedFollowing {
            type QueryId = UnboundedFollowing<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for UnboundedFollowing {
}
#[automatically_derived]impl ::core::clone::Clone for UnboundedFollowing {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for UnboundedFollowing { }
#[automatically_derived]impl ::core::fmt::Debug for UnboundedFollowing {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "UnboundedFollowing")
    }
}
impl<DB> QueryFragment<DB> for UnboundedFollowing where
    DB: crate::backend::Backend {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("UNBOUNDED FOLLOWING ");
        Ok(())
    }
}simple_frame_expr!(
144    /// A `UNBOUNDED FOLLOWING` frame bound
145    ///
146    /// This bound specifies that the frame ends with
147    /// the last row of the partition
148    ///
149    /// This option can be used as frame end
150    UnboundedFollowing,
151    "UNBOUNDED FOLLOWING "
152);
153
154// exclusion
155#[doc = r" Exclude the current row from the window frame"]
pub struct ExcludeCurrentRow;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for ExcludeCurrentRow {
            type QueryId = ExcludeCurrentRow<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ExcludeCurrentRow {
}
#[automatically_derived]impl ::core::clone::Clone for ExcludeCurrentRow {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for ExcludeCurrentRow { }
#[automatically_derived]impl ::core::fmt::Debug for ExcludeCurrentRow {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "ExcludeCurrentRow")
    }
}
impl<DB> QueryFragment<DB> for ExcludeCurrentRow where
    DB: crate::backend::Backend,
    Self: QueryFragment<DB, DB::WindowFrameExclusionSupport> {
    fn walk_ast<'b>(&'b self, pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        <Self as
                QueryFragment<DB,
                DB::WindowFrameExclusionSupport>>::walk_ast(self, pass)
    }
}
impl<DB>
    QueryFragment<DB,
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> for
    ExcludeCurrentRow where
    DB: crate::backend::Backend<WindowFrameExclusionSupport =
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("EXCLUDE CURRENT ROW ");
        Ok(())
    }
}simple_frame_expr_with_bound!(
156    /// Exclude the current row from the window frame
157    ExcludeCurrentRow,
158    WindowFrameExclusionSupport,
159    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport,
160    "EXCLUDE CURRENT ROW "
161);
162#[doc = r" Exclude the current peer group from the window frame"]
#[doc = r""]
#[doc = r" A peer group is a set of rows with an equivalent `ORDER BY`"]
#[doc = r" ordering"]
pub struct ExcludeGroup;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for ExcludeGroup {
            type QueryId = ExcludeGroup<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ExcludeGroup {
}
#[automatically_derived]impl ::core::clone::Clone for ExcludeGroup {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for ExcludeGroup { }
#[automatically_derived]impl ::core::fmt::Debug for ExcludeGroup {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "ExcludeGroup")
    }
}
impl<DB> QueryFragment<DB> for ExcludeGroup where DB: crate::backend::Backend,
    Self: QueryFragment<DB, DB::WindowFrameExclusionSupport> {
    fn walk_ast<'b>(&'b self, pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        <Self as
                QueryFragment<DB,
                DB::WindowFrameExclusionSupport>>::walk_ast(self, pass)
    }
}
impl<DB>
    QueryFragment<DB,
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> for
    ExcludeGroup where
    DB: crate::backend::Backend<WindowFrameExclusionSupport =
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("EXCLUDE GROUP ");
        Ok(())
    }
}simple_frame_expr_with_bound!(
163    /// Exclude the current peer group from the window frame
164    ///
165    /// A peer group is a set of rows with an equivalent `ORDER BY`
166    /// ordering
167    ExcludeGroup,
168    WindowFrameExclusionSupport,
169    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport,
170    "EXCLUDE GROUP "
171);
172#[doc = r" Exclude any peers, but not the current row from the window frame"]
#[doc = r""]
#[doc = r" This excludes any row with an equivalent `ORDER BY` ordering"]
#[doc = r" to the current row from the frame window"]
pub struct ExcludeTies;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for ExcludeTies {
            type QueryId = ExcludeTies<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ExcludeTies {
}
#[automatically_derived]impl ::core::clone::Clone for ExcludeTies {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for ExcludeTies { }
#[automatically_derived]impl ::core::fmt::Debug for ExcludeTies {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "ExcludeTies")
    }
}
impl<DB> QueryFragment<DB> for ExcludeTies where DB: crate::backend::Backend,
    Self: QueryFragment<DB, DB::WindowFrameExclusionSupport> {
    fn walk_ast<'b>(&'b self, pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        <Self as
                QueryFragment<DB,
                DB::WindowFrameExclusionSupport>>::walk_ast(self, pass)
    }
}
impl<DB>
    QueryFragment<DB,
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> for
    ExcludeTies where
    DB: crate::backend::Backend<WindowFrameExclusionSupport =
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("EXCLUDE TIES ");
        Ok(())
    }
}simple_frame_expr_with_bound!(
173    /// Exclude any peers, but not the current row from the window frame
174    ///
175    /// This excludes any row with an equivalent `ORDER BY` ordering
176    /// to the current row from the frame window
177    ExcludeTies,
178    WindowFrameExclusionSupport,
179    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport,
180    "EXCLUDE TIES "
181);
182#[doc = r" Exclude no rows from the frame windows"]
#[doc = r""]
#[doc = r" This is the default behaviour if not specified"]
pub struct ExcludeNoOthers;
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for ExcludeNoOthers {
            type QueryId = ExcludeNoOthers<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for ExcludeNoOthers {
}
#[automatically_derived]impl ::core::clone::Clone for ExcludeNoOthers {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for ExcludeNoOthers { }
#[automatically_derived]impl ::core::fmt::Debug for ExcludeNoOthers {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "ExcludeNoOthers")
    }
}
impl<DB> QueryFragment<DB> for ExcludeNoOthers where
    DB: crate::backend::Backend,
    Self: QueryFragment<DB, DB::WindowFrameExclusionSupport> {
    fn walk_ast<'b>(&'b self, pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        <Self as
                QueryFragment<DB,
                DB::WindowFrameExclusionSupport>>::walk_ast(self, pass)
    }
}
impl<DB>
    QueryFragment<DB,
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> for
    ExcludeNoOthers where
    DB: crate::backend::Backend<WindowFrameExclusionSupport =
    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport> {
    fn walk_ast<'b>(&'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        pass.push_sql("EXCLUDE NO OTHERS ");
        Ok(())
    }
}simple_frame_expr_with_bound!(
183    /// Exclude no rows from the frame windows
184    ///
185    /// This is the default behaviour if not specified
186    ExcludeNoOthers,
187    WindowFrameExclusionSupport,
188    sql_dialect::window_frame_exclusion_support::FrameExclusionSupport,
189    "EXCLUDE NO OTHERS "
190);
191
192/// A preceding frame clause expression with a fixed offset
193///
194/// Can be constructed via [`FrameBoundDsl::preceding`]
195#[derive(#[automatically_derived]impl<T: ::core::clone::Clone> ::core::clone::Clone for
    OffsetPreceding<T> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self {
        OffsetPreceding(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]impl<T: ::core::marker::Copy> ::core::marker::Copy for
    OffsetPreceding<T> {
}Copy, #[automatically_derived]impl<T: ::core::fmt::Debug> ::core::fmt::Debug for
    OffsetPreceding<T> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "OffsetPreceding", &&self.0)
    }
}Debug)]
196pub struct OffsetPreceding<T = u64>(T);
197
198// manual impl as the derive makes this dependent on a `T: QueryId` impl
199// which is wrong
200impl QueryId for OffsetPreceding {
201    type QueryId = ();
202
203    // it's not safe to cache by type id
204    // as we inline a dynamic value (the offset) directly
205    // into the SQL
206    const HAS_STATIC_QUERY_ID: bool = false;
207}
208
209impl<DB> QueryFragment<DB> for OffsetPreceding
210where
211    DB: crate::backend::Backend,
212{
213    fn walk_ast<'b>(
214        &'b self,
215        mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
216    ) -> crate::QueryResult<()> {
217        // we cannot use binds here as mysql doesn't support it :(
218        // at least it's safe to just insert a number here
219        pass.push_sql(&self.0.to_string());
220        pass.push_sql(" PRECEDING ");
221        Ok(())
222    }
223}
224
225/// A following frame clause expression with a fixed offset
226///
227/// Can be constructed via [`FrameBoundDsl::following`]
228#[derive(#[automatically_derived]impl<I: ::core::clone::Clone> ::core::clone::Clone for
    OffsetFollowing<I> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self {
        OffsetFollowing(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]impl<I: ::core::marker::Copy> ::core::marker::Copy for
    OffsetFollowing<I> {
}Copy, #[automatically_derived]impl<I: ::core::fmt::Debug> ::core::fmt::Debug for
    OffsetFollowing<I> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "OffsetFollowing", &&self.0)
    }
}Debug)]
229pub struct OffsetFollowing<I = u64>(I);
230
231// manual impl as the derive makes this dependent on a `T: QueryId` impl
232// which is wrong
233impl QueryId for OffsetFollowing {
234    type QueryId = ();
235
236    // it's not safe to cache by type id
237    // as we inline a dynamic value (the offset) directly
238    // into the SQL
239    const HAS_STATIC_QUERY_ID: bool = false;
240}
241
242impl<DB> QueryFragment<DB> for OffsetFollowing
243where
244    DB: crate::backend::Backend,
245{
246    fn walk_ast<'b>(
247        &'b self,
248        mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
249    ) -> crate::QueryResult<()> {
250        // we cannot use binds here as mysql doesn't support it :(
251        // at least it's safe to just insert a number here
252        pass.push_sql(&self.0.to_string());
253        pass.push_sql(" FOLLOWING ");
254        Ok(())
255    }
256}
257
258pub trait FrameDsl<F> {
259    type Output;
260
261    fn frame(self, expr: F) -> Self::Output;
262}
263
264#[diagnostic::on_unimplemented(
265    message = "`Groups` frame clauses require a ordered window function",
266    note = "call `.window_order(some_column)` first"
267)]
268pub trait ValidFrameClause<O> {}
269
270impl<O, Kind, Start, End, Exclusion> ValidFrameClause<O>
271    for BetweenFrame<Kind, Start, End, Exclusion>
272where
273    Kind: ValidFrameClause<O>,
274{
275}
276impl<O, Kind, Start, Exclusion> ValidFrameClause<O> for StartFrame<Kind, Start, Exclusion> where
277    Kind: ValidFrameClause<O>
278{
279}
280impl<O> ValidFrameClause<O> for Rows {}
281impl<O> ValidFrameClause<O> for Range {}
282impl<O> ValidFrameClause<Order<O, true>> for Groups {}
283
284impl<E, Fn, Filter, Frame, Partition, Order> FrameDsl<E>
285    for AggregateExpression<Fn, NoPrefix, NoOrder, Filter, OverClause<Partition, Order, Frame>>
286where
287    E: FrameClauseExpression,
288    E: ValidFrameClause<Order>,
289    Filter: ValidAggregateFilterForWindow<Fn, OverClause<Partition, Order, FrameClause<E>>>,
290{
291    type Output = AggregateExpression<
292        Fn,
293        NoPrefix,
294        NoOrder,
295        Filter,
296        OverClause<Partition, Order, FrameClause<E>>,
297    >;
298
299    fn frame(self, expr: E) -> Self::Output {
300        AggregateExpression {
301            prefix: self.prefix,
302            function: self.function,
303            order: self.order,
304            filter: self.filter,
305            window: OverClause {
306                partition_by: self.window.partition_by,
307                order: self.window.order,
308                frame_clause: FrameClause(expr),
309            },
310        }
311    }
312}
313
314impl<E, Fn, Filter> FrameDsl<E> for AggregateExpression<Fn, NoPrefix, NoOrder, Filter, NoWindow>
315where
316    E: FrameClauseExpression,
317    E: ValidFrameClause<NoOrder>,
318    Filter: ValidAggregateFilterForWindow<Fn, OverClause<NoPartition, NoOrder, FrameClause<E>>>,
319{
320    type Output = AggregateExpression<
321        Fn,
322        NoPrefix,
323        NoOrder,
324        Filter,
325        OverClause<NoPartition, NoOrder, FrameClause<E>>,
326    >;
327
328    fn frame(self, expr: E) -> Self::Output {
329        AggregateExpression {
330            prefix: self.prefix,
331            function: self.function,
332            order: self.order,
333            filter: self.filter,
334            window: OverClause {
335                partition_by: NoPartition,
336                order: NoOrder,
337                frame_clause: FrameClause(expr),
338            },
339        }
340    }
341}
342
343impl<E, Fn> FrameDsl<E> for Fn
344where
345    Fn: IsWindowFunction,
346    E: FrameClauseExpression,
347    E: ValidFrameClause<NoOrder>,
348{
349    type Output = AggregateExpression<
350        Fn,
351        NoPrefix,
352        NoOrder,
353        NoFilter,
354        OverClause<NoPartition, NoOrder, FrameClause<E>>,
355    >;
356
357    fn frame(self, expr: E) -> Self::Output {
358        AggregateExpression {
359            prefix: NoPrefix,
360            function: self,
361            order: NoOrder,
362            filter: NoFilter,
363            window: OverClause {
364                partition_by: NoPartition,
365                order: NoOrder,
366                frame_clause: FrameClause(expr),
367            },
368        }
369    }
370}
371
372pub trait FrameClauseExpression {}
373
374/// A marker trait for possible start frame expressions
375///
376/// See the list of types implementing this trait to understand
377/// what can be used in this position
378pub trait FrameClauseStartBound: Sealed {}
379
380/// A marker trait for possible end frame expressions
381///
382/// See the list of types implementing this trait to understand
383/// what can be used in this position
384pub trait FrameClauseEndBound: Sealed {}
385
386impl FrameClauseEndBound for UnboundedFollowing {}
387impl Sealed for UnboundedFollowing {}
388impl FrameClauseStartBound for UnboundedPreceding {}
389impl Sealed for UnboundedPreceding {}
390impl FrameClauseEndBound for CurrentRow {}
391impl FrameClauseStartBound for CurrentRow {}
392impl Sealed for CurrentRow {}
393impl FrameClauseEndBound for OffsetFollowing {}
394impl Sealed for OffsetFollowing {}
395impl FrameClauseStartBound for OffsetPreceding {}
396impl Sealed for OffsetPreceding {}
397
398/// A marker trait for possible frame exclusion expressions
399///
400/// See the list of types implementing this trait to understand
401/// what can be used in this position
402pub trait FrameClauseExclusion: Sealed {}
403
404impl FrameClauseExclusion for ExcludeGroup {}
405impl Sealed for ExcludeGroup {}
406impl FrameClauseExclusion for ExcludeNoOthers {}
407impl Sealed for ExcludeNoOthers {}
408impl FrameClauseExclusion for ExcludeTies {}
409impl Sealed for ExcludeTies {}
410impl FrameClauseExclusion for ExcludeCurrentRow {}
411impl Sealed for ExcludeCurrentRow {}
412
413/// Construct a frame clause for window functions from an integer
414pub trait FrameBoundDsl {
415    /// Use the preceding frame clause specification
416    fn preceding(self) -> OffsetPreceding;
417
418    /// Use the following frame clause specification
419    fn following(self) -> OffsetFollowing;
420}
421
422impl FrameBoundDsl for u64 {
423    fn preceding(self) -> OffsetPreceding {
424        OffsetPreceding(self)
425    }
426
427    fn following(self) -> OffsetFollowing {
428        OffsetFollowing(self)
429    }
430}
431// TODO: We might want to implement
432// it for datetime and date intervals?
433// The postgres documentation indicates that
434// something like `RANGE BETWEEN '1 day' PRECEDING AND '10 days' FOLLOWING`
435// is valid
436
437pub struct NoExclusion;
#[automatically_derived]impl ::core::fmt::Debug for NoExclusion {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "NoExclusion")
    }
}
#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for NoExclusion {
}
#[automatically_derived]impl ::core::clone::Clone for NoExclusion {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]impl ::core::marker::Copy for NoExclusion { }
const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for NoExclusion {
            type QueryId = NoExclusion<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };
impl<DB> crate::query_builder::QueryFragment<DB> for NoExclusion where
    DB: crate::backend::Backend + crate::backend::DieselReserveSpecialization
    {
    fn walk_ast<'b>(&'b self,
        _pass: crate::query_builder::AstPass<'_, 'b, DB>)
        -> crate::QueryResult<()> {
        Ok(())
    }
}empty_clause!(NoExclusion);
438
439#[derive(const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<Kind: diesel::query_builder::QueryId,
            Start: diesel::query_builder::QueryId,
            Exclusion: diesel::query_builder::QueryId>
            diesel::query_builder::QueryId for
            StartFrame<Kind, Start, Exclusion> {
            type QueryId =
                StartFrame<<Kind as diesel::query_builder::QueryId>::QueryId,
                <Start as diesel::query_builder::QueryId>::QueryId,
                <Exclusion as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <Kind as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                            &&
                            <Start as
                                diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                        <Exclusion as
                            diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <Kind as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                            ||
                            <Start as
                                diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                        <Exclusion as
                            diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                    false;
        }
    };QueryId, #[automatically_derived]impl<Kind: ::core::marker::Copy,
    Start: ::core::marker::Copy, Exclusion: ::core::marker::Copy>
    ::core::marker::Copy for StartFrame<Kind, Start, Exclusion> {
}Copy, #[automatically_derived]impl<Kind: ::core::clone::Clone,
    Start: ::core::clone::Clone, Exclusion: ::core::clone::Clone>
    ::core::clone::Clone for StartFrame<Kind, Start, Exclusion> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self {
        StartFrame {
            kind: ::core::clone::Clone::clone(&self.kind),
            start: ::core::clone::Clone::clone(&self.start),
            exclusion: ::core::clone::Clone::clone(&self.exclusion),
        }
    }
}Clone, #[automatically_derived]impl<Kind: ::core::fmt::Debug,
    Start: ::core::fmt::Debug, Exclusion: ::core::fmt::Debug>
    ::core::fmt::Debug for StartFrame<Kind, Start, Exclusion> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "StartFrame kind start exclusion", &self.kind, &self.start,
            &&self.exclusion)
    }
}Debug)]
440pub struct StartFrame<Kind, Start, Exclusion = NoExclusion> {
441    kind: Kind,
442    start: Start,
443    exclusion: Exclusion,
444}
445
446impl<Kind, Start, Exclusion, DB> QueryFragment<DB> for StartFrame<Kind, Start, Exclusion>
447where
448    Kind: QueryFragment<DB>,
449    Start: QueryFragment<DB>,
450    Exclusion: QueryFragment<DB>,
451    DB: crate::backend::Backend,
452{
453    fn walk_ast<'b>(
454        &'b self,
455        mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
456    ) -> crate::QueryResult<()> {
457        self.kind.walk_ast(pass.reborrow())?;
458        self.start.walk_ast(pass.reborrow())?;
459        self.exclusion.walk_ast(pass.reborrow())?;
460        Ok(())
461    }
462}
463
464impl<Kind, Start, Exclusion> FrameClauseExpression for StartFrame<Kind, Start, Exclusion> {}
465
466#[derive(const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<Kind: diesel::query_builder::QueryId,
            Start: diesel::query_builder::QueryId,
            End: diesel::query_builder::QueryId,
            Exclusion: diesel::query_builder::QueryId>
            diesel::query_builder::QueryId for
            BetweenFrame<Kind, Start, End, Exclusion> {
            type QueryId =
                BetweenFrame<<Kind as
                diesel::query_builder::QueryId>::QueryId,
                <Start as diesel::query_builder::QueryId>::QueryId,
                <End as diesel::query_builder::QueryId>::QueryId,
                <Exclusion as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <Kind as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                                &&
                                <Start as
                                    diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                            <End as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                        &&
                        <Exclusion as
                            diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <Kind as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                                ||
                                <Start as
                                    diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                            <End as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                        ||
                        <Exclusion as
                            diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                    false;
        }
    };QueryId, #[automatically_derived]impl<Kind: ::core::marker::Copy,
    Start: ::core::marker::Copy, End: ::core::marker::Copy,
    Exclusion: ::core::marker::Copy> ::core::marker::Copy for
    BetweenFrame<Kind, Start, End, Exclusion> {
}Copy, #[automatically_derived]impl<Kind: ::core::clone::Clone,
    Start: ::core::clone::Clone, End: ::core::clone::Clone,
    Exclusion: ::core::clone::Clone> ::core::clone::Clone for
    BetweenFrame<Kind, Start, End, Exclusion> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn clone(&self) -> Self {
        BetweenFrame {
            kind: ::core::clone::Clone::clone(&self.kind),
            start: ::core::clone::Clone::clone(&self.start),
            end: ::core::clone::Clone::clone(&self.end),
            exclusion: ::core::clone::Clone::clone(&self.exclusion),
        }
    }
}Clone, #[automatically_derived]impl<Kind: ::core::fmt::Debug,
    Start: ::core::fmt::Debug, End: ::core::fmt::Debug,
    Exclusion: ::core::fmt::Debug> ::core::fmt::Debug for
    BetweenFrame<Kind, Start, End, Exclusion> {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f,
            "BetweenFrame kind start end exclusion", &self.kind, &self.start,
            &self.end, &&self.exclusion)
    }
}Debug)]
467pub struct BetweenFrame<Kind, Start, End, Exclusion = NoExclusion> {
468    kind: Kind,
469    start: Start,
470    end: End,
471    exclusion: Exclusion,
472}
473
474impl<Kind, Start, End, Exclusion, DB> QueryFragment<DB>
475    for BetweenFrame<Kind, Start, End, Exclusion>
476where
477    Kind: QueryFragment<DB>,
478    Start: QueryFragment<DB>,
479    End: QueryFragment<DB>,
480    Exclusion: QueryFragment<DB>,
481    DB: crate::backend::Backend,
482{
483    fn walk_ast<'b>(
484        &'b self,
485        mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
486    ) -> crate::QueryResult<()> {
487        self.kind.walk_ast(pass.reborrow())?;
488        pass.push_sql(" BETWEEN ");
489        self.start.walk_ast(pass.reborrow())?;
490        pass.push_sql(" AND ");
491        self.end.walk_ast(pass.reborrow())?;
492        self.exclusion.walk_ast(pass.reborrow())?;
493        Ok(())
494    }
495}
496
497impl<Kind, Start, End, Exclusion> FrameClauseExpression
498    for BetweenFrame<Kind, Start, End, Exclusion>
499{
500}
501
502pub trait FrameClauseDslHelper: Sized {}
503
504/// Construct a frame clause for window functions
505pub trait FrameClauseDsl: FrameClauseDslHelper {
506    /// Construct a frame clause with a starting bound
507    fn frame_start_with<E>(self, start: E) -> super::dsl::FrameStartWith<Self, E>
508    where
509        E: FrameClauseStartBound,
510    {
511        StartFrame {
512            kind: self,
513            start,
514            exclusion: NoExclusion,
515        }
516    }
517
518    /// Construct a frame clause with a starting bound and an exclusion condition
519    fn frame_start_with_exclusion<E1, E2>(
520        self,
521        start: E1,
522        exclusion: E2,
523    ) -> super::dsl::FrameStartWithExclusion<Self, E1, E2>
524    where
525        E1: FrameClauseStartBound,
526        E2: FrameClauseExclusion,
527    {
528        StartFrame {
529            kind: self,
530            start,
531            exclusion,
532        }
533    }
534
535    /// Construct a between frame clause with a starting and end bound
536    fn frame_between<E1, E2>(self, start: E1, end: E2) -> super::dsl::FrameBetween<Self, E1, E2>
537    where
538        E1: FrameClauseStartBound,
539        E2: FrameClauseEndBound,
540    {
541        BetweenFrame {
542            kind: self,
543            start,
544            end,
545            exclusion: NoExclusion,
546        }
547    }
548
549    /// Construct a between frame clause with a starting and end bound  with an exclusion condition
550    fn frame_between_with_exclusion<E1, E2, E3>(
551        self,
552        start: E1,
553        end: E2,
554        exclusion: E3,
555    ) -> super::dsl::FrameBetweenWithExclusion<Self, E1, E2, E3>
556    where
557        E1: FrameClauseStartBound,
558        E2: FrameClauseEndBound,
559        E3: FrameClauseExclusion,
560    {
561        BetweenFrame {
562            kind: self,
563            start,
564            end,
565            exclusion,
566        }
567    }
568}
569
570impl<T> FrameClauseDsl for T where T: FrameClauseDslHelper {}
571
572impl FrameClauseDslHelper for Range {}
573impl FrameClauseDslHelper for Rows {}
574impl FrameClauseDslHelper for Groups {}
575
576pub trait Sealed {}