rbatis_core/mysql/
sqlx_value.rs

1use rbson::{Binary, Bson, to_bson};
2use sqlx_core::column::Column;
3use sqlx_core::decode::Decode;
4use sqlx_core::error::BoxDynError;
5use sqlx_core::mysql::{MySql, MySqlRow, MySqlValue, MySqlValueRef};
6use sqlx_core::row::Row;
7use sqlx_core::type_info::TypeInfo;
8use sqlx_core::types::{BigDecimal, Json};
9use sqlx_core::value::ValueRef;
10
11use crate::convert::{JsonCodec, RefJsonCodec, ResultCodec};
12use chrono::{DateTime, Utc, NaiveDate};
13
14use crate::{to_bson_macro};
15use rbson::bson;
16use rbson::spec::BinarySubtype;
17use crate::db::db_adapter::DataDecoder;
18
19
20impl<'r> JsonCodec for sqlx_core::mysql::MySqlValueRef<'r> {
21    fn try_to_bson(self) -> crate::Result<Bson> {
22        match self.type_info().name() {
23            "NULL" => {
24                return Ok(Bson::Null);
25            }
26            "DECIMAL" => {
27                let r: Option<String> = Decode::<'_, MySql>::decode(self)?;
28                if let Some(date) = r {
29                    return Ok(Bson::String(date));
30                }
31                return Ok(Bson::Null);
32            }
33            "BIGINT UNSIGNED" => {
34                let r: Option<u64> = Decode::<'_, MySql>::decode(self)?;
35                if let Some(r) = r {
36                    return Ok(bson!(r));
37                }
38                return Ok(Bson::Null);
39            }
40            "BIGINT" => {
41                let r: Option<i64> = Decode::<'_, MySql>::decode(self)?;
42                return Ok(to_bson_macro!(r));
43            }
44            "INT UNSIGNED" | "MEDIUMINT UNSIGNED" => {
45                let r: Option<u32> = Decode::<'_, MySql>::decode(self)?;
46                return Ok(to_bson_macro!(r));
47            }
48            "INT" | "MEDIUMINT" => {
49                let r: Option<i32> = Decode::<'_, MySql>::decode(self)?;
50                return Ok(to_bson_macro!(r));
51            }
52            "SMALLINT" => {
53                let r: Option<i16> = Decode::<'_, MySql>::decode(self)?;
54                if let Some(r) = r {
55                    return Ok(bson!(r as i32));
56                }
57                return Ok(Bson::Null);
58            }
59            "SMALLINT UNSIGNED" => {
60                let r: Option<u16> = Decode::<'_, MySql>::decode(self)?;
61                if let Some(r) = r {
62                    return Ok(bson!(r as u32));
63                }
64                return Ok(Bson::Null);
65            }
66            "TINYINT UNSIGNED" => {
67                let r: Option<u8> = Decode::<'_, MySql>::decode(self)?;
68                if let Some(r) = r {
69                    return Ok(bson!(r as u32));
70                }
71                return Ok(Bson::Null);
72            }
73            "TINYINT" => {
74                let r: Option<i8> = Decode::<'_, MySql>::decode(self)?;
75                if let Some(r) = r {
76                    return Ok(bson!(r as i32));
77                }
78                return Ok(Bson::Null);
79            }
80            "FLOAT" => {
81                let r: Option<f32> = Decode::<'_, MySql>::decode(self)?;
82                return Ok(to_bson_macro!(r));
83            }
84            "DOUBLE" => {
85                let r: Option<f64> = Decode::<'_, MySql>::decode(self)?;
86                return Ok(to_bson_macro!(r));
87            }
88            "BINARY" | "VARBINARY" | "CHAR" | "VARCHAR" | "TEXT" | "ENUM" => {
89                let r: Option<String> = Decode::<'_, MySql>::decode(self)?;
90                return Ok(to_bson_macro!(r));
91            }
92            "BLOB" | "TINYBLOB" | "MEDIUMBLOB" | "LONGBLOB" | "TINYTEXT" | "MEDIUMTEXT"
93            | "LONGTEXT" => {
94                let r: Option<Vec<u8>> = Decode::<'_, MySql>::decode(self)?;
95                if let Some(r) = r {
96                    return Ok(Bson::Binary(rbson::Binary {
97                        subtype: BinarySubtype::Generic,
98                        bytes: r,
99                    }));
100                }
101                return Ok(Bson::Null);
102            }
103            "BIT" => {
104                let r: Option<u8> = Decode::<'_, MySql>::decode(self)?;
105                if let Some(r) = r {
106                    return Ok(bson!(r as i32));
107                }
108                return Ok(Bson::Null);
109            }
110            "BOOLEAN" => {
111                let r: Option<u8> = Decode::<'_, MySql>::decode(self)?;
112                if let Some(r) = r {
113                    let mut b = false;
114                    if r == 1 {
115                        b = true;
116                    }
117                    return Ok(bson!(b));
118                }
119                return Ok(Bson::Null);
120            }
121            "DATE" => {
122                let r: Option<chrono::NaiveDate> = Decode::<'_, MySql>::decode(self)?;
123                return Ok(to_bson(&r).unwrap_or_default());
124            }
125            "TIME" | "YEAR" => {
126                let r: Option<chrono::NaiveTime> = Decode::<'_, MySql>::decode(self)?;
127                return Ok(to_bson(&r).unwrap_or_default());
128            }
129            "DATETIME" => {
130                let r: Option<chrono::NaiveDateTime> = Decode::<'_, MySql>::decode(self)?;
131                if let Some(dt) = r {
132                    return Ok(Bson::String(dt.format("%Y-%m-%dT%H:%M:%S").to_string()));
133                }
134                return Ok(Bson::Null);
135            }
136            "TIMESTAMP" => {
137                let r: Option<chrono::NaiveDateTime> = Decode::<'_, MySql>::decode(self)?;
138                if let Some(dt) = r {
139                    return Ok(Bson::String(dt.format("%Y-%m-%dT%H:%M:%S").to_string()));
140                }
141                return Ok(Bson::Null);
142            }
143            "JSON" => {
144                let r: Option<Json<serde_json::Value>> = Decode::<'_, MySql>::decode(self)?;
145                if let Some(r) = r {
146                    return Ok(to_bson(&r.0).unwrap_or_default());
147                }
148                return Ok(Bson::Null);
149            }
150            _ => {
151                //TODO "GEOMETRY" support. for now you can use already supported types to decode this
152                let r: Option<Vec<u8>> = Decode::<'_, MySql>::decode(self)?;
153                if let Some(r) = r {
154                    return Ok(Bson::Binary(rbson::Binary {
155                        subtype: BinarySubtype::Generic,
156                        bytes: r,
157                    }));
158                }
159                return Ok(Bson::Null);
160            }
161        }
162    }
163}
164
165impl RefJsonCodec for Vec<MySqlRow> {
166    fn try_to_bson(&self, decoder: &dyn DataDecoder) -> crate::Result<rbson::Bson> {
167        let mut arr = Vec::with_capacity(self.len());
168        for row in self {
169            let mut m = rbson::Document::new();
170            let columns = row.columns();
171            for x in columns {
172                let key = x.name();
173                let v: MySqlValueRef = row.try_get_raw(key)?;
174                let mut bson = v.try_to_bson()?;
175                decoder.decode(key, &mut bson)?;
176                m.insert(key.to_owned(), bson);
177            }
178            arr.push(rbson::Bson::Document(m));
179        }
180        Ok(Bson::Array(arr))
181    }
182}