1#[cfg(feature = "bigdecimal")]
2mod decimal;
3
4use crate::{
5 ast::Value,
6 connector::queryable::{GetRow, ToColumnNames},
7 error::{Error, ErrorKind},
8};
9#[cfg(feature = "bigdecimal")]
10use bigdecimal::{num_bigint::BigInt, BigDecimal, FromPrimitive, ToPrimitive};
11use bit_vec::BitVec;
12use bytes::BytesMut;
13#[cfg(feature = "chrono")]
14use chrono::{DateTime, NaiveDateTime, Utc};
15#[cfg(feature = "bigdecimal")]
16pub(crate) use decimal::DecimalWrapper;
17use postgres_types::{FromSql, ToSql, WrongType};
18use std::{convert::TryFrom, error::Error as StdError};
19use tokio_postgres::{
20 types::{self, IsNull, Kind, Type as PostgresType},
21 Row as PostgresRow, Statement as PostgresStatement,
22};
23
24#[cfg(feature = "uuid")]
25use uuid::Uuid;
26
27pub(crate) fn conv_params<'a>(params: &'a [Value<'a>]) -> Vec<&'a (dyn types::ToSql + Sync)> {
28 params.iter().map(|x| x as &(dyn ToSql + Sync)).collect::<Vec<_>>()
29}
30
31pub(crate) fn params_to_types(params: &[Value<'_>]) -> Vec<PostgresType> {
33 params
34 .iter()
35 .map(|p| -> PostgresType {
36 if p.is_null() {
39 return PostgresType::UNKNOWN;
40 }
41
42 match p {
43 Value::Int32(_) => PostgresType::INT4,
44 Value::Int64(_) => PostgresType::INT8,
45 Value::Float(_) => PostgresType::FLOAT4,
46 Value::Double(_) => PostgresType::FLOAT8,
47 Value::Text(_) => PostgresType::TEXT,
48 Value::Enum(_) => PostgresType::UNKNOWN,
50 Value::Bytes(_) => PostgresType::BYTEA,
51 Value::Boolean(_) => PostgresType::BOOL,
52 Value::Char(_) => PostgresType::CHAR,
53 #[cfg(feature = "bigdecimal")]
54 Value::Numeric(_) => PostgresType::NUMERIC,
55 #[cfg(feature = "json")]
56 Value::Json(_) => PostgresType::JSONB,
57 Value::Xml(_) => PostgresType::XML,
58 #[cfg(feature = "uuid")]
59 Value::Uuid(_) => PostgresType::UUID,
60 #[cfg(feature = "chrono")]
61 Value::DateTime(_) => PostgresType::TIMESTAMPTZ,
62 #[cfg(feature = "chrono")]
63 Value::Date(_) => PostgresType::TIMESTAMP,
64 #[cfg(feature = "chrono")]
65 Value::Time(_) => PostgresType::TIME,
66 Value::Array(ref arr) => {
67 let arr = arr.as_ref().unwrap();
68
69 if arr.is_empty() {
71 return PostgresType::UNKNOWN;
72 }
73
74 let first = arr.first().unwrap();
75
76 if arr.iter().any(|val| std::mem::discriminant(first) != std::mem::discriminant(val)) {
78 return PostgresType::UNKNOWN;
79 }
80
81 match first {
82 Value::Int32(_) => PostgresType::INT4_ARRAY,
83 Value::Int64(_) => PostgresType::INT8_ARRAY,
84 Value::Float(_) => PostgresType::FLOAT4_ARRAY,
85 Value::Double(_) => PostgresType::FLOAT8_ARRAY,
86 Value::Text(_) => PostgresType::TEXT_ARRAY,
87 Value::Enum(_) => PostgresType::UNKNOWN,
89 Value::Bytes(_) => PostgresType::BYTEA_ARRAY,
90 Value::Boolean(_) => PostgresType::BOOL_ARRAY,
91 Value::Char(_) => PostgresType::CHAR_ARRAY,
92 #[cfg(feature = "bigdecimal")]
93 Value::Numeric(_) => PostgresType::NUMERIC_ARRAY,
94 #[cfg(feature = "json")]
95 Value::Json(_) => PostgresType::JSONB_ARRAY,
96 Value::Xml(_) => PostgresType::XML_ARRAY,
97 #[cfg(feature = "uuid")]
98 Value::Uuid(_) => PostgresType::UUID_ARRAY,
99 #[cfg(feature = "chrono")]
100 Value::DateTime(_) => PostgresType::TIMESTAMPTZ_ARRAY,
101 #[cfg(feature = "chrono")]
102 Value::Date(_) => PostgresType::TIMESTAMP_ARRAY,
103 #[cfg(feature = "chrono")]
104 Value::Time(_) => PostgresType::TIME_ARRAY,
105 Value::Array(_) => PostgresType::UNKNOWN,
107 }
108 }
109 }
110 })
111 .collect()
112}
113
114struct XmlString(pub String);
115
116impl<'a> FromSql<'a> for XmlString {
117 fn from_sql(_ty: &PostgresType, raw: &'a [u8]) -> Result<XmlString, Box<dyn std::error::Error + Sync + Send>> {
118 Ok(XmlString(String::from_utf8(raw.to_owned()).unwrap()))
119 }
120
121 fn accepts(ty: &PostgresType) -> bool {
122 ty == &PostgresType::XML
123 }
124}
125
126struct EnumString {
127 value: String,
128}
129
130impl<'a> FromSql<'a> for EnumString {
131 fn from_sql(_ty: &PostgresType, raw: &'a [u8]) -> Result<EnumString, Box<dyn std::error::Error + Sync + Send>> {
132 Ok(EnumString { value: String::from_utf8(raw.to_owned()).unwrap() })
133 }
134
135 fn accepts(_ty: &PostgresType) -> bool {
136 true
137 }
138}
139
140#[cfg(feature = "chrono")]
141struct TimeTz(chrono::NaiveTime);
142
143#[cfg(feature = "chrono")]
144impl<'a> FromSql<'a> for TimeTz {
145 fn from_sql(_ty: &PostgresType, raw: &'a [u8]) -> Result<TimeTz, Box<dyn std::error::Error + Sync + Send>> {
146 let time: chrono::NaiveTime = chrono::NaiveTime::from_sql(&PostgresType::TIMETZ, &raw[..8])?;
148 Ok(TimeTz(time))
149 }
150
151 fn accepts(ty: &PostgresType) -> bool {
152 ty == &PostgresType::TIMETZ
153 }
154}
155
156#[cfg(feature = "bigdecimal")]
161struct NaiveMoney(BigDecimal);
162
163#[cfg(feature = "bigdecimal")]
164impl<'a> FromSql<'a> for NaiveMoney {
165 fn from_sql(_ty: &PostgresType, raw: &'a [u8]) -> Result<NaiveMoney, Box<dyn std::error::Error + Sync + Send>> {
166 let cents = i64::from_sql(&PostgresType::INT8, raw)?;
167
168 Ok(NaiveMoney(BigDecimal::new(BigInt::from_i64(cents).unwrap(), 2)))
169 }
170
171 fn accepts(ty: &PostgresType) -> bool {
172 ty == &PostgresType::MONEY
173 }
174}
175
176impl GetRow for PostgresRow {
177 fn get_result_row(&self) -> crate::Result<Vec<Value<'static>>> {
178 fn convert(row: &PostgresRow, i: usize) -> crate::Result<Value<'static>> {
179 let result = match *row.columns()[i].type_() {
180 PostgresType::BOOL => Value::Boolean(row.try_get(i)?),
181 PostgresType::INT2 => match row.try_get(i)? {
182 Some(val) => {
183 let val: i16 = val;
184 Value::int32(val)
185 }
186 None => Value::Int32(None),
187 },
188 PostgresType::INT4 => match row.try_get(i)? {
189 Some(val) => {
190 let val: i32 = val;
191 Value::int32(val)
192 }
193 None => Value::Int32(None),
194 },
195 PostgresType::INT8 => match row.try_get(i)? {
196 Some(val) => {
197 let val: i64 = val;
198 Value::int64(val)
199 }
200 None => Value::Int64(None),
201 },
202 PostgresType::FLOAT4 => match row.try_get(i)? {
203 Some(val) => {
204 let val: f32 = val;
205 Value::float(val)
206 }
207 None => Value::Float(None),
208 },
209 PostgresType::FLOAT8 => match row.try_get(i)? {
210 Some(val) => {
211 let val: f64 = val;
212 Value::double(val)
213 }
214 None => Value::Double(None),
215 },
216 PostgresType::BYTEA => match row.try_get(i)? {
217 Some(val) => {
218 let val: &[u8] = val;
219 Value::bytes(val.to_owned())
220 }
221 None => Value::Bytes(None),
222 },
223 PostgresType::BYTEA_ARRAY => match row.try_get(i)? {
224 Some(val) => {
225 let val: Vec<Option<Vec<u8>>> = val;
226 let byteas = val.into_iter().map(|b| Value::Bytes(b.map(Into::into)));
227
228 Value::array(byteas)
229 }
230 None => Value::Array(None),
231 },
232 #[cfg(feature = "bigdecimal")]
233 PostgresType::NUMERIC => {
234 let dw: Option<DecimalWrapper> = row.try_get(i)?;
235
236 Value::Numeric(dw.map(|dw| dw.0))
237 }
238 #[cfg(feature = "bigdecimal")]
239 PostgresType::MONEY => match row.try_get(i)? {
240 Some(val) => {
241 let val: NaiveMoney = val;
242 Value::numeric(val.0)
243 }
244 None => Value::Numeric(None),
245 },
246 #[cfg(feature = "chrono")]
247 PostgresType::TIMESTAMP => match row.try_get(i)? {
248 Some(val) => {
249 let ts: NaiveDateTime = val;
250 let dt = DateTime::<Utc>::from_utc(ts, Utc);
251 Value::datetime(dt)
252 }
253 None => Value::DateTime(None),
254 },
255 #[cfg(feature = "chrono")]
256 PostgresType::TIMESTAMPTZ => match row.try_get(i)? {
257 Some(val) => {
258 let ts: DateTime<Utc> = val;
259 Value::datetime(ts)
260 }
261 None => Value::DateTime(None),
262 },
263 #[cfg(feature = "chrono")]
264 PostgresType::DATE => match row.try_get(i)? {
265 Some(val) => Value::date(val),
266 None => Value::Date(None),
267 },
268 #[cfg(feature = "chrono")]
269 PostgresType::TIME => match row.try_get(i)? {
270 Some(val) => Value::time(val),
271 None => Value::Time(None),
272 },
273 #[cfg(feature = "chrono")]
274 PostgresType::TIMETZ => match row.try_get(i)? {
275 Some(val) => {
276 let time: TimeTz = val;
277 Value::time(time.0)
278 }
279 None => Value::Time(None),
280 },
281 #[cfg(feature = "uuid")]
282 PostgresType::UUID => match row.try_get(i)? {
283 Some(val) => {
284 let val: Uuid = val;
285 Value::uuid(val)
286 }
287 None => Value::Uuid(None),
288 },
289 #[cfg(feature = "uuid")]
290 PostgresType::UUID_ARRAY => match row.try_get(i)? {
291 Some(val) => {
292 let val: Vec<Option<Uuid>> = val;
293 let val = val.into_iter().map(Value::Uuid);
294
295 Value::array(val)
296 }
297 None => Value::Array(None),
298 },
299 #[cfg(feature = "json")]
300 PostgresType::JSON | PostgresType::JSONB => Value::Json(row.try_get(i)?),
301 PostgresType::INT2_ARRAY => match row.try_get(i)? {
302 Some(val) => {
303 let val: Vec<Option<i16>> = val;
304 let ints = val.into_iter().map(|i| Value::Int32(i.map(|i| i as i32)));
305
306 Value::array(ints)
307 }
308 None => Value::Array(None),
309 },
310 PostgresType::INT4_ARRAY => match row.try_get(i)? {
311 Some(val) => {
312 let val: Vec<Option<i32>> = val;
313 let ints = val.into_iter().map(Value::Int32);
314
315 Value::array(ints)
316 }
317 None => Value::Array(None),
318 },
319 PostgresType::INT8_ARRAY => match row.try_get(i)? {
320 Some(val) => {
321 let val: Vec<Option<i64>> = val;
322 let ints = val.into_iter().map(Value::Int64);
323
324 Value::array(ints)
325 }
326 None => Value::Array(None),
327 },
328 PostgresType::FLOAT4_ARRAY => match row.try_get(i)? {
329 Some(val) => {
330 let val: Vec<Option<f32>> = val;
331 let floats = val.into_iter().map(Value::Float);
332
333 Value::array(floats)
334 }
335 None => Value::Array(None),
336 },
337 PostgresType::FLOAT8_ARRAY => match row.try_get(i)? {
338 Some(val) => {
339 let val: Vec<Option<f64>> = val;
340 let floats = val.into_iter().map(Value::Double);
341
342 Value::array(floats)
343 }
344 None => Value::Array(None),
345 },
346 PostgresType::BOOL_ARRAY => match row.try_get(i)? {
347 Some(val) => {
348 let val: Vec<Option<bool>> = val;
349 let bools = val.into_iter().map(Value::Boolean);
350
351 Value::array(bools)
352 }
353 None => Value::Array(None),
354 },
355 #[cfg(feature = "chrono")]
356 PostgresType::TIMESTAMP_ARRAY => match row.try_get(i)? {
357 Some(val) => {
358 let val: Vec<Option<NaiveDateTime>> = val;
359
360 let dates =
361 val.into_iter().map(|dt| Value::DateTime(dt.map(|dt| DateTime::<Utc>::from_utc(dt, Utc))));
362
363 Value::array(dates)
364 }
365 None => Value::Array(None),
366 },
367 #[cfg(feature = "bigdecimal")]
368 PostgresType::NUMERIC_ARRAY => match row.try_get(i)? {
369 Some(val) => {
370 let val: Vec<Option<DecimalWrapper>> = val;
371
372 let decimals = val
373 .into_iter()
374 .map(|dec| Value::Numeric(dec.map(|dec| dec.0.to_string().parse().unwrap())));
375
376 Value::array(decimals)
377 }
378 None => Value::Array(None),
379 },
380 PostgresType::TEXT_ARRAY | PostgresType::NAME_ARRAY | PostgresType::VARCHAR_ARRAY => {
381 match row.try_get(i)? {
382 Some(val) => {
383 let strings: Vec<Option<&str>> = val;
384
385 Value::array(strings.into_iter().map(|s| s.map(|s| s.to_string())))
386 }
387 None => Value::Array(None),
388 }
389 }
390 #[cfg(feature = "bigdecimal")]
391 PostgresType::MONEY_ARRAY => match row.try_get(i)? {
392 Some(val) => {
393 let val: Vec<Option<NaiveMoney>> = val;
394 let nums = val.into_iter().map(|num| Value::Numeric(num.map(|num| num.0)));
395
396 Value::array(nums)
397 }
398 None => Value::Array(None),
399 },
400 PostgresType::OID_ARRAY => match row.try_get(i)? {
401 Some(val) => {
402 let val: Vec<Option<u32>> = val;
403 let nums = val.into_iter().map(|oid| Value::Int64(oid.map(|oid| oid as i64)));
404
405 Value::array(nums)
406 }
407 None => Value::Array(None),
408 },
409 #[cfg(feature = "chrono")]
410 PostgresType::TIMESTAMPTZ_ARRAY => match row.try_get(i)? {
411 Some(val) => {
412 let val: Vec<Option<DateTime<Utc>>> = val;
413 let dates = val.into_iter().map(Value::DateTime);
414
415 Value::array(dates)
416 }
417 None => Value::Array(None),
418 },
419 #[cfg(feature = "chrono")]
420 PostgresType::DATE_ARRAY => match row.try_get(i)? {
421 Some(val) => {
422 let val: Vec<Option<chrono::NaiveDate>> = val;
423 let dates = val.into_iter().map(Value::Date);
424
425 Value::array(dates)
426 }
427 None => Value::Array(None),
428 },
429 #[cfg(feature = "chrono")]
430 PostgresType::TIME_ARRAY => match row.try_get(i)? {
431 Some(val) => {
432 let val: Vec<Option<chrono::NaiveTime>> = val;
433 let times = val.into_iter().map(Value::Time);
434
435 Value::array(times)
436 }
437 None => Value::Array(None),
438 },
439 #[cfg(feature = "chrono")]
440 PostgresType::TIMETZ_ARRAY => match row.try_get(i)? {
441 Some(val) => {
442 let val: Vec<Option<TimeTz>> = val;
443 let timetzs = val.into_iter().map(|time| Value::Time(time.map(|time| time.0)));
444
445 Value::array(timetzs)
446 }
447 None => Value::Array(None),
448 },
449 #[cfg(feature = "json")]
450 PostgresType::JSON_ARRAY => match row.try_get(i)? {
451 Some(val) => {
452 let val: Vec<Option<serde_json::Value>> = val;
453 let jsons = val.into_iter().map(Value::Json);
454
455 Value::array(jsons)
456 }
457 None => Value::Array(None),
458 },
459 #[cfg(feature = "json")]
460 PostgresType::JSONB_ARRAY => match row.try_get(i)? {
461 Some(val) => {
462 let val: Vec<Option<serde_json::Value>> = val;
463 let jsons = val.into_iter().map(Value::Json);
464
465 Value::array(jsons)
466 }
467 None => Value::Array(None),
468 },
469 PostgresType::OID => match row.try_get(i)? {
470 Some(val) => {
471 let val: u32 = val;
472 Value::int64(val)
473 }
474 None => Value::Int64(None),
475 },
476 PostgresType::CHAR => match row.try_get(i)? {
477 Some(val) => {
478 let val: i8 = val;
479 Value::character((val as u8) as char)
480 }
481 None => Value::Char(None),
482 },
483 PostgresType::INET | PostgresType::CIDR => match row.try_get(i)? {
484 Some(val) => {
485 let val: std::net::IpAddr = val;
486 Value::text(val.to_string())
487 }
488 None => Value::Text(None),
489 },
490 PostgresType::INET_ARRAY | PostgresType::CIDR_ARRAY => match row.try_get(i)? {
491 Some(val) => {
492 let val: Vec<Option<std::net::IpAddr>> = val;
493 let addrs = val.into_iter().map(|ip| Value::Text(ip.map(|ip| ip.to_string().into())));
494
495 Value::array(addrs)
496 }
497 None => Value::Array(None),
498 },
499 PostgresType::BIT | PostgresType::VARBIT => match row.try_get(i)? {
500 Some(val) => {
501 let val: BitVec = val;
502 Value::text(bits_to_string(&val)?)
503 }
504 None => Value::Text(None),
505 },
506 PostgresType::BIT_ARRAY | PostgresType::VARBIT_ARRAY => match row.try_get(i)? {
507 Some(val) => {
508 let val: Vec<Option<BitVec>> = val;
509 let stringified = val
510 .into_iter()
511 .map(|bits| match bits {
512 Some(bits) => bits_to_string(&bits).map(Value::text),
513 None => Ok(Value::Text(None)),
514 })
515 .collect::<crate::Result<Vec<_>>>()?;
516
517 Value::array(stringified)
518 }
519 None => Value::Array(None),
520 },
521 PostgresType::XML => match row.try_get(i)? {
522 Some(val) => {
523 let val: XmlString = val;
524 Value::xml(val.0)
525 }
526 None => Value::Xml(None),
527 },
528 PostgresType::XML_ARRAY => match row.try_get(i)? {
529 Some(val) => {
530 let val: Vec<Option<XmlString>> = val;
531 let xmls = val.into_iter().map(|xml| xml.map(|xml| xml.0));
532
533 Value::array(xmls)
534 }
535 None => Value::Array(None),
536 },
537 ref x => match x.kind() {
538 Kind::Enum(_) => match row.try_get(i)? {
539 Some(val) => {
540 let val: EnumString = val;
541
542 Value::enum_variant(val.value)
543 }
544 None => Value::Enum(None),
545 },
546 Kind::Array(inner) => match inner.kind() {
547 Kind::Enum(_) => match row.try_get(i)? {
548 Some(val) => {
549 let val: Vec<Option<EnumString>> = val;
550 let variants = val.into_iter().map(|x| Value::Enum(x.map(|x| x.value.into())));
551
552 Ok(Value::array(variants))
553 }
554 None => Ok(Value::Array(None)),
555 },
556 _ => match row.try_get(i) {
557 Ok(Some(val)) => {
558 let val: Vec<Option<String>> = val;
559 let strings = val.into_iter().map(|str| Value::Text(str.map(Into::into)));
560
561 Ok(Value::array(strings))
562 }
563 Ok(None) => Ok(Value::Array(None)),
564 Err(err) => {
565 if err.source().map(|err| err.is::<WrongType>()).unwrap_or(false) {
566 let kind = ErrorKind::UnsupportedColumnType { column_type: x.to_string() };
567
568 return Err(Error::builder(kind).build());
569 } else {
570 Err(err)
571 }
572 }
573 },
574 }?,
575 _ => match row.try_get(i) {
576 Ok(Some(val)) => {
577 let val: String = val;
578
579 Ok(Value::text(val))
580 }
581 Ok(None) => Ok(Value::Text(None)),
582 Err(err) => {
583 if err.source().map(|err| err.is::<WrongType>()).unwrap_or(false) {
584 let kind = ErrorKind::UnsupportedColumnType { column_type: x.to_string() };
585
586 return Err(Error::builder(kind).build());
587 } else {
588 Err(err)
589 }
590 }
591 }?,
592 },
593 };
594
595 Ok(result)
596 }
597
598 let num_columns = self.columns().len();
599 let mut row = Vec::with_capacity(num_columns);
600
601 for i in 0..num_columns {
602 row.push(convert(self, i)?);
603 }
604
605 Ok(row)
606 }
607}
608
609impl ToColumnNames for PostgresStatement {
610 fn to_column_names(&self) -> Vec<String> {
611 self.columns().iter().map(|c| c.name().into()).collect()
612 }
613}
614
615impl<'a> ToSql for Value<'a> {
616 fn to_sql(
617 &self,
618 ty: &PostgresType,
619 out: &mut BytesMut,
620 ) -> Result<IsNull, Box<dyn StdError + 'static + Send + Sync>> {
621 let res = match (self, ty) {
622 (Value::Int32(integer), &PostgresType::INT2) => match integer {
623 Some(i) => {
624 let integer = i16::try_from(*i).map_err(|_| {
625 let kind = ErrorKind::conversion(format!(
626 "Unable to fit integer value '{i}' into an INT2 (16-bit signed integer)."
627 ));
628
629 Error::builder(kind).build()
630 })?;
631
632 Some(integer.to_sql(ty, out))
633 }
634 _ => None,
635 },
636 (Value::Int32(integer), &PostgresType::INT4) => integer.map(|integer| integer.to_sql(ty, out)),
637 (Value::Int32(integer), &PostgresType::INT8) => integer.map(|integer| (integer as i64).to_sql(ty, out)),
638 (Value::Int64(integer), &PostgresType::INT2) => match integer {
639 Some(i) => {
640 let integer = i16::try_from(*i).map_err(|_| {
641 let kind = ErrorKind::conversion(format!(
642 "Unable to fit integer value '{i}' into an INT2 (16-bit signed integer)."
643 ));
644
645 Error::builder(kind).build()
646 })?;
647
648 Some(integer.to_sql(ty, out))
649 }
650 _ => None,
651 },
652 (Value::Int64(integer), &PostgresType::INT4) => match integer {
653 Some(i) => {
654 let integer = i32::try_from(*i).map_err(|_| {
655 let kind = ErrorKind::conversion(format!(
656 "Unable to fit integer value '{i}' into an INT4 (32-bit signed integer)."
657 ));
658
659 Error::builder(kind).build()
660 })?;
661
662 Some(integer.to_sql(ty, out))
663 }
664 _ => None,
665 },
666 (Value::Int64(integer), &PostgresType::INT8) => integer.map(|integer| integer.to_sql(ty, out)),
667 #[cfg(feature = "bigdecimal")]
668 (Value::Int32(integer), &PostgresType::NUMERIC) => integer
669 .map(|integer| BigDecimal::from_i32(integer).unwrap())
670 .map(DecimalWrapper)
671 .map(|dw| dw.to_sql(ty, out)),
672 #[cfg(feature = "bigdecimal")]
673 (Value::Int64(integer), &PostgresType::NUMERIC) => integer
674 .map(|integer| BigDecimal::from_i64(integer).unwrap())
675 .map(DecimalWrapper)
676 .map(|dw| dw.to_sql(ty, out)),
677 (Value::Int32(integer), &PostgresType::TEXT) => integer.map(|integer| format!("{integer}").to_sql(ty, out)),
678 (Value::Int64(integer), &PostgresType::TEXT) => integer.map(|integer| format!("{integer}").to_sql(ty, out)),
679 (Value::Int32(integer), &PostgresType::OID) => match integer {
680 Some(i) => {
681 let integer = u32::try_from(*i).map_err(|_| {
682 let kind = ErrorKind::conversion(format!(
683 "Unable to fit integer value '{i}' into an OID (32-bit unsigned integer)."
684 ));
685
686 Error::builder(kind).build()
687 })?;
688
689 Some(integer.to_sql(ty, out))
690 }
691 _ => None,
692 },
693 (Value::Int64(integer), &PostgresType::OID) => match integer {
694 Some(i) => {
695 let integer = u32::try_from(*i).map_err(|_| {
696 let kind = ErrorKind::conversion(format!(
697 "Unable to fit integer value '{i}' into an OID (32-bit unsigned integer)."
698 ));
699
700 Error::builder(kind).build()
701 })?;
702
703 Some(integer.to_sql(ty, out))
704 }
705 _ => None,
706 },
707 (Value::Int32(integer), _) => integer.map(|integer| integer.to_sql(ty, out)),
708 (Value::Int64(integer), _) => integer.map(|integer| integer.to_sql(ty, out)),
709 (Value::Float(float), &PostgresType::FLOAT8) => float.map(|float| (float as f64).to_sql(ty, out)),
710 #[cfg(feature = "bigdecimal")]
711 (Value::Float(float), &PostgresType::NUMERIC) => {
712 float.map(|float| BigDecimal::from_f32(float).unwrap()).map(DecimalWrapper).map(|dw| dw.to_sql(ty, out))
713 }
714 (Value::Float(float), _) => float.map(|float| float.to_sql(ty, out)),
715 (Value::Double(double), &PostgresType::FLOAT4) => double.map(|double| (double as f32).to_sql(ty, out)),
716 #[cfg(feature = "bigdecimal")]
717 (Value::Double(double), &PostgresType::NUMERIC) => double
718 .map(|double| BigDecimal::from_f64(double).unwrap())
719 .map(DecimalWrapper)
720 .map(|dw| dw.to_sql(ty, out)),
721 (Value::Double(double), _) => double.map(|double| double.to_sql(ty, out)),
722 #[cfg(feature = "bigdecimal")]
723 (Value::Numeric(decimal), &PostgresType::FLOAT4) => decimal.as_ref().map(|decimal| {
724 let f = decimal.to_string().parse::<f32>().expect("decimal to f32 conversion");
725 f.to_sql(ty, out)
726 }),
727 #[cfg(feature = "bigdecimal")]
728 (Value::Numeric(decimal), &PostgresType::FLOAT8) => decimal.as_ref().map(|decimal| {
729 let f = decimal.to_string().parse::<f64>().expect("decimal to f64 conversion");
730 f.to_sql(ty, out)
731 }),
732 #[cfg(feature = "bigdecimal")]
733 (Value::Array(values), &PostgresType::FLOAT4_ARRAY) => values.as_ref().map(|values| {
734 let mut floats = Vec::with_capacity(values.len());
735
736 for value in values.iter() {
737 let float = match value {
738 Value::Numeric(n) => n.as_ref().and_then(|n| n.to_string().parse::<f32>().ok()),
739 Value::Int64(n) => n.map(|n| n as f32),
740 Value::Float(f) => *f,
741 Value::Double(d) => d.map(|d| d as f32),
742 v if v.is_null() => None,
743 v => {
744 let kind = ErrorKind::conversion(format!(
745 "Couldn't add value of type `{v:?}` into a float array."
746 ));
747
748 return Err(Error::builder(kind).build().into());
749 }
750 };
751
752 floats.push(float);
753 }
754
755 floats.to_sql(ty, out)
756 }),
757 #[cfg(feature = "bigdecimal")]
758 (Value::Array(values), &PostgresType::FLOAT8_ARRAY) => values.as_ref().map(|values| {
759 let mut floats = Vec::with_capacity(values.len());
760
761 for value in values.iter() {
762 let float = match value {
763 Value::Numeric(n) => n.as_ref().and_then(|n| n.to_string().parse::<f64>().ok()),
764 Value::Int64(n) => n.map(|n| n as f64),
765 Value::Float(f) => f.map(|f| f as f64),
766 Value::Double(d) => *d,
767 v if v.is_null() => None,
768 v => {
769 let kind = ErrorKind::conversion(format!(
770 "Couldn't add value of type `{v:?}` into a double array."
771 ));
772
773 return Err(Error::builder(kind).build().into());
774 }
775 };
776
777 floats.push(float);
778 }
779
780 floats.to_sql(ty, out)
781 }),
782 #[cfg(feature = "bigdecimal")]
783 (Value::Numeric(decimal), &PostgresType::MONEY) => decimal.as_ref().map(|decimal| {
784 let decimal = (decimal * BigInt::from_i32(100).unwrap()).round(0);
785
786 let i = decimal.to_i64().ok_or_else(|| {
787 let kind = ErrorKind::conversion("Couldn't convert BigDecimal to i64.");
788 Error::builder(kind).build()
789 })?;
790
791 i.to_sql(ty, out)
792 }),
793 #[cfg(feature = "bigdecimal")]
794 (Value::Numeric(decimal), &PostgresType::NUMERIC) => {
795 decimal.as_ref().map(|decimal| DecimalWrapper(decimal.clone()).to_sql(ty, out))
796 }
797 #[cfg(feature = "bigdecimal")]
798 (Value::Numeric(float), _) => float.as_ref().map(|float| DecimalWrapper(float.clone()).to_sql(ty, out)),
799 #[cfg(feature = "uuid")]
800 (Value::Text(string), &PostgresType::UUID) => string.as_ref().map(|string| {
801 let parsed_uuid: Uuid = string.parse()?;
802 parsed_uuid.to_sql(ty, out)
803 }),
804 #[cfg(feature = "uuid")]
805 (Value::Array(values), &PostgresType::UUID_ARRAY) => values.as_ref().map(|values| {
806 let parsed_uuid: Vec<Option<Uuid>> =
807 values.iter().map(<Option<Uuid>>::try_from).collect::<crate::Result<Vec<_>>>()?;
808
809 parsed_uuid.to_sql(ty, out)
810 }),
811 (Value::Text(string), &PostgresType::INET) | (Value::Text(string), &PostgresType::CIDR) => {
812 string.as_ref().map(|string| {
813 let parsed_ip_addr: std::net::IpAddr = string.parse()?;
814 parsed_ip_addr.to_sql(ty, out)
815 })
816 }
817 (Value::Array(values), &PostgresType::INET_ARRAY) | (Value::Array(values), &PostgresType::CIDR_ARRAY) => {
818 values.as_ref().map(|values| {
819 let parsed_ip_addr: Vec<Option<std::net::IpAddr>> =
820 values.iter().map(<Option<std::net::IpAddr>>::try_from).collect::<crate::Result<_>>()?;
821
822 parsed_ip_addr.to_sql(ty, out)
823 })
824 }
825 #[cfg(feature = "json")]
826 (Value::Text(string), &PostgresType::JSON) | (Value::Text(string), &PostgresType::JSONB) => {
827 string.as_ref().map(|string| serde_json::from_str::<serde_json::Value>(string)?.to_sql(ty, out))
828 }
829 (Value::Text(string), &PostgresType::BIT) | (Value::Text(string), &PostgresType::VARBIT) => {
830 string.as_ref().map(|string| {
831 let bits: BitVec = string_to_bits(string)?;
832
833 bits.to_sql(ty, out)
834 })
835 }
836 (Value::Text(string), _) => string.as_ref().map(|ref string| string.to_sql(ty, out)),
837 (Value::Array(values), &PostgresType::BIT_ARRAY) | (Value::Array(values), &PostgresType::VARBIT_ARRAY) => {
838 values.as_ref().map(|values| {
839 let bitvecs: Vec<Option<BitVec>> =
840 values.iter().map(<Option<BitVec>>::try_from).collect::<crate::Result<Vec<_>>>()?;
841
842 bitvecs.to_sql(ty, out)
843 })
844 }
845 (Value::Bytes(bytes), _) => bytes.as_ref().map(|bytes| bytes.as_ref().to_sql(ty, out)),
846 (Value::Enum(string), _) => string.as_ref().map(|string| {
847 out.extend_from_slice(string.as_bytes());
848 Ok(IsNull::No)
849 }),
850 (Value::Boolean(boo), _) => boo.map(|boo| boo.to_sql(ty, out)),
851 (Value::Char(c), _) => c.map(|c| (c as i8).to_sql(ty, out)),
852 (Value::Array(vec), typ) if matches!(typ.kind(), Kind::Array(_)) => {
853 vec.as_ref().map(|vec| vec.to_sql(ty, out))
854 }
855 (Value::Array(vec), typ) => {
856 let kind = ErrorKind::conversion(format!(
857 "Couldn't serialize value `{vec:?}` into a `{typ}`. Value is a list but `{typ}` is not."
858 ));
859
860 return Err(Error::builder(kind).build().into());
861 }
862 #[cfg(feature = "json")]
863 (Value::Json(value), _) => value.as_ref().map(|value| value.to_sql(ty, out)),
864 (Value::Xml(value), _) => value.as_ref().map(|value| value.to_sql(ty, out)),
865 #[cfg(feature = "uuid")]
866 (Value::Uuid(value), _) => value.map(|value| value.to_sql(ty, out)),
867 #[cfg(feature = "chrono")]
868 (Value::DateTime(value), &PostgresType::DATE) => value.map(|value| value.date_naive().to_sql(ty, out)),
869 #[cfg(feature = "chrono")]
870 (Value::Date(value), _) => value.map(|value| value.to_sql(ty, out)),
871 #[cfg(feature = "chrono")]
872 (Value::Time(value), _) => value.map(|value| value.to_sql(ty, out)),
873 #[cfg(feature = "chrono")]
874 (Value::DateTime(value), &PostgresType::TIME) => value.map(|value| value.time().to_sql(ty, out)),
875 #[cfg(feature = "chrono")]
876 (Value::DateTime(value), &PostgresType::TIMETZ) => value.map(|value| {
877 let result = value.time().to_sql(ty, out)?;
878 out.extend_from_slice(&[0; 4]);
880 Ok(result)
881 }),
882 #[cfg(feature = "chrono")]
883 (Value::DateTime(value), _) => value.map(|value| value.naive_utc().to_sql(ty, out)),
884 };
885
886 match res {
887 Some(res) => res,
888 None => Ok(IsNull::Yes),
889 }
890 }
891
892 fn accepts(_: &PostgresType) -> bool {
893 true }
895
896 tokio_postgres::types::to_sql_checked!();
897}
898
899fn string_to_bits(s: &str) -> crate::Result<BitVec> {
900 use bit_vec::*;
901
902 let mut bits = BitVec::with_capacity(s.len());
903
904 for c in s.chars() {
905 match c {
906 '0' => bits.push(false),
907 '1' => bits.push(true),
908 _ => {
909 let msg = "Unexpected character for bits input. Expected only 1 and 0.";
910 let kind = ErrorKind::conversion(msg);
911
912 return Err(Error::builder(kind).build());
913 }
914 }
915 }
916
917 Ok(bits)
918}
919
920fn bits_to_string(bits: &BitVec) -> crate::Result<String> {
921 let mut s = String::with_capacity(bits.len());
922
923 for bit in bits {
924 if bit {
925 s.push('1');
926 } else {
927 s.push('0');
928 }
929 }
930
931 Ok(s)
932}
933
934impl<'a> TryFrom<&Value<'a>> for Option<BitVec> {
935 type Error = Error;
936
937 fn try_from(value: &Value<'a>) -> Result<Option<BitVec>, Self::Error> {
938 match value {
939 val @ Value::Text(Some(_)) => {
940 let text = val.as_str().unwrap();
941
942 string_to_bits(text).map(Option::Some)
943 }
944 val @ Value::Bytes(Some(_)) => {
945 let text = val.as_str().unwrap();
946
947 string_to_bits(text).map(Option::Some)
948 }
949 v if v.is_null() => Ok(None),
950 v => {
951 let kind = ErrorKind::conversion(format!("Couldn't convert value of type `{v:?}` to bit_vec::BitVec."));
952
953 Err(Error::builder(kind).build())
954 }
955 }
956 }
957}