wick_sql/sqlx/sqlite/
serialize.rs1use serde::ser::{SerializeMap, SerializeSeq};
2use serde::{Serialize, Serializer};
3use sqlx::sqlite::{SqliteRow, SqliteValueRef};
4use sqlx::{Column, Decode, Row, Sqlite, TypeInfo, Value, ValueRef};
5
6pub(crate) fn serialize_value_ref<S>(value: &SqliteValueRef, s: S) -> Result<S::Ok, S::Error>
8where
9 S: Serializer,
10{
11 if value.is_null() {
12 return s.serialize_none();
13 }
14
15 let info = value.type_info();
16 let value = value.to_owned();
17 let value = value.as_ref();
18
19 let name = info.name();
20
21 match name {
22 "NULL" => s.serialize_none(),
23
24 "TEXT" => {
25 let v: String = Decode::<Sqlite>::decode(value).unwrap();
26 s.serialize_str(&v)
27 }
28 "REAL" => {
29 let v: f64 = Decode::<Sqlite>::decode(value).unwrap();
30 s.serialize_f64(v)
31 }
32 "BLOB" => {
33 let v: Vec<u8> = Decode::<Sqlite>::decode(value).unwrap();
34 s.serialize_bytes(&v)
35 }
36 "INTEGER" => {
37 let v: i64 = Decode::<Sqlite>::decode(value).unwrap();
38 s.serialize_i64(v)
39 }
40 "NUMERIC" => {
41 let v: f64 = Decode::<Sqlite>::decode(value).unwrap();
42 s.serialize_f64(v)
43 }
44 "BOOLEAN" => {
45 let v: bool = Decode::<Sqlite>::decode(value).unwrap();
46 s.serialize_bool(v)
47 }
48 "DATE" => {
49 let v: wick_packet::DateTime = Decode::<Sqlite>::decode(value).map_err(serde::ser::Error::custom)?;
50 s.serialize_str(&v.to_rfc3339())
51 }
52 "TIME" => {
53 unimplemented!("TIME not supported");
54 }
55 "DATETIME" => {
56 let v: wick_packet::DateTime = Decode::<Sqlite>::decode(value).map_err(serde::ser::Error::custom)?;
57 s.serialize_str(&v.to_rfc3339())
58 }
59 _ => {
60 warn!(name=%name,"unknown type");
61 let v: String = Decode::<Sqlite>::decode(value).unwrap();
62 s.serialize_str(&v)
63 }
64 }
65}
66
67pub(crate) fn serialize_row_as_vec<S>(x: &SqliteRow, s: S) -> Result<S::Ok, S::Error>
69where
70 S: Serializer,
71{
72 let cols = x.columns();
73 let mut seq = s.serialize_seq(Some(cols.len()))?;
74 for c in cols {
75 let c: SqliteValueRef = x.try_get_raw(c.ordinal()).unwrap();
76 let c = SerValueRef(c);
77 seq.serialize_element(&c)?;
78 }
79 seq.end()
80}
81
82pub(crate) fn serialize_row_as_map<S>(x: &SqliteRow, s: S) -> Result<S::Ok, S::Error>
84where
85 S: Serializer,
86{
87 let cols = x.columns();
88 let mut map = s.serialize_map(Some(cols.len()))?;
89 for col in cols {
90 let c = x.try_get_raw(col.ordinal()).unwrap();
91 let c = SerValueRef(c);
92 map.serialize_entry(col.name(), &c)?;
93 }
94 map.end()
95}
96
97#[derive(Serialize)]
98pub(crate) struct SerVecRow(#[serde(serialize_with = "serialize_row_as_vec")] SqliteRow);
99
100#[derive(Serialize)]
101pub(crate) struct SerMapRow(#[serde(serialize_with = "serialize_row_as_map")] SqliteRow);
102
103impl From<SqliteRow> for SerMapRow {
104 fn from(row: SqliteRow) -> Self {
105 SerMapRow(row)
106 }
107}
108
109#[derive(Serialize)]
110pub(crate) struct SerValueRef<'r>(#[serde(serialize_with = "serialize_value_ref")] SqliteValueRef<'r>);
111
112impl From<SqliteRow> for SerVecRow {
113 fn from(row: SqliteRow) -> Self {
114 SerVecRow(row)
115 }
116}
117
118#[cfg(test)]
119mod integration_test {
120 use anyhow::Result;
121 use pretty_assertions::assert_eq;
122 use serde_json::Value;
123 use sqlx::{Connection, Executor, SqliteConnection};
124
125 use super::*;
126
127 fn read_row(row: &SqliteRow) -> Vec<Value> {
128 let columns = row.columns();
129 let mut result: Vec<Value> = Vec::with_capacity(columns.len());
130 for c in columns {
131 let value = row.try_get_raw(c.ordinal()).unwrap();
132 let value = SerValueRef(value);
133 let value = serde_json::to_value(&value).unwrap();
134 result.push(value);
135 }
136 result
137 }
138
139 async fn connect() -> SqliteConnection {
140 let db = std::env::var("SQLITE_DB").unwrap();
141 let conn_string = format!("file://{}", db);
142
143 SqliteConnection::connect(&conn_string).await.unwrap()
144 }
145
146 #[test_logger::test(tokio::test)]
147 async fn test_int() -> Result<()> {
148 let mut conn = connect().await;
149 let row = conn.fetch_one("select cast(3 as integer);").await?;
150 let row = read_row(&row);
151 assert_eq!(row[0].as_i64().unwrap(), 3);
152 Ok(())
153 }
154
155 #[test_logger::test(tokio::test)]
156 async fn test_map() -> Result<()> {
157 let mut conn = connect().await;
159
160 let row = conn
161 .fetch_one("select cast(1 as tinyint) as foo, cast('hello' as nvarchar(50)) as bar")
162 .await?;
163 let row = SerMapRow::from(row);
164 let row = serde_json::to_string(&row).unwrap();
165 assert_eq!(row, r#"{"foo":1,"bar":"hello"}"#);
166 Ok(())
167 }
168}