1use std::error::Error as StdError;
28
29use prax_query::row::{RowError, RowRef, into_row_error};
30use tokio_postgres::Row;
31use tokio_postgres::types::{FromSql, Kind, Type};
32
33struct AnyText(String);
42
43impl<'a> FromSql<'a> for AnyText {
44 fn from_sql(_ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn StdError + Sync + Send>> {
45 Ok(AnyText(std::str::from_utf8(raw)?.to_owned()))
46 }
47 fn accepts(_ty: &Type) -> bool {
48 true
49 }
50}
51
52struct NullProbe;
65
66impl<'a> FromSql<'a> for NullProbe {
67 fn from_sql(_ty: &Type, _raw: &'a [u8]) -> Result<Self, Box<dyn StdError + Sync + Send>> {
68 Ok(NullProbe)
69 }
70 fn accepts(_ty: &Type) -> bool {
71 true
72 }
73}
74
75#[repr(transparent)]
83pub struct PgRow(Row);
84
85impl PgRow {
86 pub fn into_inner(self) -> Row {
88 self.0
89 }
90}
91
92impl std::ops::Deref for PgRow {
93 type Target = Row;
94 fn deref(&self) -> &Self::Target {
95 &self.0
96 }
97}
98
99impl From<Row> for PgRow {
100 fn from(row: Row) -> Self {
101 PgRow(row)
102 }
103}
104
105impl RowRef for PgRow {
106 fn get_i32(&self, c: &str) -> Result<i32, RowError> {
107 into_row_error(c, self.try_get::<_, i32>(c))
108 }
109 fn get_i32_opt(&self, c: &str) -> Result<Option<i32>, RowError> {
110 into_row_error(c, self.try_get::<_, Option<i32>>(c))
111 }
112 fn get_i64(&self, c: &str) -> Result<i64, RowError> {
113 into_row_error(c, self.try_get::<_, i64>(c))
114 }
115 fn get_i64_opt(&self, c: &str) -> Result<Option<i64>, RowError> {
116 into_row_error(c, self.try_get::<_, Option<i64>>(c))
117 }
118 fn get_f64(&self, c: &str) -> Result<f64, RowError> {
119 into_row_error(c, self.try_get::<_, f64>(c))
120 }
121 fn get_f64_opt(&self, c: &str) -> Result<Option<f64>, RowError> {
122 into_row_error(c, self.try_get::<_, Option<f64>>(c))
123 }
124 fn get_bool(&self, c: &str) -> Result<bool, RowError> {
125 into_row_error(c, self.try_get::<_, bool>(c))
126 }
127 fn get_bool_opt(&self, c: &str) -> Result<Option<bool>, RowError> {
128 into_row_error(c, self.try_get::<_, Option<bool>>(c))
129 }
130 fn get_str(&self, c: &str) -> Result<&str, RowError> {
131 into_row_error(c, self.try_get::<_, &str>(c))
132 }
133 fn get_str_opt(&self, c: &str) -> Result<Option<&str>, RowError> {
134 into_row_error(c, self.try_get::<_, Option<&str>>(c))
135 }
136 fn get_string(&self, c: &str) -> Result<String, RowError> {
153 let columns = self.0.columns();
154 if let Some(col) = columns.iter().find(|col| col.name() == c) {
155 let ty = col.type_();
156 if *ty == Type::UUID {
157 return into_row_error(c, self.try_get::<_, ::uuid::Uuid>(c))
158 .map(|u| u.to_string());
159 }
160 if matches!(ty.kind(), Kind::Enum(_)) {
161 return into_row_error(c, self.try_get::<_, AnyText>(c)).map(|t| t.0);
162 }
163 }
164 into_row_error(c, self.try_get::<_, &str>(c)).map(|s| s.to_string())
165 }
166 fn get_string_opt(&self, c: &str) -> Result<Option<String>, RowError> {
167 let columns = self.0.columns();
168 if let Some(col) = columns.iter().find(|col| col.name() == c) {
169 let ty = col.type_();
170 if *ty == Type::UUID {
171 return into_row_error(c, self.try_get::<_, Option<::uuid::Uuid>>(c))
172 .map(|opt| opt.map(|u| u.to_string()));
173 }
174 if matches!(ty.kind(), Kind::Enum(_)) {
175 return into_row_error(c, self.try_get::<_, Option<AnyText>>(c))
176 .map(|opt| opt.map(|t| t.0));
177 }
178 }
179 into_row_error(c, self.try_get::<_, Option<&str>>(c)).map(|opt| opt.map(|s| s.to_string()))
180 }
181 fn is_null(&self, c: &str) -> Result<bool, RowError> {
192 into_row_error(c, self.try_get::<_, Option<NullProbe>>(c)).map(|opt| opt.is_none())
193 }
194
195 fn get_bytes(&self, c: &str) -> Result<&[u8], RowError> {
196 into_row_error(c, self.try_get::<_, &[u8]>(c))
197 }
198 fn get_bytes_opt(&self, c: &str) -> Result<Option<&[u8]>, RowError> {
199 into_row_error(c, self.try_get::<_, Option<&[u8]>>(c))
200 }
201 fn get_datetime_utc(&self, c: &str) -> Result<chrono::DateTime<chrono::Utc>, RowError> {
202 into_row_error(c, self.try_get::<_, chrono::DateTime<chrono::Utc>>(c))
203 }
204 fn get_datetime_utc_opt(
205 &self,
206 c: &str,
207 ) -> Result<Option<chrono::DateTime<chrono::Utc>>, RowError> {
208 into_row_error(
209 c,
210 self.try_get::<_, Option<chrono::DateTime<chrono::Utc>>>(c),
211 )
212 }
213 fn get_naive_datetime(&self, c: &str) -> Result<chrono::NaiveDateTime, RowError> {
214 into_row_error(c, self.try_get::<_, chrono::NaiveDateTime>(c))
215 }
216 fn get_naive_datetime_opt(&self, c: &str) -> Result<Option<chrono::NaiveDateTime>, RowError> {
217 into_row_error(c, self.try_get::<_, Option<chrono::NaiveDateTime>>(c))
218 }
219 fn get_naive_date(&self, c: &str) -> Result<chrono::NaiveDate, RowError> {
220 into_row_error(c, self.try_get::<_, chrono::NaiveDate>(c))
221 }
222 fn get_naive_date_opt(&self, c: &str) -> Result<Option<chrono::NaiveDate>, RowError> {
223 into_row_error(c, self.try_get::<_, Option<chrono::NaiveDate>>(c))
224 }
225 fn get_naive_time(&self, c: &str) -> Result<chrono::NaiveTime, RowError> {
226 into_row_error(c, self.try_get::<_, chrono::NaiveTime>(c))
227 }
228 fn get_naive_time_opt(&self, c: &str) -> Result<Option<chrono::NaiveTime>, RowError> {
229 into_row_error(c, self.try_get::<_, Option<chrono::NaiveTime>>(c))
230 }
231 fn get_uuid(&self, c: &str) -> Result<uuid::Uuid, RowError> {
232 into_row_error(c, self.try_get::<_, uuid::Uuid>(c))
233 }
234 fn get_uuid_opt(&self, c: &str) -> Result<Option<uuid::Uuid>, RowError> {
235 into_row_error(c, self.try_get::<_, Option<uuid::Uuid>>(c))
236 }
237 fn get_json(&self, c: &str) -> Result<serde_json::Value, RowError> {
238 into_row_error(c, self.try_get::<_, serde_json::Value>(c))
239 }
240 fn get_json_opt(&self, c: &str) -> Result<Option<serde_json::Value>, RowError> {
241 into_row_error(c, self.try_get::<_, Option<serde_json::Value>>(c))
242 }
243 fn get_decimal(&self, c: &str) -> Result<rust_decimal::Decimal, RowError> {
244 into_row_error(c, self.try_get::<_, rust_decimal::Decimal>(c))
245 }
246 fn get_decimal_opt(&self, c: &str) -> Result<Option<rust_decimal::Decimal>, RowError> {
247 into_row_error(c, self.try_get::<_, Option<rust_decimal::Decimal>>(c))
248 }
249}