1mod conversions;
4mod drivers;
5mod insert;
6#[cfg(feature = "serde")]
7mod json;
8mod owned;
9mod update;
10
11pub use insert::*;
12#[cfg(feature = "serde")]
13pub use json::PostgresJsonType;
14pub use owned::*;
15pub use update::*;
16
17use drizzle_core::{error::DrizzleError, sql::SQL, traits::SQLParam};
18
19#[cfg(feature = "uuid")]
20use uuid::Uuid;
21
22#[cfg(feature = "chrono")]
23use chrono::{DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
24
25#[cfg(feature = "time")]
26use time::{
27 Date as TimeDate, Duration as TimeDuration, OffsetDateTime, PrimitiveDateTime, Time as TimeTime,
28};
29
30#[cfg(feature = "jiff")]
31use jiff::{
32 Timestamp as JiffTimestamp,
33 civil::{Date as JiffDate, DateTime as JiffDateTime, Time as JiffTime},
34};
35
36#[cfg(feature = "cidr")]
37use cidr::{IpCidr, IpInet};
38
39#[cfg(feature = "geo-types")]
40use geo_types::{LineString, Point, Rect};
41
42#[cfg(feature = "bit-vec")]
43use bit_vec::BitVec;
44
45#[cfg(feature = "rust-decimal")]
46use rust_decimal::Decimal;
47
48use crate::prelude::*;
49
50use crate::traits::{FromPostgresValue, PostgresEnum};
51
52#[derive(Debug, Clone, PartialEq, Default)]
78pub enum PostgresValue<'a> {
79 Smallint(i16),
81 Integer(i32),
83 Bigint(i64),
85 Real(f32),
87 DoublePrecision(f64),
89 #[cfg(feature = "rust-decimal")]
91 Numeric(Decimal),
92 Text(Cow<'a, str>),
94 Bytea(Cow<'a, [u8]>),
96 Boolean(bool),
98 #[cfg(feature = "uuid")]
100 Uuid(Uuid),
101 #[cfg(feature = "serde")]
103 Json(serde_json::Value),
104 #[cfg(feature = "serde")]
106 Jsonb(serde_json::Value),
107 Enum(Box<dyn PostgresEnum>),
109
110 #[cfg(feature = "chrono")]
113 Date(NaiveDate),
114 #[cfg(feature = "chrono")]
116 Time(NaiveTime),
117 #[cfg(feature = "chrono")]
119 Timestamp(NaiveDateTime),
120 #[cfg(feature = "chrono")]
122 TimestampTz(DateTime<FixedOffset>),
123 #[cfg(feature = "chrono")]
125 Interval(Duration),
126
127 #[cfg(feature = "time")]
130 TimeDate(TimeDate),
131 #[cfg(feature = "time")]
133 TimeTime(TimeTime),
134 #[cfg(feature = "time")]
136 TimeTimestamp(PrimitiveDateTime),
137 #[cfg(feature = "time")]
139 TimeTimestampTz(OffsetDateTime),
140 #[cfg(feature = "time")]
142 TimeInterval(TimeDuration),
143 #[cfg(feature = "jiff")]
145 JiffDate(JiffDate),
146 #[cfg(feature = "jiff")]
148 JiffTime(JiffTime),
149 #[cfg(feature = "jiff")]
151 JiffDateTime(JiffDateTime),
152 #[cfg(feature = "jiff")]
154 JiffTimestamp(JiffTimestamp),
155
156 #[cfg(feature = "cidr")]
159 Inet(IpInet),
160 #[cfg(feature = "cidr")]
162 Cidr(IpCidr),
163 #[cfg(feature = "cidr")]
165 MacAddr([u8; 6]),
166 #[cfg(feature = "cidr")]
168 MacAddr8([u8; 8]),
169
170 #[cfg(feature = "geo-types")]
173 Point(Point<f64>),
174 #[cfg(feature = "geo-types")]
176 LineString(LineString<f64>),
177 #[cfg(feature = "geo-types")]
179 Rect(Rect<f64>),
180
181 #[cfg(feature = "bit-vec")]
184 BitVec(BitVec),
185
186 Array(Vec<Self>),
189
190 #[default]
192 Null,
193}
194
195impl core::fmt::Display for PostgresValue<'_> {
196 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
197 let value = match self {
198 PostgresValue::Smallint(i) => i.to_string(),
199 PostgresValue::Integer(i) => i.to_string(),
200 PostgresValue::Bigint(i) => i.to_string(),
201 PostgresValue::Real(r) => r.to_string(),
202 PostgresValue::DoublePrecision(r) => r.to_string(),
203 #[cfg(feature = "rust-decimal")]
204 PostgresValue::Numeric(d) => d.to_string(),
205 PostgresValue::Text(cow) => cow.to_string(),
206 PostgresValue::Bytea(cow) => {
207 use core::fmt::Write;
208 let mut s = String::with_capacity(2 + cow.len() * 2);
209 s.push_str("\\x");
210 for byte in cow.iter() {
211 write!(s, "{byte:02x}").expect("writing to String cannot fail");
212 }
213 s
214 }
215 PostgresValue::Boolean(b) => b.to_string(),
216 #[cfg(feature = "uuid")]
217 PostgresValue::Uuid(uuid) => uuid.to_string(),
218 #[cfg(feature = "serde")]
219 PostgresValue::Json(json) => json.to_string(),
220 #[cfg(feature = "serde")]
221 PostgresValue::Jsonb(json) => json.to_string(),
222 PostgresValue::Enum(enum_val) => enum_val.variant_name().to_string(),
223
224 #[cfg(feature = "chrono")]
226 PostgresValue::Date(date) => date.to_string(),
227 #[cfg(feature = "chrono")]
228 PostgresValue::Time(time) => time.to_string(),
229 #[cfg(feature = "chrono")]
230 PostgresValue::Timestamp(ts) => ts.to_string(),
231 #[cfg(feature = "chrono")]
232 PostgresValue::TimestampTz(ts) => ts.to_string(),
233 #[cfg(feature = "chrono")]
234 PostgresValue::Interval(dur) => format!("{} seconds", dur.num_seconds()),
235
236 #[cfg(feature = "time")]
238 PostgresValue::TimeDate(date) => date.to_string(),
239 #[cfg(feature = "time")]
240 PostgresValue::TimeTime(time) => time.to_string(),
241 #[cfg(feature = "time")]
242 PostgresValue::TimeTimestamp(ts) => ts.to_string(),
243 #[cfg(feature = "time")]
244 PostgresValue::TimeTimestampTz(ts) => ts.to_string(),
245 #[cfg(feature = "time")]
246 PostgresValue::TimeInterval(dur) => format!("{} seconds", dur.whole_seconds()),
247 #[cfg(feature = "jiff")]
248 PostgresValue::JiffDate(date) => date.to_string(),
249 #[cfg(feature = "jiff")]
250 PostgresValue::JiffTime(time) => time.to_string(),
251 #[cfg(feature = "jiff")]
252 PostgresValue::JiffDateTime(ts) => ts.to_string(),
253 #[cfg(feature = "jiff")]
254 PostgresValue::JiffTimestamp(ts) => ts.to_string(),
255
256 #[cfg(feature = "cidr")]
258 PostgresValue::Inet(net) => net.to_string(),
259 #[cfg(feature = "cidr")]
260 PostgresValue::Cidr(net) => net.to_string(),
261 #[cfg(feature = "cidr")]
262 PostgresValue::MacAddr(mac) => format!(
263 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
264 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
265 ),
266 #[cfg(feature = "cidr")]
267 PostgresValue::MacAddr8(mac) => format!(
268 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
269 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6], mac[7]
270 ),
271
272 #[cfg(feature = "geo-types")]
274 PostgresValue::Point(point) => format!("({},{})", point.x(), point.y()),
275 #[cfg(feature = "geo-types")]
276 PostgresValue::LineString(line) => {
277 let coords: Vec<String> = line
278 .coords()
279 .map(|coord| format!("({},{})", coord.x, coord.y))
280 .collect();
281 format!("[{}]", coords.join(","))
282 }
283 #[cfg(feature = "geo-types")]
284 PostgresValue::Rect(rect) => {
285 format!(
286 "(({},{}),({},{}))",
287 rect.min().x,
288 rect.min().y,
289 rect.max().x,
290 rect.max().y
291 )
292 }
293
294 #[cfg(feature = "bit-vec")]
296 PostgresValue::BitVec(bv) => bv
297 .iter()
298 .map(|b| if b { '1' } else { '0' })
299 .collect::<String>(),
300
301 PostgresValue::Array(arr) => {
303 let elements: Vec<String> = arr.iter().map(ToString::to_string).collect();
304 format!("{{{}}}", elements.join(","))
305 }
306
307 PostgresValue::Null => String::new(),
308 };
309 write!(f, "{value}")
310 }
311}
312
313impl PostgresValue<'_> {
314 #[inline]
316 #[must_use]
317 pub const fn is_null(&self) -> bool {
318 matches!(self, PostgresValue::Null)
319 }
320
321 #[inline]
323 #[must_use]
324 pub const fn as_bool(&self) -> Option<bool> {
325 match self {
326 PostgresValue::Boolean(value) => Some(*value),
327 _ => None,
328 }
329 }
330
331 #[inline]
333 #[must_use]
334 pub const fn as_i16(&self) -> Option<i16> {
335 match self {
336 PostgresValue::Smallint(value) => Some(*value),
337 _ => None,
338 }
339 }
340
341 #[inline]
343 #[must_use]
344 pub const fn as_i32(&self) -> Option<i32> {
345 match self {
346 PostgresValue::Integer(value) => Some(*value),
347 _ => None,
348 }
349 }
350
351 #[inline]
353 #[must_use]
354 pub const fn as_i64(&self) -> Option<i64> {
355 match self {
356 PostgresValue::Bigint(value) => Some(*value),
357 _ => None,
358 }
359 }
360
361 #[inline]
363 #[must_use]
364 pub const fn as_f32(&self) -> Option<f32> {
365 match self {
366 PostgresValue::Real(value) => Some(*value),
367 _ => None,
368 }
369 }
370
371 #[inline]
373 #[must_use]
374 pub const fn as_f64(&self) -> Option<f64> {
375 match self {
376 PostgresValue::DoublePrecision(value) => Some(*value),
377 _ => None,
378 }
379 }
380
381 #[inline]
383 #[cfg(feature = "rust-decimal")]
384 #[must_use]
385 pub const fn as_decimal(&self) -> Option<&Decimal> {
386 match self {
387 PostgresValue::Numeric(value) => Some(value),
388 _ => None,
389 }
390 }
391
392 #[inline]
394 #[must_use]
395 pub fn as_str(&self) -> Option<&str> {
396 match self {
397 PostgresValue::Text(value) => Some(value.as_ref()),
398 _ => None,
399 }
400 }
401
402 #[inline]
404 #[must_use]
405 pub fn as_bytes(&self) -> Option<&[u8]> {
406 match self {
407 PostgresValue::Bytea(value) => Some(value.as_ref()),
408 _ => None,
409 }
410 }
411
412 #[inline]
414 #[cfg(feature = "uuid")]
415 #[must_use]
416 pub const fn as_uuid(&self) -> Option<Uuid> {
417 match self {
418 PostgresValue::Uuid(value) => Some(*value),
419 _ => None,
420 }
421 }
422
423 #[inline]
425 #[cfg(feature = "serde")]
426 #[must_use]
427 pub const fn as_json(&self) -> Option<&serde_json::Value> {
428 match self {
429 PostgresValue::Json(value) => Some(value),
430 _ => None,
431 }
432 }
433
434 #[inline]
436 #[cfg(feature = "serde")]
437 #[must_use]
438 pub const fn as_jsonb(&self) -> Option<&serde_json::Value> {
439 match self {
440 PostgresValue::Jsonb(value) => Some(value),
441 _ => None,
442 }
443 }
444
445 #[inline]
447 #[must_use]
448 pub fn as_enum(&self) -> Option<&dyn PostgresEnum> {
449 match self {
450 PostgresValue::Enum(value) => Some(value.as_ref()),
451 _ => None,
452 }
453 }
454
455 #[inline]
457 #[cfg(feature = "chrono")]
458 #[must_use]
459 pub const fn as_date(&self) -> Option<&NaiveDate> {
460 match self {
461 PostgresValue::Date(value) => Some(value),
462 _ => None,
463 }
464 }
465
466 #[inline]
468 #[cfg(feature = "chrono")]
469 #[must_use]
470 pub const fn as_time(&self) -> Option<&NaiveTime> {
471 match self {
472 PostgresValue::Time(value) => Some(value),
473 _ => None,
474 }
475 }
476
477 #[inline]
479 #[cfg(feature = "chrono")]
480 #[must_use]
481 pub const fn as_timestamp(&self) -> Option<&NaiveDateTime> {
482 match self {
483 PostgresValue::Timestamp(value) => Some(value),
484 _ => None,
485 }
486 }
487
488 #[inline]
490 #[cfg(feature = "chrono")]
491 #[must_use]
492 pub const fn as_timestamp_tz(&self) -> Option<&DateTime<FixedOffset>> {
493 match self {
494 PostgresValue::TimestampTz(value) => Some(value),
495 _ => None,
496 }
497 }
498
499 #[inline]
501 #[cfg(feature = "chrono")]
502 #[must_use]
503 pub const fn as_interval(&self) -> Option<&Duration> {
504 match self {
505 PostgresValue::Interval(value) => Some(value),
506 _ => None,
507 }
508 }
509
510 #[inline]
512 #[cfg(feature = "cidr")]
513 #[must_use]
514 pub const fn as_inet(&self) -> Option<&IpInet> {
515 match self {
516 PostgresValue::Inet(value) => Some(value),
517 _ => None,
518 }
519 }
520
521 #[inline]
523 #[cfg(feature = "cidr")]
524 #[must_use]
525 pub const fn as_cidr(&self) -> Option<&IpCidr> {
526 match self {
527 PostgresValue::Cidr(value) => Some(value),
528 _ => None,
529 }
530 }
531
532 #[inline]
534 #[cfg(feature = "cidr")]
535 #[must_use]
536 pub const fn as_macaddr(&self) -> Option<[u8; 6]> {
537 match self {
538 PostgresValue::MacAddr(value) => Some(*value),
539 _ => None,
540 }
541 }
542
543 #[inline]
545 #[cfg(feature = "cidr")]
546 #[must_use]
547 pub const fn as_macaddr8(&self) -> Option<[u8; 8]> {
548 match self {
549 PostgresValue::MacAddr8(value) => Some(*value),
550 _ => None,
551 }
552 }
553
554 #[inline]
556 #[cfg(feature = "geo-types")]
557 #[must_use]
558 pub const fn as_point(&self) -> Option<&Point<f64>> {
559 match self {
560 PostgresValue::Point(value) => Some(value),
561 _ => None,
562 }
563 }
564
565 #[inline]
567 #[cfg(feature = "geo-types")]
568 #[must_use]
569 pub const fn as_line_string(&self) -> Option<&LineString<f64>> {
570 match self {
571 PostgresValue::LineString(value) => Some(value),
572 _ => None,
573 }
574 }
575
576 #[inline]
578 #[cfg(feature = "geo-types")]
579 #[must_use]
580 pub const fn as_rect(&self) -> Option<&Rect<f64>> {
581 match self {
582 PostgresValue::Rect(value) => Some(value),
583 _ => None,
584 }
585 }
586
587 #[inline]
589 #[cfg(feature = "bit-vec")]
590 #[must_use]
591 pub const fn as_bitvec(&self) -> Option<&BitVec> {
592 match self {
593 PostgresValue::BitVec(value) => Some(value),
594 _ => None,
595 }
596 }
597
598 #[inline]
600 #[cfg(feature = "time")]
601 #[must_use]
602 pub const fn as_time_date(&self) -> Option<&TimeDate> {
603 match self {
604 PostgresValue::TimeDate(value) => Some(value),
605 _ => None,
606 }
607 }
608
609 #[inline]
611 #[cfg(feature = "time")]
612 #[must_use]
613 pub const fn as_time_time(&self) -> Option<&TimeTime> {
614 match self {
615 PostgresValue::TimeTime(value) => Some(value),
616 _ => None,
617 }
618 }
619
620 #[inline]
622 #[cfg(feature = "time")]
623 #[must_use]
624 pub const fn as_time_timestamp(&self) -> Option<&PrimitiveDateTime> {
625 match self {
626 PostgresValue::TimeTimestamp(value) => Some(value),
627 _ => None,
628 }
629 }
630
631 #[inline]
633 #[cfg(feature = "time")]
634 #[must_use]
635 pub const fn as_time_timestamp_tz(&self) -> Option<&OffsetDateTime> {
636 match self {
637 PostgresValue::TimeTimestampTz(value) => Some(value),
638 _ => None,
639 }
640 }
641
642 #[inline]
644 #[cfg(feature = "time")]
645 #[must_use]
646 pub const fn as_time_interval(&self) -> Option<&TimeDuration> {
647 match self {
648 PostgresValue::TimeInterval(value) => Some(value),
649 _ => None,
650 }
651 }
652
653 #[inline]
655 #[cfg(feature = "jiff")]
656 #[must_use]
657 pub const fn as_jiff_date(&self) -> Option<&JiffDate> {
658 match self {
659 PostgresValue::JiffDate(value) => Some(value),
660 _ => None,
661 }
662 }
663
664 #[inline]
666 #[cfg(feature = "jiff")]
667 #[must_use]
668 pub const fn as_jiff_time(&self) -> Option<&JiffTime> {
669 match self {
670 PostgresValue::JiffTime(value) => Some(value),
671 _ => None,
672 }
673 }
674
675 #[inline]
677 #[cfg(feature = "jiff")]
678 #[must_use]
679 pub const fn as_jiff_datetime(&self) -> Option<&JiffDateTime> {
680 match self {
681 PostgresValue::JiffDateTime(value) => Some(value),
682 _ => None,
683 }
684 }
685
686 #[inline]
688 #[cfg(feature = "jiff")]
689 #[must_use]
690 pub const fn as_jiff_timestamp(&self) -> Option<&JiffTimestamp> {
691 match self {
692 PostgresValue::JiffTimestamp(value) => Some(value),
693 _ => None,
694 }
695 }
696
697 #[inline]
699 #[must_use]
700 pub fn as_array(&self) -> Option<&[Self]> {
701 match self {
702 PostgresValue::Array(values) => Some(values),
703 _ => None,
704 }
705 }
706
707 #[inline]
709 #[must_use]
710 pub fn into_owned(self) -> OwnedPostgresValue {
711 self.into()
712 }
713
714 pub fn convert<T: FromPostgresValue>(self) -> Result<T, DrizzleError> {
721 match self {
722 PostgresValue::Boolean(value) => T::from_postgres_bool(value),
723 PostgresValue::Smallint(value) => T::from_postgres_i16(value),
724 PostgresValue::Integer(value) => T::from_postgres_i32(value),
725 PostgresValue::Bigint(value) => T::from_postgres_i64(value),
726 PostgresValue::Real(value) => T::from_postgres_f32(value),
727 PostgresValue::DoublePrecision(value) => T::from_postgres_f64(value),
728 #[cfg(feature = "rust-decimal")]
729 PostgresValue::Numeric(value) => {
730 let text = value.to_string();
731 T::from_postgres_text(&text)
732 }
733 PostgresValue::Text(value) => T::from_postgres_text(&value),
734 PostgresValue::Bytea(value) => T::from_postgres_bytes(&value),
735 #[cfg(feature = "uuid")]
736 PostgresValue::Uuid(value) => T::from_postgres_uuid(value),
737 #[cfg(feature = "serde")]
738 PostgresValue::Json(value) => T::from_postgres_json(value),
739 #[cfg(feature = "serde")]
740 PostgresValue::Jsonb(value) => T::from_postgres_jsonb(value),
741 PostgresValue::Enum(value) => T::from_postgres_text(value.variant_name()),
742 #[cfg(feature = "chrono")]
743 PostgresValue::Date(value) => T::from_postgres_date(value),
744 #[cfg(feature = "chrono")]
745 PostgresValue::Time(value) => T::from_postgres_time(value),
746 #[cfg(feature = "chrono")]
747 PostgresValue::Timestamp(value) => T::from_postgres_timestamp(value),
748 #[cfg(feature = "chrono")]
749 PostgresValue::TimestampTz(value) => T::from_postgres_timestamptz(value),
750 #[cfg(feature = "chrono")]
751 PostgresValue::Interval(value) => T::from_postgres_interval(value),
752 #[cfg(feature = "time")]
753 PostgresValue::TimeDate(value) => T::from_postgres_time_date(value),
754 #[cfg(feature = "time")]
755 PostgresValue::TimeTime(value) => T::from_postgres_time_time(value),
756 #[cfg(feature = "time")]
757 PostgresValue::TimeTimestamp(value) => T::from_postgres_time_timestamp(value),
758 #[cfg(feature = "time")]
759 PostgresValue::TimeTimestampTz(value) => T::from_postgres_time_timestamptz(value),
760 #[cfg(feature = "time")]
761 PostgresValue::TimeInterval(value) => T::from_postgres_time_interval(value),
762 #[cfg(feature = "jiff")]
763 PostgresValue::JiffDate(value) => T::from_postgres_jiff_date(value),
764 #[cfg(feature = "jiff")]
765 PostgresValue::JiffTime(value) => T::from_postgres_jiff_time(value),
766 #[cfg(feature = "jiff")]
767 PostgresValue::JiffDateTime(value) => T::from_postgres_jiff_datetime(value),
768 #[cfg(feature = "jiff")]
769 PostgresValue::JiffTimestamp(value) => T::from_postgres_jiff_timestamp(value),
770 #[cfg(feature = "cidr")]
771 PostgresValue::Inet(value) => T::from_postgres_inet(value),
772 #[cfg(feature = "cidr")]
773 PostgresValue::Cidr(value) => T::from_postgres_cidr(value),
774 #[cfg(feature = "cidr")]
775 PostgresValue::MacAddr(value) => T::from_postgres_macaddr(value),
776 #[cfg(feature = "cidr")]
777 PostgresValue::MacAddr8(value) => T::from_postgres_macaddr8(value),
778 #[cfg(feature = "geo-types")]
779 PostgresValue::Point(value) => T::from_postgres_point(value),
780 #[cfg(feature = "geo-types")]
781 PostgresValue::LineString(value) => T::from_postgres_linestring(value),
782 #[cfg(feature = "geo-types")]
783 PostgresValue::Rect(value) => T::from_postgres_rect(value),
784 #[cfg(feature = "bit-vec")]
785 PostgresValue::BitVec(value) => T::from_postgres_bitvec(value),
786 PostgresValue::Array(value) => T::from_postgres_array(value),
787 PostgresValue::Null => T::from_postgres_null(),
788 }
789 }
790
791 pub fn convert_ref<T: FromPostgresValue>(&self) -> Result<T, DrizzleError> {
798 match self {
799 PostgresValue::Boolean(value) => T::from_postgres_bool(*value),
800 PostgresValue::Smallint(value) => T::from_postgres_i16(*value),
801 PostgresValue::Integer(value) => T::from_postgres_i32(*value),
802 PostgresValue::Bigint(value) => T::from_postgres_i64(*value),
803 PostgresValue::Real(value) => T::from_postgres_f32(*value),
804 PostgresValue::DoublePrecision(value) => T::from_postgres_f64(*value),
805 #[cfg(feature = "rust-decimal")]
806 PostgresValue::Numeric(value) => {
807 let text = value.to_string();
808 T::from_postgres_text(&text)
809 }
810 PostgresValue::Text(value) => T::from_postgres_text(value),
811 PostgresValue::Bytea(value) => T::from_postgres_bytes(value),
812 #[cfg(feature = "uuid")]
813 PostgresValue::Uuid(value) => T::from_postgres_uuid(*value),
814 #[cfg(feature = "serde")]
815 PostgresValue::Json(value) => T::from_postgres_json(value.clone()),
816 #[cfg(feature = "serde")]
817 PostgresValue::Jsonb(value) => T::from_postgres_jsonb(value.clone()),
818 PostgresValue::Enum(value) => T::from_postgres_text(value.variant_name()),
819 #[cfg(feature = "chrono")]
820 PostgresValue::Date(value) => T::from_postgres_date(*value),
821 #[cfg(feature = "chrono")]
822 PostgresValue::Time(value) => T::from_postgres_time(*value),
823 #[cfg(feature = "chrono")]
824 PostgresValue::Timestamp(value) => T::from_postgres_timestamp(*value),
825 #[cfg(feature = "chrono")]
826 PostgresValue::TimestampTz(value) => T::from_postgres_timestamptz(*value),
827 #[cfg(feature = "chrono")]
828 PostgresValue::Interval(value) => T::from_postgres_interval(*value),
829 #[cfg(feature = "time")]
830 PostgresValue::TimeDate(value) => T::from_postgres_time_date(*value),
831 #[cfg(feature = "time")]
832 PostgresValue::TimeTime(value) => T::from_postgres_time_time(*value),
833 #[cfg(feature = "time")]
834 PostgresValue::TimeTimestamp(value) => T::from_postgres_time_timestamp(*value),
835 #[cfg(feature = "time")]
836 PostgresValue::TimeTimestampTz(value) => T::from_postgres_time_timestamptz(*value),
837 #[cfg(feature = "time")]
838 PostgresValue::TimeInterval(value) => T::from_postgres_time_interval(*value),
839 #[cfg(feature = "jiff")]
840 PostgresValue::JiffDate(value) => T::from_postgres_jiff_date(*value),
841 #[cfg(feature = "jiff")]
842 PostgresValue::JiffTime(value) => T::from_postgres_jiff_time(*value),
843 #[cfg(feature = "jiff")]
844 PostgresValue::JiffDateTime(value) => T::from_postgres_jiff_datetime(*value),
845 #[cfg(feature = "jiff")]
846 PostgresValue::JiffTimestamp(value) => T::from_postgres_jiff_timestamp(*value),
847 #[cfg(feature = "cidr")]
848 PostgresValue::Inet(value) => T::from_postgres_inet(*value),
849 #[cfg(feature = "cidr")]
850 PostgresValue::Cidr(value) => T::from_postgres_cidr(*value),
851 #[cfg(feature = "cidr")]
852 PostgresValue::MacAddr(value) => T::from_postgres_macaddr(*value),
853 #[cfg(feature = "cidr")]
854 PostgresValue::MacAddr8(value) => T::from_postgres_macaddr8(*value),
855 #[cfg(feature = "geo-types")]
856 PostgresValue::Point(value) => T::from_postgres_point(*value),
857 #[cfg(feature = "geo-types")]
858 PostgresValue::LineString(value) => T::from_postgres_linestring(value.clone()),
859 #[cfg(feature = "geo-types")]
860 PostgresValue::Rect(value) => T::from_postgres_rect(*value),
861 #[cfg(feature = "bit-vec")]
862 PostgresValue::BitVec(value) => T::from_postgres_bitvec(value.clone()),
863 PostgresValue::Array(value) => T::from_postgres_array(value.clone()),
864 PostgresValue::Null => T::from_postgres_null(),
865 }
866 }
867}
868
869impl SQLParam for PostgresValue<'_> {
871 const DIALECT: drizzle_core::dialect::Dialect = drizzle_core::dialect::Dialect::PostgreSQL;
872 type DialectMarker = drizzle_core::dialect::PostgresDialect;
873
874 #[inline]
877 fn pagination_param(value: usize) -> Option<Self> {
878 i64::try_from(value).ok().map(Self::Bigint)
879 }
880
881 fn write_literal(&self, buf: &mut String) -> bool {
882 let mut literal = String::new();
883 let written = write_postgres_literal(self, &mut literal).is_some();
884 if written {
885 buf.push_str(&literal);
886 }
887 written
888 }
889}
890
891fn write_quoted_literal(buf: &mut String, text: &str) -> Option<()> {
893 if text.contains('\0') {
894 return None;
895 }
896 buf.push('\'');
897 buf.push_str(&text.replace('\'', "''"));
898 buf.push('\'');
899 Some(())
900}
901
902fn write_cast_literal(buf: &mut String, text: &str, sql_type: &str) -> Option<()> {
904 write_quoted_literal(buf, text)?;
905 buf.push_str("::");
906 buf.push_str(sql_type);
907 Some(())
908}
909
910fn float_text(value: f64) -> String {
911 if value.is_nan() {
912 "NaN".to_string()
913 } else if value.is_infinite() {
914 if value.is_sign_positive() {
915 "Infinity"
916 } else {
917 "-Infinity"
918 }
919 .to_string()
920 } else {
921 format!("{value:?}")
922 }
923}
924
925fn write_postgres_literal(value: &PostgresValue<'_>, buf: &mut String) -> Option<()> {
930 use core::fmt::Write;
931 match value {
932 PostgresValue::Null => buf.push_str("NULL"),
933 PostgresValue::Smallint(v) => {
934 let _ = write!(buf, "{v}::smallint");
935 }
936 PostgresValue::Integer(v) => {
937 let _ = write!(buf, "{v}::integer");
938 }
939 PostgresValue::Bigint(v) => {
940 let _ = write!(buf, "{v}::bigint");
941 }
942 PostgresValue::Real(v) => write_cast_literal(buf, &float_text(f64::from(*v)), "real")?,
943 PostgresValue::DoublePrecision(v) => {
944 write_cast_literal(buf, &float_text(*v), "double precision")?;
945 }
946 #[cfg(feature = "rust-decimal")]
947 PostgresValue::Numeric(v) => write_cast_literal(buf, &v.to_string(), "numeric")?,
948 PostgresValue::Text(text) => write_quoted_literal(buf, text)?,
949 PostgresValue::Bytea(bytes) => {
950 let mut hex = String::with_capacity(2 + bytes.len() * 2);
951 hex.push_str("\\x");
952 for byte in bytes.iter() {
953 let _ = write!(hex, "{byte:02x}");
954 }
955 write_cast_literal(buf, &hex, "bytea")?;
956 }
957 PostgresValue::Boolean(v) => buf.push_str(if *v { "TRUE" } else { "FALSE" }),
958 #[cfg(feature = "uuid")]
959 PostgresValue::Uuid(v) => write_cast_literal(buf, &v.to_string(), "uuid")?,
960 #[cfg(feature = "serde")]
961 PostgresValue::Json(v) => write_cast_literal(buf, &v.to_string(), "json")?,
962 #[cfg(feature = "serde")]
963 PostgresValue::Jsonb(v) => write_cast_literal(buf, &v.to_string(), "jsonb")?,
964 PostgresValue::Enum(v) => write_quoted_literal(buf, v.variant_name())?,
965 #[cfg(feature = "chrono")]
966 PostgresValue::Date(v) => write_cast_literal(buf, &v.to_string(), "date")?,
967 #[cfg(feature = "chrono")]
968 PostgresValue::Time(v) => write_cast_literal(buf, &v.to_string(), "time")?,
969 #[cfg(feature = "chrono")]
970 PostgresValue::Timestamp(v) => write_cast_literal(buf, &v.to_string(), "timestamp")?,
971 #[cfg(feature = "chrono")]
972 PostgresValue::TimestampTz(v) => {
973 write_cast_literal(buf, &v.to_rfc3339(), "timestamptz")?;
974 }
975 #[cfg(feature = "chrono")]
976 PostgresValue::Interval(v) => {
977 let micros = v.num_microseconds()?;
978 write_cast_literal(buf, &format!("{micros} microseconds"), "interval")?;
979 }
980 #[cfg(feature = "time")]
981 PostgresValue::TimeDate(v) => write_cast_literal(buf, &v.to_string(), "date")?,
982 #[cfg(feature = "time")]
983 PostgresValue::TimeTime(v) => write_cast_literal(buf, &v.to_string(), "time")?,
984 #[cfg(feature = "time")]
985 PostgresValue::TimeTimestamp(v) => {
986 write_cast_literal(buf, &format!("{} {}", v.date(), v.time()), "timestamp")?;
987 }
988 #[cfg(feature = "time")]
989 PostgresValue::TimeTimestampTz(v) => {
990 let utc = v.to_offset(time::UtcOffset::UTC);
991 write_cast_literal(
992 buf,
993 &format!("{} {}+00", utc.date(), utc.time()),
994 "timestamptz",
995 )?;
996 }
997 #[cfg(feature = "time")]
998 PostgresValue::TimeInterval(v) => {
999 let micros = v.whole_microseconds();
1000 write_cast_literal(buf, &format!("{micros} microseconds"), "interval")?;
1001 }
1002 #[cfg(feature = "jiff")]
1003 PostgresValue::JiffDate(v) => write_cast_literal(buf, &v.to_string(), "date")?,
1004 #[cfg(feature = "jiff")]
1005 PostgresValue::JiffTime(v) => write_cast_literal(buf, &v.to_string(), "time")?,
1006 #[cfg(feature = "jiff")]
1007 PostgresValue::JiffDateTime(v) => write_cast_literal(buf, &v.to_string(), "timestamp")?,
1008 #[cfg(feature = "jiff")]
1009 PostgresValue::JiffTimestamp(v) => write_cast_literal(buf, &v.to_string(), "timestamptz")?,
1010 #[cfg(feature = "cidr")]
1011 PostgresValue::Inet(v) => write_cast_literal(buf, &v.to_string(), "inet")?,
1012 #[cfg(feature = "cidr")]
1013 PostgresValue::Cidr(v) => write_cast_literal(buf, &v.to_string(), "cidr")?,
1014 #[cfg(feature = "cidr")]
1015 PostgresValue::MacAddr(bytes) => {
1016 let text = bytes
1017 .iter()
1018 .map(|byte| format!("{byte:02x}"))
1019 .collect::<Vec<_>>()
1020 .join(":");
1021 write_cast_literal(buf, &text, "macaddr")?;
1022 }
1023 #[cfg(feature = "cidr")]
1024 PostgresValue::MacAddr8(bytes) => {
1025 let text = bytes
1026 .iter()
1027 .map(|byte| format!("{byte:02x}"))
1028 .collect::<Vec<_>>()
1029 .join(":");
1030 write_cast_literal(buf, &text, "macaddr8")?;
1031 }
1032 #[cfg(feature = "geo-types")]
1033 PostgresValue::Point(v) => {
1034 let text = format!("({:?},{:?})", v.x(), v.y());
1035 write_cast_literal(buf, &text, "point")?;
1036 }
1037 #[cfg(feature = "geo-types")]
1038 PostgresValue::LineString(v) => {
1039 let points = v
1040 .coords()
1041 .map(|coord| format!("({:?},{:?})", coord.x, coord.y))
1042 .collect::<Vec<_>>()
1043 .join(",");
1044 write_cast_literal(buf, &format!("[{points}]"), "path")?;
1045 }
1046 #[cfg(feature = "geo-types")]
1047 PostgresValue::Rect(v) => {
1048 let (min, max) = (v.min(), v.max());
1049 let text = format!("(({:?},{:?}),({:?},{:?}))", max.x, max.y, min.x, min.y);
1050 write_cast_literal(buf, &text, "box")?;
1051 }
1052 #[cfg(feature = "bit-vec")]
1053 PostgresValue::BitVec(v) => {
1054 buf.push_str("B'");
1055 for bit in v.iter() {
1056 buf.push(if bit { '1' } else { '0' });
1057 }
1058 buf.push('\'');
1059 }
1060 PostgresValue::Array(values) if values.is_empty() => buf.push_str("'{}'"),
1061 PostgresValue::Array(values) => {
1062 buf.push_str("ARRAY[");
1063 for (index, value) in values.iter().enumerate() {
1064 if index > 0 {
1065 buf.push_str(", ");
1066 }
1067 write_postgres_literal(value, buf)?;
1068 }
1069 buf.push(']');
1070 }
1071 }
1072 Some(())
1073}
1074
1075impl<'a> From<PostgresValue<'a>> for SQL<'a, PostgresValue<'a>> {
1076 fn from(value: PostgresValue<'a>) -> Self {
1077 SQL::param(value)
1078 }
1079}
1080
1081impl<'a> From<PostgresValue<'a>> for Cow<'a, PostgresValue<'a>> {
1083 fn from(value: PostgresValue<'a>) -> Self {
1084 Cow::Owned(value)
1085 }
1086}
1087
1088impl<'a> From<&'a PostgresValue<'a>> for Cow<'a, PostgresValue<'a>> {
1089 fn from(value: &'a PostgresValue<'a>) -> Self {
1090 Cow::Borrowed(value)
1091 }
1092}