Skip to main content

elefant_client/types/
bool.rs

1use crate::protocol::FieldDescription;
2use crate::types::{FromSqlBase, FromSqlBinary, FromSqlText, ToSql};
3use crate::PostgresType;
4use std::error::Error;
5
6impl<'a> FromSqlBase<'a> for bool {
7    fn accepts_postgres_type(oid: i32) -> bool {
8        oid == PostgresType::BOOL.oid
9    }
10}
11
12impl<'a> FromSqlBinary<'a> for bool {
13    fn from_sql_binary(
14        raw: &'a [u8],
15        field: &FieldDescription,
16    ) -> Result<Self, Box<dyn Error + Sync + Send>> {
17        if raw.len() != 1 {
18            return Err(format!("Invalid length for boolean. Expected 1 byte, got {} bytes instead. Error occurred when parsing field {:?}", raw.len(), field).into());
19        }
20
21        Ok(raw[0] == 1)
22    }
23}
24
25impl<'a> FromSqlText<'a> for bool {
26    fn from_sql_text(
27        raw: &'a str,
28        field: &FieldDescription,
29    ) -> Result<Self, Box<dyn Error + Sync + Send>> {
30        match raw {
31            "t" => Ok(true),
32            "f" => Ok(false),
33            _ => Err(format!(
34                "Invalid value for boolean: {raw}. Error occurred when parsing field {field:?}"
35            )
36            .into()),
37        }
38    }
39}
40
41impl ToSql for bool {
42    fn to_sql_binary(
43        &self,
44        target_buffer: &mut Vec<u8>,
45    ) -> Result<(), Box<dyn Error + Sync + Send>> {
46        target_buffer.push(if *self { 1 } else { 0 });
47        Ok(())
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    #[cfg(feature = "tokio")]
54    mod tokio_connection {
55        use crate::test_helpers::get_settings;
56        use crate::tokio_connection::new_client;
57        use tokio::test;
58
59        #[test]
60        async fn test_bool_type() {
61            let mut client = new_client(get_settings()).await.unwrap();
62
63            let b: bool = client.read_single_value("select 't'::bool;", &[]).await;
64            assert!(b);
65
66            let b: bool = client.read_single_value("select 'f'::bool;", &[]).await;
67            assert!(!b);
68
69            let b: bool = client.read_single_value("select $1::bool;", &[&true]).await;
70            assert!(b);
71
72            let b: bool = client
73                .read_single_value("select $1::bool;", &[&false])
74                .await;
75            assert!(!b);
76        }
77
78        #[test]
79        async fn test_bool_dual_mode() {
80            let mut client = new_client(get_settings()).await.unwrap();
81
82            let value: bool = client.read_single_value_dual_mode("select 't'::bool").await;
83            assert!(value);
84
85            let value: bool = client
86                .read_single_value_dual_mode("select false::bool")
87                .await;
88            assert!(!value);
89
90            let value: bool = client
91                .read_single_value_dual_mode("select true::bool")
92                .await;
93            assert!(value);
94
95            let value: bool = client.read_single_value_dual_mode("select 'f'::bool").await;
96            assert!(!value);
97        }
98    }
99}