drizzle-postgres 0.1.7

A type-safe SQL query builder for Rust
Documentation
mod column;
mod table;
mod value;

#[cfg(not(feature = "std"))]
use crate::prelude::*;
pub use column::*;
use core::any::Any;
use drizzle_core::error::DrizzleError;
pub use table::*;
pub use value::*;

use crate::values::PostgresValue;

/// Trait for `PostgreSQL` native enum types that can be used as dyn objects
#[allow(clippy::wrong_self_convention)]
pub trait PostgresEnum: Send + Sync + Any {
    /// Get the enum type name for `PostgreSQL`
    fn enum_type_name(&self) -> &'static str;

    fn as_enum(&self) -> &dyn PostgresEnum;

    /// Get the string representation of this enum variant
    fn variant_name(&self) -> &'static str;

    /// Clone this enum as a boxed trait object
    fn into_boxed(&self) -> Box<dyn PostgresEnum>;

    /// Try to create this enum from a string value
    ///
    /// # Errors
    ///
    /// Returns [`DrizzleError::ConversionError`] when `value` is not a valid
    /// variant name for this enum.
    fn try_from_str(value: &str) -> Result<Self, DrizzleError>
    where
        Self: Sized;
}

impl core::fmt::Debug for &dyn PostgresEnum {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("PostgresSQLEnum")
            .field("type", &self.enum_type_name())
            .field("variant", &self.variant_name())
            .finish()
    }
}

impl PartialEq for &dyn PostgresEnum {
    fn eq(&self, other: &Self) -> bool {
        self.enum_type_name() == other.enum_type_name()
            && self.variant_name() == other.variant_name()
    }
}

impl core::fmt::Debug for Box<dyn PostgresEnum> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("PostgresSQLEnum")
            .field("type", &self.enum_type_name())
            .field("variant", &self.variant_name())
            .finish()
    }
}

impl Clone for Box<dyn PostgresEnum> {
    fn clone(&self) -> Self {
        self.into_boxed()
    }
}

impl PartialEq for Box<dyn PostgresEnum> {
    fn eq(&self, other: &Self) -> bool {
        self.enum_type_name() == other.enum_type_name()
            && self.variant_name() == other.variant_name()
    }
}

/// Marker trait for custom Rust types that map to a `PostgreSQL` column.
///
/// Generated by `#[derive(PostgresEnum)]`. The table macro uses this trait to
/// auto-detect enum types without requiring `#[column(ENUM)]`.
///
/// # Associated Constants
///
/// - `SQL_TYPE`: The `PostgreSQL` column type (e.g. `"text"`, `"integer"`, or the lowercased enum name)
/// - `NEEDS_CREATE_TYPE`: Whether this requires a `CREATE TYPE` (native PG enum)
///
/// # Required Methods
///
/// - `from_postgres_row`: Read self from a postgres Row at the given index
/// - `to_postgres_value`: Convert self to a `PostgresValue` for insertion/updates
#[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
#[diagnostic::on_unimplemented(
    message = "`{Self}` cannot be used as a PostgreSQL column type",
    note = "add #[derive(PostgresEnum)] for enum types, or use a supported primitive type"
)]
pub trait DrizzlePostgresColumn: Sized {
    /// `PostgreSQL` column type: `"text"`, `"integer"`, or native enum type name
    const SQL_TYPE: &'static str;

    /// Whether this requires a `CREATE TYPE` (native PG enum).
    const NEEDS_CREATE_TYPE: bool = false;

    /// Read self from a postgres Row at the given index.
    ///
    /// # Errors
    ///
    /// Returns [`DrizzleError::ConversionError`] when the column at `idx`
    /// cannot be decoded into this type.
    fn from_postgres_row(row: &crate::Row, idx: usize) -> Result<Self, DrizzleError>;

    /// Convert self to a `PostgresValue` for insertion/updates.
    fn to_postgres_value(&self) -> PostgresValue<'static>;
}

/// Stub trait when no postgres driver is enabled — allows enum derives to compile
/// without a driver feature, but the table macro's `TryFrom` impls won't be generated.
#[cfg(not(any(feature = "postgres-sync", feature = "tokio-postgres")))]
#[diagnostic::on_unimplemented(
    message = "`{Self}` cannot be used as a PostgreSQL column type",
    note = "add #[derive(PostgresEnum)] for enum types, or use a supported primitive type"
)]
pub trait DrizzlePostgresColumn: Sized {
    /// `PostgreSQL` column type: `"text"`, `"integer"`, or native enum type name
    const SQL_TYPE: &'static str;

    /// Whether this requires a `CREATE TYPE` (native PG enum).
    const NEEDS_CREATE_TYPE: bool = false;

    /// Convert self to a `PostgresValue` for insertion/updates.
    fn to_postgres_value(&self) -> PostgresValue<'static>;
}