diesel/pg/types/
pg_lsn.rs

1use diesel_derives::AsExpression;
2use diesel_derives::FromSqlRow;
3
4use super::sql_types;
5use crate::deserialize::{self, FromSql};
6use crate::pg::{Pg, PgValue};
7use crate::serialize::{self, IsNull, Output, ToSql};
8use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
9
10/// A type encoding a position in the PostgreSQL *Write Ahead Log* (WAL).
11/// In Postgres, it is represented as an unsigned 64 bit integer.
12#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PgLsn {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PgLsn",
            &&self.0)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for PgLsn {
    #[inline]
    fn default() -> PgLsn { PgLsn(::core::default::Default::default()) }
}Default, #[automatically_derived]
impl ::core::marker::Copy for PgLsn { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PgLsn {
    #[inline]
    fn clone(&self) -> PgLsn {
        let _: ::core::clone::AssertParamIsClone<u64>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PgLsn {
    #[inline]
    fn eq(&self, other: &PgLsn) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PgLsn {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<u64>;
    }
}Eq, const _: () =
    {
        use diesel;
        impl<'__expr> diesel::expression::AsExpression<sql_types::PgLsn> for
            &'__expr PgLsn {
            type Expression =
                diesel::internal::derives::as_expression::Bound<sql_types::PgLsn,
                Self>;
            fn as_expression(self)
                ->
                    <Self as
                    diesel::expression::AsExpression<sql_types::PgLsn>>::Expression {
                diesel::internal::derives::as_expression::Bound::new(self)
            }
        }
        impl<'__expr>
            diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::PgLsn>>
            for &'__expr PgLsn {
            type Expression =
                diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<sql_types::PgLsn>,
                Self>;
            fn as_expression(self)
                ->
                    <Self as
                    diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::PgLsn>>>::Expression {
                diesel::internal::derives::as_expression::Bound::new(self)
            }
        }
        impl<'__expr, '__expr2>
            diesel::expression::AsExpression<sql_types::PgLsn> for
            &'__expr2 &'__expr PgLsn {
            type Expression =
                diesel::internal::derives::as_expression::Bound<sql_types::PgLsn,
                Self>;
            fn as_expression(self)
                ->
                    <Self as
                    diesel::expression::AsExpression<sql_types::PgLsn>>::Expression {
                diesel::internal::derives::as_expression::Bound::new(self)
            }
        }
        impl<'__expr, '__expr2>
            diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::PgLsn>>
            for &'__expr2 &'__expr PgLsn {
            type Expression =
                diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<sql_types::PgLsn>,
                Self>;
            fn as_expression(self)
                ->
                    <Self as
                    diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::PgLsn>>>::Expression {
                diesel::internal::derives::as_expression::Bound::new(self)
            }
        }
        impl<__DB>
            diesel::serialize::ToSql<diesel::sql_types::Nullable<sql_types::PgLsn>,
            __DB> for PgLsn where __DB: diesel::backend::Backend,
            Self: diesel::serialize::ToSql<sql_types::PgLsn, __DB> {
            fn to_sql<'__b>(&'__b self,
                out: &mut diesel::serialize::Output<'__b, '_, __DB>)
                -> diesel::serialize::Result {
                diesel::serialize::ToSql::<sql_types::PgLsn,
                        __DB>::to_sql(self, out)
            }
        }
        impl diesel::expression::AsExpression<sql_types::PgLsn> for PgLsn {
            type Expression =
                diesel::internal::derives::as_expression::Bound<sql_types::PgLsn,
                Self>;
            fn as_expression(self)
                ->
                    <Self as
                    diesel::expression::AsExpression<sql_types::PgLsn>>::Expression {
                diesel::internal::derives::as_expression::Bound::new(self)
            }
        }
        impl diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::PgLsn>>
            for PgLsn {
            type Expression =
                diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<sql_types::PgLsn>,
                Self>;
            fn as_expression(self)
                ->
                    <Self as
                    diesel::expression::AsExpression<diesel::sql_types::Nullable<sql_types::PgLsn>>>::Expression {
                diesel::internal::derives::as_expression::Bound::new(self)
            }
        }
    };AsExpression, const _: () =
    {
        use diesel;
        impl<__DB, __ST> diesel::deserialize::Queryable<__ST, __DB> for PgLsn
            where __DB: diesel::backend::Backend,
            __ST: diesel::sql_types::SingleValue,
            Self: diesel::deserialize::FromSql<__ST, __DB> {
            type Row = Self;
            fn build(row: Self) -> diesel::deserialize::Result<Self> {
                diesel::deserialize::Result::Ok(row)
            }
        }
    };FromSqlRow)]
13#[diesel(sql_type = sql_types::PgLsn)]
14pub struct PgLsn(pub u64);
15
16#[cfg(feature = "postgres_backend")]
17impl FromSql<sql_types::PgLsn, Pg> for PgLsn {
18    fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
19        let mut bytes = value.as_bytes();
20        if bytes.len() < 8 {
21            return emit_size_error(
22                "Received less than 8 bytes while decoding a pg_lsn. \
23                    Was an Integer expression accidentally marked as pg_lsn?",
24            );
25        }
26
27        if bytes.len() > 8 {
28            return emit_size_error(
29                "Received more than 8 bytes while decoding a pg_lsn. \
30                    Was an expression of a different type expression accidentally marked as pg_lsn?"
31            );
32        }
33        let val = bytes
34            .read_u64::<NetworkEndian>()
35            .map_err(|e| Box::new(e) as Box<_>)?;
36        Ok(PgLsn(val))
37    }
38}
39
40#[cold]
41#[inline(never)]
42fn emit_size_error<T>(var_name: &str) -> deserialize::Result<T> {
43    deserialize::Result::Err(var_name.into())
44}
45
46#[cfg(feature = "postgres_backend")]
47impl ToSql<sql_types::PgLsn, Pg> for PgLsn {
48    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
49        out.write_u64::<NetworkEndian>(self.0)
50            .map(|_| IsNull::No)
51            .map_err(Into::into)
52    }
53}
54
55#[cfg(test)]
56#[diesel_test_helper::test]
57fn lsn_roundtrip() {
58    use crate::query_builder::bind_collector::ByteWrapper;
59
60    let mut buffer = Vec::new();
61    let mut bytes = Output::test(ByteWrapper(&mut buffer));
62    let input_lsn = PgLsn(0x525400fbc61617ff);
63    ToSql::<sql_types::PgLsn, Pg>::to_sql(&input_lsn, &mut bytes).unwrap();
64    let output_lsn: PgLsn = FromSql::from_sql(PgValue::for_test(&buffer)).unwrap();
65    assert_eq!(input_lsn, output_lsn);
66}