Skip to main content

diesel/sqlite/query_builder/
limit_offset.rs

1use crate::query_builder::limit_clause::{LimitClause, NoLimitClause};
2use crate::query_builder::limit_offset_clause::{
3    BoxedCloneLimitOffsetClause, BoxedLimitOffsetClause, LimitOffsetClause,
4};
5use crate::query_builder::offset_clause::{NoOffsetClause, OffsetClause};
6use crate::query_builder::{AstPass, IntoBoxedClause, IntoBoxedCloneClause, QueryFragment};
7use crate::result::QueryResult;
8use crate::sqlite::Sqlite;
9use alloc::boxed::Box;
10use alloc::sync::Arc;
11
12impl QueryFragment<Sqlite> for LimitOffsetClause<NoLimitClause, NoOffsetClause> {
13    fn walk_ast<'b>(&'b self, _out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
14        Ok(())
15    }
16}
17
18impl<L> QueryFragment<Sqlite> for LimitOffsetClause<LimitClause<L>, NoOffsetClause>
19where
20    LimitClause<L>: QueryFragment<Sqlite>,
21{
22    fn walk_ast<'b>(&'b self, out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
23        self.limit_clause.walk_ast(out)?;
24        Ok(())
25    }
26}
27
28impl<O> QueryFragment<Sqlite> for LimitOffsetClause<NoLimitClause, OffsetClause<O>>
29where
30    OffsetClause<O>: QueryFragment<Sqlite>,
31{
32    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
33        // Sqlite requires a limit clause in front of any offset clause
34        // using `LIMIT -1` is the same as not having any limit clause
35        // https://sqlite.org/lang_select.html
36        out.push_sql(" LIMIT -1 ");
37        self.offset_clause.walk_ast(out)?;
38        Ok(())
39    }
40}
41
42impl<L, O> QueryFragment<Sqlite> for LimitOffsetClause<LimitClause<L>, OffsetClause<O>>
43where
44    LimitClause<L>: QueryFragment<Sqlite>,
45    OffsetClause<O>: QueryFragment<Sqlite>,
46{
47    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
48        self.limit_clause.walk_ast(out.reborrow())?;
49        self.offset_clause.walk_ast(out.reborrow())?;
50        Ok(())
51    }
52}
53
54impl QueryFragment<Sqlite> for BoxedLimitOffsetClause<'_, Sqlite> {
55    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
56        match (self.limit.as_ref(), self.offset.as_ref()) {
57            (Some(limit), Some(offset)) => {
58                limit.walk_ast(out.reborrow())?;
59                offset.walk_ast(out.reborrow())?;
60            }
61            (Some(limit), None) => {
62                limit.walk_ast(out.reborrow())?;
63            }
64            (None, Some(offset)) => {
65                // See the `QueryFragment` implementation for `LimitOffsetClause` for details.
66                out.push_sql(" LIMIT -1 ");
67                offset.walk_ast(out.reborrow())?;
68            }
69            (None, None) => {}
70        }
71        Ok(())
72    }
73}
74
75impl QueryFragment<Sqlite> for BoxedCloneLimitOffsetClause<'_, Sqlite> {
76    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
77        match (self.limit.as_ref(), self.offset.as_ref()) {
78            (Some(limit), Some(offset)) => {
79                limit.walk_ast(out.reborrow())?;
80                offset.walk_ast(out.reborrow())?;
81            }
82            (Some(limit), None) => {
83                limit.walk_ast(out.reborrow())?;
84            }
85            (None, Some(offset)) => {
86                // See the `QueryFragment` implementation for `LimitOffsetClause` for details.
87                out.push_sql(" LIMIT -1 ");
88                offset.walk_ast(out.reborrow())?;
89            }
90            (None, None) => {}
91        }
92        Ok(())
93    }
94}
95
96// Have explicit impls here because we need to set `Some`/`None` for the clauses
97// correspondingly, otherwise we cannot match on it in the `QueryFragment` impl
98// above
99impl<'a> IntoBoxedClause<'a, Sqlite> for LimitOffsetClause<NoLimitClause, NoOffsetClause> {
100    type BoxedClause = BoxedLimitOffsetClause<'a, Sqlite>;
101
102    fn into_boxed(self) -> Self::BoxedClause {
103        BoxedLimitOffsetClause {
104            limit: None,
105            offset: None,
106        }
107    }
108}
109
110impl<'a, L> IntoBoxedClause<'a, Sqlite> for LimitOffsetClause<LimitClause<L>, NoOffsetClause>
111where
112    L: QueryFragment<Sqlite> + Send + 'a,
113{
114    type BoxedClause = BoxedLimitOffsetClause<'a, Sqlite>;
115
116    fn into_boxed(self) -> Self::BoxedClause {
117        BoxedLimitOffsetClause {
118            limit: Some(Box::new(self.limit_clause)),
119            offset: None,
120        }
121    }
122}
123
124impl<'a, O> IntoBoxedClause<'a, Sqlite> for LimitOffsetClause<NoLimitClause, OffsetClause<O>>
125where
126    O: QueryFragment<Sqlite> + Send + 'a,
127{
128    type BoxedClause = BoxedLimitOffsetClause<'a, Sqlite>;
129
130    fn into_boxed(self) -> Self::BoxedClause {
131        BoxedLimitOffsetClause {
132            limit: None,
133            offset: Some(Box::new(self.offset_clause)),
134        }
135    }
136}
137
138impl<'a, L, O> IntoBoxedClause<'a, Sqlite> for LimitOffsetClause<LimitClause<L>, OffsetClause<O>>
139where
140    L: QueryFragment<Sqlite> + Send + 'a,
141    O: QueryFragment<Sqlite> + Send + 'a,
142{
143    type BoxedClause = BoxedLimitOffsetClause<'a, Sqlite>;
144
145    fn into_boxed(self) -> Self::BoxedClause {
146        BoxedLimitOffsetClause {
147            limit: Some(Box::new(self.limit_clause)),
148            offset: Some(Box::new(self.offset_clause)),
149        }
150    }
151}
152
153impl<'a> IntoBoxedCloneClause<'a, Sqlite> for LimitOffsetClause<NoLimitClause, NoOffsetClause> {
154    type BoxedCloneClause = BoxedCloneLimitOffsetClause<'a, Sqlite>;
155
156    fn into_boxed_clone(self) -> Self::BoxedCloneClause {
157        BoxedCloneLimitOffsetClause {
158            limit: None,
159            offset: None,
160        }
161    }
162}
163
164impl<'a, L> IntoBoxedCloneClause<'a, Sqlite> for LimitOffsetClause<LimitClause<L>, NoOffsetClause>
165where
166    L: QueryFragment<Sqlite> + Send + Sync + 'a,
167{
168    type BoxedCloneClause = BoxedCloneLimitOffsetClause<'a, Sqlite>;
169
170    fn into_boxed_clone(self) -> Self::BoxedCloneClause {
171        BoxedCloneLimitOffsetClause {
172            limit: Some(Arc::new(self.limit_clause)),
173            offset: None,
174        }
175    }
176}
177
178impl<'a, O> IntoBoxedCloneClause<'a, Sqlite> for LimitOffsetClause<NoLimitClause, OffsetClause<O>>
179where
180    O: QueryFragment<Sqlite> + Send + Sync + 'a,
181{
182    type BoxedCloneClause = BoxedCloneLimitOffsetClause<'a, Sqlite>;
183
184    fn into_boxed_clone(self) -> Self::BoxedCloneClause {
185        BoxedCloneLimitOffsetClause {
186            limit: None,
187            offset: Some(Arc::new(self.offset_clause)),
188        }
189    }
190}
191
192impl<'a, L, O> IntoBoxedCloneClause<'a, Sqlite>
193    for LimitOffsetClause<LimitClause<L>, OffsetClause<O>>
194where
195    L: QueryFragment<Sqlite> + Send + Sync + 'a,
196    O: QueryFragment<Sqlite> + Send + Sync + 'a,
197{
198    type BoxedCloneClause = BoxedCloneLimitOffsetClause<'a, Sqlite>;
199
200    fn into_boxed_clone(self) -> Self::BoxedCloneClause {
201        BoxedCloneLimitOffsetClause {
202            limit: Some(Arc::new(self.limit_clause)),
203            offset: Some(Arc::new(self.offset_clause)),
204        }
205    }
206}