Skip to main content

drizzle_postgres/traits/
value.rs

1//! Conversion of `PostgreSQL` values into Rust types ([`FromPostgresValue`]),
2//! and driver-neutral row access ([`DrizzleRowByIndex`], [`DrizzleRowByName`]).
3
4use crate::prelude::*;
5use crate::values::{OwnedPostgresValue, PostgresValue};
6use drizzle_core::conv::checked_float_to_int;
7use drizzle_core::error::DrizzleError;
8
9/// A Rust type that can be built from a [`PostgresValue`].
10///
11/// There is one method per kind of stored value. The required ones cover
12/// booleans, integers, floats, text and bytes; the others (NULL, UUID, JSON,
13/// arrays, dates and times, network, geometric and bit types) default to an
14/// error, and some exist only with the matching feature. Implement the ones
15/// that make sense for your type and return an error from the rest.
16///
17/// This crate implements it for `bool`, all primitive integer types, `f32`,
18/// `f64`, strings, byte vectors, `Option<T>` (NULL becomes `None`), the
19/// optional crates' types, and every [`PostgresEnum`](super::PostgresEnum), so
20/// native enums from `#[derive(PostgresEnum)]` get it automatically.
21/// [`PostgresValue::convert`] dispatches to the right method.
22pub trait FromPostgresValue: Sized {
23    /// Converts from a boolean value.
24    ///
25    /// # Errors
26    ///
27    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
28    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError>;
29
30    /// Converts from a 16-bit integer value.
31    ///
32    /// # Errors
33    ///
34    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
35    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError>;
36
37    /// Converts from a 32-bit integer value.
38    ///
39    /// # Errors
40    ///
41    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
42    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError>;
43
44    /// Converts from a 64-bit integer value.
45    ///
46    /// # Errors
47    ///
48    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
49    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError>;
50
51    /// Converts from a 32-bit float value.
52    ///
53    /// # Errors
54    ///
55    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
56    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError>;
57
58    /// Converts from a 64-bit float value.
59    ///
60    /// # Errors
61    ///
62    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
63    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError>;
64
65    /// Converts from a text/string value.
66    ///
67    /// # Errors
68    ///
69    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
70    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError>;
71
72    /// Converts from a binary/bytea value.
73    ///
74    /// # Errors
75    ///
76    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
77    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError>;
78
79    /// Converts from NULL. The default returns an error.
80    ///
81    /// # Errors
82    ///
83    /// Returns [`DrizzleError::ConversionError`] unless the implementor treats NULL as a valid value.
84    fn from_postgres_null() -> Result<Self, DrizzleError> {
85        Err(DrizzleError::ConversionError(
86            "unexpected NULL value".into(),
87        ))
88    }
89
90    /// Converts from a UUID value.
91    ///
92    /// # Errors
93    ///
94    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a UUID.
95    #[cfg(feature = "uuid")]
96    fn from_postgres_uuid(value: uuid::Uuid) -> Result<Self, DrizzleError> {
97        Err(DrizzleError::ConversionError(
98            format!("cannot convert UUID {value} to target type").into(),
99        ))
100    }
101
102    /// Converts from a JSON value.
103    ///
104    /// # Errors
105    ///
106    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a JSON value.
107    #[cfg(feature = "serde")]
108    fn from_postgres_json(value: serde_json::Value) -> Result<Self, DrizzleError> {
109        Err(DrizzleError::ConversionError(
110            format!("cannot convert JSON {value} to target type").into(),
111        ))
112    }
113
114    /// Converts from a JSONB value.
115    ///
116    /// # Errors
117    ///
118    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a JSONB value.
119    #[cfg(feature = "serde")]
120    fn from_postgres_jsonb(value: serde_json::Value) -> Result<Self, DrizzleError> {
121        Err(DrizzleError::ConversionError(
122            format!("cannot convert JSONB {value} to target type").into(),
123        ))
124    }
125
126    /// Converts from an ARRAY value.
127    ///
128    /// # Errors
129    ///
130    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an ARRAY value.
131    fn from_postgres_array(_value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
132        Err(DrizzleError::ConversionError(
133            "cannot convert ARRAY to target type".into(),
134        ))
135    }
136
137    /// Converts from a DATE value.
138    ///
139    /// # Errors
140    ///
141    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a DATE.
142    #[cfg(feature = "chrono")]
143    fn from_postgres_date(value: chrono::NaiveDate) -> Result<Self, DrizzleError> {
144        Err(DrizzleError::ConversionError(
145            format!("cannot convert DATE {value} to target type").into(),
146        ))
147    }
148
149    /// Converts from a TIME value.
150    ///
151    /// # Errors
152    ///
153    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIME.
154    #[cfg(feature = "chrono")]
155    fn from_postgres_time(value: chrono::NaiveTime) -> Result<Self, DrizzleError> {
156        Err(DrizzleError::ConversionError(
157            format!("cannot convert TIME {value} to target type").into(),
158        ))
159    }
160
161    /// Converts from a TIMESTAMP value.
162    ///
163    /// # Errors
164    ///
165    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMP.
166    #[cfg(feature = "chrono")]
167    fn from_postgres_timestamp(value: chrono::NaiveDateTime) -> Result<Self, DrizzleError> {
168        Err(DrizzleError::ConversionError(
169            format!("cannot convert TIMESTAMP {value} to target type").into(),
170        ))
171    }
172
173    /// Converts from a TIMESTAMPTZ value.
174    ///
175    /// # Errors
176    ///
177    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMPTZ.
178    #[cfg(feature = "chrono")]
179    fn from_postgres_timestamptz(
180        value: chrono::DateTime<chrono::FixedOffset>,
181    ) -> Result<Self, DrizzleError> {
182        Err(DrizzleError::ConversionError(
183            format!("cannot convert TIMESTAMPTZ {value} to target type").into(),
184        ))
185    }
186
187    /// Converts from an INTERVAL value.
188    ///
189    /// # Errors
190    ///
191    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an INTERVAL.
192    #[cfg(feature = "chrono")]
193    fn from_postgres_interval(value: chrono::Duration) -> Result<Self, DrizzleError> {
194        Err(DrizzleError::ConversionError(
195            format!("cannot convert INTERVAL {value} to target type").into(),
196        ))
197    }
198
199    /// Converts from a DATE value (time crate).
200    ///
201    /// # Errors
202    ///
203    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a DATE.
204    #[cfg(feature = "time")]
205    fn from_postgres_time_date(value: time::Date) -> Result<Self, DrizzleError> {
206        Err(DrizzleError::ConversionError(
207            format!("cannot convert DATE (time) {value:?} to target type").into(),
208        ))
209    }
210
211    /// Converts from a TIME value (time crate).
212    ///
213    /// # Errors
214    ///
215    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIME.
216    #[cfg(feature = "time")]
217    fn from_postgres_time_time(value: time::Time) -> Result<Self, DrizzleError> {
218        Err(DrizzleError::ConversionError(
219            format!("cannot convert TIME (time) {value:?} to target type").into(),
220        ))
221    }
222
223    /// Converts from a TIMESTAMP value (time crate).
224    ///
225    /// # Errors
226    ///
227    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMP.
228    #[cfg(feature = "time")]
229    fn from_postgres_time_timestamp(value: time::PrimitiveDateTime) -> Result<Self, DrizzleError> {
230        Err(DrizzleError::ConversionError(
231            format!("cannot convert TIMESTAMP (time) {value:?} to target type").into(),
232        ))
233    }
234
235    /// Converts from a TIMESTAMPTZ value (time crate).
236    ///
237    /// # Errors
238    ///
239    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMPTZ.
240    #[cfg(feature = "time")]
241    fn from_postgres_time_timestamptz(value: time::OffsetDateTime) -> Result<Self, DrizzleError> {
242        Err(DrizzleError::ConversionError(
243            format!("cannot convert TIMESTAMPTZ (time) {value:?} to target type").into(),
244        ))
245    }
246
247    /// Converts from an INTERVAL value (time crate).
248    ///
249    /// # Errors
250    ///
251    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an INTERVAL.
252    #[cfg(feature = "time")]
253    fn from_postgres_time_interval(value: time::Duration) -> Result<Self, DrizzleError> {
254        Err(DrizzleError::ConversionError(
255            format!("cannot convert INTERVAL (time) {value:?} to target type").into(),
256        ))
257    }
258
259    /// Converts from a DATE value (jiff).
260    ///
261    /// # Errors
262    ///
263    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a DATE.
264    #[cfg(feature = "jiff")]
265    fn from_postgres_jiff_date(value: jiff::civil::Date) -> Result<Self, DrizzleError> {
266        Err(DrizzleError::ConversionError(
267            format!("cannot convert DATE (jiff) {value:?} to target type").into(),
268        ))
269    }
270
271    /// Converts from a TIME value (jiff).
272    ///
273    /// # Errors
274    ///
275    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIME.
276    #[cfg(feature = "jiff")]
277    fn from_postgres_jiff_time(value: jiff::civil::Time) -> Result<Self, DrizzleError> {
278        Err(DrizzleError::ConversionError(
279            format!("cannot convert TIME (jiff) {value:?} to target type").into(),
280        ))
281    }
282
283    /// Converts from a TIMESTAMP value (jiff).
284    ///
285    /// # Errors
286    ///
287    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMP.
288    #[cfg(feature = "jiff")]
289    fn from_postgres_jiff_datetime(value: jiff::civil::DateTime) -> Result<Self, DrizzleError> {
290        Err(DrizzleError::ConversionError(
291            format!("cannot convert TIMESTAMP (jiff) {value:?} to target type").into(),
292        ))
293    }
294
295    /// Converts from a TIMESTAMPTZ value (jiff).
296    ///
297    /// # Errors
298    ///
299    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMPTZ.
300    #[cfg(feature = "jiff")]
301    fn from_postgres_jiff_timestamp(value: jiff::Timestamp) -> Result<Self, DrizzleError> {
302        Err(DrizzleError::ConversionError(
303            format!("cannot convert TIMESTAMPTZ (jiff) {value:?} to target type").into(),
304        ))
305    }
306
307    /// Converts from an INET value.
308    ///
309    /// # Errors
310    ///
311    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an INET address.
312    #[cfg(feature = "cidr")]
313    fn from_postgres_inet(value: cidr::IpInet) -> Result<Self, DrizzleError> {
314        Err(DrizzleError::ConversionError(
315            format!("cannot convert INET {value} to target type").into(),
316        ))
317    }
318
319    /// Converts from a CIDR value.
320    ///
321    /// # Errors
322    ///
323    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a CIDR network.
324    #[cfg(feature = "cidr")]
325    fn from_postgres_cidr(value: cidr::IpCidr) -> Result<Self, DrizzleError> {
326        Err(DrizzleError::ConversionError(
327            format!("cannot convert CIDR {value} to target type").into(),
328        ))
329    }
330
331    /// Converts from a MACADDR value.
332    ///
333    /// # Errors
334    ///
335    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a MAC address.
336    #[cfg(feature = "cidr")]
337    fn from_postgres_macaddr(value: [u8; 6]) -> Result<Self, DrizzleError> {
338        Err(DrizzleError::ConversionError(
339            format!("cannot convert MACADDR {value:?} to target type").into(),
340        ))
341    }
342
343    /// Converts from a MACADDR8 value.
344    ///
345    /// # Errors
346    ///
347    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an 8-byte MAC address.
348    #[cfg(feature = "cidr")]
349    fn from_postgres_macaddr8(value: [u8; 8]) -> Result<Self, DrizzleError> {
350        Err(DrizzleError::ConversionError(
351            format!("cannot convert MACADDR8 {value:?} to target type").into(),
352        ))
353    }
354
355    /// Converts from a POINT value.
356    ///
357    /// # Errors
358    ///
359    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a POINT.
360    #[cfg(feature = "geo-types")]
361    fn from_postgres_point(value: geo_types::Point<f64>) -> Result<Self, DrizzleError> {
362        Err(DrizzleError::ConversionError(
363            format!("cannot convert POINT {value:?} to target type").into(),
364        ))
365    }
366
367    /// Converts from a PATH value.
368    ///
369    /// # Errors
370    ///
371    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a PATH.
372    #[cfg(feature = "geo-types")]
373    fn from_postgres_linestring(value: geo_types::LineString<f64>) -> Result<Self, DrizzleError> {
374        Err(DrizzleError::ConversionError(
375            format!("cannot convert PATH {value:?} to target type").into(),
376        ))
377    }
378
379    /// Converts from a BOX value.
380    ///
381    /// # Errors
382    ///
383    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a BOX.
384    #[cfg(feature = "geo-types")]
385    fn from_postgres_rect(value: geo_types::Rect<f64>) -> Result<Self, DrizzleError> {
386        Err(DrizzleError::ConversionError(
387            format!("cannot convert BOX {value:?} to target type").into(),
388        ))
389    }
390
391    /// Converts from a BIT/VARBIT value.
392    ///
393    /// # Errors
394    ///
395    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a bit vector.
396    #[cfg(feature = "bit-vec")]
397    fn from_postgres_bitvec(value: bit_vec::BitVec) -> Result<Self, DrizzleError> {
398        Err(DrizzleError::ConversionError(
399            format!("cannot convert BITVEC {value:?} to target type").into(),
400        ))
401    }
402}
403
404/// A driver row whose columns can be read by position.
405pub trait DrizzleRowByIndex {
406    /// Reads column `idx` (zero-based) as `T`.
407    ///
408    /// # Errors
409    ///
410    /// Returns [`DrizzleError`] if the column is out of bounds, the value is NULL for a non-nullable target,
411    /// or the stored value cannot be converted into `T`.
412    fn get_column<T: FromPostgresValue>(&self, idx: usize) -> Result<T, DrizzleError>;
413}
414
415/// A driver row whose columns can be read by name.
416pub trait DrizzleRowByName: DrizzleRowByIndex {
417    /// Reads the column named `name` as `T`.
418    ///
419    /// # Errors
420    ///
421    /// Returns [`DrizzleError`] if the column name is unknown, the value is NULL for a non-nullable target,
422    /// or the stored value cannot be converted into `T`.
423    fn get_column_by_name<T: FromPostgresValue>(&self, name: &str) -> Result<T, DrizzleError>;
424}
425
426// =============================================================================
427// Primitive implementations
428// =============================================================================
429
430impl FromPostgresValue for bool {
431    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
432        Ok(value)
433    }
434
435    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
436        Ok(value != 0)
437    }
438
439    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
440        Ok(value != 0)
441    }
442
443    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
444        Ok(value != 0)
445    }
446
447    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
448        Err(DrizzleError::ConversionError(
449            "cannot convert f32 to bool".into(),
450        ))
451    }
452
453    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
454        Err(DrizzleError::ConversionError(
455            "cannot convert f64 to bool".into(),
456        ))
457    }
458
459    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
460        match value.to_lowercase().as_str() {
461            "true" | "t" | "1" | "yes" | "on" => Ok(true),
462            "false" | "f" | "0" | "no" | "off" => Ok(false),
463            _ => Err(DrizzleError::ConversionError(
464                format!("cannot parse '{value}' as bool").into(),
465            )),
466        }
467    }
468
469    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
470        Err(DrizzleError::ConversionError(
471            "cannot convert bytes to bool".into(),
472        ))
473    }
474}
475
476// Implements `FromPostgresValue` for integer types.
477macro_rules! impl_from_postgres_value_int {
478    ($($ty:ty),+ $(,)?) => {
479        $(
480            impl FromPostgresValue for $ty {
481                fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
482                    Ok(if value { 1 } else { 0 })
483                }
484
485                fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
486                    value.try_into().map_err(|e| {
487                        DrizzleError::ConversionError(
488                            format!("i16 {} out of range for {}: {}", value, stringify!($ty), e).into(),
489                        )
490                    })
491                }
492
493                fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
494                    value.try_into().map_err(|e| {
495                        DrizzleError::ConversionError(
496                            format!("i32 {} out of range for {}: {}", value, stringify!($ty), e).into(),
497                        )
498                    })
499                }
500
501                fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
502                    value.try_into().map_err(|e| {
503                        DrizzleError::ConversionError(
504                            format!("i64 {} out of range for {}: {}", value, stringify!($ty), e).into(),
505                        )
506                    })
507                }
508
509                fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
510                    checked_float_to_int(f64::from(value), stringify!($ty))
511                }
512
513                fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
514                    checked_float_to_int(value, stringify!($ty))
515                }
516
517                fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
518                    value.parse().map_err(|e| {
519                        DrizzleError::ConversionError(
520                            format!("cannot parse '{}' as {}: {}", value, stringify!($ty), e).into()
521                        )
522                    })
523                }
524
525                fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
526                    Err(DrizzleError::ConversionError(
527                        concat!("cannot convert bytes to ", stringify!($ty)).into()
528                    ))
529                }
530            }
531        )+
532    };
533}
534
535// Special case for i16 - no conversion needed
536impl FromPostgresValue for i16 {
537    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
538        Ok(Self::from(value))
539    }
540
541    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
542        Ok(value)
543    }
544
545    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
546        value.try_into().map_err(|e| {
547            DrizzleError::ConversionError(format!("i32 {value} out of range for i16: {e}").into())
548        })
549    }
550
551    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
552        value.try_into().map_err(|e| {
553            DrizzleError::ConversionError(format!("i64 {value} out of range for i16: {e}").into())
554        })
555    }
556
557    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
558        checked_float_to_int(f64::from(value), "i16")
559    }
560
561    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
562        checked_float_to_int(value, "i16")
563    }
564
565    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
566        value.parse().map_err(|e| {
567            DrizzleError::ConversionError(format!("cannot parse '{value}' as i16: {e}").into())
568        })
569    }
570
571    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
572        Err(DrizzleError::ConversionError(
573            "cannot convert bytes to i16".into(),
574        ))
575    }
576}
577
578// Special case for i32 - no conversion needed
579impl FromPostgresValue for i32 {
580    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
581        Ok(Self::from(value))
582    }
583
584    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
585        Ok(Self::from(value))
586    }
587
588    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
589        Ok(value)
590    }
591
592    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
593        value.try_into().map_err(|e| {
594            DrizzleError::ConversionError(format!("i64 {value} out of range for i32: {e}").into())
595        })
596    }
597
598    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
599        checked_float_to_int(f64::from(value), "i32")
600    }
601
602    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
603        checked_float_to_int(value, "i32")
604    }
605
606    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
607        value.parse().map_err(|e| {
608            DrizzleError::ConversionError(format!("cannot parse '{value}' as i32: {e}").into())
609        })
610    }
611
612    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
613        Err(DrizzleError::ConversionError(
614            "cannot convert bytes to i32".into(),
615        ))
616    }
617}
618
619// Special case for i64 - no conversion needed
620impl FromPostgresValue for i64 {
621    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
622        Ok(Self::from(value))
623    }
624
625    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
626        Ok(Self::from(value))
627    }
628
629    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
630        Ok(Self::from(value))
631    }
632
633    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
634        Ok(value)
635    }
636
637    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
638        checked_float_to_int(f64::from(value), "i64")
639    }
640
641    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
642        checked_float_to_int(value, "i64")
643    }
644
645    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
646        value.parse().map_err(|e| {
647            DrizzleError::ConversionError(format!("cannot parse '{value}' as i64: {e}").into())
648        })
649    }
650
651    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
652        Err(DrizzleError::ConversionError(
653            "cannot convert bytes to i64".into(),
654        ))
655    }
656}
657
658// Other integer types that need conversion
659impl_from_postgres_value_int!(i8, u8, u16, u32, u64, isize, usize);
660
661/// Parses an integer via its decimal string form into a float.
662///
663/// This avoids the `cast_precision_loss` lint for `i32 as f32` / `i64 as f32` /
664/// `i64 as f64` while preserving round-to-nearest semantics.
665#[inline]
666fn int_to_float<I: core::fmt::Display, F: core::str::FromStr>(value: I) -> Result<F, DrizzleError>
667where
668    <F as core::str::FromStr>::Err: core::fmt::Display,
669{
670    let s = format!("{value}");
671    s.parse::<F>().map_err(|e| {
672        DrizzleError::ConversionError(format!("cannot convert '{s}' to float: {e}").into())
673    })
674}
675
676impl FromPostgresValue for f64 {
677    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
678        Ok(if value { 1.0 } else { 0.0 })
679    }
680
681    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
682        Ok(Self::from(value))
683    }
684
685    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
686        Ok(Self::from(value))
687    }
688
689    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
690        // Decimal round-trip preserves round-to-nearest without an `as` cast.
691        int_to_float::<_, Self>(value)
692    }
693
694    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
695        Ok(Self::from(value))
696    }
697
698    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
699        Ok(value)
700    }
701
702    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
703        value.parse().map_err(|e: core::num::ParseFloatError| {
704            DrizzleError::ConversionError(format!("cannot parse '{value}' as f64: {e}").into())
705        })
706    }
707
708    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
709        Err(DrizzleError::ConversionError(
710            "cannot convert bytes to f64".into(),
711        ))
712    }
713}
714
715impl FromPostgresValue for f32 {
716    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
717        Ok(if value { 1.0 } else { 0.0 })
718    }
719
720    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
721        Ok(Self::from(value))
722    }
723
724    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
725        int_to_float::<_, Self>(value)
726    }
727
728    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
729        int_to_float::<_, Self>(value)
730    }
731
732    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
733        Ok(value)
734    }
735
736    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
737        // Round via decimal round-trip instead of the lossy `as` cast.
738        let s = format!("{value}");
739        s.parse::<Self>().map_err(|e| {
740            DrizzleError::ConversionError(format!("cannot convert '{s}' to f32: {e}").into())
741        })
742    }
743
744    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
745        value.parse().map_err(|e: core::num::ParseFloatError| {
746            DrizzleError::ConversionError(format!("cannot parse '{value}' as f32: {e}").into())
747        })
748    }
749
750    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
751        Err(DrizzleError::ConversionError(
752            "cannot convert bytes to f32".into(),
753        ))
754    }
755}
756
757impl FromPostgresValue for String {
758    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
759        Ok(value.to_string())
760    }
761
762    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
763        Ok(value.to_string())
764    }
765
766    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
767        Ok(value.to_string())
768    }
769
770    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
771        Ok(value.to_string())
772    }
773
774    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
775        Ok(value.to_string())
776    }
777
778    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
779        Ok(value.to_string())
780    }
781
782    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
783        Ok(value.to_string())
784    }
785
786    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
787        Self::from_utf8(value.to_vec()).map_err(|e| {
788            DrizzleError::ConversionError(format!("invalid UTF-8 in bytes: {e}").into())
789        })
790    }
791}
792
793impl FromPostgresValue for Box<String> {
794    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
795        String::from_postgres_bool(value).map(Self::new)
796    }
797
798    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
799        String::from_postgres_i16(value).map(Self::new)
800    }
801
802    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
803        String::from_postgres_i32(value).map(Self::new)
804    }
805
806    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
807        String::from_postgres_i64(value).map(Self::new)
808    }
809
810    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
811        String::from_postgres_f32(value).map(Self::new)
812    }
813
814    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
815        String::from_postgres_f64(value).map(Self::new)
816    }
817
818    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
819        String::from_postgres_text(value).map(Self::new)
820    }
821
822    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
823        String::from_postgres_bytes(value).map(Self::new)
824    }
825}
826
827impl FromPostgresValue for Rc<String> {
828    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
829        String::from_postgres_bool(value).map(Self::new)
830    }
831
832    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
833        String::from_postgres_i16(value).map(Self::new)
834    }
835
836    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
837        String::from_postgres_i32(value).map(Self::new)
838    }
839
840    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
841        String::from_postgres_i64(value).map(Self::new)
842    }
843
844    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
845        String::from_postgres_f32(value).map(Self::new)
846    }
847
848    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
849        String::from_postgres_f64(value).map(Self::new)
850    }
851
852    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
853        String::from_postgres_text(value).map(Self::new)
854    }
855
856    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
857        String::from_postgres_bytes(value).map(Self::new)
858    }
859}
860
861impl FromPostgresValue for Arc<String> {
862    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
863        String::from_postgres_bool(value).map(Self::new)
864    }
865
866    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
867        String::from_postgres_i16(value).map(Self::new)
868    }
869
870    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
871        String::from_postgres_i32(value).map(Self::new)
872    }
873
874    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
875        String::from_postgres_i64(value).map(Self::new)
876    }
877
878    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
879        String::from_postgres_f32(value).map(Self::new)
880    }
881
882    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
883        String::from_postgres_f64(value).map(Self::new)
884    }
885
886    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
887        String::from_postgres_text(value).map(Self::new)
888    }
889
890    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
891        String::from_postgres_bytes(value).map(Self::new)
892    }
893}
894
895impl FromPostgresValue for Box<str> {
896    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
897        String::from_postgres_bool(value).map(String::into_boxed_str)
898    }
899
900    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
901        String::from_postgres_i16(value).map(String::into_boxed_str)
902    }
903
904    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
905        String::from_postgres_i32(value).map(String::into_boxed_str)
906    }
907
908    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
909        String::from_postgres_i64(value).map(String::into_boxed_str)
910    }
911
912    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
913        String::from_postgres_f32(value).map(String::into_boxed_str)
914    }
915
916    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
917        String::from_postgres_f64(value).map(String::into_boxed_str)
918    }
919
920    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
921        String::from_postgres_text(value).map(String::into_boxed_str)
922    }
923
924    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
925        String::from_postgres_bytes(value).map(String::into_boxed_str)
926    }
927}
928
929impl FromPostgresValue for Rc<str> {
930    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
931        String::from_postgres_bool(value).map(Self::from)
932    }
933
934    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
935        String::from_postgres_i16(value).map(Self::from)
936    }
937
938    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
939        String::from_postgres_i32(value).map(Self::from)
940    }
941
942    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
943        String::from_postgres_i64(value).map(Self::from)
944    }
945
946    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
947        String::from_postgres_f32(value).map(Self::from)
948    }
949
950    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
951        String::from_postgres_f64(value).map(Self::from)
952    }
953
954    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
955        String::from_postgres_text(value).map(Self::from)
956    }
957
958    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
959        String::from_postgres_bytes(value).map(Self::from)
960    }
961}
962
963impl FromPostgresValue for Arc<str> {
964    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
965        String::from_postgres_bool(value).map(Self::from)
966    }
967
968    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
969        String::from_postgres_i16(value).map(Self::from)
970    }
971
972    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
973        String::from_postgres_i32(value).map(Self::from)
974    }
975
976    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
977        String::from_postgres_i64(value).map(Self::from)
978    }
979
980    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
981        String::from_postgres_f32(value).map(Self::from)
982    }
983
984    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
985        String::from_postgres_f64(value).map(Self::from)
986    }
987
988    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
989        String::from_postgres_text(value).map(Self::from)
990    }
991
992    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
993        String::from_postgres_bytes(value).map(Self::from)
994    }
995}
996
997impl FromPostgresValue for Vec<u8> {
998    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
999        Err(DrizzleError::ConversionError(
1000            "cannot convert bool to Vec<u8>".into(),
1001        ))
1002    }
1003
1004    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1005        Ok(value.to_le_bytes().to_vec())
1006    }
1007
1008    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1009        Ok(value.to_le_bytes().to_vec())
1010    }
1011
1012    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1013        Ok(value.to_le_bytes().to_vec())
1014    }
1015
1016    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1017        Ok(value.to_le_bytes().to_vec())
1018    }
1019
1020    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1021        Ok(value.to_le_bytes().to_vec())
1022    }
1023
1024    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1025        Ok(value.as_bytes().to_vec())
1026    }
1027
1028    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1029        Ok(value.to_vec())
1030    }
1031}
1032
1033impl FromPostgresValue for Box<Vec<u8>> {
1034    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1035        Vec::<u8>::from_postgres_bool(value).map(Self::new)
1036    }
1037
1038    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1039        Vec::<u8>::from_postgres_i16(value).map(Self::new)
1040    }
1041
1042    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1043        Vec::<u8>::from_postgres_i32(value).map(Self::new)
1044    }
1045
1046    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1047        Vec::<u8>::from_postgres_i64(value).map(Self::new)
1048    }
1049
1050    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1051        Vec::<u8>::from_postgres_f32(value).map(Self::new)
1052    }
1053
1054    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1055        Vec::<u8>::from_postgres_f64(value).map(Self::new)
1056    }
1057
1058    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1059        Vec::<u8>::from_postgres_text(value).map(Self::new)
1060    }
1061
1062    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1063        Vec::<u8>::from_postgres_bytes(value).map(Self::new)
1064    }
1065}
1066
1067impl FromPostgresValue for Rc<Vec<u8>> {
1068    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1069        Vec::<u8>::from_postgres_bool(value).map(Self::new)
1070    }
1071
1072    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1073        Vec::<u8>::from_postgres_i16(value).map(Self::new)
1074    }
1075
1076    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1077        Vec::<u8>::from_postgres_i32(value).map(Self::new)
1078    }
1079
1080    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1081        Vec::<u8>::from_postgres_i64(value).map(Self::new)
1082    }
1083
1084    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1085        Vec::<u8>::from_postgres_f32(value).map(Self::new)
1086    }
1087
1088    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1089        Vec::<u8>::from_postgres_f64(value).map(Self::new)
1090    }
1091
1092    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1093        Vec::<u8>::from_postgres_text(value).map(Self::new)
1094    }
1095
1096    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1097        Vec::<u8>::from_postgres_bytes(value).map(Self::new)
1098    }
1099}
1100
1101impl FromPostgresValue for Arc<Vec<u8>> {
1102    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1103        Vec::<u8>::from_postgres_bool(value).map(Self::new)
1104    }
1105
1106    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1107        Vec::<u8>::from_postgres_i16(value).map(Self::new)
1108    }
1109
1110    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1111        Vec::<u8>::from_postgres_i32(value).map(Self::new)
1112    }
1113
1114    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1115        Vec::<u8>::from_postgres_i64(value).map(Self::new)
1116    }
1117
1118    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1119        Vec::<u8>::from_postgres_f32(value).map(Self::new)
1120    }
1121
1122    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1123        Vec::<u8>::from_postgres_f64(value).map(Self::new)
1124    }
1125
1126    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1127        Vec::<u8>::from_postgres_text(value).map(Self::new)
1128    }
1129
1130    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1131        Vec::<u8>::from_postgres_bytes(value).map(Self::new)
1132    }
1133}
1134
1135// Option<T> implementation - handles NULL values
1136impl<T: FromPostgresValue> FromPostgresValue for Option<T> {
1137    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1138        T::from_postgres_bool(value).map(Some)
1139    }
1140
1141    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1142        T::from_postgres_i16(value).map(Some)
1143    }
1144
1145    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1146        T::from_postgres_i32(value).map(Some)
1147    }
1148
1149    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1150        T::from_postgres_i64(value).map(Some)
1151    }
1152
1153    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1154        T::from_postgres_f32(value).map(Some)
1155    }
1156
1157    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1158        T::from_postgres_f64(value).map(Some)
1159    }
1160
1161    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1162        T::from_postgres_text(value).map(Some)
1163    }
1164
1165    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1166        T::from_postgres_bytes(value).map(Some)
1167    }
1168
1169    #[cfg(feature = "uuid")]
1170    fn from_postgres_uuid(value: uuid::Uuid) -> Result<Self, DrizzleError> {
1171        T::from_postgres_uuid(value).map(Some)
1172    }
1173
1174    #[cfg(feature = "serde")]
1175    fn from_postgres_json(value: serde_json::Value) -> Result<Self, DrizzleError> {
1176        T::from_postgres_json(value).map(Some)
1177    }
1178
1179    #[cfg(feature = "serde")]
1180    fn from_postgres_jsonb(value: serde_json::Value) -> Result<Self, DrizzleError> {
1181        T::from_postgres_jsonb(value).map(Some)
1182    }
1183
1184    #[cfg(feature = "chrono")]
1185    fn from_postgres_date(value: chrono::NaiveDate) -> Result<Self, DrizzleError> {
1186        T::from_postgres_date(value).map(Some)
1187    }
1188
1189    #[cfg(feature = "chrono")]
1190    fn from_postgres_time(value: chrono::NaiveTime) -> Result<Self, DrizzleError> {
1191        T::from_postgres_time(value).map(Some)
1192    }
1193
1194    #[cfg(feature = "chrono")]
1195    fn from_postgres_timestamp(value: chrono::NaiveDateTime) -> Result<Self, DrizzleError> {
1196        T::from_postgres_timestamp(value).map(Some)
1197    }
1198
1199    #[cfg(feature = "chrono")]
1200    fn from_postgres_timestamptz(
1201        value: chrono::DateTime<chrono::FixedOffset>,
1202    ) -> Result<Self, DrizzleError> {
1203        T::from_postgres_timestamptz(value).map(Some)
1204    }
1205
1206    #[cfg(feature = "chrono")]
1207    fn from_postgres_interval(value: chrono::Duration) -> Result<Self, DrizzleError> {
1208        T::from_postgres_interval(value).map(Some)
1209    }
1210
1211    #[cfg(feature = "time")]
1212    fn from_postgres_time_date(value: time::Date) -> Result<Self, DrizzleError> {
1213        T::from_postgres_time_date(value).map(Some)
1214    }
1215
1216    #[cfg(feature = "time")]
1217    fn from_postgres_time_time(value: time::Time) -> Result<Self, DrizzleError> {
1218        T::from_postgres_time_time(value).map(Some)
1219    }
1220
1221    #[cfg(feature = "time")]
1222    fn from_postgres_time_timestamp(value: time::PrimitiveDateTime) -> Result<Self, DrizzleError> {
1223        T::from_postgres_time_timestamp(value).map(Some)
1224    }
1225
1226    #[cfg(feature = "time")]
1227    fn from_postgres_time_timestamptz(value: time::OffsetDateTime) -> Result<Self, DrizzleError> {
1228        T::from_postgres_time_timestamptz(value).map(Some)
1229    }
1230
1231    #[cfg(feature = "time")]
1232    fn from_postgres_time_interval(value: time::Duration) -> Result<Self, DrizzleError> {
1233        T::from_postgres_time_interval(value).map(Some)
1234    }
1235
1236    #[cfg(feature = "jiff")]
1237    fn from_postgres_jiff_date(value: jiff::civil::Date) -> Result<Self, DrizzleError> {
1238        T::from_postgres_jiff_date(value).map(Some)
1239    }
1240
1241    #[cfg(feature = "jiff")]
1242    fn from_postgres_jiff_time(value: jiff::civil::Time) -> Result<Self, DrizzleError> {
1243        T::from_postgres_jiff_time(value).map(Some)
1244    }
1245
1246    #[cfg(feature = "jiff")]
1247    fn from_postgres_jiff_datetime(value: jiff::civil::DateTime) -> Result<Self, DrizzleError> {
1248        T::from_postgres_jiff_datetime(value).map(Some)
1249    }
1250
1251    #[cfg(feature = "jiff")]
1252    fn from_postgres_jiff_timestamp(value: jiff::Timestamp) -> Result<Self, DrizzleError> {
1253        T::from_postgres_jiff_timestamp(value).map(Some)
1254    }
1255
1256    #[cfg(feature = "cidr")]
1257    fn from_postgres_inet(value: cidr::IpInet) -> Result<Self, DrizzleError> {
1258        T::from_postgres_inet(value).map(Some)
1259    }
1260
1261    #[cfg(feature = "cidr")]
1262    fn from_postgres_cidr(value: cidr::IpCidr) -> Result<Self, DrizzleError> {
1263        T::from_postgres_cidr(value).map(Some)
1264    }
1265
1266    #[cfg(feature = "cidr")]
1267    fn from_postgres_macaddr(value: [u8; 6]) -> Result<Self, DrizzleError> {
1268        T::from_postgres_macaddr(value).map(Some)
1269    }
1270
1271    #[cfg(feature = "cidr")]
1272    fn from_postgres_macaddr8(value: [u8; 8]) -> Result<Self, DrizzleError> {
1273        T::from_postgres_macaddr8(value).map(Some)
1274    }
1275
1276    #[cfg(feature = "geo-types")]
1277    fn from_postgres_point(value: geo_types::Point<f64>) -> Result<Self, DrizzleError> {
1278        T::from_postgres_point(value).map(Some)
1279    }
1280
1281    #[cfg(feature = "geo-types")]
1282    fn from_postgres_linestring(value: geo_types::LineString<f64>) -> Result<Self, DrizzleError> {
1283        T::from_postgres_linestring(value).map(Some)
1284    }
1285
1286    #[cfg(feature = "geo-types")]
1287    fn from_postgres_rect(value: geo_types::Rect<f64>) -> Result<Self, DrizzleError> {
1288        T::from_postgres_rect(value).map(Some)
1289    }
1290
1291    #[cfg(feature = "bit-vec")]
1292    fn from_postgres_bitvec(value: bit_vec::BitVec) -> Result<Self, DrizzleError> {
1293        T::from_postgres_bitvec(value).map(Some)
1294    }
1295
1296    fn from_postgres_array(value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
1297        T::from_postgres_array(value).map(Some)
1298    }
1299
1300    fn from_postgres_null() -> Result<Self, DrizzleError> {
1301        Ok(None)
1302    }
1303}
1304
1305// =============================================================================
1306// Driver-specific DrizzleRow implementations
1307// =============================================================================
1308
1309// Note: postgres::Row is a re-export of tokio_postgres::Row, so we only need
1310// to implement for one type. We use tokio_postgres::Row as it's the underlying type.
1311// When only postgres-sync is enabled, postgres::Row will be available.
1312
1313#[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
1314mod postgres_row_impl {
1315    use super::{
1316        DrizzleError, DrizzleRowByIndex, DrizzleRowByName, FromPostgresValue, PostgresValue,
1317        String, Vec,
1318    };
1319
1320    // Helper function to convert a row value to our type
1321    // This uses the native driver's try_get functionality
1322    fn convert_column<T: FromPostgresValue, R: PostgresRowLike>(
1323        row: &R,
1324        column: impl ColumnRef,
1325    ) -> Result<T, DrizzleError> {
1326        // Only a NULL cell decodes as NULL. The probe accepts every wire
1327        // type, so it never mistakes a value it cannot read for NULL.
1328        let is_null = row
1329            .try_get_any::<drizzle_core::AnyNullProbe>(&column)
1330            .map_err(|()| missing_column(&column))?
1331            .is_none();
1332        if is_null {
1333            return T::from_postgres_null();
1334        }
1335
1336        // Each probe reads the cell as one Rust type and hands it to `T`. A
1337        // probe whose value `T` rejects (a chrono timestamp for a jiff
1338        // target) does not end the search: a later probe may read the same
1339        // column as a type `T` accepts. The first rejection is reported if
1340        // none succeeds.
1341        let mut first_error = None;
1342        match try_oid_dispatch::<T, R>(row, &column) {
1343            Some(Ok(value)) => return Ok(value),
1344            Some(Err(error)) => {
1345                first_error.get_or_insert(error);
1346            }
1347            None => {}
1348        }
1349        if let Some(value) = try_scalar_fallbacks::<T, R>(row, &column, &mut first_error) {
1350            return Ok(value);
1351        }
1352        match try_array_fallbacks::<T, R>(row, &column) {
1353            Some(Ok(value)) => return Ok(value),
1354            Some(Err(error)) => {
1355                first_error.get_or_insert(error);
1356            }
1357            None => {}
1358        }
1359
1360        Err(first_error.unwrap_or_else(|| {
1361            DrizzleError::ConversionError(
1362                format!(
1363                    "cannot decode column {} of type {} as {}",
1364                    column_label(&column),
1365                    row.type_name(&column).as_deref().unwrap_or("unknown"),
1366                    core::any::type_name::<T>(),
1367                )
1368                .into(),
1369            )
1370        }))
1371    }
1372
1373    fn column_label(column: &impl ColumnRef) -> String {
1374        match (column.to_index(), column.to_name()) {
1375            (Some(idx), _) => idx.to_string(),
1376            (None, Some(name)) => format!("'{name}'"),
1377            (None, None) => "?".into(),
1378        }
1379    }
1380
1381    fn missing_column(column: &impl ColumnRef) -> DrizzleError {
1382        DrizzleError::ConversionError(format!("column {} not found", column_label(column)).into())
1383    }
1384
1385    /// `PostgreSQL` OID fast-path: when the column's declared type matches a
1386    /// known primitive OID, decode directly without running the full fallback
1387    /// chain.
1388    fn try_oid_dispatch<T: FromPostgresValue, R: PostgresRowLike>(
1389        row: &R,
1390        column: &impl ColumnRef,
1391    ) -> Option<Result<T, DrizzleError>> {
1392        let oid = row.type_oid(column)?;
1393        match oid {
1394            16 => row
1395                .try_get_bool(column)
1396                .ok()
1397                .flatten()
1398                .map(T::from_postgres_bool),
1399            20 => row
1400                .try_get_i64(column)
1401                .ok()
1402                .flatten()
1403                .map(T::from_postgres_i64),
1404            23 => row
1405                .try_get_i32(column)
1406                .ok()
1407                .flatten()
1408                .map(T::from_postgres_i32),
1409            21 => row
1410                .try_get_i16(column)
1411                .ok()
1412                .flatten()
1413                .map(T::from_postgres_i16),
1414            701 => row
1415                .try_get_f64(column)
1416                .ok()
1417                .flatten()
1418                .map(T::from_postgres_f64),
1419            700 => row
1420                .try_get_f32(column)
1421                .ok()
1422                .flatten()
1423                .map(T::from_postgres_f32),
1424            17 => row
1425                .try_get_bytes(column)
1426                .ok()
1427                .flatten()
1428                .map(|v| T::from_postgres_bytes(&v)),
1429            25 | 1043 | 1042 => row
1430                .try_get_string(column)
1431                .ok()
1432                .flatten()
1433                .map(|v| T::from_postgres_text(&v)),
1434            _ => None,
1435        }
1436    }
1437
1438    /// Scalar fallback chain: try each supported primitive / library type in
1439    /// priority order, returning the first that decodes successfully.
1440    ///
1441    /// Returns the first value `T` accepts. A probe whose value `T` rejects
1442    /// records its error in `first_error` and the search continues.
1443    fn try_scalar_fallbacks<T: FromPostgresValue, R: PostgresRowLike>(
1444        row: &R,
1445        column: &impl ColumnRef,
1446        first_error: &mut Option<DrizzleError>,
1447    ) -> Option<T> {
1448        macro_rules! probe {
1449            ($($probe:ident),+ $(,)?) => {$(
1450                match $probe::<T, R>(row, column) {
1451                    Some(Ok(value)) => return Some(value),
1452                    Some(Err(error)) => {
1453                        first_error.get_or_insert(error);
1454                    }
1455                    None => {}
1456                }
1457            )+};
1458        }
1459        probe!(
1460            try_scalar_primitives,
1461            try_scalar_uuid,
1462            try_scalar_json,
1463            try_scalar_chrono,
1464            try_scalar_time,
1465            try_scalar_jiff,
1466            try_scalar_cidr,
1467            try_scalar_geo,
1468            try_scalar_bitvec,
1469        );
1470        None
1471    }
1472
1473    #[cfg(feature = "time")]
1474    fn try_scalar_time<T: FromPostgresValue, R: PostgresRowLike>(
1475        row: &R,
1476        column: &impl ColumnRef,
1477    ) -> Option<Result<T, DrizzleError>> {
1478        if let Ok(Some(v)) = row.try_get_any::<time::Date>(column) {
1479            return Some(T::from_postgres_time_date(v));
1480        }
1481        if let Ok(Some(v)) = row.try_get_any::<time::Time>(column) {
1482            return Some(T::from_postgres_time_time(v));
1483        }
1484        if let Ok(Some(v)) = row.try_get_any::<time::PrimitiveDateTime>(column) {
1485            return Some(T::from_postgres_time_timestamp(v));
1486        }
1487        if let Ok(Some(v)) = row.try_get_any::<time::OffsetDateTime>(column) {
1488            return Some(T::from_postgres_time_timestamptz(v));
1489        }
1490        None
1491    }
1492
1493    #[cfg(not(feature = "time"))]
1494    const fn try_scalar_time<T: FromPostgresValue, R: PostgresRowLike>(
1495        _row: &R,
1496        _column: &impl ColumnRef,
1497    ) -> Option<Result<T, DrizzleError>> {
1498        None
1499    }
1500
1501    #[cfg(feature = "jiff")]
1502    fn try_scalar_jiff<T: FromPostgresValue, R: PostgresRowLike>(
1503        row: &R,
1504        column: &impl ColumnRef,
1505    ) -> Option<Result<T, DrizzleError>> {
1506        if let Ok(Some(v)) = row.try_get_any::<jiff::civil::Date>(column) {
1507            return Some(T::from_postgres_jiff_date(v));
1508        }
1509        if let Ok(Some(v)) = row.try_get_any::<jiff::civil::Time>(column) {
1510            return Some(T::from_postgres_jiff_time(v));
1511        }
1512        if let Ok(Some(v)) = row.try_get_any::<jiff::civil::DateTime>(column) {
1513            return Some(T::from_postgres_jiff_datetime(v));
1514        }
1515        if let Ok(Some(v)) = row.try_get_any::<jiff::Timestamp>(column) {
1516            return Some(T::from_postgres_jiff_timestamp(v));
1517        }
1518        None
1519    }
1520
1521    #[cfg(not(feature = "jiff"))]
1522    const fn try_scalar_jiff<T: FromPostgresValue, R: PostgresRowLike>(
1523        _row: &R,
1524        _column: &impl ColumnRef,
1525    ) -> Option<Result<T, DrizzleError>> {
1526        None
1527    }
1528
1529    /// Primitive scalar fallbacks: bool / integers / floats / text / bytes.
1530    fn try_scalar_primitives<T: FromPostgresValue, R: PostgresRowLike>(
1531        row: &R,
1532        column: &impl ColumnRef,
1533    ) -> Option<Result<T, DrizzleError>> {
1534        if let Ok(Some(v)) = row.try_get_bool(column) {
1535            return Some(T::from_postgres_bool(v));
1536        }
1537        if let Ok(Some(v)) = row.try_get_i64(column) {
1538            return Some(T::from_postgres_i64(v));
1539        }
1540        if let Ok(Some(v)) = row.try_get_i32(column) {
1541            return Some(T::from_postgres_i32(v));
1542        }
1543        if let Ok(Some(v)) = row.try_get_i16(column) {
1544            return Some(T::from_postgres_i16(v));
1545        }
1546        if let Ok(Some(v)) = row.try_get_f64(column) {
1547            return Some(T::from_postgres_f64(v));
1548        }
1549        if let Ok(Some(v)) = row.try_get_f32(column) {
1550            return Some(T::from_postgres_f32(v));
1551        }
1552        if let Ok(Some(ref v)) = row.try_get_string(column) {
1553            return Some(T::from_postgres_text(v));
1554        }
1555        if let Ok(Some(ref v)) = row.try_get_bytes(column) {
1556            return Some(T::from_postgres_bytes(v));
1557        }
1558        None
1559    }
1560
1561    #[cfg(feature = "uuid")]
1562    fn try_scalar_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1563        row: &R,
1564        column: &impl ColumnRef,
1565    ) -> Option<Result<T, DrizzleError>> {
1566        row.try_get_uuid(column)
1567            .ok()
1568            .flatten()
1569            .map(T::from_postgres_uuid)
1570    }
1571
1572    #[cfg(not(feature = "uuid"))]
1573    const fn try_scalar_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1574        _row: &R,
1575        _column: &impl ColumnRef,
1576    ) -> Option<Result<T, DrizzleError>> {
1577        None
1578    }
1579
1580    #[cfg(feature = "serde")]
1581    fn try_scalar_json<T: FromPostgresValue, R: PostgresRowLike>(
1582        row: &R,
1583        column: &impl ColumnRef,
1584    ) -> Option<Result<T, DrizzleError>> {
1585        row.try_get_json(column)
1586            .ok()
1587            .flatten()
1588            .map(T::from_postgres_json)
1589    }
1590
1591    #[cfg(not(feature = "serde"))]
1592    const fn try_scalar_json<T: FromPostgresValue, R: PostgresRowLike>(
1593        _row: &R,
1594        _column: &impl ColumnRef,
1595    ) -> Option<Result<T, DrizzleError>> {
1596        None
1597    }
1598
1599    #[cfg(feature = "chrono")]
1600    fn try_scalar_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1601        row: &R,
1602        column: &impl ColumnRef,
1603    ) -> Option<Result<T, DrizzleError>> {
1604        if let Ok(Some(v)) = row.try_get_date(column) {
1605            return Some(T::from_postgres_date(v));
1606        }
1607        if let Ok(Some(v)) = row.try_get_time(column) {
1608            return Some(T::from_postgres_time(v));
1609        }
1610        if let Ok(Some(v)) = row.try_get_timestamp(column) {
1611            return Some(T::from_postgres_timestamp(v));
1612        }
1613        if let Ok(Some(v)) = row.try_get_timestamptz(column) {
1614            return Some(T::from_postgres_timestamptz(v));
1615        }
1616        None
1617    }
1618
1619    #[cfg(not(feature = "chrono"))]
1620    const fn try_scalar_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1621        _row: &R,
1622        _column: &impl ColumnRef,
1623    ) -> Option<Result<T, DrizzleError>> {
1624        None
1625    }
1626
1627    #[cfg(feature = "cidr")]
1628    fn try_scalar_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1629        row: &R,
1630        column: &impl ColumnRef,
1631    ) -> Option<Result<T, DrizzleError>> {
1632        if let Ok(Some(v)) = row.try_get_inet(column) {
1633            return Some(T::from_postgres_inet(v));
1634        }
1635        if let Ok(Some(v)) = row.try_get_cidr(column) {
1636            return Some(T::from_postgres_cidr(v));
1637        }
1638        if let Ok(Some(v)) = row.try_get_macaddr(column) {
1639            return Some(T::from_postgres_macaddr(v));
1640        }
1641        if let Ok(Some(v)) = row.try_get_macaddr8(column) {
1642            return Some(T::from_postgres_macaddr8(v));
1643        }
1644        None
1645    }
1646
1647    #[cfg(not(feature = "cidr"))]
1648    const fn try_scalar_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1649        _row: &R,
1650        _column: &impl ColumnRef,
1651    ) -> Option<Result<T, DrizzleError>> {
1652        None
1653    }
1654
1655    #[cfg(feature = "geo-types")]
1656    fn try_scalar_geo<T: FromPostgresValue, R: PostgresRowLike>(
1657        row: &R,
1658        column: &impl ColumnRef,
1659    ) -> Option<Result<T, DrizzleError>> {
1660        if let Ok(Some(v)) = row.try_get_point(column) {
1661            return Some(T::from_postgres_point(v));
1662        }
1663        if let Ok(Some(v)) = row.try_get_linestring(column) {
1664            return Some(T::from_postgres_linestring(v));
1665        }
1666        if let Ok(Some(v)) = row.try_get_rect(column) {
1667            return Some(T::from_postgres_rect(v));
1668        }
1669        None
1670    }
1671
1672    #[cfg(not(feature = "geo-types"))]
1673    const fn try_scalar_geo<T: FromPostgresValue, R: PostgresRowLike>(
1674        _row: &R,
1675        _column: &impl ColumnRef,
1676    ) -> Option<Result<T, DrizzleError>> {
1677        None
1678    }
1679
1680    #[cfg(feature = "bit-vec")]
1681    fn try_scalar_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1682        row: &R,
1683        column: &impl ColumnRef,
1684    ) -> Option<Result<T, DrizzleError>> {
1685        row.try_get_bitvec(column)
1686            .ok()
1687            .flatten()
1688            .map(T::from_postgres_bitvec)
1689    }
1690
1691    #[cfg(not(feature = "bit-vec"))]
1692    const fn try_scalar_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1693        _row: &R,
1694        _column: &impl ColumnRef,
1695    ) -> Option<Result<T, DrizzleError>> {
1696        None
1697    }
1698
1699    /// Array fallback chain: try each supported array element type in priority
1700    /// order.
1701    fn try_array_fallbacks<T: FromPostgresValue, R: PostgresRowLike>(
1702        row: &R,
1703        column: &impl ColumnRef,
1704    ) -> Option<Result<T, DrizzleError>> {
1705        try_array_primitives::<T, R>(row, column)
1706            .or_else(|| try_array_uuid::<T, R>(row, column))
1707            .or_else(|| try_array_json::<T, R>(row, column))
1708            .or_else(|| try_array_chrono::<T, R>(row, column))
1709            .or_else(|| try_array_cidr::<T, R>(row, column))
1710            .or_else(|| try_array_geo::<T, R>(row, column))
1711            .or_else(|| try_array_bitvec::<T, R>(row, column))
1712            .or_else(|| try_array_text_bytes::<T, R>(row, column))
1713    }
1714
1715    /// Primitive array fallbacks: bool / integers / floats (priority order).
1716    fn try_array_primitives<T: FromPostgresValue, R: PostgresRowLike>(
1717        row: &R,
1718        column: &impl ColumnRef,
1719    ) -> Option<Result<T, DrizzleError>> {
1720        if let Ok(Some(values)) = row.try_get_array_bool(column) {
1721            return Some(T::from_postgres_array(array_values(values)));
1722        }
1723        if let Ok(Some(values)) = row.try_get_array_i16(column) {
1724            return Some(T::from_postgres_array(array_values(values)));
1725        }
1726        if let Ok(Some(values)) = row.try_get_array_i32(column) {
1727            return Some(T::from_postgres_array(array_values(values)));
1728        }
1729        if let Ok(Some(values)) = row.try_get_array_i64(column) {
1730            return Some(T::from_postgres_array(array_values(values)));
1731        }
1732        if let Ok(Some(values)) = row.try_get_array_f32(column) {
1733            return Some(T::from_postgres_array(array_values(values)));
1734        }
1735        if let Ok(Some(values)) = row.try_get_array_f64(column) {
1736            return Some(T::from_postgres_array(array_values(values)));
1737        }
1738        None
1739    }
1740
1741    #[cfg(feature = "uuid")]
1742    fn try_array_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1743        row: &R,
1744        column: &impl ColumnRef,
1745    ) -> Option<Result<T, DrizzleError>> {
1746        row.try_get_array_uuid(column)
1747            .ok()
1748            .flatten()
1749            .map(|values| T::from_postgres_array(array_values(values)))
1750    }
1751
1752    #[cfg(not(feature = "uuid"))]
1753    const fn try_array_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1754        _row: &R,
1755        _column: &impl ColumnRef,
1756    ) -> Option<Result<T, DrizzleError>> {
1757        None
1758    }
1759
1760    #[cfg(feature = "serde")]
1761    fn try_array_json<T: FromPostgresValue, R: PostgresRowLike>(
1762        row: &R,
1763        column: &impl ColumnRef,
1764    ) -> Option<Result<T, DrizzleError>> {
1765        row.try_get_array_json(column)
1766            .ok()
1767            .flatten()
1768            .map(|values| T::from_postgres_array(array_values(values)))
1769    }
1770
1771    #[cfg(not(feature = "serde"))]
1772    const fn try_array_json<T: FromPostgresValue, R: PostgresRowLike>(
1773        _row: &R,
1774        _column: &impl ColumnRef,
1775    ) -> Option<Result<T, DrizzleError>> {
1776        None
1777    }
1778
1779    #[cfg(feature = "chrono")]
1780    fn try_array_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1781        row: &R,
1782        column: &impl ColumnRef,
1783    ) -> Option<Result<T, DrizzleError>> {
1784        if let Ok(Some(values)) = row.try_get_array_date(column) {
1785            return Some(T::from_postgres_array(array_values(values)));
1786        }
1787        if let Ok(Some(values)) = row.try_get_array_time(column) {
1788            return Some(T::from_postgres_array(array_values(values)));
1789        }
1790        if let Ok(Some(values)) = row.try_get_array_timestamp(column) {
1791            return Some(T::from_postgres_array(array_values(values)));
1792        }
1793        if let Ok(Some(values)) = row.try_get_array_timestamptz(column) {
1794            return Some(T::from_postgres_array(array_values(values)));
1795        }
1796        None
1797    }
1798
1799    #[cfg(not(feature = "chrono"))]
1800    const fn try_array_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1801        _row: &R,
1802        _column: &impl ColumnRef,
1803    ) -> Option<Result<T, DrizzleError>> {
1804        None
1805    }
1806
1807    #[cfg(feature = "cidr")]
1808    fn try_array_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1809        row: &R,
1810        column: &impl ColumnRef,
1811    ) -> Option<Result<T, DrizzleError>> {
1812        if let Ok(Some(values)) = row.try_get_array_inet(column) {
1813            return Some(T::from_postgres_array(array_values(values)));
1814        }
1815        if let Ok(Some(values)) = row.try_get_array_cidr(column) {
1816            return Some(T::from_postgres_array(array_values(values)));
1817        }
1818        if let Ok(Some(values)) = row.try_get_array_macaddr(column) {
1819            return Some(T::from_postgres_array(array_values(values)));
1820        }
1821        if let Ok(Some(values)) = row.try_get_array_macaddr8(column) {
1822            return Some(T::from_postgres_array(array_values(values)));
1823        }
1824        None
1825    }
1826
1827    #[cfg(not(feature = "cidr"))]
1828    const fn try_array_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1829        _row: &R,
1830        _column: &impl ColumnRef,
1831    ) -> Option<Result<T, DrizzleError>> {
1832        None
1833    }
1834
1835    #[cfg(feature = "geo-types")]
1836    fn try_array_geo<T: FromPostgresValue, R: PostgresRowLike>(
1837        row: &R,
1838        column: &impl ColumnRef,
1839    ) -> Option<Result<T, DrizzleError>> {
1840        if let Ok(Some(values)) = row.try_get_array_point(column) {
1841            return Some(T::from_postgres_array(array_values(values)));
1842        }
1843        if let Ok(Some(values)) = row.try_get_array_linestring(column) {
1844            return Some(T::from_postgres_array(array_values(values)));
1845        }
1846        if let Ok(Some(values)) = row.try_get_array_rect(column) {
1847            return Some(T::from_postgres_array(array_values(values)));
1848        }
1849        None
1850    }
1851
1852    #[cfg(not(feature = "geo-types"))]
1853    const fn try_array_geo<T: FromPostgresValue, R: PostgresRowLike>(
1854        _row: &R,
1855        _column: &impl ColumnRef,
1856    ) -> Option<Result<T, DrizzleError>> {
1857        None
1858    }
1859
1860    #[cfg(feature = "bit-vec")]
1861    fn try_array_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1862        row: &R,
1863        column: &impl ColumnRef,
1864    ) -> Option<Result<T, DrizzleError>> {
1865        row.try_get_array_bitvec(column)
1866            .ok()
1867            .flatten()
1868            .map(|values| T::from_postgres_array(array_values(values)))
1869    }
1870
1871    #[cfg(not(feature = "bit-vec"))]
1872    const fn try_array_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1873        _row: &R,
1874        _column: &impl ColumnRef,
1875    ) -> Option<Result<T, DrizzleError>> {
1876        None
1877    }
1878
1879    /// Final bytes/text array fallback (lowest priority).
1880    fn try_array_text_bytes<T: FromPostgresValue, R: PostgresRowLike>(
1881        row: &R,
1882        column: &impl ColumnRef,
1883    ) -> Option<Result<T, DrizzleError>> {
1884        if let Ok(Some(values)) = row.try_get_array_bytes(column) {
1885            return Some(T::from_postgres_array(array_values(values)));
1886        }
1887        if let Ok(Some(values)) = row.try_get_array_text(column) {
1888            return Some(T::from_postgres_array(array_values(values)));
1889        }
1890        None
1891    }
1892
1893    /// Trait for column reference types (index or name)
1894    trait ColumnRef: Copy {
1895        fn to_index(&self) -> Option<usize>;
1896        fn to_name(&self) -> Option<&str>;
1897    }
1898
1899    impl ColumnRef for usize {
1900        fn to_index(&self) -> Option<usize> {
1901            Some(*self)
1902        }
1903        fn to_name(&self) -> Option<&str> {
1904            None
1905        }
1906    }
1907
1908    impl ColumnRef for &str {
1909        fn to_index(&self) -> Option<usize> {
1910            None
1911        }
1912        fn to_name(&self) -> Option<&str> {
1913            Some(*self)
1914        }
1915    }
1916
1917    fn array_values<T>(values: Vec<Option<T>>) -> Vec<PostgresValue<'static>>
1918    where
1919        T: Into<PostgresValue<'static>>,
1920    {
1921        values
1922            .into_iter()
1923            .map(|value| value.map_or(PostgresValue::Null, Into::into))
1924            .collect()
1925    }
1926
1927    #[cfg(feature = "cidr")]
1928    fn parse_mac<const N: usize>(value: &str) -> Option<[u8; N]> {
1929        let mut bytes = [0u8; N];
1930        let mut parts = value.split(':');
1931
1932        for slot in &mut bytes {
1933            let part = parts.next()?;
1934            if part.len() != 2 {
1935                return None;
1936            }
1937            *slot = u8::from_str_radix(part, 16).ok()?;
1938        }
1939
1940        if parts.next().is_some() {
1941            return None;
1942        }
1943
1944        Some(bytes)
1945    }
1946
1947    #[cfg(feature = "cidr")]
1948    fn parse_mac_array<const N: usize>(
1949        values: Vec<Option<String>>,
1950    ) -> Result<Vec<Option<[u8; N]>>, ()> {
1951        let mut parsed = Vec::with_capacity(values.len());
1952        for value in values {
1953            match value {
1954                Some(value) => {
1955                    let parsed_value = parse_mac::<N>(&value).ok_or(())?;
1956                    parsed.push(Some(parsed_value));
1957                }
1958                None => parsed.push(None),
1959            }
1960        }
1961        Ok(parsed)
1962    }
1963
1964    /// Resolve a `ColumnRef` to either an index-based or name-based `try_get` call
1965    /// on the underlying driver `Row`, returning `Err(())` when neither key resolves.
1966    macro_rules! try_get_typed {
1967        ($self:ident, $column:ident, $ty:ty) => {
1968            match ($column.to_index(), $column.to_name()) {
1969                (Some(idx), _) => $self.try_get::<_, Option<$ty>>(idx).map_err(|_| ()),
1970                (None, Some(name)) => $self.try_get::<_, Option<$ty>>(name).map_err(|_| ()),
1971                (None, None) => Err(()),
1972            }
1973        };
1974    }
1975
1976    /// Internal trait to abstract over postgres/tokio-postgres Row types
1977    trait PostgresRowLike {
1978        fn type_oid(&self, column: &impl ColumnRef) -> Option<u32>;
1979        /// The column's Postgres type name, for error messages.
1980        fn type_name(&self, column: &impl ColumnRef) -> Option<String>;
1981        /// Reads the column as any driver-decodable `T`.
1982        fn try_get_any<T: for<'a> crate::driver_types::FromSql<'a>>(
1983            &self,
1984            column: &impl ColumnRef,
1985        ) -> Result<Option<T>, ()>;
1986        fn try_get_bool(&self, column: &impl ColumnRef) -> Result<Option<bool>, ()>;
1987        fn try_get_i16(&self, column: &impl ColumnRef) -> Result<Option<i16>, ()>;
1988        fn try_get_i32(&self, column: &impl ColumnRef) -> Result<Option<i32>, ()>;
1989        fn try_get_i64(&self, column: &impl ColumnRef) -> Result<Option<i64>, ()>;
1990        fn try_get_f32(&self, column: &impl ColumnRef) -> Result<Option<f32>, ()>;
1991        fn try_get_f64(&self, column: &impl ColumnRef) -> Result<Option<f64>, ()>;
1992        fn try_get_string(&self, column: &impl ColumnRef) -> Result<Option<String>, ()>;
1993        fn try_get_bytes(&self, column: &impl ColumnRef) -> Result<Option<Vec<u8>>, ()>;
1994        #[cfg(feature = "uuid")]
1995        fn try_get_uuid(&self, column: &impl ColumnRef) -> Result<Option<uuid::Uuid>, ()>;
1996        #[cfg(feature = "serde")]
1997        fn try_get_json(&self, column: &impl ColumnRef) -> Result<Option<serde_json::Value>, ()>;
1998        #[cfg(feature = "chrono")]
1999        fn try_get_date(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveDate>, ()>;
2000        #[cfg(feature = "chrono")]
2001        fn try_get_time(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveTime>, ()>;
2002        #[cfg(feature = "chrono")]
2003        fn try_get_timestamp(
2004            &self,
2005            column: &impl ColumnRef,
2006        ) -> Result<Option<chrono::NaiveDateTime>, ()>;
2007        #[cfg(feature = "chrono")]
2008        fn try_get_timestamptz(
2009            &self,
2010            column: &impl ColumnRef,
2011        ) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, ()>;
2012        #[cfg(feature = "cidr")]
2013        fn try_get_inet(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpInet>, ()>;
2014        #[cfg(feature = "cidr")]
2015        fn try_get_cidr(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpCidr>, ()>;
2016        #[cfg(feature = "cidr")]
2017        fn try_get_macaddr(&self, column: &impl ColumnRef) -> Result<Option<[u8; 6]>, ()>;
2018        #[cfg(feature = "cidr")]
2019        fn try_get_macaddr8(&self, column: &impl ColumnRef) -> Result<Option<[u8; 8]>, ()>;
2020        #[cfg(feature = "geo-types")]
2021        fn try_get_point(
2022            &self,
2023            column: &impl ColumnRef,
2024        ) -> Result<Option<geo_types::Point<f64>>, ()>;
2025        #[cfg(feature = "geo-types")]
2026        fn try_get_linestring(
2027            &self,
2028            column: &impl ColumnRef,
2029        ) -> Result<Option<geo_types::LineString<f64>>, ()>;
2030        #[cfg(feature = "geo-types")]
2031        fn try_get_rect(&self, column: &impl ColumnRef)
2032        -> Result<Option<geo_types::Rect<f64>>, ()>;
2033        #[cfg(feature = "bit-vec")]
2034        fn try_get_bitvec(&self, column: &impl ColumnRef) -> Result<Option<bit_vec::BitVec>, ()>;
2035
2036        fn try_get_array_bool(
2037            &self,
2038            column: &impl ColumnRef,
2039        ) -> Result<Option<Vec<Option<bool>>>, ()>;
2040        fn try_get_array_i16(
2041            &self,
2042            column: &impl ColumnRef,
2043        ) -> Result<Option<Vec<Option<i16>>>, ()>;
2044        fn try_get_array_i32(
2045            &self,
2046            column: &impl ColumnRef,
2047        ) -> Result<Option<Vec<Option<i32>>>, ()>;
2048        fn try_get_array_i64(
2049            &self,
2050            column: &impl ColumnRef,
2051        ) -> Result<Option<Vec<Option<i64>>>, ()>;
2052        fn try_get_array_f32(
2053            &self,
2054            column: &impl ColumnRef,
2055        ) -> Result<Option<Vec<Option<f32>>>, ()>;
2056        fn try_get_array_f64(
2057            &self,
2058            column: &impl ColumnRef,
2059        ) -> Result<Option<Vec<Option<f64>>>, ()>;
2060        fn try_get_array_text(
2061            &self,
2062            column: &impl ColumnRef,
2063        ) -> Result<Option<Vec<Option<String>>>, ()>;
2064        fn try_get_array_bytes(
2065            &self,
2066            column: &impl ColumnRef,
2067        ) -> Result<Option<Vec<Option<Vec<u8>>>>, ()>;
2068        #[cfg(feature = "uuid")]
2069        fn try_get_array_uuid(
2070            &self,
2071            column: &impl ColumnRef,
2072        ) -> Result<Option<Vec<Option<uuid::Uuid>>>, ()>;
2073        #[cfg(feature = "serde")]
2074        fn try_get_array_json(
2075            &self,
2076            column: &impl ColumnRef,
2077        ) -> Result<Option<Vec<Option<serde_json::Value>>>, ()>;
2078        #[cfg(feature = "chrono")]
2079        fn try_get_array_date(
2080            &self,
2081            column: &impl ColumnRef,
2082        ) -> Result<Option<Vec<Option<chrono::NaiveDate>>>, ()>;
2083        #[cfg(feature = "chrono")]
2084        fn try_get_array_time(
2085            &self,
2086            column: &impl ColumnRef,
2087        ) -> Result<Option<Vec<Option<chrono::NaiveTime>>>, ()>;
2088        #[cfg(feature = "chrono")]
2089        fn try_get_array_timestamp(
2090            &self,
2091            column: &impl ColumnRef,
2092        ) -> Result<Option<Vec<Option<chrono::NaiveDateTime>>>, ()>;
2093        #[cfg(feature = "chrono")]
2094        fn try_get_array_timestamptz(
2095            &self,
2096            column: &impl ColumnRef,
2097        ) -> Result<Option<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>, ()>;
2098        #[cfg(feature = "cidr")]
2099        fn try_get_array_inet(
2100            &self,
2101            column: &impl ColumnRef,
2102        ) -> Result<Option<Vec<Option<cidr::IpInet>>>, ()>;
2103        #[cfg(feature = "cidr")]
2104        fn try_get_array_cidr(
2105            &self,
2106            column: &impl ColumnRef,
2107        ) -> Result<Option<Vec<Option<cidr::IpCidr>>>, ()>;
2108        #[cfg(feature = "cidr")]
2109        fn try_get_array_macaddr(
2110            &self,
2111            column: &impl ColumnRef,
2112        ) -> Result<Option<Vec<Option<[u8; 6]>>>, ()>;
2113        #[cfg(feature = "cidr")]
2114        fn try_get_array_macaddr8(
2115            &self,
2116            column: &impl ColumnRef,
2117        ) -> Result<Option<Vec<Option<[u8; 8]>>>, ()>;
2118        #[cfg(feature = "geo-types")]
2119        fn try_get_array_point(
2120            &self,
2121            column: &impl ColumnRef,
2122        ) -> Result<Option<Vec<Option<geo_types::Point<f64>>>>, ()>;
2123        #[cfg(feature = "geo-types")]
2124        fn try_get_array_linestring(
2125            &self,
2126            column: &impl ColumnRef,
2127        ) -> Result<Option<Vec<Option<geo_types::LineString<f64>>>>, ()>;
2128        #[cfg(feature = "geo-types")]
2129        fn try_get_array_rect(
2130            &self,
2131            column: &impl ColumnRef,
2132        ) -> Result<Option<Vec<Option<geo_types::Rect<f64>>>>, ()>;
2133        #[cfg(feature = "bit-vec")]
2134        fn try_get_array_bitvec(
2135            &self,
2136            column: &impl ColumnRef,
2137        ) -> Result<Option<Vec<Option<bit_vec::BitVec>>>, ()>;
2138    }
2139
2140    // Use tokio_postgres when available, postgres when not
2141    #[cfg(feature = "tokio-postgres")]
2142    impl PostgresRowLike for tokio_postgres::Row {
2143        fn type_oid(&self, column: &impl ColumnRef) -> Option<u32> {
2144            let idx = match (column.to_index(), column.to_name()) {
2145                (Some(idx), _) => idx,
2146                (None, Some(name)) => self.columns().iter().position(|c| c.name() == name)?,
2147                (None, None) => return None,
2148            };
2149
2150            self.columns().get(idx).map(|c| c.type_().oid())
2151        }
2152
2153        fn type_name(&self, column: &impl ColumnRef) -> Option<String> {
2154            let idx = match (column.to_index(), column.to_name()) {
2155                (Some(idx), _) => idx,
2156                (None, Some(name)) => self.columns().iter().position(|c| c.name() == name)?,
2157                (None, None) => return None,
2158            };
2159
2160            self.columns().get(idx).map(|c| c.type_().name().into())
2161        }
2162
2163        fn try_get_any<T: for<'a> crate::driver_types::FromSql<'a>>(
2164            &self,
2165            column: &impl ColumnRef,
2166        ) -> Result<Option<T>, ()> {
2167            try_get_typed!(self, column, T)
2168        }
2169
2170        fn try_get_bool(&self, column: &impl ColumnRef) -> Result<Option<bool>, ()> {
2171            try_get_typed!(self, column, bool)
2172        }
2173
2174        fn try_get_i16(&self, column: &impl ColumnRef) -> Result<Option<i16>, ()> {
2175            try_get_typed!(self, column, i16)
2176        }
2177
2178        fn try_get_i32(&self, column: &impl ColumnRef) -> Result<Option<i32>, ()> {
2179            try_get_typed!(self, column, i32)
2180        }
2181
2182        fn try_get_i64(&self, column: &impl ColumnRef) -> Result<Option<i64>, ()> {
2183            try_get_typed!(self, column, i64)
2184        }
2185
2186        fn try_get_f32(&self, column: &impl ColumnRef) -> Result<Option<f32>, ()> {
2187            try_get_typed!(self, column, f32)
2188        }
2189
2190        fn try_get_f64(&self, column: &impl ColumnRef) -> Result<Option<f64>, ()> {
2191            try_get_typed!(self, column, f64)
2192        }
2193
2194        fn try_get_string(&self, column: &impl ColumnRef) -> Result<Option<String>, ()> {
2195            try_get_typed!(self, column, String)
2196        }
2197
2198        fn try_get_bytes(&self, column: &impl ColumnRef) -> Result<Option<Vec<u8>>, ()> {
2199            try_get_typed!(self, column, Vec<u8>)
2200        }
2201
2202        #[cfg(feature = "uuid")]
2203        fn try_get_uuid(&self, column: &impl ColumnRef) -> Result<Option<uuid::Uuid>, ()> {
2204            try_get_typed!(self, column, uuid::Uuid)
2205        }
2206
2207        #[cfg(feature = "serde")]
2208        fn try_get_json(&self, column: &impl ColumnRef) -> Result<Option<serde_json::Value>, ()> {
2209            try_get_typed!(self, column, serde_json::Value)
2210        }
2211
2212        #[cfg(feature = "chrono")]
2213        fn try_get_date(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveDate>, ()> {
2214            try_get_typed!(self, column, chrono::NaiveDate)
2215        }
2216
2217        #[cfg(feature = "chrono")]
2218        fn try_get_time(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveTime>, ()> {
2219            try_get_typed!(self, column, chrono::NaiveTime)
2220        }
2221
2222        #[cfg(feature = "chrono")]
2223        fn try_get_timestamp(
2224            &self,
2225            column: &impl ColumnRef,
2226        ) -> Result<Option<chrono::NaiveDateTime>, ()> {
2227            try_get_typed!(self, column, chrono::NaiveDateTime)
2228        }
2229
2230        #[cfg(feature = "chrono")]
2231        fn try_get_timestamptz(
2232            &self,
2233            column: &impl ColumnRef,
2234        ) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, ()> {
2235            try_get_typed!(self, column, chrono::DateTime<chrono::FixedOffset>)
2236        }
2237
2238        #[cfg(feature = "cidr")]
2239        fn try_get_inet(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpInet>, ()> {
2240            try_get_typed!(self, column, cidr::IpInet)
2241        }
2242
2243        #[cfg(feature = "cidr")]
2244        fn try_get_cidr(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpCidr>, ()> {
2245            try_get_typed!(self, column, cidr::IpCidr)
2246        }
2247
2248        #[cfg(feature = "cidr")]
2249        fn try_get_macaddr(&self, column: &impl ColumnRef) -> Result<Option<[u8; 6]>, ()> {
2250            match self.try_get_string(column) {
2251                Ok(Some(value)) => parse_mac::<6>(&value).ok_or(()).map(Some),
2252                Ok(None) => Ok(None),
2253                Err(()) => Err(()),
2254            }
2255        }
2256
2257        #[cfg(feature = "cidr")]
2258        fn try_get_macaddr8(&self, column: &impl ColumnRef) -> Result<Option<[u8; 8]>, ()> {
2259            match self.try_get_string(column) {
2260                Ok(Some(value)) => parse_mac::<8>(&value).ok_or(()).map(Some),
2261                Ok(None) => Ok(None),
2262                Err(()) => Err(()),
2263            }
2264        }
2265
2266        #[cfg(feature = "geo-types")]
2267        fn try_get_point(
2268            &self,
2269            column: &impl ColumnRef,
2270        ) -> Result<Option<geo_types::Point<f64>>, ()> {
2271            try_get_typed!(self, column, geo_types::Point<f64>)
2272        }
2273
2274        #[cfg(feature = "geo-types")]
2275        fn try_get_linestring(
2276            &self,
2277            column: &impl ColumnRef,
2278        ) -> Result<Option<geo_types::LineString<f64>>, ()> {
2279            try_get_typed!(self, column, geo_types::LineString<f64>)
2280        }
2281
2282        #[cfg(feature = "geo-types")]
2283        fn try_get_rect(
2284            &self,
2285            column: &impl ColumnRef,
2286        ) -> Result<Option<geo_types::Rect<f64>>, ()> {
2287            try_get_typed!(self, column, geo_types::Rect<f64>)
2288        }
2289
2290        #[cfg(feature = "bit-vec")]
2291        fn try_get_bitvec(&self, column: &impl ColumnRef) -> Result<Option<bit_vec::BitVec>, ()> {
2292            try_get_typed!(self, column, bit_vec::BitVec)
2293        }
2294
2295        fn try_get_array_bool(
2296            &self,
2297            column: &impl ColumnRef,
2298        ) -> Result<Option<Vec<Option<bool>>>, ()> {
2299            try_get_typed!(self, column, Vec<Option<bool>>)
2300        }
2301
2302        fn try_get_array_i16(
2303            &self,
2304            column: &impl ColumnRef,
2305        ) -> Result<Option<Vec<Option<i16>>>, ()> {
2306            try_get_typed!(self, column, Vec<Option<i16>>)
2307        }
2308
2309        fn try_get_array_i32(
2310            &self,
2311            column: &impl ColumnRef,
2312        ) -> Result<Option<Vec<Option<i32>>>, ()> {
2313            try_get_typed!(self, column, Vec<Option<i32>>)
2314        }
2315
2316        fn try_get_array_i64(
2317            &self,
2318            column: &impl ColumnRef,
2319        ) -> Result<Option<Vec<Option<i64>>>, ()> {
2320            try_get_typed!(self, column, Vec<Option<i64>>)
2321        }
2322
2323        fn try_get_array_f32(
2324            &self,
2325            column: &impl ColumnRef,
2326        ) -> Result<Option<Vec<Option<f32>>>, ()> {
2327            try_get_typed!(self, column, Vec<Option<f32>>)
2328        }
2329
2330        fn try_get_array_f64(
2331            &self,
2332            column: &impl ColumnRef,
2333        ) -> Result<Option<Vec<Option<f64>>>, ()> {
2334            try_get_typed!(self, column, Vec<Option<f64>>)
2335        }
2336
2337        fn try_get_array_text(
2338            &self,
2339            column: &impl ColumnRef,
2340        ) -> Result<Option<Vec<Option<String>>>, ()> {
2341            try_get_typed!(self, column, Vec<Option<String>>)
2342        }
2343
2344        fn try_get_array_bytes(
2345            &self,
2346            column: &impl ColumnRef,
2347        ) -> Result<Option<Vec<Option<Vec<u8>>>>, ()> {
2348            try_get_typed!(self, column, Vec<Option<Vec<u8>>>)
2349        }
2350
2351        #[cfg(feature = "uuid")]
2352        fn try_get_array_uuid(
2353            &self,
2354            column: &impl ColumnRef,
2355        ) -> Result<Option<Vec<Option<uuid::Uuid>>>, ()> {
2356            try_get_typed!(self, column, Vec<Option<uuid::Uuid>>)
2357        }
2358
2359        #[cfg(feature = "serde")]
2360        fn try_get_array_json(
2361            &self,
2362            column: &impl ColumnRef,
2363        ) -> Result<Option<Vec<Option<serde_json::Value>>>, ()> {
2364            try_get_typed!(self, column, Vec<Option<serde_json::Value>>)
2365        }
2366
2367        #[cfg(feature = "chrono")]
2368        fn try_get_array_date(
2369            &self,
2370            column: &impl ColumnRef,
2371        ) -> Result<Option<Vec<Option<chrono::NaiveDate>>>, ()> {
2372            try_get_typed!(self, column, Vec<Option<chrono::NaiveDate>>)
2373        }
2374
2375        #[cfg(feature = "chrono")]
2376        fn try_get_array_time(
2377            &self,
2378            column: &impl ColumnRef,
2379        ) -> Result<Option<Vec<Option<chrono::NaiveTime>>>, ()> {
2380            try_get_typed!(self, column, Vec<Option<chrono::NaiveTime>>)
2381        }
2382
2383        #[cfg(feature = "chrono")]
2384        fn try_get_array_timestamp(
2385            &self,
2386            column: &impl ColumnRef,
2387        ) -> Result<Option<Vec<Option<chrono::NaiveDateTime>>>, ()> {
2388            try_get_typed!(self, column, Vec<Option<chrono::NaiveDateTime>>)
2389        }
2390
2391        #[cfg(feature = "chrono")]
2392        fn try_get_array_timestamptz(
2393            &self,
2394            column: &impl ColumnRef,
2395        ) -> Result<Option<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>, ()> {
2396            try_get_typed!(
2397                self,
2398                column,
2399                Vec<Option<chrono::DateTime<chrono::FixedOffset>>>
2400            )
2401        }
2402
2403        #[cfg(feature = "cidr")]
2404        fn try_get_array_inet(
2405            &self,
2406            column: &impl ColumnRef,
2407        ) -> Result<Option<Vec<Option<cidr::IpInet>>>, ()> {
2408            try_get_typed!(self, column, Vec<Option<cidr::IpInet>>)
2409        }
2410
2411        #[cfg(feature = "cidr")]
2412        fn try_get_array_cidr(
2413            &self,
2414            column: &impl ColumnRef,
2415        ) -> Result<Option<Vec<Option<cidr::IpCidr>>>, ()> {
2416            try_get_typed!(self, column, Vec<Option<cidr::IpCidr>>)
2417        }
2418
2419        #[cfg(feature = "cidr")]
2420        fn try_get_array_macaddr(
2421            &self,
2422            column: &impl ColumnRef,
2423        ) -> Result<Option<Vec<Option<[u8; 6]>>>, ()> {
2424            match self.try_get_array_text(column) {
2425                Ok(Some(values)) => parse_mac_array::<6>(values).map(Some),
2426                Ok(None) => Ok(None),
2427                Err(()) => Err(()),
2428            }
2429        }
2430
2431        #[cfg(feature = "cidr")]
2432        fn try_get_array_macaddr8(
2433            &self,
2434            column: &impl ColumnRef,
2435        ) -> Result<Option<Vec<Option<[u8; 8]>>>, ()> {
2436            match self.try_get_array_text(column) {
2437                Ok(Some(values)) => parse_mac_array::<8>(values).map(Some),
2438                Ok(None) => Ok(None),
2439                Err(()) => Err(()),
2440            }
2441        }
2442
2443        #[cfg(feature = "geo-types")]
2444        fn try_get_array_point(
2445            &self,
2446            column: &impl ColumnRef,
2447        ) -> Result<Option<Vec<Option<geo_types::Point<f64>>>>, ()> {
2448            try_get_typed!(self, column, Vec<Option<geo_types::Point<f64>>>)
2449        }
2450
2451        #[cfg(feature = "geo-types")]
2452        fn try_get_array_linestring(
2453            &self,
2454            column: &impl ColumnRef,
2455        ) -> Result<Option<Vec<Option<geo_types::LineString<f64>>>>, ()> {
2456            try_get_typed!(self, column, Vec<Option<geo_types::LineString<f64>>>)
2457        }
2458
2459        #[cfg(feature = "geo-types")]
2460        fn try_get_array_rect(
2461            &self,
2462            column: &impl ColumnRef,
2463        ) -> Result<Option<Vec<Option<geo_types::Rect<f64>>>>, ()> {
2464            try_get_typed!(self, column, Vec<Option<geo_types::Rect<f64>>>)
2465        }
2466
2467        #[cfg(feature = "bit-vec")]
2468        fn try_get_array_bitvec(
2469            &self,
2470            column: &impl ColumnRef,
2471        ) -> Result<Option<Vec<Option<bit_vec::BitVec>>>, ()> {
2472            try_get_typed!(self, column, Vec<Option<bit_vec::BitVec>>)
2473        }
2474    }
2475
2476    #[cfg(feature = "tokio-postgres")]
2477    impl DrizzleRowByIndex for tokio_postgres::Row {
2478        fn get_column<T: FromPostgresValue>(&self, idx: usize) -> Result<T, DrizzleError> {
2479            convert_column(self, idx)
2480        }
2481    }
2482
2483    #[cfg(feature = "tokio-postgres")]
2484    impl DrizzleRowByName for tokio_postgres::Row {
2485        fn get_column_by_name<T: FromPostgresValue>(&self, name: &str) -> Result<T, DrizzleError> {
2486            convert_column(self, name)
2487        }
2488    }
2489
2490    // postgres::Row is a re-export of tokio_postgres::Row, so when both features
2491    // are enabled, this implementation applies to both. When only postgres-sync
2492    // is enabled, we need a separate implementation.
2493    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
2494    impl PostgresRowLike for postgres::Row {
2495        fn type_oid(&self, column: &impl ColumnRef) -> Option<u32> {
2496            let idx = match (column.to_index(), column.to_name()) {
2497                (Some(idx), _) => idx,
2498                (None, Some(name)) => self.columns().iter().position(|c| c.name() == name)?,
2499                (None, None) => return None,
2500            };
2501
2502            self.columns().get(idx).map(|c| c.type_().oid())
2503        }
2504
2505        fn type_name(&self, column: &impl ColumnRef) -> Option<String> {
2506            let idx = match (column.to_index(), column.to_name()) {
2507                (Some(idx), _) => idx,
2508                (None, Some(name)) => self.columns().iter().position(|c| c.name() == name)?,
2509                (None, None) => return None,
2510            };
2511
2512            self.columns().get(idx).map(|c| c.type_().name().into())
2513        }
2514
2515        fn try_get_any<T: for<'a> crate::driver_types::FromSql<'a>>(
2516            &self,
2517            column: &impl ColumnRef,
2518        ) -> Result<Option<T>, ()> {
2519            try_get_typed!(self, column, T)
2520        }
2521
2522        fn try_get_bool(&self, column: &impl ColumnRef) -> Result<Option<bool>, ()> {
2523            try_get_typed!(self, column, bool)
2524        }
2525
2526        fn try_get_i16(&self, column: &impl ColumnRef) -> Result<Option<i16>, ()> {
2527            try_get_typed!(self, column, i16)
2528        }
2529
2530        fn try_get_i32(&self, column: &impl ColumnRef) -> Result<Option<i32>, ()> {
2531            try_get_typed!(self, column, i32)
2532        }
2533
2534        fn try_get_i64(&self, column: &impl ColumnRef) -> Result<Option<i64>, ()> {
2535            try_get_typed!(self, column, i64)
2536        }
2537
2538        fn try_get_f32(&self, column: &impl ColumnRef) -> Result<Option<f32>, ()> {
2539            try_get_typed!(self, column, f32)
2540        }
2541
2542        fn try_get_f64(&self, column: &impl ColumnRef) -> Result<Option<f64>, ()> {
2543            try_get_typed!(self, column, f64)
2544        }
2545
2546        fn try_get_string(&self, column: &impl ColumnRef) -> Result<Option<String>, ()> {
2547            try_get_typed!(self, column, String)
2548        }
2549
2550        fn try_get_bytes(&self, column: &impl ColumnRef) -> Result<Option<Vec<u8>>, ()> {
2551            try_get_typed!(self, column, Vec<u8>)
2552        }
2553
2554        #[cfg(feature = "uuid")]
2555        fn try_get_uuid(&self, column: &impl ColumnRef) -> Result<Option<uuid::Uuid>, ()> {
2556            try_get_typed!(self, column, uuid::Uuid)
2557        }
2558
2559        #[cfg(feature = "serde")]
2560        fn try_get_json(&self, column: &impl ColumnRef) -> Result<Option<serde_json::Value>, ()> {
2561            try_get_typed!(self, column, serde_json::Value)
2562        }
2563
2564        #[cfg(feature = "chrono")]
2565        fn try_get_date(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveDate>, ()> {
2566            try_get_typed!(self, column, chrono::NaiveDate)
2567        }
2568
2569        #[cfg(feature = "chrono")]
2570        fn try_get_time(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveTime>, ()> {
2571            try_get_typed!(self, column, chrono::NaiveTime)
2572        }
2573
2574        #[cfg(feature = "chrono")]
2575        fn try_get_timestamp(
2576            &self,
2577            column: &impl ColumnRef,
2578        ) -> Result<Option<chrono::NaiveDateTime>, ()> {
2579            try_get_typed!(self, column, chrono::NaiveDateTime)
2580        }
2581
2582        #[cfg(feature = "chrono")]
2583        fn try_get_timestamptz(
2584            &self,
2585            column: &impl ColumnRef,
2586        ) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, ()> {
2587            try_get_typed!(self, column, chrono::DateTime<chrono::FixedOffset>)
2588        }
2589
2590        #[cfg(feature = "cidr")]
2591        fn try_get_inet(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpInet>, ()> {
2592            try_get_typed!(self, column, cidr::IpInet)
2593        }
2594
2595        #[cfg(feature = "cidr")]
2596        fn try_get_cidr(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpCidr>, ()> {
2597            try_get_typed!(self, column, cidr::IpCidr)
2598        }
2599
2600        #[cfg(feature = "cidr")]
2601        fn try_get_macaddr(&self, column: &impl ColumnRef) -> Result<Option<[u8; 6]>, ()> {
2602            match self.try_get_string(column) {
2603                Ok(Some(value)) => parse_mac::<6>(&value).ok_or(()).map(Some),
2604                Ok(None) => Ok(None),
2605                Err(()) => Err(()),
2606            }
2607        }
2608
2609        #[cfg(feature = "cidr")]
2610        fn try_get_macaddr8(&self, column: &impl ColumnRef) -> Result<Option<[u8; 8]>, ()> {
2611            match self.try_get_string(column) {
2612                Ok(Some(value)) => parse_mac::<8>(&value).ok_or(()).map(Some),
2613                Ok(None) => Ok(None),
2614                Err(()) => Err(()),
2615            }
2616        }
2617
2618        #[cfg(feature = "geo-types")]
2619        fn try_get_point(
2620            &self,
2621            column: &impl ColumnRef,
2622        ) -> Result<Option<geo_types::Point<f64>>, ()> {
2623            try_get_typed!(self, column, geo_types::Point<f64>)
2624        }
2625
2626        #[cfg(feature = "geo-types")]
2627        fn try_get_linestring(
2628            &self,
2629            column: &impl ColumnRef,
2630        ) -> Result<Option<geo_types::LineString<f64>>, ()> {
2631            try_get_typed!(self, column, geo_types::LineString<f64>)
2632        }
2633
2634        #[cfg(feature = "geo-types")]
2635        fn try_get_rect(
2636            &self,
2637            column: &impl ColumnRef,
2638        ) -> Result<Option<geo_types::Rect<f64>>, ()> {
2639            try_get_typed!(self, column, geo_types::Rect<f64>)
2640        }
2641
2642        #[cfg(feature = "bit-vec")]
2643        fn try_get_bitvec(&self, column: &impl ColumnRef) -> Result<Option<bit_vec::BitVec>, ()> {
2644            try_get_typed!(self, column, bit_vec::BitVec)
2645        }
2646
2647        fn try_get_array_bool(
2648            &self,
2649            column: &impl ColumnRef,
2650        ) -> Result<Option<Vec<Option<bool>>>, ()> {
2651            try_get_typed!(self, column, Vec<Option<bool>>)
2652        }
2653
2654        fn try_get_array_i16(
2655            &self,
2656            column: &impl ColumnRef,
2657        ) -> Result<Option<Vec<Option<i16>>>, ()> {
2658            try_get_typed!(self, column, Vec<Option<i16>>)
2659        }
2660
2661        fn try_get_array_i32(
2662            &self,
2663            column: &impl ColumnRef,
2664        ) -> Result<Option<Vec<Option<i32>>>, ()> {
2665            try_get_typed!(self, column, Vec<Option<i32>>)
2666        }
2667
2668        fn try_get_array_i64(
2669            &self,
2670            column: &impl ColumnRef,
2671        ) -> Result<Option<Vec<Option<i64>>>, ()> {
2672            try_get_typed!(self, column, Vec<Option<i64>>)
2673        }
2674
2675        fn try_get_array_f32(
2676            &self,
2677            column: &impl ColumnRef,
2678        ) -> Result<Option<Vec<Option<f32>>>, ()> {
2679            try_get_typed!(self, column, Vec<Option<f32>>)
2680        }
2681
2682        fn try_get_array_f64(
2683            &self,
2684            column: &impl ColumnRef,
2685        ) -> Result<Option<Vec<Option<f64>>>, ()> {
2686            try_get_typed!(self, column, Vec<Option<f64>>)
2687        }
2688
2689        fn try_get_array_text(
2690            &self,
2691            column: &impl ColumnRef,
2692        ) -> Result<Option<Vec<Option<String>>>, ()> {
2693            try_get_typed!(self, column, Vec<Option<String>>)
2694        }
2695
2696        fn try_get_array_bytes(
2697            &self,
2698            column: &impl ColumnRef,
2699        ) -> Result<Option<Vec<Option<Vec<u8>>>>, ()> {
2700            try_get_typed!(self, column, Vec<Option<Vec<u8>>>)
2701        }
2702
2703        #[cfg(feature = "uuid")]
2704        fn try_get_array_uuid(
2705            &self,
2706            column: &impl ColumnRef,
2707        ) -> Result<Option<Vec<Option<uuid::Uuid>>>, ()> {
2708            try_get_typed!(self, column, Vec<Option<uuid::Uuid>>)
2709        }
2710
2711        #[cfg(feature = "serde")]
2712        fn try_get_array_json(
2713            &self,
2714            column: &impl ColumnRef,
2715        ) -> Result<Option<Vec<Option<serde_json::Value>>>, ()> {
2716            try_get_typed!(self, column, Vec<Option<serde_json::Value>>)
2717        }
2718
2719        #[cfg(feature = "chrono")]
2720        fn try_get_array_date(
2721            &self,
2722            column: &impl ColumnRef,
2723        ) -> Result<Option<Vec<Option<chrono::NaiveDate>>>, ()> {
2724            try_get_typed!(self, column, Vec<Option<chrono::NaiveDate>>)
2725        }
2726
2727        #[cfg(feature = "chrono")]
2728        fn try_get_array_time(
2729            &self,
2730            column: &impl ColumnRef,
2731        ) -> Result<Option<Vec<Option<chrono::NaiveTime>>>, ()> {
2732            try_get_typed!(self, column, Vec<Option<chrono::NaiveTime>>)
2733        }
2734
2735        #[cfg(feature = "chrono")]
2736        fn try_get_array_timestamp(
2737            &self,
2738            column: &impl ColumnRef,
2739        ) -> Result<Option<Vec<Option<chrono::NaiveDateTime>>>, ()> {
2740            try_get_typed!(self, column, Vec<Option<chrono::NaiveDateTime>>)
2741        }
2742
2743        #[cfg(feature = "chrono")]
2744        fn try_get_array_timestamptz(
2745            &self,
2746            column: &impl ColumnRef,
2747        ) -> Result<Option<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>, ()> {
2748            try_get_typed!(
2749                self,
2750                column,
2751                Vec<Option<chrono::DateTime<chrono::FixedOffset>>>
2752            )
2753        }
2754
2755        #[cfg(feature = "cidr")]
2756        fn try_get_array_inet(
2757            &self,
2758            column: &impl ColumnRef,
2759        ) -> Result<Option<Vec<Option<cidr::IpInet>>>, ()> {
2760            try_get_typed!(self, column, Vec<Option<cidr::IpInet>>)
2761        }
2762
2763        #[cfg(feature = "cidr")]
2764        fn try_get_array_cidr(
2765            &self,
2766            column: &impl ColumnRef,
2767        ) -> Result<Option<Vec<Option<cidr::IpCidr>>>, ()> {
2768            try_get_typed!(self, column, Vec<Option<cidr::IpCidr>>)
2769        }
2770
2771        #[cfg(feature = "cidr")]
2772        fn try_get_array_macaddr(
2773            &self,
2774            column: &impl ColumnRef,
2775        ) -> Result<Option<Vec<Option<[u8; 6]>>>, ()> {
2776            match self.try_get_array_text(column) {
2777                Ok(Some(values)) => parse_mac_array::<6>(values).map(Some),
2778                Ok(None) => Ok(None),
2779                Err(()) => Err(()),
2780            }
2781        }
2782
2783        #[cfg(feature = "cidr")]
2784        fn try_get_array_macaddr8(
2785            &self,
2786            column: &impl ColumnRef,
2787        ) -> Result<Option<Vec<Option<[u8; 8]>>>, ()> {
2788            match self.try_get_array_text(column) {
2789                Ok(Some(values)) => parse_mac_array::<8>(values).map(Some),
2790                Ok(None) => Ok(None),
2791                Err(()) => Err(()),
2792            }
2793        }
2794
2795        #[cfg(feature = "geo-types")]
2796        fn try_get_array_point(
2797            &self,
2798            column: &impl ColumnRef,
2799        ) -> Result<Option<Vec<Option<geo_types::Point<f64>>>>, ()> {
2800            try_get_typed!(self, column, Vec<Option<geo_types::Point<f64>>>)
2801        }
2802
2803        #[cfg(feature = "geo-types")]
2804        fn try_get_array_linestring(
2805            &self,
2806            column: &impl ColumnRef,
2807        ) -> Result<Option<Vec<Option<geo_types::LineString<f64>>>>, ()> {
2808            try_get_typed!(self, column, Vec<Option<geo_types::LineString<f64>>>)
2809        }
2810
2811        #[cfg(feature = "geo-types")]
2812        fn try_get_array_rect(
2813            &self,
2814            column: &impl ColumnRef,
2815        ) -> Result<Option<Vec<Option<geo_types::Rect<f64>>>>, ()> {
2816            try_get_typed!(self, column, Vec<Option<geo_types::Rect<f64>>>)
2817        }
2818
2819        #[cfg(feature = "bit-vec")]
2820        fn try_get_array_bitvec(
2821            &self,
2822            column: &impl ColumnRef,
2823        ) -> Result<Option<Vec<Option<bit_vec::BitVec>>>, ()> {
2824            try_get_typed!(self, column, Vec<Option<bit_vec::BitVec>>)
2825        }
2826    }
2827
2828    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
2829    impl DrizzleRowByIndex for postgres::Row {
2830        fn get_column<T: FromPostgresValue>(&self, idx: usize) -> Result<T, DrizzleError> {
2831            convert_column(self, idx)
2832        }
2833    }
2834
2835    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
2836    impl DrizzleRowByName for postgres::Row {
2837        fn get_column_by_name<T: FromPostgresValue>(&self, name: &str) -> Result<T, DrizzleError> {
2838            convert_column(self, name)
2839        }
2840    }
2841}
2842
2843// =============================================================================
2844// UUID support (when feature enabled)
2845// =============================================================================
2846
2847#[cfg(feature = "uuid")]
2848impl FromPostgresValue for uuid::Uuid {
2849    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
2850        Err(DrizzleError::ConversionError(
2851            "cannot convert bool to UUID".into(),
2852        ))
2853    }
2854
2855    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
2856        Err(DrizzleError::ConversionError(
2857            "cannot convert i16 to UUID".into(),
2858        ))
2859    }
2860
2861    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
2862        Err(DrizzleError::ConversionError(
2863            "cannot convert i32 to UUID".into(),
2864        ))
2865    }
2866
2867    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
2868        Err(DrizzleError::ConversionError(
2869            "cannot convert i64 to UUID".into(),
2870        ))
2871    }
2872
2873    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
2874        Err(DrizzleError::ConversionError(
2875            "cannot convert f32 to UUID".into(),
2876        ))
2877    }
2878
2879    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
2880        Err(DrizzleError::ConversionError(
2881            "cannot convert f64 to UUID".into(),
2882        ))
2883    }
2884
2885    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
2886        Self::parse_str(value).map_err(|e| {
2887            DrizzleError::ConversionError(format!("invalid UUID string '{value}': {e}").into())
2888        })
2889    }
2890
2891    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
2892        Self::from_slice(value)
2893            .map_err(|e| DrizzleError::ConversionError(format!("invalid UUID bytes: {e}").into()))
2894    }
2895
2896    fn from_postgres_uuid(value: uuid::Uuid) -> Result<Self, DrizzleError> {
2897        Ok(value)
2898    }
2899}
2900
2901macro_rules! impl_from_postgres_value_errors {
2902    ($target:expr) => {
2903        fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
2904            Err(DrizzleError::ConversionError(
2905                format!("cannot convert bool to {}", $target).into(),
2906            ))
2907        }
2908
2909        fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
2910            Err(DrizzleError::ConversionError(
2911                format!("cannot convert i16 to {}", $target).into(),
2912            ))
2913        }
2914
2915        fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
2916            Err(DrizzleError::ConversionError(
2917                format!("cannot convert i32 to {}", $target).into(),
2918            ))
2919        }
2920
2921        fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
2922            Err(DrizzleError::ConversionError(
2923                format!("cannot convert i64 to {}", $target).into(),
2924            ))
2925        }
2926
2927        fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
2928            Err(DrizzleError::ConversionError(
2929                format!("cannot convert f32 to {}", $target).into(),
2930            ))
2931        }
2932
2933        fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
2934            Err(DrizzleError::ConversionError(
2935                format!("cannot convert f64 to {}", $target).into(),
2936            ))
2937        }
2938
2939        fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
2940            Err(DrizzleError::ConversionError(
2941                format!("cannot convert text to {}", $target).into(),
2942            ))
2943        }
2944
2945        fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
2946            Err(DrizzleError::ConversionError(
2947                format!("cannot convert bytes to {}", $target).into(),
2948            ))
2949        }
2950    };
2951}
2952
2953// =============================================================================
2954// PostgresEnum support
2955// =============================================================================
2956
2957impl<T> FromPostgresValue for T
2958where
2959    T: super::PostgresEnum,
2960{
2961    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
2962        Err(DrizzleError::ConversionError(
2963            "cannot convert bool to PostgresEnum".into(),
2964        ))
2965    }
2966
2967    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
2968        Err(DrizzleError::ConversionError(
2969            "cannot convert i16 to PostgresEnum".into(),
2970        ))
2971    }
2972
2973    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
2974        Err(DrizzleError::ConversionError(
2975            "cannot convert i32 to PostgresEnum".into(),
2976        ))
2977    }
2978
2979    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
2980        Err(DrizzleError::ConversionError(
2981            "cannot convert i64 to PostgresEnum".into(),
2982        ))
2983    }
2984
2985    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
2986        Err(DrizzleError::ConversionError(
2987            "cannot convert f32 to PostgresEnum".into(),
2988        ))
2989    }
2990
2991    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
2992        Err(DrizzleError::ConversionError(
2993            "cannot convert f64 to PostgresEnum".into(),
2994        ))
2995    }
2996
2997    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
2998        T::try_from_str(value)
2999    }
3000
3001    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3002        let s = core::str::from_utf8(value).map_err(|e| {
3003            DrizzleError::ConversionError(format!("invalid UTF-8 for enum: {e}").into())
3004        })?;
3005        T::try_from_str(s)
3006    }
3007}
3008
3009// =============================================================================
3010// ARRAY support
3011// =============================================================================
3012
3013impl FromPostgresValue for Vec<PostgresValue<'_>> {
3014    impl_from_postgres_value_errors!("ARRAY");
3015
3016    fn from_postgres_array(value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
3017        let values = value
3018            .into_iter()
3019            .map(OwnedPostgresValue::from)
3020            .map(PostgresValue::from)
3021            .collect();
3022        Ok(values)
3023    }
3024}
3025
3026impl FromPostgresValue for Vec<OwnedPostgresValue> {
3027    impl_from_postgres_value_errors!("ARRAY");
3028
3029    fn from_postgres_array(value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
3030        Ok(value.into_iter().map(OwnedPostgresValue::from).collect())
3031    }
3032}
3033
3034// =============================================================================
3035// JSON support (when feature enabled)
3036// =============================================================================
3037
3038#[cfg(feature = "serde")]
3039impl FromPostgresValue for serde_json::Value {
3040    impl_from_postgres_value_errors!("JSON");
3041
3042    fn from_postgres_json(value: serde_json::Value) -> Result<Self, DrizzleError> {
3043        Ok(value)
3044    }
3045
3046    fn from_postgres_jsonb(value: serde_json::Value) -> Result<Self, DrizzleError> {
3047        Ok(value)
3048    }
3049}
3050
3051// =============================================================================
3052// Chrono support (when feature enabled)
3053// =============================================================================
3054
3055#[cfg(feature = "chrono")]
3056impl FromPostgresValue for chrono::NaiveDate {
3057    impl_from_postgres_value_errors!("NaiveDate");
3058
3059    fn from_postgres_date(value: chrono::NaiveDate) -> Result<Self, DrizzleError> {
3060        Ok(value)
3061    }
3062}
3063
3064#[cfg(feature = "chrono")]
3065impl FromPostgresValue for chrono::NaiveTime {
3066    impl_from_postgres_value_errors!("NaiveTime");
3067
3068    fn from_postgres_time(value: chrono::NaiveTime) -> Result<Self, DrizzleError> {
3069        Ok(value)
3070    }
3071}
3072
3073#[cfg(feature = "chrono")]
3074impl FromPostgresValue for chrono::NaiveDateTime {
3075    impl_from_postgres_value_errors!("NaiveDateTime");
3076
3077    fn from_postgres_timestamp(value: chrono::NaiveDateTime) -> Result<Self, DrizzleError> {
3078        Ok(value)
3079    }
3080}
3081
3082#[cfg(feature = "chrono")]
3083impl FromPostgresValue for chrono::DateTime<chrono::FixedOffset> {
3084    impl_from_postgres_value_errors!("DateTime<FixedOffset>");
3085
3086    fn from_postgres_timestamptz(
3087        value: chrono::DateTime<chrono::FixedOffset>,
3088    ) -> Result<Self, DrizzleError> {
3089        Ok(value)
3090    }
3091}
3092
3093#[cfg(feature = "chrono")]
3094impl FromPostgresValue for chrono::DateTime<chrono::Utc> {
3095    impl_from_postgres_value_errors!("DateTime<Utc>");
3096
3097    fn from_postgres_timestamptz(
3098        value: chrono::DateTime<chrono::FixedOffset>,
3099    ) -> Result<Self, DrizzleError> {
3100        Ok(value.with_timezone(&chrono::Utc))
3101    }
3102}
3103
3104#[cfg(feature = "chrono")]
3105impl FromPostgresValue for chrono::Duration {
3106    impl_from_postgres_value_errors!("Duration");
3107
3108    fn from_postgres_interval(value: chrono::Duration) -> Result<Self, DrizzleError> {
3109        Ok(value)
3110    }
3111}
3112
3113// =============================================================================
3114// Time crate support (when feature enabled)
3115// =============================================================================
3116
3117#[cfg(feature = "time")]
3118impl FromPostgresValue for time::Date {
3119    impl_from_postgres_value_errors!("time::Date");
3120
3121    fn from_postgres_time_date(value: time::Date) -> Result<Self, DrizzleError> {
3122        Ok(value)
3123    }
3124}
3125
3126#[cfg(feature = "time")]
3127impl FromPostgresValue for time::Time {
3128    impl_from_postgres_value_errors!("time::Time");
3129
3130    fn from_postgres_time_time(value: time::Time) -> Result<Self, DrizzleError> {
3131        Ok(value)
3132    }
3133}
3134
3135#[cfg(feature = "time")]
3136impl FromPostgresValue for time::PrimitiveDateTime {
3137    impl_from_postgres_value_errors!("time::PrimitiveDateTime");
3138
3139    fn from_postgres_time_timestamp(value: time::PrimitiveDateTime) -> Result<Self, DrizzleError> {
3140        Ok(value)
3141    }
3142}
3143
3144#[cfg(feature = "time")]
3145impl FromPostgresValue for time::OffsetDateTime {
3146    impl_from_postgres_value_errors!("time::OffsetDateTime");
3147
3148    fn from_postgres_time_timestamptz(value: time::OffsetDateTime) -> Result<Self, DrizzleError> {
3149        Ok(value)
3150    }
3151}
3152
3153#[cfg(feature = "time")]
3154impl FromPostgresValue for time::Duration {
3155    impl_from_postgres_value_errors!("time::Duration");
3156
3157    fn from_postgres_time_interval(value: time::Duration) -> Result<Self, DrizzleError> {
3158        Ok(value)
3159    }
3160}
3161
3162#[cfg(feature = "jiff")]
3163impl FromPostgresValue for jiff::civil::Date {
3164    impl_from_postgres_value_errors!("jiff::civil::Date");
3165
3166    fn from_postgres_jiff_date(value: jiff::civil::Date) -> Result<Self, DrizzleError> {
3167        Ok(value)
3168    }
3169}
3170
3171#[cfg(feature = "jiff")]
3172impl FromPostgresValue for jiff::civil::Time {
3173    impl_from_postgres_value_errors!("jiff::civil::Time");
3174
3175    fn from_postgres_jiff_time(value: jiff::civil::Time) -> Result<Self, DrizzleError> {
3176        Ok(value)
3177    }
3178}
3179
3180#[cfg(feature = "jiff")]
3181impl FromPostgresValue for jiff::civil::DateTime {
3182    impl_from_postgres_value_errors!("jiff::civil::DateTime");
3183
3184    fn from_postgres_jiff_datetime(value: jiff::civil::DateTime) -> Result<Self, DrizzleError> {
3185        Ok(value)
3186    }
3187}
3188
3189#[cfg(feature = "jiff")]
3190impl FromPostgresValue for jiff::Timestamp {
3191    impl_from_postgres_value_errors!("jiff::Timestamp");
3192
3193    fn from_postgres_jiff_timestamp(value: jiff::Timestamp) -> Result<Self, DrizzleError> {
3194        Ok(value)
3195    }
3196}
3197
3198// =============================================================================
3199// Network types (when feature enabled)
3200// =============================================================================
3201
3202#[cfg(feature = "cidr")]
3203impl FromPostgresValue for cidr::IpInet {
3204    impl_from_postgres_value_errors!("IpInet");
3205
3206    fn from_postgres_inet(value: cidr::IpInet) -> Result<Self, DrizzleError> {
3207        Ok(value)
3208    }
3209}
3210
3211#[cfg(feature = "cidr")]
3212impl FromPostgresValue for cidr::IpCidr {
3213    impl_from_postgres_value_errors!("IpCidr");
3214
3215    fn from_postgres_cidr(value: cidr::IpCidr) -> Result<Self, DrizzleError> {
3216        Ok(value)
3217    }
3218}
3219
3220// =============================================================================
3221// Geometric types (when feature enabled)
3222// =============================================================================
3223
3224#[cfg(feature = "geo-types")]
3225impl FromPostgresValue for geo_types::Point<f64> {
3226    impl_from_postgres_value_errors!("Point");
3227
3228    fn from_postgres_point(value: geo_types::Point<f64>) -> Result<Self, DrizzleError> {
3229        Ok(value)
3230    }
3231}
3232
3233#[cfg(feature = "geo-types")]
3234impl FromPostgresValue for geo_types::LineString<f64> {
3235    impl_from_postgres_value_errors!("LineString");
3236
3237    fn from_postgres_linestring(value: geo_types::LineString<f64>) -> Result<Self, DrizzleError> {
3238        Ok(value)
3239    }
3240}
3241
3242#[cfg(feature = "geo-types")]
3243impl FromPostgresValue for geo_types::Rect<f64> {
3244    impl_from_postgres_value_errors!("Rect");
3245
3246    fn from_postgres_rect(value: geo_types::Rect<f64>) -> Result<Self, DrizzleError> {
3247        Ok(value)
3248    }
3249}
3250
3251// =============================================================================
3252// Bit string types (when feature enabled)
3253// =============================================================================
3254
3255#[cfg(feature = "bit-vec")]
3256impl FromPostgresValue for bit_vec::BitVec {
3257    impl_from_postgres_value_errors!("BitVec");
3258
3259    fn from_postgres_bitvec(value: bit_vec::BitVec) -> Result<Self, DrizzleError> {
3260        Ok(value)
3261    }
3262}
3263
3264// =============================================================================
3265// ArrayVec/ArrayString support (when feature enabled)
3266// =============================================================================
3267
3268#[cfg(feature = "arrayvec")]
3269impl<const N: usize> FromPostgresValue for arrayvec::ArrayString<N> {
3270    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3271        let s = value.to_string();
3272        Self::from(&s).map_err(|_| {
3273            DrizzleError::ConversionError(
3274                format!(
3275                    "String length {} exceeds ArrayString capacity {}",
3276                    s.len(),
3277                    N
3278                )
3279                .into(),
3280            )
3281        })
3282    }
3283
3284    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3285        let s = value.to_string();
3286        Self::from(&s).map_err(|_| {
3287            DrizzleError::ConversionError(
3288                format!(
3289                    "String length {} exceeds ArrayString capacity {}",
3290                    s.len(),
3291                    N
3292                )
3293                .into(),
3294            )
3295        })
3296    }
3297
3298    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3299        let s = value.to_string();
3300        Self::from(&s).map_err(|_| {
3301            DrizzleError::ConversionError(
3302                format!(
3303                    "String length {} exceeds ArrayString capacity {}",
3304                    s.len(),
3305                    N
3306                )
3307                .into(),
3308            )
3309        })
3310    }
3311
3312    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3313        let s = value.to_string();
3314        Self::from(&s).map_err(|_| {
3315            DrizzleError::ConversionError(
3316                format!(
3317                    "String length {} exceeds ArrayString capacity {}",
3318                    s.len(),
3319                    N
3320                )
3321                .into(),
3322            )
3323        })
3324    }
3325
3326    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3327        let s = value.to_string();
3328        Self::from(&s).map_err(|_| {
3329            DrizzleError::ConversionError(
3330                format!(
3331                    "String length {} exceeds ArrayString capacity {}",
3332                    s.len(),
3333                    N
3334                )
3335                .into(),
3336            )
3337        })
3338    }
3339
3340    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3341        let s = value.to_string();
3342        Self::from(&s).map_err(|_| {
3343            DrizzleError::ConversionError(
3344                format!(
3345                    "String length {} exceeds ArrayString capacity {}",
3346                    s.len(),
3347                    N
3348                )
3349                .into(),
3350            )
3351        })
3352    }
3353
3354    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3355        Self::from(value).map_err(|_| {
3356            DrizzleError::ConversionError(
3357                format!(
3358                    "Text length {} exceeds ArrayString capacity {}",
3359                    value.len(),
3360                    N
3361                )
3362                .into(),
3363            )
3364        })
3365    }
3366
3367    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3368        let s = String::from_utf8(value.to_vec())
3369            .map_err(|e| DrizzleError::ConversionError(format!("invalid UTF-8: {e}").into()))?;
3370        Self::from(&s).map_err(|_| {
3371            DrizzleError::ConversionError(
3372                format!(
3373                    "String length {} exceeds ArrayString capacity {}",
3374                    s.len(),
3375                    N
3376                )
3377                .into(),
3378            )
3379        })
3380    }
3381}
3382
3383impl<const N: usize> FromPostgresValue for [u8; N] {
3384    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
3385        Err(DrizzleError::ConversionError(
3386            "cannot convert bool to [u8; N], use BYTEA".into(),
3387        ))
3388    }
3389
3390    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
3391        Err(DrizzleError::ConversionError(
3392            "cannot convert i16 to [u8; N], use BYTEA".into(),
3393        ))
3394    }
3395
3396    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
3397        Err(DrizzleError::ConversionError(
3398            "cannot convert i32 to [u8; N], use BYTEA".into(),
3399        ))
3400    }
3401
3402    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
3403        Err(DrizzleError::ConversionError(
3404            "cannot convert i64 to [u8; N], use BYTEA".into(),
3405        ))
3406    }
3407
3408    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
3409        Err(DrizzleError::ConversionError(
3410            "cannot convert f32 to [u8; N], use BYTEA".into(),
3411        ))
3412    }
3413
3414    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
3415        Err(DrizzleError::ConversionError(
3416            "cannot convert f64 to [u8; N], use BYTEA".into(),
3417        ))
3418    }
3419
3420    fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
3421        Err(DrizzleError::ConversionError(
3422            "cannot convert TEXT to [u8; N], use BYTEA".into(),
3423        ))
3424    }
3425
3426    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3427        Self::try_from(value).map_err(|_| {
3428            DrizzleError::ConversionError(
3429                format!("expected {N} bytes for [u8; {N}], got {}", value.len()).into(),
3430            )
3431        })
3432    }
3433
3434    // A MACADDR / MACADDR8 cell is its raw bytes.
3435    #[cfg(feature = "cidr")]
3436    fn from_postgres_macaddr(value: [u8; 6]) -> Result<Self, DrizzleError> {
3437        Self::from_postgres_bytes(&value)
3438    }
3439
3440    #[cfg(feature = "cidr")]
3441    fn from_postgres_macaddr8(value: [u8; 8]) -> Result<Self, DrizzleError> {
3442        Self::from_postgres_bytes(&value)
3443    }
3444}
3445
3446#[cfg(feature = "arrayvec")]
3447impl<const N: usize> FromPostgresValue for arrayvec::ArrayVec<u8, N> {
3448    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
3449        Err(DrizzleError::ConversionError(
3450            "cannot convert bool to ArrayVec<u8>, use BYTEA".into(),
3451        ))
3452    }
3453
3454    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
3455        Err(DrizzleError::ConversionError(
3456            "cannot convert i16 to ArrayVec<u8>, use BYTEA".into(),
3457        ))
3458    }
3459
3460    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
3461        Err(DrizzleError::ConversionError(
3462            "cannot convert i32 to ArrayVec<u8>, use BYTEA".into(),
3463        ))
3464    }
3465
3466    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
3467        Err(DrizzleError::ConversionError(
3468            "cannot convert i64 to ArrayVec<u8>, use BYTEA".into(),
3469        ))
3470    }
3471
3472    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
3473        Err(DrizzleError::ConversionError(
3474            "cannot convert f32 to ArrayVec<u8>, use BYTEA".into(),
3475        ))
3476    }
3477
3478    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
3479        Err(DrizzleError::ConversionError(
3480            "cannot convert f64 to ArrayVec<u8>, use BYTEA".into(),
3481        ))
3482    }
3483
3484    fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
3485        Err(DrizzleError::ConversionError(
3486            "cannot convert TEXT to ArrayVec<u8>, use BYTEA".into(),
3487        ))
3488    }
3489
3490    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3491        Self::try_from(value).map_err(|_| {
3492            DrizzleError::ConversionError(
3493                format!(
3494                    "Bytes length {} exceeds ArrayVec capacity {}",
3495                    value.len(),
3496                    N
3497                )
3498                .into(),
3499            )
3500        })
3501    }
3502}
3503
3504#[cfg(feature = "compact-str")]
3505impl FromPostgresValue for compact_str::CompactString {
3506    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3507        Ok(Self::new(value.to_string()))
3508    }
3509
3510    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3511        Ok(Self::new(value.to_string()))
3512    }
3513
3514    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3515        Ok(Self::new(value.to_string()))
3516    }
3517
3518    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3519        Ok(Self::new(value.to_string()))
3520    }
3521
3522    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3523        Ok(Self::new(value.to_string()))
3524    }
3525
3526    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3527        Ok(Self::new(value.to_string()))
3528    }
3529
3530    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3531        Ok(Self::new(value))
3532    }
3533
3534    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3535        let s = String::from_utf8(value.to_vec()).map_err(|e| {
3536            DrizzleError::ConversionError(format!("invalid UTF-8 in BYTEA: {e}").into())
3537        })?;
3538        Ok(Self::new(s))
3539    }
3540}
3541
3542#[cfg(feature = "bytes")]
3543impl FromPostgresValue for bytes::Bytes {
3544    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3545        Vec::<u8>::from_postgres_bool(value).map(Self::from)
3546    }
3547
3548    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3549        Vec::<u8>::from_postgres_i16(value).map(Self::from)
3550    }
3551
3552    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3553        Vec::<u8>::from_postgres_i32(value).map(Self::from)
3554    }
3555
3556    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3557        Vec::<u8>::from_postgres_i64(value).map(Self::from)
3558    }
3559
3560    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3561        Vec::<u8>::from_postgres_f32(value).map(Self::from)
3562    }
3563
3564    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3565        Vec::<u8>::from_postgres_f64(value).map(Self::from)
3566    }
3567
3568    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3569        Vec::<u8>::from_postgres_text(value).map(Self::from)
3570    }
3571
3572    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3573        Ok(Self::copy_from_slice(value))
3574    }
3575}
3576
3577#[cfg(feature = "bytes")]
3578impl FromPostgresValue for bytes::BytesMut {
3579    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3580        Vec::<u8>::from_postgres_bool(value).map(|v| Self::from(v.as_slice()))
3581    }
3582
3583    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3584        Vec::<u8>::from_postgres_i16(value).map(|v| Self::from(v.as_slice()))
3585    }
3586
3587    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3588        Vec::<u8>::from_postgres_i32(value).map(|v| Self::from(v.as_slice()))
3589    }
3590
3591    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3592        Vec::<u8>::from_postgres_i64(value).map(|v| Self::from(v.as_slice()))
3593    }
3594
3595    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3596        Vec::<u8>::from_postgres_f32(value).map(|v| Self::from(v.as_slice()))
3597    }
3598
3599    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3600        Vec::<u8>::from_postgres_f64(value).map(|v| Self::from(v.as_slice()))
3601    }
3602
3603    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3604        Vec::<u8>::from_postgres_text(value).map(|v| Self::from(v.as_slice()))
3605    }
3606
3607    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3608        Ok(Self::from(value))
3609    }
3610}
3611
3612#[cfg(feature = "smallvec")]
3613impl<const N: usize> FromPostgresValue for smallvec::SmallVec<[u8; N]> {
3614    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
3615        Err(DrizzleError::ConversionError(
3616            "cannot convert bool to SmallVec<u8>, use BYTEA".into(),
3617        ))
3618    }
3619
3620    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
3621        Err(DrizzleError::ConversionError(
3622            "cannot convert i16 to SmallVec<u8>, use BYTEA".into(),
3623        ))
3624    }
3625
3626    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
3627        Err(DrizzleError::ConversionError(
3628            "cannot convert i32 to SmallVec<u8>, use BYTEA".into(),
3629        ))
3630    }
3631
3632    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
3633        Err(DrizzleError::ConversionError(
3634            "cannot convert i64 to SmallVec<u8>, use BYTEA".into(),
3635        ))
3636    }
3637
3638    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
3639        Err(DrizzleError::ConversionError(
3640            "cannot convert f32 to SmallVec<u8>, use BYTEA".into(),
3641        ))
3642    }
3643
3644    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
3645        Err(DrizzleError::ConversionError(
3646            "cannot convert f64 to SmallVec<u8>, use BYTEA".into(),
3647        ))
3648    }
3649
3650    fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
3651        Err(DrizzleError::ConversionError(
3652            "cannot convert TEXT to SmallVec<u8>, use BYTEA".into(),
3653        ))
3654    }
3655
3656    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3657        let mut out = Self::new();
3658        out.extend_from_slice(value);
3659        Ok(out)
3660    }
3661}