Skip to main content

drizzle_postgres/traits/
value.rs

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