1use sqlx::postgres::{PgRow, PgValueRef, Postgres};
2use sqlx::{Column, Decode, Row, TypeInfo, ValueRef};
3use serde_json::{Value};
4
5use serde::{Serialize, Serializer};
6use serde::ser::{SerializeMap, SerializeSeq};
7
8pub fn read_header(row: &PgRow) -> Vec<String> {
9 let columns = row.columns();
10 let mut headers = vec![];
11 for c in columns {
12 headers.push(c.name().to_string());
13 }
14 headers
15}
16
17pub fn read_row(row: &PgRow) -> Vec<Value> {
18 let columns = row.columns();
19 let mut result: Vec<Value> = Vec::with_capacity(columns.len());
20 for c in columns {
21 let value = row.try_get_raw(c.ordinal()).unwrap();
22 let value = SerPgValueRef(value);
23 let value = serde_json::to_value(&value).unwrap();
24 result.push(value);
25 }
26 result
27}
28
29pub fn serialize_pgvalueref<S>(value: &PgValueRef, s: S) -> Result<S::Ok, S::Error>
31 where
32 S: Serializer,
33{
34 if value.is_null() {
35 return s.serialize_none();
36 }
37 let value = value.clone();
38 let info = value.type_info();
39 let name = info.name();
40 match name {
41 "BOOL" => {
42 let v: bool = Decode::<Postgres>::decode(value).unwrap();
43 s.serialize_bool(v)
44 }
45 "INT2" => {
46 let v: i16 = Decode::<Postgres>::decode(value).unwrap();
47 s.serialize_i16(v)
48 }
49 "INT4" => {
50 let v: i32 = Decode::<Postgres>::decode(value).unwrap();
51 s.serialize_i32(v)
52 }
53 "INT8" => {
54 let v: i64 = Decode::<Postgres>::decode(value).unwrap();
55 s.serialize_i64(v)
56 }
57 "FLOAT4" => {
58 let v: f32 = Decode::<Postgres>::decode(value).unwrap();
59 s.serialize_f32(v)
60 }
61 "FLOAT8" => {
62 let v: f64 = Decode::<Postgres>::decode(value).unwrap();
63 s.serialize_f64(v)
64 }
65 #[cfg(feature = "decimal")]
66 "NUMERIC" => {
67 let v: sqlx::types::Decimal = Decode::<Postgres>::decode(value).unwrap();
68 s.serialize_str(&v.to_string())
69 }
70 "CHAR" | "VARCHAR" | "TEXT" | "\"CHAR\"" => {
71 let v: String = Decode::<Postgres>::decode(value).unwrap();
72 s.serialize_str(&v)
73 }
74 "BYTEA" => {
75 let v: Vec<u8> = Decode::<Postgres>::decode(value).unwrap();
76 s.serialize_some(&v)
77 }
78 "JSON" | "JSONB" => {
79 let v: Value = Decode::<Postgres>::decode(value).unwrap();
80 s.serialize_some(&v)
81 }
82 #[cfg(feature = "chrono")]
83 "TIMESTAMP" => {
84 let v: sqlx::types::chrono::NaiveDateTime = Decode::<Postgres>::decode(value).unwrap();
85 let v = v.format("%Y-%m-%dT%H:%M:%S.%f").to_string();
86 s.serialize_str(&v)
87 }
88 #[cfg(feature = "chrono")]
89 "TIMESTAMPTZ" => {
90 use sqlx::types::chrono;
91 let v: chrono::DateTime::<chrono::Utc> = Decode::<Postgres>::decode(value).unwrap();
92 s.serialize_str(&v.to_rfc3339())
93 }
94 #[cfg(feature = "chrono")]
95 "DATE" => {
96 use sqlx::types::chrono;
97 let v: chrono::NaiveDate = Decode::<Postgres>::decode(value).unwrap();
98 s.serialize_str(&v.to_string())
99 }
100 #[cfg(feature = "chrono")]
101 "TIME" => {
102 use sqlx::types::chrono;
103 let v: chrono::NaiveTime = Decode::<Postgres>::decode(value).unwrap();
104 s.serialize_str(&v.to_string())
105 }
106 #[cfg(feature = "uuid")]
107 "UUID" => {
108 let v: sqlx::types::Uuid = Decode::<Postgres>::decode(value).unwrap();
109 let v = v.to_string();
110 s.serialize_str(&v)
111 }
112 #[cfg(not(feature = "uuid"))]
113 "UUID" => {
114 panic!("UUID type is not supported. Please enable the `uuid` feature on crate sqlx_serde.")
115 }
116 _ => {
117 let error_message = format!("Failed to deserialize postgres type {} as string", name);
118 let v: String = Decode::<Postgres>::decode(value).expect(&error_message);
119 s.serialize_str(&v)
120 }
121 }
200}
201
202pub fn serialize_pgrow_as_vec<S>(x: &PgRow, s: S) -> Result<S::Ok, S::Error>
204 where
205 S: Serializer,
206{
207 let cols = x.columns();
208 let mut seq = s.serialize_seq(Some(cols.len()))?;
209 for c in cols {
210 let c: PgValueRef = x.try_get_raw(c.ordinal()).unwrap();
211 let c = SerPgValueRef(c);
212 seq.serialize_element(&c)?;
213 }
214 seq.end()
215}
216
217pub fn serialize_pgrow_as_map<S>(x: &PgRow, s: S) -> Result<S::Ok, S::Error>
219 where
220 S: Serializer,
221{
222 let cols = x.columns();
223 let mut map = s.serialize_map(Some(cols.len()))?;
224 for col in cols {
225 let c: PgValueRef = x.try_get_raw(col.ordinal()).unwrap();
226 let c = SerPgValueRef(c);
227 map.serialize_entry(col.name(), &c)?;
228 }
229 map.end()
230}
231
232#[derive(Serialize)]
234pub struct SerVecPgRow(
235 #[serde(serialize_with = "serialize_pgrow_as_vec")]
236 PgRow
237);
238
239#[derive(Serialize)]
242pub struct SerMapPgRow(
243 #[serde(serialize_with = "serialize_pgrow_as_map")]
244 PgRow
245);
246
247impl From<PgRow> for SerMapPgRow {
248 fn from(row: PgRow) -> Self {
249 SerMapPgRow(row)
250 }
251}
252
253impl std::ops::Deref for SerMapPgRow {
254 type Target = PgRow;
255
256 fn deref(&self) -> &Self::Target {
257 &self.0
258 }
259}
260
261impl std::ops::DerefMut for SerMapPgRow {
262 fn deref_mut(&mut self) -> &mut Self::Target {
263 &mut self.0
264 }
265}
266
267impl Into<PgRow> for SerMapPgRow {
268 fn into(self) -> PgRow {
269 self.0
270 }
271}
272
273#[derive(Serialize)]
275pub struct SerPgValueRef<'r>(
276 #[serde(serialize_with = "serialize_pgvalueref")]
277 PgValueRef<'r>,
278);
279
280impl From<PgRow> for SerVecPgRow {
281 fn from(row: PgRow) -> Self {
282 SerVecPgRow(row)
283 }
284}
285
286impl std::ops::Deref for SerVecPgRow {
287 type Target = PgRow;
288
289 fn deref(&self) -> &Self::Target {
290 &self.0
291 }
292}
293
294impl std::ops::DerefMut for SerVecPgRow {
295 fn deref_mut(&mut self) -> &mut Self::Target {
296 &mut self.0
297 }
298}
299
300impl Into<PgRow> for SerVecPgRow {
301 fn into(self) -> PgRow {
302 self.0
303 }
304}
305
306
307#[cfg(test)]
308mod tests {
309 use sqlx::{Connection, Executor, PgConnection};
310 use super::*;
311
312 #[tokio::test]
313 async fn it_works() {
314 use sqlx::types::chrono;
315 let mut conn = PgConnection::connect("postgres://localhost:5432/postgres").await.unwrap();
316 let row = conn.fetch_one("SELECT NOW()").await.unwrap();
317 let row = read_row(&row);
318 chrono::DateTime::parse_from_rfc3339(row[0].as_str().unwrap()).unwrap();
319
320 let row = conn.fetch_one("select '00000000-0000-0000-0000-000000000000'::uuid").await.unwrap();
321 let row = read_row(&row);
322 assert_eq!(row[0].as_str().unwrap(), "00000000-0000-0000-0000-000000000000");
323
324 let row = conn.fetch_one("select 3.3").await.unwrap();
325 let row = read_row(&row);
326 assert_eq!(row[0].as_str().unwrap(), "3.3");
327
328 let row = conn.fetch_one("select 3.3::numeric(19,4)").await.unwrap();
329 let row = read_row(&row);
330 assert_eq!(row[0].as_str().unwrap(), "3.3000");
331
332 let row = conn.fetch_one("select 'null'::jsonb").await.unwrap();
333 let row = read_row(&row);
334 assert_eq!(row[0], Value::Null);
335
336 let row = conn.fetch_one("select 1 as foo, 'hello' as bar").await.unwrap();
337 let row = SerMapPgRow::from(row);
338 let row = serde_json::to_string(&row).unwrap();
339 assert_eq!(row, r#"{"foo":1,"bar":"hello"}"#);
340
341 let row = conn.fetch_one("select 1 as foo, 'hello' as bar").await.unwrap();
342 let row = SerVecPgRow::from(row);
343 let row = serde_json::to_string(&row).unwrap();
344 assert_eq!(row, r#"[1,"hello"]"#);
345
346 let row = conn.fetch_one("select null::text as foo ").await.unwrap();
347 let row = SerVecPgRow::from(row);
348 let row = serde_json::to_string(&row).unwrap();
349 assert_eq!(row, r#"[null]"#);
350 }
351}