drizzle-core 0.1.5

A type-safe SQL query builder for Rust
Documentation
//! Type-safe SQL expression system.
//!
//! This module provides a type-safe wrapper around SQL expressions that tracks:
//! - The SQL data type of the expression
//! - Whether the expression can be NULL
//! - Whether the expression is an aggregate or scalar
//!
//! # Example
//!
//! ```ignore
//! use drizzle_core::expr::*;
//!
//! // Type-safe comparisons
//! let condition = eq(users.id, 10);  // OK: Int == Int
//! // let bad = eq(users.id, "hello"); // ERROR: Int != Text
//!
//! // Type-safe arithmetic
//! let total = users.price + users.tax;  // OK: both Numeric
//! // let bad = users.name + users.id;   // ERROR: Text + Int
//! ```

mod agg;
mod cmp;
mod column_ops;
mod datetime;
mod logical;
mod math;
mod null;
mod ops;
mod primitives;
mod set;
mod string;
mod typed;
mod util;

pub use agg::*;
pub use cmp::*;
#[doc(hidden)]
pub use column_ops::*;
pub use datetime::*;
pub use logical::*;
pub use math::*;
pub use null::*;
pub use set::*;
pub use string::*;
// ops has only trait impls - no items to re-export
pub use typed::*;
pub use util::*;

use crate::traits::{SQLParam, ToSQL};
use crate::types::DataType;

// =============================================================================
// Sealed Trait Pattern
// =============================================================================

mod private {
    pub trait Sealed {}
}

// =============================================================================
// Nullability Markers
// =============================================================================

/// Marker trait for nullability state.
pub trait Nullability: private::Sealed + Copy + Default + 'static {}

/// Marker indicating an expression cannot be NULL.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct NonNull;

/// Marker indicating an expression can be NULL.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Null;

impl private::Sealed for NonNull {}
impl private::Sealed for Null {}
impl Nullability for NonNull {}
impl Nullability for Null {}

// =============================================================================
// Aggregate Kind Markers
// =============================================================================

/// Marker trait for expression aggregation state.
pub trait AggregateKind: private::Sealed + Copy + Default + 'static {}

/// Marker indicating a scalar (non-aggregate) expression.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Scalar;

/// Marker indicating an aggregate expression (COUNT, SUM, etc.).
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Agg;

impl private::Sealed for Scalar {}
impl private::Sealed for Agg {}
impl AggregateKind for Scalar {}
impl AggregateKind for Agg {}

// =============================================================================
// Core Expression Trait
// =============================================================================

/// An expression in SQL with an associated data type.
///
/// This is the core trait for type-safe SQL expressions. Every SQL expression
/// (column, literal, function result) implements this with its SQL type.
///
/// # Type Parameters
///
/// - `'a`: Lifetime of borrowed data in the expression
/// - `V`: The dialect's value type (SQLiteValue, PostgresValue)
///
/// # Associated Types
///
/// - `SQLType`: The SQL data type this expression evaluates to
/// - `Nullable`: Whether this expression can be NULL
/// - `Aggregate`: Whether this is an aggregate or scalar expression
///
/// # Example
///
/// ```ignore
/// use drizzle_core::expr::{Expr, NonNull, Scalar};
/// use drizzle_core::types::Int;
///
/// // i32 literals are Int, NonNull, Scalar
/// fn check_expr<'a, V, E: Expr<'a, V>>() {}
/// check_expr::<_, i32>(); // SQLType=Int, Nullable=NonNull, Aggregate=Scalar
/// ```
pub trait Expr<'a, V: SQLParam>: ToSQL<'a, V> {
    /// The SQL data type this expression evaluates to.
    type SQLType: DataType;

    /// Whether this expression can be NULL.
    type Nullable: Nullability;

    /// Whether this is an aggregate (COUNT, SUM) or scalar expression.
    type Aggregate: AggregateKind;
}

// Note: Columns implement Expr via explicit impls generated by macros,
// not via a blanket impl, to avoid conflicts with `impl Expr for &T`.