diesel/pg/types/
primitives.rs1use std::io::prelude::*;
2
3#[cfg(feature = "postgres_backend")]
4use crate::deserialize::FromSqlRef;
5use crate::deserialize::{self, FromSql, Queryable};
6use crate::pg::{Pg, PgValue};
7use crate::serialize::{self, IsNull, Output, ToSql};
8use crate::sql_types;
9
10#[cfg(feature = "postgres_backend")]
11impl FromSql<sql_types::Bool, Pg> for bool {
12 fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
13 let first_byte = bytes
14 .as_bytes()
15 .first()
16 .ok_or("Received an empty response from the server")?;
17 Ok(*first_byte != 0)
18 }
19}
20
21#[cfg(feature = "postgres_backend")]
22impl ToSql<sql_types::Bool, Pg> for bool {
23 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
24 out.write_all(&[*self as u8])
25 .map(|_| IsNull::No)
26 .map_err(Into::into)
27 }
28}
29
30#[cfg(feature = "postgres_backend")]
31impl FromSql<sql_types::CChar, Pg> for u8 {
32 fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
33 let first_byte = bytes
34 .as_bytes()
35 .first()
36 .ok_or("Received an empty response from the server")?;
37 Ok(*first_byte)
38 }
39}
40
41#[cfg(feature = "postgres_backend")]
42impl ToSql<sql_types::CChar, Pg> for u8 {
43 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
44 out.write_all(&[*self])
45 .map(|_| IsNull::No)
46 .map_err(Into::into)
47 }
48}
49
50#[cfg(feature = "postgres_backend")]
56impl FromSql<sql_types::Text, Pg> for *const str {
57 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
58 use core::str;
59 let string = str::from_utf8(value.as_bytes())?;
60 Ok(string as *const _)
61 }
62}
63
64#[cfg(feature = "postgres_backend")]
65impl<'a> FromSqlRef<'a, sql_types::Text, Pg> for &'a str {
66 fn from_sql(value: &'a mut PgValue<'_>) -> deserialize::Result<Self> {
67 Ok(core::str::from_utf8(value.as_bytes())?)
68 }
69}
70
71#[cfg(feature = "postgres_backend")]
72impl Queryable<sql_types::VarChar, Pg> for *const str {
73 type Row = Self;
74
75 fn build(row: Self::Row) -> deserialize::Result<Self> {
76 Ok(row)
77 }
78}
79
80#[cfg(feature = "postgres_backend")]
81impl ToSql<sql_types::Citext, Pg> for String {
82 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
83 out.write_all(self.as_bytes())?;
84 Ok(IsNull::No)
85 }
86}
87
88#[cfg(feature = "postgres_backend")]
89impl ToSql<sql_types::Citext, Pg> for str {
90 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
91 out.write_all(self.as_bytes())?;
92 Ok(IsNull::No)
93 }
94}
95
96#[cfg(feature = "postgres_backend")]
97impl FromSql<sql_types::Citext, Pg> for String {
98 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
99 let string = String::from_utf8(value.as_bytes().to_vec())?;
100 Ok(string)
101 }
102}
103
104#[cfg(feature = "postgres_backend")]
105impl ToSql<crate::pg::sql_types::Bpchar, Pg> for str {
106 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
107 <str as ToSql<sql_types::Text, Pg>>::to_sql(self, out)
108 }
109}
110
111#[cfg(feature = "postgres_backend")]
112impl ToSql<crate::pg::sql_types::Bpchar, Pg> for String {
113 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
114 <String as ToSql<sql_types::Text, Pg>>::to_sql(self, out)
115 }
116}
117
118#[cfg(feature = "postgres_backend")]
119impl<'a> FromSqlRef<'a, crate::pg::sql_types::Bpchar, Pg> for &'a str {
120 fn from_sql(value: &'a mut PgValue<'_>) -> deserialize::Result<Self> {
121 Ok(core::str::from_utf8(value.as_bytes())?)
122 }
123}
124
125#[cfg(feature = "postgres_backend")]
131impl FromSql<sql_types::Binary, Pg> for *const [u8] {
132 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
133 Ok(value.as_bytes() as *const _)
134 }
135}
136
137impl<'a> FromSqlRef<'a, sql_types::Binary, Pg> for &'a [u8] {
138 fn from_sql(bytes: &'a mut PgValue<'_>) -> deserialize::Result<Self> {
139 Ok(bytes.as_bytes())
140 }
141}
142
143#[cfg(feature = "postgres_backend")]
144impl Queryable<sql_types::Binary, Pg> for *const [u8] {
145 type Row = Self;
146
147 fn build(row: Self::Row) -> deserialize::Result<Self> {
148 Ok(row)
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use crate::test_helpers::format_error;
156
157 #[diesel_test_helper::test]
158 fn cchar_to_sql() {
159 use crate::query_builder::bind_collector::ByteWrapper;
160
161 let mut buffer = Vec::new();
162 let mut bytes = Output::test(ByteWrapper(&mut buffer));
163 ToSql::<sql_types::CChar, Pg>::to_sql(&b'A', &mut bytes).unwrap();
164 ToSql::<sql_types::CChar, Pg>::to_sql(&b'\xc4', &mut bytes).unwrap();
165 assert_eq!(buffer, vec![65u8, 196u8]);
166 }
167
168 #[diesel_test_helper::test]
169 fn cchar_from_sql() {
170 let result = <u8 as FromSql<sql_types::CChar, Pg>>::from_nullable_sql(None);
171 assert_eq!(
172 format_error(&*result.unwrap_err()),
173 "Unexpected null for non-null column"
174 );
175 }
176
177 #[diesel_test_helper::test]
178 fn bool_to_sql() {
179 use crate::query_builder::bind_collector::ByteWrapper;
180
181 let mut buffer = Vec::new();
182 let mut bytes = Output::test(ByteWrapper(&mut buffer));
183 ToSql::<sql_types::Bool, Pg>::to_sql(&true, &mut bytes).unwrap();
184 ToSql::<sql_types::Bool, Pg>::to_sql(&false, &mut bytes).unwrap();
185 assert_eq!(buffer, vec![1u8, 0u8]);
186 }
187
188 #[diesel_test_helper::test]
189 fn no_bool_from_sql() {
190 let result = <bool as FromSql<sql_types::Bool, Pg>>::from_nullable_sql(None);
191 assert_eq!(
192 format_error(&*result.unwrap_err()),
193 "Unexpected null for non-null column"
194 );
195 }
196}