rbatis_core/db/
bind_pg.rs

1use std::str::FromStr;
2use rbson::Bson;
3use rbson::spec::BinarySubtype;
4use sqlx_core::query::Query;
5use crate::error::Error;
6use crate::types::{DateNative, DateTimeUtc, DateUtc, Decimal, TimeNative, TimestampZ, TimeUtc};
7use std::time::SystemTime;
8use bigdecimal_::BigDecimal;
9use sqlx_core::encode::{Encode, IsNull};
10use sqlx_core::postgres::{Postgres, PgArguments, PgArgumentBuffer, PgHasArrayType, PgTypeInfo};
11use sqlx_core::types::Type;
12use crate::types::DateTimeNative;
13use crate::Uuid;
14
15pub struct PgNull {}
16
17impl Type<Postgres> for PgNull {
18    fn type_info() -> PgTypeInfo {
19        PgTypeInfo::with_name("UNKNOWN")
20    }
21}
22
23impl PgHasArrayType for PgNull {
24    fn array_type_info() -> PgTypeInfo {
25        PgTypeInfo::with_name("UNKNOWN")
26    }
27}
28
29
30impl Encode<'_, Postgres> for PgNull {
31    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
32        IsNull::Yes
33    }
34}
35
36#[inline]
37pub fn bind(t: Bson, mut q: Query<Postgres, PgArguments>) -> crate::Result<Query<Postgres, PgArguments>> {
38    match t {
39        Bson::String(s) => {
40            if s.starts_with("TimestampZ(") {
41                let data: TimestampZ = rbson::from_bson(Bson::String(s))?;
42                q = q.bind(data.inner);
43                return Ok(q);
44            }
45            if s.starts_with("DateTimeUtc(") {
46                let data: DateTimeUtc = rbson::from_bson(Bson::String(s))?;
47                q = q.bind(data.inner);
48                return Ok(q);
49            }
50            if s.starts_with("DateTimeNative(") {
51                let data: DateTimeNative = rbson::from_bson(Bson::String(s))?;
52                q = q.bind(data.inner);
53                return Ok(q);
54            }
55            if s.starts_with("DateNative(") {
56                let data: DateNative = rbson::from_bson(Bson::String(s))?;
57                q = q.bind(data.inner);
58                return Ok(q);
59            }
60            if s.starts_with("DateUtc(") {
61                let data: DateUtc = rbson::from_bson(Bson::String(s))?;
62                q = q.bind(data.inner);
63                return Ok(q);
64            }
65            if s.starts_with("TimeUtc(") {
66                let data: TimeUtc = rbson::from_bson(Bson::String(s))?;
67                q = q.bind(data.inner);
68                return Ok(q);
69            }
70            if s.starts_with("TimeNative(") {
71                let data: TimeNative = rbson::from_bson(Bson::String(s))?;
72                q = q.bind(data.inner);
73                return Ok(q);
74            }
75            if s.starts_with("Decimal(") {
76                let data: Decimal = rbson::from_bson(Bson::String(s))?;
77                q = q.bind(data.inner.to_string());
78                return Ok(q);
79            }
80            if s.starts_with("Uuid(") {
81                let data: Uuid = rbson::from_bson(Bson::String(s))?;
82                q = q.bind(data.inner);
83                return Ok(q);
84            }
85            q = q.bind(Some(s));
86        }
87        Bson::Null => {
88            q = q.bind(PgNull {});
89        }
90        Bson::Int32(n) => {
91            q = q.bind(n);
92        }
93        Bson::Int64(n) => {
94            q = q.bind(n);
95        }
96        Bson::UInt32(n) => {
97            q = q.bind(n);
98        }
99        Bson::UInt64(n) => {
100            q = q.bind(n as i64);
101        }
102        Bson::Double(n) => {
103            q = q.bind(n);
104        }
105        Bson::Boolean(b) => {
106            q = q.bind(b);
107        }
108        Bson::Decimal128(d) => {
109            q = q.bind(BigDecimal::from_str(&d.to_string()).unwrap_or_default());
110        }
111        Bson::Binary(d) => {
112            match d.subtype {
113                BinarySubtype::Generic => {
114                    q = q.bind(d.bytes);
115                }
116                BinarySubtype::Uuid => {
117                    q = q.bind(crate::types::Uuid::from(d).inner);
118                }
119                BinarySubtype::UserDefined(type_id) => {
120                    match type_id {
121                        crate::types::BINARY_SUBTYPE_JSON => {
122                            q = q.bind(serde_json::from_slice::<serde_json::Value>(&d.bytes).unwrap_or_default());
123                        }
124                        _ => {
125                            return Err(Error::from("un supported bind type!"));
126                        }
127                    }
128                }
129                _ => {
130                    return Err(Error::from("un supported bind type!"));
131                }
132            }
133        }
134        Bson::DateTime(d) => {
135            q = q.bind(DateTimeNative::from(d).inner);
136        }
137        Bson::Timestamp(d) => {
138            let timestamp = {
139                let upper = (d.time.to_le() as u64) << 32;
140                let lower = d.increment.to_le() as u64;
141                (upper | lower) as i64
142            };
143            let sec = timestamp / 1000;
144            let ns = (timestamp % 1000 * 1000000) as u32;
145            let primitive_date_time = chrono::NaiveDateTime::from_timestamp(sec, ns);
146            q = q.bind(primitive_date_time);
147        }
148        Bson::Array(arr) => {
149            let mut arr_null = vec![];
150            let mut arr_str = vec![];
151            let mut arr_i32 = vec![];
152            let mut arr_i64 = vec![];
153            let mut arr_double = vec![];
154            let mut arr_bool = vec![];
155            let mut arr_decimal = vec![];
156            let mut arr_bytes = vec![];
157            let mut arr_uuid = vec![];
158            let mut arr_json = vec![];
159            let mut arr_timestampz = vec![];
160            let mut arr_datetime_utc = vec![];
161            let mut arr_datetime_native = vec![];
162            let mut arr_datenative = vec![];
163            let mut arr_dateutc = vec![];
164            let mut arr_timeutc = vec![];
165            let mut arr_timenative = vec![];
166            for x in arr {
167                match x {
168                    Bson::String(s) => {
169                        if s.starts_with("TimestampZ(") {
170                            let data: TimestampZ = rbson::from_bson(Bson::String(s))?;
171                            arr_timestampz.push(data.inner);
172                            continue;
173                        }
174                        if s.starts_with("DateTimeUtc(") {
175                            let data: DateTimeUtc = rbson::from_bson(Bson::String(s))?;
176                            arr_datetime_utc.push(data.inner);
177                            continue;
178                        }
179                        if s.starts_with("DateTimeNative(") {
180                            let data: DateTimeNative = rbson::from_bson(Bson::String(s))?;
181                            arr_datetime_native.push(data.inner);
182                            continue;
183                        }
184                        if s.starts_with("DateNative(") {
185                            let data: DateNative = rbson::from_bson(Bson::String(s))?;
186                            arr_datenative.push(data.inner);
187                            continue;
188                        }
189                        if s.starts_with("DateUtc(") {
190                            let data: DateUtc = rbson::from_bson(Bson::String(s))?;
191                            arr_dateutc.push(data.inner);
192                            continue;
193                        }
194                        if s.starts_with("TimeUtc(") {
195                            let data: TimeUtc = rbson::from_bson(Bson::String(s))?;
196                            arr_timeutc.push(data.inner);
197                            continue;
198                        }
199                        if s.starts_with("TimeNative(") {
200                            let data: TimeNative = rbson::from_bson(Bson::String(s))?;
201                            arr_timenative.push(data.inner);
202                            continue;
203                        }
204                        if s.starts_with("Decimal(") {
205                            let data: Decimal = rbson::from_bson(Bson::String(s))?;
206                            arr_decimal.push(data.inner);
207                            continue;
208                        }
209                        if s.starts_with("Uuid(") {
210                            let data: Uuid = rbson::from_bson(Bson::String(s))?;
211                            arr_uuid.push(data.inner);
212                            continue;
213                        }
214                        arr_str.push(s);
215                    }
216                    Bson::Null => {
217                        arr_null.push(PgNull {});
218                    }
219                    Bson::Int32(n) => {
220                        arr_i32.push(n);
221                    }
222                    Bson::Int64(n) => {
223                        arr_i64.push(n);
224                    }
225                    Bson::Double(n) => {
226                        arr_double.push(n);
227                    }
228                    Bson::Boolean(b) => {
229                        arr_bool.push(b);
230                    }
231                    Bson::Decimal128(d) => {
232                        arr_decimal.push(BigDecimal::from_str(&d.to_string()).unwrap_or_default());
233                    }
234                    Bson::Binary(d) => {
235                        match d.subtype {
236                            BinarySubtype::Generic => {
237                                arr_bytes.push(d.bytes);
238                            }
239                            BinarySubtype::Uuid => {
240                                arr_uuid.push(crate::types::Uuid::from(d).inner);
241                            }
242                            BinarySubtype::UserDefined(type_id) => {
243                                match type_id {
244                                    crate::types::BINARY_SUBTYPE_JSON => {
245                                        arr_json.push(serde_json::from_slice::<serde_json::Value>(&d.bytes).unwrap_or_default());
246                                    }
247                                    _ => {
248                                        return Err(Error::from("un supported bind type!"));
249                                    }
250                                }
251                            }
252                            _ => {
253                                return Err(Error::from("un supported bind type!"));
254                            }
255                        }
256                    }
257                    Bson::DateTime(d) => {
258                        q = q.bind(DateTimeNative::from(d).inner);
259                    }
260                    Bson::Timestamp(d) => {
261                        let timestamp = {
262                            let upper = (d.time.to_le() as u64) << 32;
263                            let lower = d.increment.to_le() as u64;
264                            (upper | lower) as i64
265                        };
266                        let sec = timestamp / 1000;
267                        let ns = (timestamp % 1000 * 1000000) as u32;
268                        let primitive_date_time = chrono::NaiveDateTime::from_timestamp(sec, ns);
269                        q = q.bind(primitive_date_time);
270                    }
271                    _ => {
272                        return crate::Result::Err(crate::Error::from("unsupported type!"));
273                    }
274                }
275            }
276            if !arr_null.is_empty() {
277                q = q.bind(arr_null);
278            }
279            if !arr_str.is_empty() {
280                q = q.bind(arr_str);
281            }
282            if !arr_i32.is_empty() {
283                q = q.bind(arr_i32);
284            }
285            if !arr_i64.is_empty() {
286                q = q.bind(arr_i64);
287            }
288            if !arr_double.is_empty() {
289                q = q.bind(arr_double);
290            }
291            if !arr_decimal.is_empty() {
292                q = q.bind(arr_decimal);
293            }
294            if !arr_bytes.is_empty() {
295                q = q.bind(arr_bytes);
296            }
297            if !arr_uuid.is_empty() {
298                q = q.bind(arr_uuid);
299            }
300            if !arr_json.is_empty() {
301                q = q.bind(arr_json);
302            }
303            if !arr_timestampz.is_empty() {
304                q = q.bind(arr_timestampz);
305            }
306            if !arr_datetime_utc.is_empty() {
307                q = q.bind(arr_datetime_utc);
308            }
309            if !arr_datetime_native.is_empty() {
310                q = q.bind(arr_datetime_native);
311            }
312            if !arr_datenative.is_empty() {
313                q = q.bind(arr_datenative);
314            }
315            if !arr_dateutc.is_empty() {
316                q = q.bind(arr_dateutc);
317            }
318            if !arr_timeutc.is_empty() {
319                q = q.bind(arr_timeutc);
320            }
321            if !arr_timenative.is_empty() {
322                q = q.bind(arr_timenative);
323            }
324        }
325        _ => {
326            return crate::Result::Err(crate::Error::from("unsupported type!"));
327        }
328    }
329    return Ok(q);
330}