drizzle_core/
pagination.rs1use crate::SQL;
2use crate::expr::Nullability;
3use crate::placeholder::{Placeholder, TypedPlaceholder};
4use crate::prelude::Cow;
5use crate::traits::{SQLParam, ToSQL};
6use crate::types::Integral;
7
8mod private {
9 pub trait Sealed {}
10}
11
12#[diagnostic::on_unimplemented(
26 message = "`{Self}` cannot be used as a LIMIT/OFFSET argument",
27 label = "expected a non-negative integer value or an integer placeholder"
28)]
29pub trait PaginationArg<'a, V: SQLParam + 'a>: private::Sealed {
30 #[track_caller]
31 fn into_pagination_sql(self) -> SQL<'a, V>;
32}
33
34fn pagination_value_sql<'a, V>(value: usize) -> SQL<'a, V>
37where
38 V: SQLParam + 'a,
39{
40 match V::pagination_param(value) {
41 Some(param) => SQL::param(Cow::Owned(param)),
42 None => SQL::number(value),
43 }
44}
45
46macro_rules! impl_unsigned_pagination_arg {
47 ($($ty:ty),+ $(,)?) => {
48 $(
49 impl private::Sealed for $ty {}
50
51 impl<'a, V> PaginationArg<'a, V> for $ty
52 where
53 V: SQLParam + 'a,
54 {
55 #[track_caller]
56 fn into_pagination_sql(self) -> SQL<'a, V> {
57 let value =
58 usize::try_from(self).expect("LIMIT/OFFSET value must fit usize");
59 pagination_value_sql(value)
60 }
61 }
62 )+
63 };
64}
65
66macro_rules! impl_signed_pagination_arg {
67 ($($ty:ty),+ $(,)?) => {
68 $(
69 impl private::Sealed for $ty {}
70
71 impl<'a, V> PaginationArg<'a, V> for $ty
72 where
73 V: SQLParam + 'a,
74 {
75 #[track_caller]
76 fn into_pagination_sql(self) -> SQL<'a, V> {
77 let value = usize::try_from(self)
78 .expect("LIMIT/OFFSET value must be non-negative and fit usize");
79 pagination_value_sql(value)
80 }
81 }
82 )+
83 };
84}
85
86impl_unsigned_pagination_arg!(usize, u8, u16, u32, u64);
87impl_signed_pagination_arg!(isize, i8, i16, i32, i64);
88
89impl private::Sealed for Placeholder {}
90
91impl<'a, V> PaginationArg<'a, V> for Placeholder
92where
93 V: SQLParam + 'a,
94{
95 #[track_caller]
96 fn into_pagination_sql(self) -> SQL<'a, V> {
97 self.to_sql()
98 }
99}
100
101impl<T, N> private::Sealed for TypedPlaceholder<T, N>
102where
103 T: Integral,
104 N: Nullability,
105{
106}
107
108impl<'a, V, T, N> PaginationArg<'a, V> for TypedPlaceholder<T, N>
109where
110 V: SQLParam + 'a,
111 T: Integral,
112 N: Nullability,
113{
114 #[track_caller]
115 fn into_pagination_sql(self) -> SQL<'a, V> {
116 self.to_sql()
117 }
118}