1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#![allow(clippy::as_conversions)]
use std::error::Error;
use std::fmt;
use byteorder::{NetworkEndian, ReadBytesExt};
use bytes::{BufMut, BytesMut};
use postgres_types::{to_sql_checked, FromSql, IsNull, ToSql, Type};
use repr::adt::interval::Interval as ReprInterval;
#[derive(Debug, Clone)]
pub struct Interval(pub ReprInterval);
impl fmt::Display for Interval {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl ToSql for Interval {
fn to_sql(
&self,
_: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + 'static + Send + Sync>> {
let days = std::cmp::min(self.0.days() as i128, i32::MAX as i128);
let ns = self.0.duration - days * 24 * 60 * 60 * 1_000_000_000;
out.put_i64((ns / 1000) as i64);
out.put_i32(days as i32);
out.put_i32(self.0.months);
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
matches!(*ty, Type::INTERVAL)
}
to_sql_checked!();
}
impl<'a> FromSql<'a> for Interval {
fn from_sql(_: &Type, mut raw: &'a [u8]) -> Result<Interval, Box<dyn Error + Sync + Send>> {
let micros = raw.read_i64::<NetworkEndian>()?;
let days = raw.read_i32::<NetworkEndian>()?;
let months = raw.read_i32::<NetworkEndian>()?;
Ok(Interval(
ReprInterval::new(months, days as i64 * 24 * 60 * 60, micros * 1000).unwrap(),
))
}
fn accepts(ty: &Type) -> bool {
matches!(*ty, Type::INTERVAL)
}
}