Skip to main content

drizzle_postgres/values/
mod.rs

1//! `PostgreSQL` value conversion traits and types
2
3mod conversions;
4mod drivers;
5mod insert;
6mod owned;
7mod update;
8
9pub use insert::*;
10pub use owned::*;
11pub use update::*;
12
13use drizzle_core::{error::DrizzleError, sql::SQL, traits::SQLParam};
14
15#[cfg(feature = "uuid")]
16use uuid::Uuid;
17
18#[cfg(feature = "chrono")]
19use chrono::{DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
20
21#[cfg(feature = "time")]
22use time::{
23    Date as TimeDate, Duration as TimeDuration, OffsetDateTime, PrimitiveDateTime, Time as TimeTime,
24};
25
26#[cfg(feature = "cidr")]
27use cidr::{IpCidr, IpInet};
28
29#[cfg(feature = "geo-types")]
30use geo_types::{LineString, Point, Rect};
31
32#[cfg(feature = "bit-vec")]
33use bit_vec::BitVec;
34
35#[cfg(feature = "rust-decimal")]
36use rust_decimal::Decimal;
37
38use crate::prelude::*;
39
40use crate::traits::{FromPostgresValue, PostgresEnum};
41
42//------------------------------------------------------------------------------
43// PostgresValue Definition
44//------------------------------------------------------------------------------
45
46/// Represents a `PostgreSQL` value.
47///
48/// This enum provides type-safe value handling for `PostgreSQL` operations.
49///
50/// # Examples
51///
52/// ```
53/// use drizzle_postgres::values::PostgresValue;
54///
55/// // Integer conversion
56/// let int_val: PostgresValue<'_> = 42i32.into();
57/// assert!(matches!(int_val, PostgresValue::Integer(42)));
58///
59/// // String conversion
60/// let str_val: PostgresValue<'_> = "hello".into();
61/// assert!(matches!(str_val, PostgresValue::Text(_)));
62///
63/// // Boolean conversion
64/// let bool_val: PostgresValue<'_> = true.into();
65/// assert!(matches!(bool_val, PostgresValue::Boolean(true)));
66/// ```
67#[derive(Debug, Clone, PartialEq, Default)]
68pub enum PostgresValue<'a> {
69    /// SMALLINT values (16-bit signed integer)
70    Smallint(i16),
71    /// INTEGER values (32-bit signed integer)
72    Integer(i32),
73    /// BIGINT values (64-bit signed integer)
74    Bigint(i64),
75    /// REAL values (32-bit floating point)
76    Real(f32),
77    /// DOUBLE PRECISION values (64-bit floating point)
78    DoublePrecision(f64),
79    /// NUMERIC/DECIMAL values
80    #[cfg(feature = "rust-decimal")]
81    Numeric(Decimal),
82    /// TEXT, VARCHAR, CHAR values
83    Text(Cow<'a, str>),
84    /// BYTEA values (binary data)
85    Bytea(Cow<'a, [u8]>),
86    /// BOOLEAN values
87    Boolean(bool),
88    /// UUID values
89    #[cfg(feature = "uuid")]
90    Uuid(Uuid),
91    /// JSON values (stored as text in `PostgreSQL`)
92    #[cfg(feature = "serde")]
93    Json(serde_json::Value),
94    /// JSONB values (stored as binary in `PostgreSQL`)
95    #[cfg(feature = "serde")]
96    Jsonb(serde_json::Value),
97    /// Native `PostgreSQL` ENUM values
98    Enum(Box<dyn PostgresEnum>),
99
100    // Date and time types
101    /// DATE values
102    #[cfg(feature = "chrono")]
103    Date(NaiveDate),
104    /// TIME values
105    #[cfg(feature = "chrono")]
106    Time(NaiveTime),
107    /// TIMESTAMP values (without timezone)
108    #[cfg(feature = "chrono")]
109    Timestamp(NaiveDateTime),
110    /// TIMESTAMPTZ values (with timezone)
111    #[cfg(feature = "chrono")]
112    TimestampTz(DateTime<FixedOffset>),
113    /// INTERVAL values
114    #[cfg(feature = "chrono")]
115    Interval(Duration),
116
117    // Date and time types (time crate)
118    /// DATE values (time crate)
119    #[cfg(feature = "time")]
120    TimeDate(TimeDate),
121    /// TIME values (time crate)
122    #[cfg(feature = "time")]
123    TimeTime(TimeTime),
124    /// TIMESTAMP values without timezone (time crate)
125    #[cfg(feature = "time")]
126    TimeTimestamp(PrimitiveDateTime),
127    /// TIMESTAMPTZ values with timezone (time crate)
128    #[cfg(feature = "time")]
129    TimeTimestampTz(OffsetDateTime),
130    /// INTERVAL values (time crate)
131    #[cfg(feature = "time")]
132    TimeInterval(TimeDuration),
133
134    // Network address types
135    /// INET values (host address with optional netmask)
136    #[cfg(feature = "cidr")]
137    Inet(IpInet),
138    /// CIDR values (network specification)
139    #[cfg(feature = "cidr")]
140    Cidr(IpCidr),
141    /// MACADDR values (MAC addresses)
142    #[cfg(feature = "cidr")]
143    MacAddr([u8; 6]),
144    /// MACADDR8 values (EUI-64 MAC addresses)
145    #[cfg(feature = "cidr")]
146    MacAddr8([u8; 8]),
147
148    // Geometric types (native PostgreSQL support via postgres-rs)
149    /// POINT values
150    #[cfg(feature = "geo-types")]
151    Point(Point<f64>),
152    /// PATH values (open path from `LineString`)
153    #[cfg(feature = "geo-types")]
154    LineString(LineString<f64>),
155    /// BOX values (bounding rectangle)
156    #[cfg(feature = "geo-types")]
157    Rect(Rect<f64>),
158
159    // Bit string types
160    /// BIT, BIT VARYING values
161    #[cfg(feature = "bit-vec")]
162    BitVec(BitVec),
163
164    // Array types (using Vec for simplicity)
165    /// Array of any `PostgreSQL` type
166    Array(Vec<Self>),
167
168    /// NULL value
169    #[default]
170    Null,
171}
172
173impl core::fmt::Display for PostgresValue<'_> {
174    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175        let value = match self {
176            PostgresValue::Smallint(i) => i.to_string(),
177            PostgresValue::Integer(i) => i.to_string(),
178            PostgresValue::Bigint(i) => i.to_string(),
179            PostgresValue::Real(r) => r.to_string(),
180            PostgresValue::DoublePrecision(r) => r.to_string(),
181            #[cfg(feature = "rust-decimal")]
182            PostgresValue::Numeric(d) => d.to_string(),
183            PostgresValue::Text(cow) => cow.to_string(),
184            PostgresValue::Bytea(cow) => {
185                use core::fmt::Write;
186                let mut s = String::with_capacity(2 + cow.len() * 2);
187                s.push_str("\\x");
188                for byte in cow.iter() {
189                    write!(s, "{byte:02x}").expect("writing to String cannot fail");
190                }
191                s
192            }
193            PostgresValue::Boolean(b) => b.to_string(),
194            #[cfg(feature = "uuid")]
195            PostgresValue::Uuid(uuid) => uuid.to_string(),
196            #[cfg(feature = "serde")]
197            PostgresValue::Json(json) => json.to_string(),
198            #[cfg(feature = "serde")]
199            PostgresValue::Jsonb(json) => json.to_string(),
200            PostgresValue::Enum(enum_val) => enum_val.variant_name().to_string(),
201
202            // Date and time types
203            #[cfg(feature = "chrono")]
204            PostgresValue::Date(date) => date.to_string(),
205            #[cfg(feature = "chrono")]
206            PostgresValue::Time(time) => time.to_string(),
207            #[cfg(feature = "chrono")]
208            PostgresValue::Timestamp(ts) => ts.to_string(),
209            #[cfg(feature = "chrono")]
210            PostgresValue::TimestampTz(ts) => ts.to_string(),
211            #[cfg(feature = "chrono")]
212            PostgresValue::Interval(dur) => format!("{} seconds", dur.num_seconds()),
213
214            // Date and time types (time crate)
215            #[cfg(feature = "time")]
216            PostgresValue::TimeDate(date) => date.to_string(),
217            #[cfg(feature = "time")]
218            PostgresValue::TimeTime(time) => time.to_string(),
219            #[cfg(feature = "time")]
220            PostgresValue::TimeTimestamp(ts) => ts.to_string(),
221            #[cfg(feature = "time")]
222            PostgresValue::TimeTimestampTz(ts) => ts.to_string(),
223            #[cfg(feature = "time")]
224            PostgresValue::TimeInterval(dur) => format!("{} seconds", dur.whole_seconds()),
225
226            // Network address types
227            #[cfg(feature = "cidr")]
228            PostgresValue::Inet(net) => net.to_string(),
229            #[cfg(feature = "cidr")]
230            PostgresValue::Cidr(net) => net.to_string(),
231            #[cfg(feature = "cidr")]
232            PostgresValue::MacAddr(mac) => format!(
233                "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
234                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
235            ),
236            #[cfg(feature = "cidr")]
237            PostgresValue::MacAddr8(mac) => format!(
238                "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
239                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6], mac[7]
240            ),
241
242            // Geometric types
243            #[cfg(feature = "geo-types")]
244            PostgresValue::Point(point) => format!("({},{})", point.x(), point.y()),
245            #[cfg(feature = "geo-types")]
246            PostgresValue::LineString(line) => {
247                let coords: Vec<String> = line
248                    .coords()
249                    .map(|coord| format!("({},{})", coord.x, coord.y))
250                    .collect();
251                format!("[{}]", coords.join(","))
252            }
253            #[cfg(feature = "geo-types")]
254            PostgresValue::Rect(rect) => {
255                format!(
256                    "(({},{}),({},{}))",
257                    rect.min().x,
258                    rect.min().y,
259                    rect.max().x,
260                    rect.max().y
261                )
262            }
263
264            // Bit string types
265            #[cfg(feature = "bit-vec")]
266            PostgresValue::BitVec(bv) => bv
267                .iter()
268                .map(|b| if b { '1' } else { '0' })
269                .collect::<String>(),
270
271            // Array types
272            PostgresValue::Array(arr) => {
273                let elements: Vec<String> = arr.iter().map(ToString::to_string).collect();
274                format!("{{{}}}", elements.join(","))
275            }
276
277            PostgresValue::Null => String::new(),
278        };
279        write!(f, "{value}")
280    }
281}
282
283impl PostgresValue<'_> {
284    /// Returns true if this value is NULL.
285    #[inline]
286    #[must_use]
287    pub const fn is_null(&self) -> bool {
288        matches!(self, PostgresValue::Null)
289    }
290
291    /// Returns the boolean value if this is BOOLEAN.
292    #[inline]
293    #[must_use]
294    pub const fn as_bool(&self) -> Option<bool> {
295        match self {
296            PostgresValue::Boolean(value) => Some(*value),
297            _ => None,
298        }
299    }
300
301    /// Returns the i16 value if this is SMALLINT.
302    #[inline]
303    #[must_use]
304    pub const fn as_i16(&self) -> Option<i16> {
305        match self {
306            PostgresValue::Smallint(value) => Some(*value),
307            _ => None,
308        }
309    }
310
311    /// Returns the i32 value if this is INTEGER.
312    #[inline]
313    #[must_use]
314    pub const fn as_i32(&self) -> Option<i32> {
315        match self {
316            PostgresValue::Integer(value) => Some(*value),
317            _ => None,
318        }
319    }
320
321    /// Returns the i64 value if this is BIGINT.
322    #[inline]
323    #[must_use]
324    pub const fn as_i64(&self) -> Option<i64> {
325        match self {
326            PostgresValue::Bigint(value) => Some(*value),
327            _ => None,
328        }
329    }
330
331    /// Returns the f32 value if this is REAL.
332    #[inline]
333    #[must_use]
334    pub const fn as_f32(&self) -> Option<f32> {
335        match self {
336            PostgresValue::Real(value) => Some(*value),
337            _ => None,
338        }
339    }
340
341    /// Returns the f64 value if this is DOUBLE PRECISION.
342    #[inline]
343    #[must_use]
344    pub const fn as_f64(&self) -> Option<f64> {
345        match self {
346            PostgresValue::DoublePrecision(value) => Some(*value),
347            _ => None,
348        }
349    }
350
351    /// Returns the decimal value if this is NUMERIC.
352    #[inline]
353    #[cfg(feature = "rust-decimal")]
354    #[must_use]
355    pub const fn as_decimal(&self) -> Option<&Decimal> {
356        match self {
357            PostgresValue::Numeric(value) => Some(value),
358            _ => None,
359        }
360    }
361
362    /// Returns the text value if this is TEXT.
363    #[inline]
364    #[must_use]
365    pub fn as_str(&self) -> Option<&str> {
366        match self {
367            PostgresValue::Text(value) => Some(value.as_ref()),
368            _ => None,
369        }
370    }
371
372    /// Returns the bytea value if this is BYTEA.
373    #[inline]
374    #[must_use]
375    pub fn as_bytes(&self) -> Option<&[u8]> {
376        match self {
377            PostgresValue::Bytea(value) => Some(value.as_ref()),
378            _ => None,
379        }
380    }
381
382    /// Returns the UUID value if this is UUID.
383    #[inline]
384    #[cfg(feature = "uuid")]
385    #[must_use]
386    pub const fn as_uuid(&self) -> Option<Uuid> {
387        match self {
388            PostgresValue::Uuid(value) => Some(*value),
389            _ => None,
390        }
391    }
392
393    /// Returns the JSON value if this is JSON.
394    #[inline]
395    #[cfg(feature = "serde")]
396    #[must_use]
397    pub const fn as_json(&self) -> Option<&serde_json::Value> {
398        match self {
399            PostgresValue::Json(value) => Some(value),
400            _ => None,
401        }
402    }
403
404    /// Returns the JSONB value if this is JSONB.
405    #[inline]
406    #[cfg(feature = "serde")]
407    #[must_use]
408    pub const fn as_jsonb(&self) -> Option<&serde_json::Value> {
409        match self {
410            PostgresValue::Jsonb(value) => Some(value),
411            _ => None,
412        }
413    }
414
415    /// Returns the enum value if this is a `PostgreSQL` enum.
416    #[inline]
417    #[must_use]
418    pub fn as_enum(&self) -> Option<&dyn PostgresEnum> {
419        match self {
420            PostgresValue::Enum(value) => Some(value.as_ref()),
421            _ => None,
422        }
423    }
424
425    /// Returns the date value if this is DATE.
426    #[inline]
427    #[cfg(feature = "chrono")]
428    #[must_use]
429    pub const fn as_date(&self) -> Option<&NaiveDate> {
430        match self {
431            PostgresValue::Date(value) => Some(value),
432            _ => None,
433        }
434    }
435
436    /// Returns the time value if this is TIME.
437    #[inline]
438    #[cfg(feature = "chrono")]
439    #[must_use]
440    pub const fn as_time(&self) -> Option<&NaiveTime> {
441        match self {
442            PostgresValue::Time(value) => Some(value),
443            _ => None,
444        }
445    }
446
447    /// Returns the timestamp value if this is TIMESTAMP.
448    #[inline]
449    #[cfg(feature = "chrono")]
450    #[must_use]
451    pub const fn as_timestamp(&self) -> Option<&NaiveDateTime> {
452        match self {
453            PostgresValue::Timestamp(value) => Some(value),
454            _ => None,
455        }
456    }
457
458    /// Returns the timestamp with timezone value if this is TIMESTAMPTZ.
459    #[inline]
460    #[cfg(feature = "chrono")]
461    #[must_use]
462    pub const fn as_timestamp_tz(&self) -> Option<&DateTime<FixedOffset>> {
463        match self {
464            PostgresValue::TimestampTz(value) => Some(value),
465            _ => None,
466        }
467    }
468
469    /// Returns the interval value if this is INTERVAL.
470    #[inline]
471    #[cfg(feature = "chrono")]
472    #[must_use]
473    pub const fn as_interval(&self) -> Option<&Duration> {
474        match self {
475            PostgresValue::Interval(value) => Some(value),
476            _ => None,
477        }
478    }
479
480    /// Returns the inet value if this is INET.
481    #[inline]
482    #[cfg(feature = "cidr")]
483    #[must_use]
484    pub const fn as_inet(&self) -> Option<&IpInet> {
485        match self {
486            PostgresValue::Inet(value) => Some(value),
487            _ => None,
488        }
489    }
490
491    /// Returns the cidr value if this is CIDR.
492    #[inline]
493    #[cfg(feature = "cidr")]
494    #[must_use]
495    pub const fn as_cidr(&self) -> Option<&IpCidr> {
496        match self {
497            PostgresValue::Cidr(value) => Some(value),
498            _ => None,
499        }
500    }
501
502    /// Returns the MAC address if this is MACADDR.
503    #[inline]
504    #[cfg(feature = "cidr")]
505    #[must_use]
506    pub const fn as_macaddr(&self) -> Option<[u8; 6]> {
507        match self {
508            PostgresValue::MacAddr(value) => Some(*value),
509            _ => None,
510        }
511    }
512
513    /// Returns the MAC address if this is MACADDR8.
514    #[inline]
515    #[cfg(feature = "cidr")]
516    #[must_use]
517    pub const fn as_macaddr8(&self) -> Option<[u8; 8]> {
518        match self {
519            PostgresValue::MacAddr8(value) => Some(*value),
520            _ => None,
521        }
522    }
523
524    /// Returns the point value if this is POINT.
525    #[inline]
526    #[cfg(feature = "geo-types")]
527    #[must_use]
528    pub const fn as_point(&self) -> Option<&Point<f64>> {
529        match self {
530            PostgresValue::Point(value) => Some(value),
531            _ => None,
532        }
533    }
534
535    /// Returns the line string value if this is PATH.
536    #[inline]
537    #[cfg(feature = "geo-types")]
538    #[must_use]
539    pub const fn as_line_string(&self) -> Option<&LineString<f64>> {
540        match self {
541            PostgresValue::LineString(value) => Some(value),
542            _ => None,
543        }
544    }
545
546    /// Returns the rect value if this is BOX.
547    #[inline]
548    #[cfg(feature = "geo-types")]
549    #[must_use]
550    pub const fn as_rect(&self) -> Option<&Rect<f64>> {
551        match self {
552            PostgresValue::Rect(value) => Some(value),
553            _ => None,
554        }
555    }
556
557    /// Returns the bit vector if this is BIT/VARBIT.
558    #[inline]
559    #[cfg(feature = "bit-vec")]
560    #[must_use]
561    pub const fn as_bitvec(&self) -> Option<&BitVec> {
562        match self {
563            PostgresValue::BitVec(value) => Some(value),
564            _ => None,
565        }
566    }
567
568    /// Returns the date value if this is DATE (time crate).
569    #[inline]
570    #[cfg(feature = "time")]
571    #[must_use]
572    pub const fn as_time_date(&self) -> Option<&TimeDate> {
573        match self {
574            PostgresValue::TimeDate(value) => Some(value),
575            _ => None,
576        }
577    }
578
579    /// Returns the time value if this is TIME (time crate).
580    #[inline]
581    #[cfg(feature = "time")]
582    #[must_use]
583    pub const fn as_time_time(&self) -> Option<&TimeTime> {
584        match self {
585            PostgresValue::TimeTime(value) => Some(value),
586            _ => None,
587        }
588    }
589
590    /// Returns the timestamp value if this is TIMESTAMP (time crate).
591    #[inline]
592    #[cfg(feature = "time")]
593    #[must_use]
594    pub const fn as_time_timestamp(&self) -> Option<&PrimitiveDateTime> {
595        match self {
596            PostgresValue::TimeTimestamp(value) => Some(value),
597            _ => None,
598        }
599    }
600
601    /// Returns the timestamp with timezone value if this is TIMESTAMPTZ (time crate).
602    #[inline]
603    #[cfg(feature = "time")]
604    #[must_use]
605    pub const fn as_time_timestamp_tz(&self) -> Option<&OffsetDateTime> {
606        match self {
607            PostgresValue::TimeTimestampTz(value) => Some(value),
608            _ => None,
609        }
610    }
611
612    /// Returns the interval value if this is INTERVAL (time crate).
613    #[inline]
614    #[cfg(feature = "time")]
615    #[must_use]
616    pub const fn as_time_interval(&self) -> Option<&TimeDuration> {
617        match self {
618            PostgresValue::TimeInterval(value) => Some(value),
619            _ => None,
620        }
621    }
622
623    /// Returns the array elements if this is an ARRAY.
624    #[inline]
625    #[must_use]
626    pub fn as_array(&self) -> Option<&[Self]> {
627        match self {
628            PostgresValue::Array(values) => Some(values),
629            _ => None,
630        }
631    }
632
633    /// Converts this value into an owned representation.
634    #[inline]
635    #[must_use]
636    pub fn into_owned(self) -> OwnedPostgresValue {
637        self.into()
638    }
639
640    /// Convert this `PostgreSQL` value to a Rust type using the `FromPostgresValue` trait.
641    ///
642    /// # Errors
643    ///
644    /// Returns [`DrizzleError::ConversionError`] when the stored variant's
645    /// native type does not match the target type `T`.
646    pub fn convert<T: FromPostgresValue>(self) -> Result<T, DrizzleError> {
647        match self {
648            PostgresValue::Boolean(value) => T::from_postgres_bool(value),
649            PostgresValue::Smallint(value) => T::from_postgres_i16(value),
650            PostgresValue::Integer(value) => T::from_postgres_i32(value),
651            PostgresValue::Bigint(value) => T::from_postgres_i64(value),
652            PostgresValue::Real(value) => T::from_postgres_f32(value),
653            PostgresValue::DoublePrecision(value) => T::from_postgres_f64(value),
654            #[cfg(feature = "rust-decimal")]
655            PostgresValue::Numeric(value) => {
656                let text = value.to_string();
657                T::from_postgres_text(&text)
658            }
659            PostgresValue::Text(value) => T::from_postgres_text(&value),
660            PostgresValue::Bytea(value) => T::from_postgres_bytes(&value),
661            #[cfg(feature = "uuid")]
662            PostgresValue::Uuid(value) => T::from_postgres_uuid(value),
663            #[cfg(feature = "serde")]
664            PostgresValue::Json(value) => T::from_postgres_json(value),
665            #[cfg(feature = "serde")]
666            PostgresValue::Jsonb(value) => T::from_postgres_jsonb(value),
667            PostgresValue::Enum(value) => T::from_postgres_text(value.variant_name()),
668            #[cfg(feature = "chrono")]
669            PostgresValue::Date(value) => T::from_postgres_date(value),
670            #[cfg(feature = "chrono")]
671            PostgresValue::Time(value) => T::from_postgres_time(value),
672            #[cfg(feature = "chrono")]
673            PostgresValue::Timestamp(value) => T::from_postgres_timestamp(value),
674            #[cfg(feature = "chrono")]
675            PostgresValue::TimestampTz(value) => T::from_postgres_timestamptz(value),
676            #[cfg(feature = "chrono")]
677            PostgresValue::Interval(value) => T::from_postgres_interval(value),
678            #[cfg(feature = "time")]
679            PostgresValue::TimeDate(value) => T::from_postgres_time_date(value),
680            #[cfg(feature = "time")]
681            PostgresValue::TimeTime(value) => T::from_postgres_time_time(value),
682            #[cfg(feature = "time")]
683            PostgresValue::TimeTimestamp(value) => T::from_postgres_time_timestamp(value),
684            #[cfg(feature = "time")]
685            PostgresValue::TimeTimestampTz(value) => T::from_postgres_time_timestamptz(value),
686            #[cfg(feature = "time")]
687            PostgresValue::TimeInterval(value) => T::from_postgres_time_interval(value),
688            #[cfg(feature = "cidr")]
689            PostgresValue::Inet(value) => T::from_postgres_inet(value),
690            #[cfg(feature = "cidr")]
691            PostgresValue::Cidr(value) => T::from_postgres_cidr(value),
692            #[cfg(feature = "cidr")]
693            PostgresValue::MacAddr(value) => T::from_postgres_macaddr(value),
694            #[cfg(feature = "cidr")]
695            PostgresValue::MacAddr8(value) => T::from_postgres_macaddr8(value),
696            #[cfg(feature = "geo-types")]
697            PostgresValue::Point(value) => T::from_postgres_point(value),
698            #[cfg(feature = "geo-types")]
699            PostgresValue::LineString(value) => T::from_postgres_linestring(value),
700            #[cfg(feature = "geo-types")]
701            PostgresValue::Rect(value) => T::from_postgres_rect(value),
702            #[cfg(feature = "bit-vec")]
703            PostgresValue::BitVec(value) => T::from_postgres_bitvec(value),
704            PostgresValue::Array(value) => T::from_postgres_array(value),
705            PostgresValue::Null => T::from_postgres_null(),
706        }
707    }
708
709    /// Convert a reference to this `PostgreSQL` value to a Rust type.
710    ///
711    /// # Errors
712    ///
713    /// Returns [`DrizzleError::ConversionError`] when the stored variant's
714    /// native type does not match the target type `T`.
715    pub fn convert_ref<T: FromPostgresValue>(&self) -> Result<T, DrizzleError> {
716        match self {
717            PostgresValue::Boolean(value) => T::from_postgres_bool(*value),
718            PostgresValue::Smallint(value) => T::from_postgres_i16(*value),
719            PostgresValue::Integer(value) => T::from_postgres_i32(*value),
720            PostgresValue::Bigint(value) => T::from_postgres_i64(*value),
721            PostgresValue::Real(value) => T::from_postgres_f32(*value),
722            PostgresValue::DoublePrecision(value) => T::from_postgres_f64(*value),
723            #[cfg(feature = "rust-decimal")]
724            PostgresValue::Numeric(value) => {
725                let text = value.to_string();
726                T::from_postgres_text(&text)
727            }
728            PostgresValue::Text(value) => T::from_postgres_text(value),
729            PostgresValue::Bytea(value) => T::from_postgres_bytes(value),
730            #[cfg(feature = "uuid")]
731            PostgresValue::Uuid(value) => T::from_postgres_uuid(*value),
732            #[cfg(feature = "serde")]
733            PostgresValue::Json(value) => T::from_postgres_json(value.clone()),
734            #[cfg(feature = "serde")]
735            PostgresValue::Jsonb(value) => T::from_postgres_jsonb(value.clone()),
736            PostgresValue::Enum(value) => T::from_postgres_text(value.variant_name()),
737            #[cfg(feature = "chrono")]
738            PostgresValue::Date(value) => T::from_postgres_date(*value),
739            #[cfg(feature = "chrono")]
740            PostgresValue::Time(value) => T::from_postgres_time(*value),
741            #[cfg(feature = "chrono")]
742            PostgresValue::Timestamp(value) => T::from_postgres_timestamp(*value),
743            #[cfg(feature = "chrono")]
744            PostgresValue::TimestampTz(value) => T::from_postgres_timestamptz(*value),
745            #[cfg(feature = "chrono")]
746            PostgresValue::Interval(value) => T::from_postgres_interval(*value),
747            #[cfg(feature = "time")]
748            PostgresValue::TimeDate(value) => T::from_postgres_time_date(*value),
749            #[cfg(feature = "time")]
750            PostgresValue::TimeTime(value) => T::from_postgres_time_time(*value),
751            #[cfg(feature = "time")]
752            PostgresValue::TimeTimestamp(value) => T::from_postgres_time_timestamp(*value),
753            #[cfg(feature = "time")]
754            PostgresValue::TimeTimestampTz(value) => T::from_postgres_time_timestamptz(*value),
755            #[cfg(feature = "time")]
756            PostgresValue::TimeInterval(value) => T::from_postgres_time_interval(*value),
757            #[cfg(feature = "cidr")]
758            PostgresValue::Inet(value) => T::from_postgres_inet(*value),
759            #[cfg(feature = "cidr")]
760            PostgresValue::Cidr(value) => T::from_postgres_cidr(*value),
761            #[cfg(feature = "cidr")]
762            PostgresValue::MacAddr(value) => T::from_postgres_macaddr(*value),
763            #[cfg(feature = "cidr")]
764            PostgresValue::MacAddr8(value) => T::from_postgres_macaddr8(*value),
765            #[cfg(feature = "geo-types")]
766            PostgresValue::Point(value) => T::from_postgres_point(*value),
767            #[cfg(feature = "geo-types")]
768            PostgresValue::LineString(value) => T::from_postgres_linestring(value.clone()),
769            #[cfg(feature = "geo-types")]
770            PostgresValue::Rect(value) => T::from_postgres_rect(*value),
771            #[cfg(feature = "bit-vec")]
772            PostgresValue::BitVec(value) => T::from_postgres_bitvec(value.clone()),
773            PostgresValue::Array(value) => T::from_postgres_array(value.clone()),
774            PostgresValue::Null => T::from_postgres_null(),
775        }
776    }
777}
778
779// Implement core traits required by Drizzle
780impl SQLParam for PostgresValue<'_> {
781    const DIALECT: drizzle_core::dialect::Dialect = drizzle_core::dialect::Dialect::PostgreSQL;
782    type DialectMarker = drizzle_core::dialect::PostgresDialect;
783}
784
785impl<'a> From<PostgresValue<'a>> for SQL<'a, PostgresValue<'a>> {
786    fn from(value: PostgresValue<'a>) -> Self {
787        SQL::param(value)
788    }
789}
790
791// Cow integration for SQL struct
792impl<'a> From<PostgresValue<'a>> for Cow<'a, PostgresValue<'a>> {
793    fn from(value: PostgresValue<'a>) -> Self {
794        Cow::Owned(value)
795    }
796}
797
798impl<'a> From<&'a PostgresValue<'a>> for Cow<'a, PostgresValue<'a>> {
799    fn from(value: &'a PostgresValue<'a>) -> Self {
800        Cow::Borrowed(value)
801    }
802}