Skip to main content

sentinel_driver/types/
interval.rs

1use bytes::{BufMut, BytesMut};
2
3use crate::error::{Error, Result};
4use crate::types::{FromSql, Oid, ToSql};
5
6/// PostgreSQL INTERVAL type.
7///
8/// Stored as three components matching PG's internal representation:
9/// - `months` -- number of months (years x 12 + months)
10/// - `days` -- number of days (not normalized to months)
11/// - `microseconds` -- time component in microseconds
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub struct PgInterval {
14    pub months: i32,
15    pub days: i32,
16    pub microseconds: i64,
17}
18
19impl ToSql for PgInterval {
20    fn oid(&self) -> Oid {
21        Oid::INTERVAL
22    }
23
24    fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
25        buf.put_i64(self.microseconds);
26        buf.put_i32(self.days);
27        buf.put_i32(self.months);
28        Ok(())
29    }
30}
31
32impl FromSql for PgInterval {
33    fn oid() -> Oid {
34        Oid::INTERVAL
35    }
36
37    fn from_sql(buf: &[u8]) -> Result<Self> {
38        if buf.len() != 16 {
39            return Err(Error::Decode(format!(
40                "interval: expected 16 bytes, got {}",
41                buf.len()
42            )));
43        }
44
45        let microseconds = i64::from_be_bytes([
46            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
47        ]);
48        let days = i32::from_be_bytes([buf[8], buf[9], buf[10], buf[11]]);
49        let months = i32::from_be_bytes([buf[12], buf[13], buf[14], buf[15]]);
50
51        Ok(PgInterval {
52            months,
53            days,
54            microseconds,
55        })
56    }
57}