Skip to main content

qraft_core/
alias.rs

1//! Alias utilities for reusing tables, subqueries, and projected expressions.
2//!
3//! For derived `Qraft` models you can also use the `qraft::alias!` macro to
4//! declare a module-style alias, for example `qraft::alias!(u: User);`.
5
6use crate::{
7    Boolean, Qrafting, Query, TypeMeta,
8    expression::{As, Column, ColumnStar, Expression},
9    query::{JoinOn, LowerProject, OnJoin, Table},
10};
11
12/// Wraps a value with a SQL alias.
13#[derive(Debug, Clone, Copy)]
14pub struct Aliased<T: Alias> {
15    pub(crate) alias: &'static str,
16    pub(crate) inner: T,
17}
18
19impl<M: Qrafting> Aliased<Table<M>> {
20    /// Returns `alias.*` for the aliased table.
21    pub const fn star(&self) -> As<ColumnStar<M>> {
22        As {
23            table: self.alias,
24            inner: ColumnStar {
25                marker: std::marker::PhantomData,
26            },
27        }
28    }
29
30    /// Rebinds a generated column to this alias.
31    pub fn col<T: IntoColumn>(&self, col: T) -> As<T::Out> {
32        col.into_as(self.alias)
33    }
34
35    /// Starts a joined table source with the given predicate.
36    pub fn on<E>(&self, e: E) -> JoinOn<Self, E>
37    where
38        E: Expression,
39        E::Type: Boolean,
40    {
41        OnJoin::on(*self, e)
42    }
43}
44
45/// Converts a column-like value into its aliased form.
46pub trait IntoColumn: Sized {
47    /// The column type produced after aliasing.
48    type Out;
49    /// Rebinds the value to the provided alias.
50    fn into_as(self, alias: &'static str) -> As<Self::Out>;
51}
52
53impl<M, Ty: TypeMeta> IntoColumn for Column<M, Ty> {
54    type Out = Column<M, Ty>;
55
56    fn into_as(self, alias: &'static str) -> As<Self::Out> {
57        As {
58            table: alias,
59            inner: self,
60        }
61    }
62}
63
64impl IntoColumn for &'static str {
65    type Out = &'static str;
66
67    fn into_as(self, alias: &'static str) -> As<Self::Out> {
68        As {
69            table: alias,
70            inner: self,
71        }
72    }
73}
74
75impl<T: Alias> Aliased<T> {
76    /// Wraps a value with the given alias.
77    pub const fn new(inner: T, alias: &'static str) -> Self {
78        Self { inner, alias }
79    }
80}
81
82/// Implemented by values that can carry a SQL alias.
83///
84/// This is the lower-level aliasing API behind patterns like
85/// `table.alias("u")`. For derived `Qraft` models, `qraft::alias!` provides a
86/// shorthand for creating a typed alias module.
87pub trait Alias {
88    /// Returns the same value tagged with the provided alias.
89    fn alias(self, alias: &'static str) -> Aliased<Self>
90    where
91        Self: Sized,
92    {
93        Aliased::new(self, alias)
94    }
95}
96
97impl Alias for Query {}
98impl<T> Alias for T where T: LowerProject {}