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