1use crate::deserialize::{self, Defaultable, FromSql};
2use crate::expression::AsExpression;
3use crate::expression::bound::Bound as SqlBound;
4use crate::pg::{Pg, PgTypeMetadata, PgValue};
5use crate::query_builder::bind_collector::ByteWrapper;
6use crate::serialize::{self, IsNull, Output, ToSql};
7use crate::sql_types::*;
8use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
9use core::ops::Bound;
10use core::ops::RangeBounds;
11use std::io::Write;
12
13macro_rules! multirange_has_sql_type {
15 ($ty:ty, $oid:expr_2021, $array_oid:expr_2021) => {
16 #[cfg(feature = "postgres_backend")]
17 impl HasSqlType<$ty> for Pg {
18 fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
19 PgTypeMetadata::new($oid, $array_oid)
20 }
21 }
22 };
23}
24impl HasSqlType<Datemultirange> for Pg {
fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
PgTypeMetadata::new(4535, 6155)
}
}multirange_has_sql_type!(Datemultirange, 4535, 6155);
25impl HasSqlType<Int4multirange> for Pg {
fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
PgTypeMetadata::new(4451, 6150)
}
}multirange_has_sql_type!(Int4multirange, 4451, 6150);
26impl HasSqlType<Int8multirange> for Pg {
fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
PgTypeMetadata::new(4536, 6157)
}
}multirange_has_sql_type!(Int8multirange, 4536, 6157);
27impl HasSqlType<Nummultirange> for Pg {
fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
PgTypeMetadata::new(4532, 6151)
}
}multirange_has_sql_type!(Nummultirange, 4532, 6151);
28impl HasSqlType<Tsmultirange> for Pg {
fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
PgTypeMetadata::new(4533, 6152)
}
}multirange_has_sql_type!(Tsmultirange, 4533, 6152);
29impl HasSqlType<Tstzmultirange> for Pg {
fn metadata(_: &mut Self::MetadataLookup) -> PgTypeMetadata {
PgTypeMetadata::new(4534, 6153)
}
}multirange_has_sql_type!(Tstzmultirange, 4534, 6153);
30
31macro_rules! multirange_as_expression {
32 ($ty:ty, $sql_type:ty) => {
33 #[cfg(feature = "postgres_backend")]
34 #[allow(clippy::extra_unused_lifetimes)]
37 impl<'a, 'b, ST: 'static, T> AsExpression<$sql_type> for $ty {
38 type Expression = SqlBound<$sql_type, Self>;
39 fn as_expression(self) -> Self::Expression {
40 SqlBound::new(self)
41 }
42 }
43 };
44}
45
46macro_rules! multirange_as_expressions {
47 ($ty:ty) => {
48 multirange_as_expression!(&'a [$ty], Multirange<ST>);
49 multirange_as_expression!(&'a [$ty], Nullable<Multirange<ST>>);
50 multirange_as_expression!(&'a &'b [$ty], Multirange<ST>);
51 multirange_as_expression!(&'a &'b [$ty], Nullable<Multirange<ST>>);
52 multirange_as_expression!(Vec<$ty>, Multirange<ST>);
53 multirange_as_expression!(Vec<$ty>, Nullable<Multirange<ST>>);
54 multirange_as_expression!(&'a Vec<$ty>, Multirange<ST>);
55 multirange_as_expression!(&'a Vec<$ty>, Nullable<Multirange<ST>>);
56 multirange_as_expression!(&'a &'b Vec<$ty>, Multirange<ST>);
57 multirange_as_expression!(&'a &'b Vec<$ty>, Nullable<Multirange<ST>>);
58 };
59}
60
61#[allow(clippy :: extra_unused_lifetimes)]
impl<'a, 'b, ST: 'static, T> AsExpression<Nullable<Multirange<ST>>> for
&'a &'b Vec<(Bound<T>, Bound<T>)> {
type Expression = SqlBound<Nullable<Multirange<ST>>, Self>;
fn as_expression(self) -> Self::Expression { SqlBound::new(self) }
}multirange_as_expressions!((Bound<T>, Bound<T>));
62#[allow(clippy :: extra_unused_lifetimes)]
impl<'a, 'b, ST: 'static, T> AsExpression<Nullable<Multirange<ST>>> for
&'a &'b Vec<core::ops::Range<T>> {
type Expression = SqlBound<Nullable<Multirange<ST>>, Self>;
fn as_expression(self) -> Self::Expression { SqlBound::new(self) }
}multirange_as_expressions!(core::ops::Range<T>);
63#[allow(clippy :: extra_unused_lifetimes)]
impl<'a, 'b, ST: 'static, T> AsExpression<Nullable<Multirange<ST>>> for
&'a &'b Vec<core::ops::RangeInclusive<T>> {
type Expression = SqlBound<Nullable<Multirange<ST>>, Self>;
fn as_expression(self) -> Self::Expression { SqlBound::new(self) }
}multirange_as_expressions!(core::ops::RangeInclusive<T>);
64#[allow(clippy :: extra_unused_lifetimes)]
impl<'a, 'b, ST: 'static, T> AsExpression<Nullable<Multirange<ST>>> for
&'a &'b Vec<core::ops::RangeToInclusive<T>> {
type Expression = SqlBound<Nullable<Multirange<ST>>, Self>;
fn as_expression(self) -> Self::Expression { SqlBound::new(self) }
}multirange_as_expressions!(core::ops::RangeToInclusive<T>);
65#[allow(clippy :: extra_unused_lifetimes)]
impl<'a, 'b, ST: 'static, T> AsExpression<Nullable<Multirange<ST>>> for
&'a &'b Vec<core::ops::RangeFrom<T>> {
type Expression = SqlBound<Nullable<Multirange<ST>>, Self>;
fn as_expression(self) -> Self::Expression { SqlBound::new(self) }
}multirange_as_expressions!(core::ops::RangeFrom<T>);
66#[allow(clippy :: extra_unused_lifetimes)]
impl<'a, 'b, ST: 'static, T> AsExpression<Nullable<Multirange<ST>>> for
&'a &'b Vec<core::ops::RangeTo<T>> {
type Expression = SqlBound<Nullable<Multirange<ST>>, Self>;
fn as_expression(self) -> Self::Expression { SqlBound::new(self) }
}multirange_as_expressions!(core::ops::RangeTo<T>);
67
68#[cfg(feature = "postgres_backend")]
69impl<T, ST> FromSql<Multirange<ST>, Pg> for Vec<(Bound<T>, Bound<T>)>
70where
71 T: FromSql<ST, Pg> + Defaultable,
72{
73 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
74 let mut bytes = value.as_bytes();
75 let len = bytes.read_u32::<NetworkEndian>()?;
76
77 (0..len)
78 .map(|_| {
79 let range_size: usize = bytes.read_i32::<NetworkEndian>()?.try_into()?;
80 let (range_bytes, new_bytes) = bytes.split_at(range_size);
81 bytes = new_bytes;
82 FromSql::from_sql(PgValue::new_internal(range_bytes, &value))
83 })
84 .collect()
85 }
86}
87
88fn to_sql<'c, ST, T, I>(iter: I, out: &mut Output<'_, '_, Pg>) -> serialize::Result
89where
90 ST: 'static,
91 T: ToSql<ST, Pg> + 'c,
92 I: Iterator<Item = (Bound<&'c T>, Bound<&'c T>)> + ExactSizeIterator,
93{
94 out.write_u32::<NetworkEndian>(iter.len().try_into()?)?;
95
96 let mut buffer = Vec::new();
97 for value in iter {
98 {
99 let mut inner_buffer = Output::new(ByteWrapper(&mut buffer), out.metadata_lookup());
100 ToSql::<Range<ST>, Pg>::to_sql(&value, &mut inner_buffer)?;
101 }
102 let buffer_len: i32 = buffer.len().try_into()?;
103 out.write_i32::<NetworkEndian>(buffer_len)?;
104 out.write_all(&buffer)?;
105 buffer.clear();
106 }
107
108 Ok(IsNull::No)
109}
110
111#[cfg(feature = "postgres_backend")]
112impl<T, ST> ToSql<Multirange<ST>, Pg> for [(Bound<T>, Bound<T>)]
113where
114 T: ToSql<ST, Pg>,
115{
116 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
117 to_sql(self.iter().map(|r| (r.0.as_ref(), r.1.as_ref())), out)
118 }
119}
120
121#[cfg(feature = "postgres_backend")]
122impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<(Bound<T>, Bound<T>)>
123where
124 T: ToSql<ST, Pg>,
125 [(Bound<T>, Bound<T>)]: ToSql<Multirange<ST>, Pg>,
126{
127 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
128 ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
129 }
130}
131
132macro_rules! multirange_std_to_sql {
133 ($ty:ty) => {
134 #[cfg(feature = "postgres_backend")]
135 impl<ST, T> ToSql<Multirange<ST>, Pg> for [$ty]
136 where
137 ST: 'static,
138 T: ToSql<ST, Pg>,
139 {
140 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
141 to_sql(
142 self.into_iter().map(|r| (r.start_bound(), r.end_bound())),
143 out,
144 )
145 }
146 }
147
148 #[cfg(feature = "postgres_backend")]
149 impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<$ty>
150 where
151 T: ToSql<ST, Pg>,
152 [$ty]: ToSql<Multirange<ST>, Pg>,
153 {
154 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
155 ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
156 }
157 }
158 };
159}
160
161impl<ST, T> ToSql<Multirange<ST>, Pg> for [core::ops::Range<T>] where
ST: 'static, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
to_sql(self.into_iter().map(|r| (r.start_bound(), r.end_bound())),
out)
}
}
impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<core::ops::Range<T>> where
T: ToSql<ST, Pg>, [core::ops::Range<T>]: ToSql<Multirange<ST>, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
}
}multirange_std_to_sql!(core::ops::Range<T>);
162impl<ST, T> ToSql<Multirange<ST>, Pg> for [core::ops::RangeInclusive<T>] where
ST: 'static, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
to_sql(self.into_iter().map(|r| (r.start_bound(), r.end_bound())),
out)
}
}
impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<core::ops::RangeInclusive<T>>
where T: ToSql<ST, Pg>,
[core::ops::RangeInclusive<T>]: ToSql<Multirange<ST>, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
}
}multirange_std_to_sql!(core::ops::RangeInclusive<T>);
163impl<ST, T> ToSql<Multirange<ST>, Pg> for [core::ops::RangeFrom<T>] where
ST: 'static, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
to_sql(self.into_iter().map(|r| (r.start_bound(), r.end_bound())),
out)
}
}
impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<core::ops::RangeFrom<T>> where
T: ToSql<ST, Pg>, [core::ops::RangeFrom<T>]: ToSql<Multirange<ST>, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
}
}multirange_std_to_sql!(core::ops::RangeFrom<T>);
164impl<ST, T> ToSql<Multirange<ST>, Pg> for [core::ops::RangeTo<T>] where
ST: 'static, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
to_sql(self.into_iter().map(|r| (r.start_bound(), r.end_bound())),
out)
}
}
impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<core::ops::RangeTo<T>> where
T: ToSql<ST, Pg>, [core::ops::RangeTo<T>]: ToSql<Multirange<ST>, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
}
}multirange_std_to_sql!(core::ops::RangeTo<T>);
165impl<ST, T> ToSql<Multirange<ST>, Pg> for [core::ops::RangeToInclusive<T>]
where ST: 'static, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
to_sql(self.into_iter().map(|r| (r.start_bound(), r.end_bound())),
out)
}
}
impl<T, ST> ToSql<Multirange<ST>, Pg> for Vec<core::ops::RangeToInclusive<T>>
where T: ToSql<ST, Pg>,
[core::ops::RangeToInclusive<T>]: ToSql<Multirange<ST>, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self.as_slice(), out)
}
}multirange_std_to_sql!(core::ops::RangeToInclusive<T>);
166
167macro_rules! multirange_to_sql_nullable {
168 ($ty:ty) => {
169 impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for [$ty]
170 where
171 ST: 'static,
172 [$ty]: ToSql<ST, Pg>,
173 T: ToSql<ST, Pg>,
174 {
175 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
176 ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
177 }
178 }
179
180 impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for Vec<$ty>
181 where
182 ST: 'static,
183 Vec<$ty>: ToSql<ST, Pg>,
184 T: ToSql<ST, Pg>,
185 {
186 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
187 ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
188 }
189 }
190 };
191}
192
193impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for [(Bound<T>, Bound<T>)]
where ST: 'static, [(Bound<T>, Bound<T>)]: ToSql<ST, Pg>, T: ToSql<ST, Pg>
{
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}
impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for Vec<(Bound<T>, Bound<T>)>
where ST: 'static, Vec<(Bound<T>, Bound<T>)>: ToSql<ST, Pg>,
T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}multirange_to_sql_nullable!((Bound<T>, Bound<T>));
194impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for [core::ops::Range<T>]
where ST: 'static, [core::ops::Range<T>]: ToSql<ST, Pg>, T: ToSql<ST, Pg>
{
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}
impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for Vec<core::ops::Range<T>>
where ST: 'static, Vec<core::ops::Range<T>>: ToSql<ST, Pg>,
T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}multirange_to_sql_nullable!(core::ops::Range<T>);
195impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for
[core::ops::RangeInclusive<T>] where ST: 'static,
[core::ops::RangeInclusive<T>]: ToSql<ST, Pg>, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}
impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for
Vec<core::ops::RangeInclusive<T>> where ST: 'static,
Vec<core::ops::RangeInclusive<T>>: ToSql<ST, Pg>, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}multirange_to_sql_nullable!(core::ops::RangeInclusive<T>);
196impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for [core::ops::RangeFrom<T>]
where ST: 'static, [core::ops::RangeFrom<T>]: ToSql<ST, Pg>,
T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}
impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for
Vec<core::ops::RangeFrom<T>> where ST: 'static,
Vec<core::ops::RangeFrom<T>>: ToSql<ST, Pg>, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}multirange_to_sql_nullable!(core::ops::RangeFrom<T>);
197impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for [core::ops::RangeTo<T>]
where ST: 'static, [core::ops::RangeTo<T>]: ToSql<ST, Pg>,
T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}
impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for Vec<core::ops::RangeTo<T>>
where ST: 'static, Vec<core::ops::RangeTo<T>>: ToSql<ST, Pg>,
T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}multirange_to_sql_nullable!(core::ops::RangeTo<T>);
198impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for
[core::ops::RangeToInclusive<T>] where ST: 'static,
[core::ops::RangeToInclusive<T>]: ToSql<ST, Pg>, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}
impl<T, ST> ToSql<Nullable<Multirange<ST>>, Pg> for
Vec<core::ops::RangeToInclusive<T>> where ST: 'static,
Vec<core::ops::RangeToInclusive<T>>: ToSql<ST, Pg>, T: ToSql<ST, Pg> {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>)
-> serialize::Result {
ToSql::<Multirange<ST>, Pg>::to_sql(self, out)
}
}multirange_to_sql_nullable!(core::ops::RangeToInclusive<T>);