rbatis_core/db/
bind_pg.rs1use 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}