Skip to main content

alibi_sqlx/
integer.rs

1//! INTEGER decoding across PostgreSQL int4 and SQLite 64-bit storage.
2use crate::value::ValueTypeError;
3use crate::{ColumnKind, SqlValue, SqlxValue};
4use sqlx::error::BoxDynError;
5use sqlx::{Decode, Type, ValueRef};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
8#[serde(transparent)]
9pub struct Integer(pub i64);
10
11impl From<i64> for Integer {
12    fn from(value: i64) -> Self {
13        Self(value)
14    }
15}
16impl SqlxValue for Integer {
17    const KIND: ColumnKind = ColumnKind::BigInt;
18    fn null() -> SqlValue {
19        SqlValue::BigInt(None)
20    }
21    fn into_sql_value(self) -> SqlValue {
22        SqlValue::BigInt(Some(self.0))
23    }
24    fn from_sql_value(value: SqlValue) -> Result<Self, ValueTypeError> {
25        match value {
26            SqlValue::BigInt(Some(value)) => Ok(Self(value)),
27            SqlValue::Int(Some(value)) => Ok(Self(i64::from(value))),
28            _ => Err(ValueTypeError),
29        }
30    }
31}
32#[cfg(feature = "sqlite")]
33impl Type<sqlx::Sqlite> for Integer {
34    fn type_info() -> sqlx::sqlite::SqliteTypeInfo {
35        <i64 as Type<sqlx::Sqlite>>::type_info()
36    }
37    fn compatible(ty: &sqlx::sqlite::SqliteTypeInfo) -> bool {
38        <i64 as Type<sqlx::Sqlite>>::compatible(ty)
39    }
40}
41#[cfg(feature = "sqlite")]
42impl<'r> Decode<'r, sqlx::Sqlite> for Integer {
43    fn decode(value: sqlx::sqlite::SqliteValueRef<'r>) -> Result<Self, BoxDynError> {
44        <i64 as Decode<'r, sqlx::Sqlite>>::decode(value).map(Self)
45    }
46}
47#[cfg(feature = "postgres")]
48impl Type<sqlx::Postgres> for Integer {
49    fn type_info() -> sqlx::postgres::PgTypeInfo {
50        <i32 as Type<sqlx::Postgres>>::type_info()
51    }
52    fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool {
53        <i64 as Type<sqlx::Postgres>>::compatible(ty)
54            || <i32 as Type<sqlx::Postgres>>::compatible(ty)
55    }
56}
57#[cfg(feature = "postgres")]
58impl<'r> Decode<'r, sqlx::Postgres> for Integer {
59    fn decode(value: sqlx::postgres::PgValueRef<'r>) -> Result<Self, BoxDynError> {
60        if <i64 as Type<sqlx::Postgres>>::compatible(&value.type_info()) {
61            <i64 as Decode<'r, sqlx::Postgres>>::decode(value).map(Self)
62        } else {
63            <i32 as Decode<'r, sqlx::Postgres>>::decode(value).map(|value| Self(i64::from(value)))
64        }
65    }
66}
67#[cfg(feature = "sqlite")]
68impl sqlx::Encode<'_, sqlx::Sqlite> for Integer {
69    fn encode_by_ref(
70        &self,
71        buffer: &mut sqlx::sqlite::SqliteArgumentsBuffer,
72    ) -> Result<sqlx::encode::IsNull, BoxDynError> {
73        <i64 as sqlx::Encode<'_, sqlx::Sqlite>>::encode_by_ref(&self.0, buffer)
74    }
75}
76#[cfg(feature = "postgres")]
77impl sqlx::Encode<'_, sqlx::Postgres> for Integer {
78    fn encode_by_ref(
79        &self,
80        buffer: &mut sqlx::postgres::PgArgumentBuffer,
81    ) -> Result<sqlx::encode::IsNull, BoxDynError> {
82        <i32 as sqlx::Encode<'_, sqlx::Postgres>>::encode(i32::try_from(self.0)?, buffer)
83    }
84}