qraft-core 0.1.2

Core type system, query model, decoding, and SQL lowering primitives for qraft.
Documentation
//! Alias utilities for reusing tables, subqueries, and projected expressions.
//!
//! For derived `Qraft` models you can also use the `qraft::alias!` macro to
//! declare a module-style alias, for example `qraft::alias!(u: User);`.

use crate::{
    Boolean, Qrafting, Query, TypeMeta,
    expression::{As, Column, ColumnStar, Expression},
    query::{JoinOn, LowerProject, OnJoin, Table},
};

/// Wraps a value with a SQL alias.
#[derive(Debug, Clone, Copy)]
pub struct Aliased<T: Alias> {
    pub(crate) alias: &'static str,
    pub(crate) inner: T,
}

impl<M: Qrafting> Aliased<Table<M>> {
    /// Returns `alias.*` for the aliased table.
    pub const fn star(&self) -> As<ColumnStar<M>> {
        As {
            table: self.alias,
            inner: ColumnStar {
                marker: std::marker::PhantomData,
            },
        }
    }

    /// Rebinds a generated column to this alias.
    pub fn col<T: IntoColumn>(&self, col: T) -> As<T::Out> {
        col.into_as(self.alias)
    }

    /// Starts a joined table source with the given predicate.
    pub fn on<E>(&self, e: E) -> JoinOn<Self, E>
    where
        E: Expression,
        E::Type: Boolean,
    {
        OnJoin::on(*self, e)
    }
}

/// Converts a column-like value into its aliased form.
pub trait IntoColumn: Sized {
    /// The column type produced after aliasing.
    type Out;
    /// Rebinds the value to the provided alias.
    fn into_as(self, alias: &'static str) -> As<Self::Out>;
}

impl<M, Ty: TypeMeta> IntoColumn for Column<M, Ty> {
    type Out = Column<M, Ty>;

    fn into_as(self, alias: &'static str) -> As<Self::Out> {
        As {
            table: alias,
            inner: self,
        }
    }
}

impl IntoColumn for &'static str {
    type Out = &'static str;

    fn into_as(self, alias: &'static str) -> As<Self::Out> {
        As {
            table: alias,
            inner: self,
        }
    }
}

impl<T: Alias> Aliased<T> {
    /// Wraps a value with the given alias.
    pub const fn new(inner: T, alias: &'static str) -> Self {
        Self { inner, alias }
    }
}

/// Implemented by values that can carry a SQL alias.
///
/// This is the lower-level aliasing API behind patterns like
/// `table.alias("u")`. For derived `Qraft` models, `qraft::alias!` provides a
/// shorthand for creating a typed alias module.
pub trait Alias {
    /// Returns the same value tagged with the provided alias.
    fn alias(self, alias: &'static str) -> Aliased<Self>
    where
        Self: Sized,
    {
        Aliased::new(self, alias)
    }
}

impl Alias for Query {}
impl<T> Alias for T where T: LowerProject {}